mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Store class names in metadata as a pair of package and simple name
This commit is contained in:
parent
0a94c91ff2
commit
681e21ecca
|
@ -20,8 +20,10 @@ import com.carrotsearch.hppc.ObjectIntMap;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -487,22 +489,17 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
|
||||
private void renderClassMetadata(List<ClassNode> classes) {
|
||||
Set<String> classesRequiringName = new HashSet<>();
|
||||
MethodDependencyInfo getNameMethod = context.getDependencyInfo().getMethod(
|
||||
new MethodReference(Class.class, "getName", String.class));
|
||||
if (getNameMethod != null) {
|
||||
classesRequiringName.addAll(Arrays.asList(getNameMethod.getVariable(0).getClassValueNode().getTypes()));
|
||||
}
|
||||
MethodDependencyInfo getSimpleNameMethod = context.getDependencyInfo().getMethod(
|
||||
new MethodReference(Class.class, "getSimpleName", String.class));
|
||||
if (getSimpleNameMethod != null) {
|
||||
classesRequiringName.addAll(Arrays.asList(
|
||||
getSimpleNameMethod.getVariable(0).getClassValueNode().getTypes()));
|
||||
if (classes.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<String> classesRequiringName = findClassesRequiringName();
|
||||
|
||||
int start = writer.getOffset();
|
||||
try {
|
||||
writer.append("$rt_metadata([");
|
||||
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, classesRequiringName);
|
||||
|
||||
boolean first = true;
|
||||
for (ClassNode cls : classes) {
|
||||
if (!first) {
|
||||
|
@ -512,7 +509,12 @@ public class Renderer implements RenderingManager {
|
|||
writer.appendClass(cls.getName()).append(",").ws();
|
||||
|
||||
if (classesRequiringName.contains(cls.getName())) {
|
||||
writer.append("\"").append(RenderingUtil.escapeString(cls.getName())).append("\"");
|
||||
String className = cls.getName();
|
||||
int dotIndex = className.lastIndexOf('.') + 1;
|
||||
String packageName = className.substring(0, dotIndex);
|
||||
className = className.substring(dotIndex);
|
||||
writer.append("\"").append(RenderingUtil.escapeString(className)).append("\"").append(",").ws();
|
||||
writer.append(String.valueOf(packageIndexes.getOrDefault(packageName, -1)));
|
||||
} else {
|
||||
writer.append("0");
|
||||
}
|
||||
|
@ -566,6 +568,85 @@ public class Renderer implements RenderingManager {
|
|||
metadataSize = writer.getOffset() - start;
|
||||
}
|
||||
|
||||
private ObjectIntMap<String> generatePackageMetadata(List<ClassNode> classes, Set<String> classesRequiringName)
|
||||
throws IOException {
|
||||
PackageNode root = new PackageNode(null);
|
||||
|
||||
for (ClassNode classNode : classes) {
|
||||
String className = classNode.getName();
|
||||
if (!classesRequiringName.contains(className)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int dotIndex = className.lastIndexOf('.');
|
||||
if (dotIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addPackageName(root, className.substring(0, dotIndex));
|
||||
}
|
||||
|
||||
ObjectIntMap<String> indexes = new ObjectIntHashMap<>();
|
||||
writer.append(String.valueOf(root.count())).append(",").ws();
|
||||
writePackageStructure(root, -1, "", indexes);
|
||||
writer.softNewLine();
|
||||
return indexes;
|
||||
}
|
||||
|
||||
private int writePackageStructure(PackageNode node, int startIndex, String prefix, ObjectIntMap<String> indexes)
|
||||
throws IOException {
|
||||
int index = startIndex;
|
||||
for (PackageNode child : node.children.values()) {
|
||||
writer.append(String.valueOf(startIndex)).append(",").ws()
|
||||
.append("\"").append(RenderingUtil.escapeString(child.name)).append("\",").ws();
|
||||
String fullName = prefix + child.name + ".";
|
||||
++index;
|
||||
indexes.put(fullName, index);
|
||||
index = writePackageStructure(child, index, fullName, indexes);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
static class PackageNode {
|
||||
String name;
|
||||
Map<String, PackageNode> children = new HashMap<>();
|
||||
|
||||
PackageNode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
int count() {
|
||||
int result = 0;
|
||||
for (PackageNode child : children.values()) {
|
||||
result += 1 + child.count();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private void addPackageName(PackageNode node, String name) {
|
||||
String[] parts = name.split("\\.");
|
||||
for (String part : parts) {
|
||||
node = node.children.computeIfAbsent(part, PackageNode::new);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> findClassesRequiringName() {
|
||||
Set<String> classesRequiringName = new HashSet<>();
|
||||
MethodDependencyInfo getNameMethod = context.getDependencyInfo().getMethod(
|
||||
new MethodReference(Class.class, "getName", String.class));
|
||||
if (getNameMethod != null) {
|
||||
classesRequiringName.addAll(Arrays.asList(getNameMethod.getVariable(0).getClassValueNode().getTypes()));
|
||||
}
|
||||
MethodDependencyInfo getSimpleNameMethod = context.getDependencyInfo().getMethod(
|
||||
new MethodReference(Class.class, "getSimpleName", String.class));
|
||||
if (getSimpleNameMethod != null) {
|
||||
classesRequiringName.addAll(Arrays.asList(
|
||||
getSimpleNameMethod.getVariable(0).getClassValueNode().getTypes()));
|
||||
}
|
||||
return classesRequiringName;
|
||||
}
|
||||
|
||||
private void collectMethodsToCopyFromInterfaces(ClassReader cls, List<MethodReference> targetList) {
|
||||
Set<MethodDescriptor> implementedMethods = new HashSet<>();
|
||||
implementedMethods.addAll(targetList.stream().map(method -> method.getDescriptor())
|
||||
|
|
|
@ -429,23 +429,40 @@ function $rt_putStderr(ch) {
|
|||
}
|
||||
}
|
||||
function $rt_metadata(data) {
|
||||
for (var i = 0; i < data.length; i += 8) {
|
||||
var cls = data[i];
|
||||
var i = 0;
|
||||
var packageCount = data[i++];
|
||||
var packages = new Array(packageCount);
|
||||
for (var j = 0; j < packageCount; ++j) {
|
||||
var prefixIndex = data[i++];
|
||||
var prefix = prefixIndex >= 0 ? packages[prefixIndex] : "";
|
||||
packages[j] = prefix + data[i++] + ".";
|
||||
}
|
||||
|
||||
while (i < data.length) {
|
||||
var cls = data[i++];
|
||||
cls.$meta = {};
|
||||
var m = cls.$meta;
|
||||
var className = data[i + 1];
|
||||
var className = data[i++];
|
||||
|
||||
m.name = className !== 0 ? className : null;
|
||||
if (m.name !== null) {
|
||||
var packageIndex = data[i++];
|
||||
if (packageIndex >= 0) {
|
||||
m.name = packages[packageIndex] + m.name;
|
||||
}
|
||||
}
|
||||
|
||||
m.binaryName = "L" + m.name + ";";
|
||||
var superclass = data[i + 2];
|
||||
var superclass = data[i++];
|
||||
m.superclass = superclass !== 0 ? superclass : null;
|
||||
m.supertypes = data[i + 3];
|
||||
m.supertypes = data[i++];
|
||||
if (m.superclass) {
|
||||
m.supertypes.push(m.superclass);
|
||||
cls.prototype = Object.create(m.superclass.prototype);
|
||||
} else {
|
||||
cls.prototype = {};
|
||||
}
|
||||
var flags = data[i + 4];
|
||||
var flags = data[i++];
|
||||
m.enum = (flags & 16) !== 0;
|
||||
m.flags = flags;
|
||||
m.primitive = false;
|
||||
|
@ -453,13 +470,13 @@ function $rt_metadata(data) {
|
|||
cls.prototype.constructor = cls;
|
||||
cls.classObject = null;
|
||||
|
||||
m.accessLevel = data[i + 5];
|
||||
m.accessLevel = data[i++];
|
||||
|
||||
var clinit = data[i + 6];
|
||||
var clinit = data[i++];
|
||||
cls.$clinit = clinit !== 0 ? clinit : function() {};
|
||||
|
||||
var virtualMethods = data[i + 7];
|
||||
for (var j = 0; j < virtualMethods.length; j += 2) {
|
||||
var virtualMethods = data[i++];
|
||||
for (j = 0; j < virtualMethods.length; j += 2) {
|
||||
var name = virtualMethods[j];
|
||||
var func = virtualMethods[j + 1];
|
||||
if (typeof name === 'string') {
|
||||
|
|
Loading…
Reference in New Issue
Block a user