mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
C/Wasm: don't generate names for classes when possible
This commit is contained in:
parent
f7620704fc
commit
c78874f426
|
@ -34,6 +34,8 @@ public class ClassDependencyListener implements DependencyPlugin {
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
case "getSimpleNameCacheLowLevel":
|
case "getSimpleNameCacheLowLevel":
|
||||||
|
case "getCanonicalNameCacheLowLevel":
|
||||||
|
case "getNameCacheLowLevel":
|
||||||
method.getResult().propagate(agent.getType("java.lang.String"));
|
method.getResult().propagate(agent.getType("java.lang.String"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,7 +106,21 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
||||||
@Unmanaged
|
@Unmanaged
|
||||||
public String getName() {
|
public String getName() {
|
||||||
if (PlatformDetector.isLowLevel()) {
|
if (PlatformDetector.isLowLevel()) {
|
||||||
return Platform.getName(platformClass);
|
String result = getNameCache(this);
|
||||||
|
if (result == null) {
|
||||||
|
result = Platform.getName(platformClass);
|
||||||
|
if (result == null) {
|
||||||
|
if (isArray()) {
|
||||||
|
TClass<?> componentType = getComponentType();
|
||||||
|
String componentName = componentType.getName();
|
||||||
|
if (componentName != null) {
|
||||||
|
result = componentType.isArray() ? "[" + componentName : "[L" + componentName + ";";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setNameCache(this, result);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
} else {
|
} else {
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
name = Platform.getName(platformClass);
|
name = Platform.getName(platformClass);
|
||||||
|
@ -167,6 +181,27 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
||||||
self.simpleNameCache = object;
|
self.simpleNameCache = object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@DelegateTo("getNameCacheLowLevel")
|
||||||
|
private static String getNameCache(TClass<?> self) {
|
||||||
|
return self.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmanaged
|
||||||
|
@PluggableDependency(ClassDependencyListener.class)
|
||||||
|
private static RuntimeObject getNameCacheLowLevel(RuntimeClass self) {
|
||||||
|
return self.nameCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@DelegateTo("setNameCacheLowLevel")
|
||||||
|
private static void setNameCache(TClass<?> self, String value) {
|
||||||
|
self.name = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Unmanaged
|
||||||
|
private static void setNameCacheLowLevel(RuntimeClass self, RuntimeObject object) {
|
||||||
|
self.nameCache = object;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCanonicalName() {
|
public String getCanonicalName() {
|
||||||
String result = getCanonicalNameCache();
|
String result = getCanonicalNameCache();
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
|
|
|
@ -64,7 +64,8 @@ public class CNameProvider extends LowLevelNameProvider {
|
||||||
|
|
||||||
preserveFieldNames(RuntimeClass.class.getName(), "size", "flags", "tag", "canary", "name", "itemType",
|
preserveFieldNames(RuntimeClass.class.getName(), "size", "flags", "tag", "canary", "name", "itemType",
|
||||||
"arrayType", "isSupertypeOf", "init", "enumValues", "layout", "simpleName", "superinterfaceCount",
|
"arrayType", "isSupertypeOf", "init", "enumValues", "layout", "simpleName", "superinterfaceCount",
|
||||||
"superinterfaces", "simpleNameCache", "declaringClass", "enclosingClass", "canonicalName");
|
"superinterfaces", "simpleNameCache", "declaringClass", "enclosingClass", "canonicalName",
|
||||||
|
"nameCache");
|
||||||
memberFieldNames.put(new FieldReference(RuntimeClass.class.getName(), "parent"), "superclass");
|
memberFieldNames.put(new FieldReference(RuntimeClass.class.getName(), "parent"), "superclass");
|
||||||
preserveFieldNames(RuntimeReference.class.getName(), "queue", "object", "next");
|
preserveFieldNames(RuntimeReference.class.getName(), "queue", "object", "next");
|
||||||
preserveFieldNames(RuntimeReferenceQueue.class.getName(), "first", "last");
|
preserveFieldNames(RuntimeReferenceQueue.class.getName(), "first", "last");
|
||||||
|
|
|
@ -58,6 +58,7 @@ import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.analysis.ClassMetadataRequirements;
|
||||||
import org.teavm.model.classes.TagRegistry;
|
import org.teavm.model.classes.TagRegistry;
|
||||||
import org.teavm.model.classes.VirtualTable;
|
import org.teavm.model.classes.VirtualTable;
|
||||||
import org.teavm.model.classes.VirtualTableEntry;
|
import org.teavm.model.classes.VirtualTableEntry;
|
||||||
|
@ -104,6 +105,7 @@ public class ClassGenerator {
|
||||||
private MethodNodeCache astCache = EmptyMethodNodeCache.INSTANCE;
|
private MethodNodeCache astCache = EmptyMethodNodeCache.INSTANCE;
|
||||||
private AstDependencyExtractor dependencyExtractor = new AstDependencyExtractor();
|
private AstDependencyExtractor dependencyExtractor = new AstDependencyExtractor();
|
||||||
private List<CallSiteDescriptor> callSites;
|
private List<CallSiteDescriptor> callSites;
|
||||||
|
private ClassMetadataRequirements metadataRequirements;
|
||||||
|
|
||||||
public ClassGenerator(GenerationContext context, TagRegistry tagRegistry, Decompiler decompiler,
|
public ClassGenerator(GenerationContext context, TagRegistry tagRegistry, Decompiler decompiler,
|
||||||
CacheStatus cacheStatus) {
|
CacheStatus cacheStatus) {
|
||||||
|
@ -111,6 +113,7 @@ public class ClassGenerator {
|
||||||
this.tagRegistry = tagRegistry;
|
this.tagRegistry = tagRegistry;
|
||||||
this.decompiler = decompiler;
|
this.decompiler = decompiler;
|
||||||
this.cacheStatus = cacheStatus;
|
this.cacheStatus = cacheStatus;
|
||||||
|
metadataRequirements = new ClassMetadataRequirements(context.getDependencies());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAstCache(MethodNodeCache astCache) {
|
public void setAstCache(MethodNodeCache astCache) {
|
||||||
|
@ -778,7 +781,10 @@ public class ClassGenerator {
|
||||||
itemTypeExpr = "NULL";
|
itemTypeExpr = "NULL";
|
||||||
}
|
}
|
||||||
|
|
||||||
int nameRef = context.getStringPool().getStringIndex(nameOfType(type));
|
String metadataName = nameOfType(type);
|
||||||
|
String nameRef = metadataName != null
|
||||||
|
? "(TeaVM_Object**) &TEAVM_GET_STRING(" + context.getStringPool().getStringIndex(metadataName) + ")"
|
||||||
|
: "NULL";
|
||||||
String superTypeFunction = context.getNames().forSupertypeFunction(type);
|
String superTypeFunction = context.getNames().forSupertypeFunction(type);
|
||||||
|
|
||||||
ValueType arrayType = ValueType.arrayOf(type);
|
ValueType arrayType = ValueType.arrayOf(type);
|
||||||
|
@ -802,7 +808,7 @@ public class ClassGenerator {
|
||||||
codeWriter.println(".flags = " + flags + ",");
|
codeWriter.println(".flags = " + flags + ",");
|
||||||
codeWriter.println(".tag = " + tag + ",");
|
codeWriter.println(".tag = " + tag + ",");
|
||||||
codeWriter.println(".canary = 0,");
|
codeWriter.println(".canary = 0,");
|
||||||
codeWriter.println(".name = (TeaVM_Object**) &TEAVM_GET_STRING(" + nameRef + "),");
|
codeWriter.println(".name = " + nameRef + ",");
|
||||||
codeWriter.println(".simpleName = " + simpleName + ",");
|
codeWriter.println(".simpleName = " + simpleName + ",");
|
||||||
codeWriter.println(".arrayType = " + arrayTypeExpr + ",");
|
codeWriter.println(".arrayType = " + arrayTypeExpr + ",");
|
||||||
codeWriter.println(".itemType = " + itemTypeExpr + ",");
|
codeWriter.println(".itemType = " + itemTypeExpr + ",");
|
||||||
|
@ -1168,7 +1174,7 @@ public class ClassGenerator {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String nameOfType(ValueType type) {
|
public String nameOfType(ValueType type) {
|
||||||
if (type instanceof ValueType.Primitive) {
|
if (type instanceof ValueType.Primitive) {
|
||||||
switch (((ValueType.Primitive) type).getKind()) {
|
switch (((ValueType.Primitive) type).getKind()) {
|
||||||
case BOOLEAN:
|
case BOOLEAN:
|
||||||
|
@ -1191,16 +1197,28 @@ public class ClassGenerator {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
} else if (type instanceof ValueType.Array) {
|
} else if (type instanceof ValueType.Array) {
|
||||||
|
if (isArrayOfPrimitives(type)) {
|
||||||
return type.toString().replace('/', '.');
|
return type.toString().replace('/', '.');
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
} else if (type == ValueType.VOID) {
|
} else if (type == ValueType.VOID) {
|
||||||
return "void";
|
return "void";
|
||||||
} else if (type instanceof ValueType.Object) {
|
} else if (type instanceof ValueType.Object) {
|
||||||
return ((ValueType.Object) type).getClassName();
|
String name = ((ValueType.Object) type).getClassName();
|
||||||
|
return metadataRequirements.getInfo(name).name() ? name : null;
|
||||||
} else {
|
} else {
|
||||||
throw new AssertionError();
|
throw new AssertionError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean isArrayOfPrimitives(ValueType type) {
|
||||||
|
while (type instanceof ValueType.Array) {
|
||||||
|
type = ((ValueType.Array) type).getItemType();
|
||||||
|
}
|
||||||
|
return type instanceof ValueType.Primitive || type == ValueType.VOID;
|
||||||
|
}
|
||||||
|
|
||||||
private void generateIsSupertypeFunction(ValueType type) {
|
private void generateIsSupertypeFunction(ValueType type) {
|
||||||
String name = context.getNames().forSupertypeFunction(type);
|
String name = context.getNames().forSupertypeFunction(type);
|
||||||
headerWriter.println("extern int32_t " + name + "(TeaVM_Class*);");
|
headerWriter.println("extern int32_t " + name + "(TeaVM_Class*);");
|
||||||
|
|
|
@ -62,8 +62,11 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
|
||||||
printFieldAccess(context, invocation, SUPERCLASS_FIELD);
|
printFieldAccess(context, invocation, SUPERCLASS_FIELD);
|
||||||
break;
|
break;
|
||||||
case "getName":
|
case "getName":
|
||||||
context.writer().print("*");
|
context.writer().print("(");
|
||||||
printFieldAccess(context, invocation, NAME_FIELD);
|
printFieldAccess(context, invocation, NAME_FIELD);
|
||||||
|
context.writer().print(" ? *");
|
||||||
|
printFieldAccess(context, invocation, NAME_FIELD);
|
||||||
|
context.writer().print(" : NULL)");
|
||||||
break;
|
break;
|
||||||
case "getSimpleName":
|
case "getSimpleName":
|
||||||
context.writer().print("(");
|
context.writer().print("(");
|
||||||
|
|
|
@ -45,7 +45,6 @@ import org.teavm.common.ServiceRepository;
|
||||||
import org.teavm.debugging.information.DebugInformationEmitter;
|
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||||
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.dependency.MethodDependencyInfo;
|
|
||||||
import org.teavm.diagnostics.Diagnostics;
|
import org.teavm.diagnostics.Diagnostics;
|
||||||
import org.teavm.model.ClassReader;
|
import org.teavm.model.ClassReader;
|
||||||
import org.teavm.model.ClassReaderSource;
|
import org.teavm.model.ClassReaderSource;
|
||||||
|
@ -57,6 +56,7 @@ import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReader;
|
import org.teavm.model.MethodReader;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.ValueType;
|
import org.teavm.model.ValueType;
|
||||||
|
import org.teavm.model.analysis.ClassMetadataRequirements;
|
||||||
import org.teavm.vm.RenderingException;
|
import org.teavm.vm.RenderingException;
|
||||||
import org.teavm.vm.TeaVMProgressFeedback;
|
import org.teavm.vm.TeaVMProgressFeedback;
|
||||||
|
|
||||||
|
@ -475,17 +475,17 @@ public class Renderer implements RenderingManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, RequiredClassMetadata> classesRequiringName = findRequiredClassMetadata();
|
ClassMetadataRequirements metadataRequirements = new ClassMetadataRequirements(context.getDependencyInfo());
|
||||||
|
|
||||||
int start = writer.getOffset();
|
int start = writer.getOffset();
|
||||||
try {
|
try {
|
||||||
writer.append("$rt_packages([");
|
writer.append("$rt_packages([");
|
||||||
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, classesRequiringName);
|
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, metadataRequirements);
|
||||||
writer.append("]);").newLine();
|
writer.append("]);").newLine();
|
||||||
|
|
||||||
for (int i = 0; i < classes.size(); i += 50) {
|
for (int i = 0; i < classes.size(); i += 50) {
|
||||||
int j = Math.min(i + 50, classes.size());
|
int j = Math.min(i + 50, classes.size());
|
||||||
renderClassMetadataPortion(classes.subList(i, j), packageIndexes, classesRequiringName);
|
renderClassMetadataPortion(classes.subList(i, j), packageIndexes, metadataRequirements);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
@ -496,7 +496,7 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renderClassMetadataPortion(List<PreparedClass> classes, ObjectIntMap<String> packageIndexes,
|
private void renderClassMetadataPortion(List<PreparedClass> classes, ObjectIntMap<String> packageIndexes,
|
||||||
Map<String, RequiredClassMetadata> metadataRequirements) throws IOException {
|
ClassMetadataRequirements metadataRequirements) throws IOException {
|
||||||
writer.append("$rt_metadata([");
|
writer.append("$rt_metadata([");
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (PreparedClass cls : classes) {
|
for (PreparedClass cls : classes) {
|
||||||
|
@ -507,8 +507,8 @@ public class Renderer implements RenderingManager {
|
||||||
debugEmitter.emitClass(cls.getName());
|
debugEmitter.emitClass(cls.getName());
|
||||||
writer.appendClass(cls.getName()).append(",").ws();
|
writer.appendClass(cls.getName()).append(",").ws();
|
||||||
|
|
||||||
RequiredClassMetadata requiredMetadata = metadataRequirements.get(cls.getName());
|
ClassMetadataRequirements.Info requiredMetadata = metadataRequirements.getInfo(cls.getName());
|
||||||
if (requiredMetadata != null && requiredMetadata.name) {
|
if (requiredMetadata.name()) {
|
||||||
String className = cls.getName();
|
String className = cls.getName();
|
||||||
int dotIndex = className.lastIndexOf('.') + 1;
|
int dotIndex = className.lastIndexOf('.') + 1;
|
||||||
String packageName = className.substring(0, dotIndex);
|
String packageName = className.substring(0, dotIndex);
|
||||||
|
@ -540,24 +540,24 @@ public class Renderer implements RenderingManager {
|
||||||
writer.append(ElementModifier.pack(cls.getClassHolder().getModifiers())).append(',').ws();
|
writer.append(ElementModifier.pack(cls.getClassHolder().getModifiers())).append(',').ws();
|
||||||
writer.append(cls.getClassHolder().getLevel().ordinal()).append(',').ws();
|
writer.append(cls.getClassHolder().getLevel().ordinal()).append(',').ws();
|
||||||
|
|
||||||
if (requiredMetadata == null || !(requiredMetadata.enclosingClass
|
if (!requiredMetadata.enclosingClass() && !requiredMetadata.declaringClass()
|
||||||
|| requiredMetadata.declaringClass || requiredMetadata.simpleName)) {
|
&& !requiredMetadata.simpleName()) {
|
||||||
writer.append("0");
|
writer.append("0");
|
||||||
} else {
|
} else {
|
||||||
writer.append('[');
|
writer.append('[');
|
||||||
if (requiredMetadata.enclosingClass && cls.getClassHolder().getOwnerName() != null) {
|
if (requiredMetadata.enclosingClass() && cls.getClassHolder().getOwnerName() != null) {
|
||||||
writer.appendClass(cls.getClassHolder().getOwnerName());
|
writer.appendClass(cls.getClassHolder().getOwnerName());
|
||||||
} else {
|
} else {
|
||||||
writer.append('0');
|
writer.append('0');
|
||||||
}
|
}
|
||||||
writer.append(',');
|
writer.append(',');
|
||||||
if (requiredMetadata.declaringClass && cls.getClassHolder().getDeclaringClassName() != null) {
|
if (requiredMetadata.declaringClass() && cls.getClassHolder().getDeclaringClassName() != null) {
|
||||||
writer.appendClass(cls.getClassHolder().getDeclaringClassName());
|
writer.appendClass(cls.getClassHolder().getDeclaringClassName());
|
||||||
} else {
|
} else {
|
||||||
writer.append('0');
|
writer.append('0');
|
||||||
}
|
}
|
||||||
writer.append(',');
|
writer.append(',');
|
||||||
if (requiredMetadata.simpleName && cls.getClassHolder().getSimpleName() != null) {
|
if (requiredMetadata.simpleName() && cls.getClassHolder().getSimpleName() != null) {
|
||||||
writer.append("\"").append(RenderingUtil.escapeString(cls.getClassHolder().getSimpleName()))
|
writer.append("\"").append(RenderingUtil.escapeString(cls.getClassHolder().getSimpleName()))
|
||||||
.append("\"");
|
.append("\"");
|
||||||
} else {
|
} else {
|
||||||
|
@ -590,13 +590,13 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private ObjectIntMap<String> generatePackageMetadata(List<PreparedClass> classes,
|
private ObjectIntMap<String> generatePackageMetadata(List<PreparedClass> classes,
|
||||||
Map<String, RequiredClassMetadata> metadataRequirements) throws IOException {
|
ClassMetadataRequirements metadataRequirements) throws IOException {
|
||||||
PackageNode root = new PackageNode(null);
|
PackageNode root = new PackageNode(null);
|
||||||
|
|
||||||
for (PreparedClass classNode : classes) {
|
for (PreparedClass classNode : classes) {
|
||||||
String className = classNode.getName();
|
String className = classNode.getName();
|
||||||
RequiredClassMetadata requiredMetadata = metadataRequirements.get(className);
|
ClassMetadataRequirements.Info requiredMetadata = metadataRequirements.getInfo(className);
|
||||||
if (requiredMetadata == null || !requiredMetadata.name) {
|
if (!requiredMetadata.name()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,65 +655,6 @@ public class Renderer implements RenderingManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, RequiredClassMetadata> findRequiredClassMetadata() {
|
|
||||||
Map<String, RequiredClassMetadata> requirements = new HashMap<>();
|
|
||||||
|
|
||||||
MethodDependencyInfo getNameMethod = context.getDependencyInfo().getMethod(
|
|
||||||
new MethodReference(Class.class, "getName", String.class));
|
|
||||||
if (getNameMethod != null) {
|
|
||||||
addClassesRequiringName(requirements, getNameMethod.getVariable(0).getClassValueNode().getTypes());
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodDependencyInfo getSimpleNameMethod = context.getDependencyInfo().getMethod(
|
|
||||||
new MethodReference(Class.class, "getSimpleName", String.class));
|
|
||||||
if (getSimpleNameMethod != null) {
|
|
||||||
String[] classNames = getSimpleNameMethod.getVariable(0).getClassValueNode().getTypes();
|
|
||||||
addClassesRequiringName(requirements, classNames);
|
|
||||||
for (String className : classNames) {
|
|
||||||
RequiredClassMetadata requiredMetadata = requirements.computeIfAbsent(className,
|
|
||||||
k -> new RequiredClassMetadata());
|
|
||||||
requiredMetadata.simpleName = true;
|
|
||||||
requiredMetadata.enclosingClass = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodDependencyInfo getDeclaringClassMethod = context.getDependencyInfo().getMethod(
|
|
||||||
new MethodReference(Class.class, "getDeclaringClass", Class.class));
|
|
||||||
if (getDeclaringClassMethod != null) {
|
|
||||||
String[] classNames = getDeclaringClassMethod.getVariable(0).getClassValueNode().getTypes();
|
|
||||||
for (String className : classNames) {
|
|
||||||
requirements.computeIfAbsent(className, k -> new RequiredClassMetadata()).declaringClass = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MethodDependencyInfo getEnclosingClassMethod = context.getDependencyInfo().getMethod(
|
|
||||||
new MethodReference(Class.class, "getEnclosingClass", Class.class));
|
|
||||||
if (getEnclosingClassMethod != null) {
|
|
||||||
String[] classNames = getEnclosingClassMethod.getVariable(0).getClassValueNode().getTypes();
|
|
||||||
for (String className : classNames) {
|
|
||||||
requirements.computeIfAbsent(className, k -> new RequiredClassMetadata()).enclosingClass = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return requirements;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void addClassesRequiringName(Map<String, RequiredClassMetadata> target, String[] source) {
|
|
||||||
for (String typeName : source) {
|
|
||||||
if (typeName.startsWith("[")) {
|
|
||||||
if (!typeName.endsWith(";")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int index = 0;
|
|
||||||
while (typeName.charAt(index) == '[') {
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
typeName = typeName.substring(index, typeName.length() - 1).replace('/', '.');
|
|
||||||
}
|
|
||||||
target.computeIfAbsent(typeName, k -> new RequiredClassMetadata()).name = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void collectMethodsToCopyFromInterfaces(ClassReader cls, List<MethodReference> targetList) {
|
private void collectMethodsToCopyFromInterfaces(ClassReader cls, List<MethodReference> targetList) {
|
||||||
Set<MethodDescriptor> implementedMethods = new HashSet<>();
|
Set<MethodDescriptor> implementedMethods = new HashSet<>();
|
||||||
implementedMethods.addAll(targetList.stream().map(method -> method.getDescriptor())
|
implementedMethods.addAll(targetList.stream().map(method -> method.getDescriptor())
|
||||||
|
@ -1217,11 +1158,4 @@ public class Renderer implements RenderingManager {
|
||||||
private boolean isVirtual(MethodReference method) {
|
private boolean isVirtual(MethodReference method) {
|
||||||
return context.isVirtual(method);
|
return context.isVirtual(method);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class RequiredClassMetadata {
|
|
||||||
boolean name;
|
|
||||||
boolean simpleName;
|
|
||||||
boolean declaringClass;
|
|
||||||
boolean enclosingClass;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,6 +72,7 @@ public class WasmClassGenerator {
|
||||||
DataPrimitives.INT, /* tag */
|
DataPrimitives.INT, /* tag */
|
||||||
DataPrimitives.INT, /* canary */
|
DataPrimitives.INT, /* canary */
|
||||||
DataPrimitives.ADDRESS, /* name */
|
DataPrimitives.ADDRESS, /* name */
|
||||||
|
DataPrimitives.ADDRESS, /* name cache */
|
||||||
DataPrimitives.ADDRESS, /* item type */
|
DataPrimitives.ADDRESS, /* item type */
|
||||||
DataPrimitives.ADDRESS, /* array type */
|
DataPrimitives.ADDRESS, /* array type */
|
||||||
DataPrimitives.ADDRESS, /* declaring class */
|
DataPrimitives.ADDRESS, /* declaring class */
|
||||||
|
@ -96,16 +97,16 @@ public class WasmClassGenerator {
|
||||||
private static final int CLASS_TAG = 3;
|
private static final int CLASS_TAG = 3;
|
||||||
private static final int CLASS_CANARY = 4;
|
private static final int CLASS_CANARY = 4;
|
||||||
private static final int CLASS_NAME = 5;
|
private static final int CLASS_NAME = 5;
|
||||||
private static final int CLASS_ITEM_TYPE = 6;
|
private static final int CLASS_ITEM_TYPE = 7;
|
||||||
private static final int CLASS_ARRAY_TYPE = 7;
|
private static final int CLASS_ARRAY_TYPE = 8;
|
||||||
private static final int CLASS_DECLARING_CLASS = 8;
|
private static final int CLASS_DECLARING_CLASS = 9;
|
||||||
private static final int CLASS_ENCLOSING_CLASS = 9;
|
private static final int CLASS_ENCLOSING_CLASS = 10;
|
||||||
private static final int CLASS_IS_INSTANCE = 10;
|
private static final int CLASS_IS_INSTANCE = 11;
|
||||||
private static final int CLASS_INIT = 11;
|
private static final int CLASS_INIT = 12;
|
||||||
private static final int CLASS_PARENT = 12;
|
private static final int CLASS_PARENT = 13;
|
||||||
private static final int CLASS_ENUM_VALUES = 15;
|
private static final int CLASS_ENUM_VALUES = 16;
|
||||||
private static final int CLASS_LAYOUT = 16;
|
private static final int CLASS_LAYOUT = 17;
|
||||||
private static final int CLASS_SIMPLE_NAME = 17;
|
private static final int CLASS_SIMPLE_NAME = 18;
|
||||||
|
|
||||||
public WasmClassGenerator(ClassReaderSource processedClassSource, ClassReaderSource classSource,
|
public WasmClassGenerator(ClassReaderSource processedClassSource, ClassReaderSource classSource,
|
||||||
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, BinaryWriter binaryWriter,
|
VirtualTableProvider vtableProvider, TagRegistry tagRegistry, BinaryWriter binaryWriter,
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2019 Alexey Andreev.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.teavm.model.analysis;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.teavm.dependency.DependencyInfo;
|
||||||
|
import org.teavm.dependency.MethodDependencyInfo;
|
||||||
|
import org.teavm.model.MethodReference;
|
||||||
|
|
||||||
|
public class ClassMetadataRequirements {
|
||||||
|
private static final MethodReference GET_NAME_METHOD = new MethodReference(Class.class, "getName", String.class);
|
||||||
|
private static final MethodReference GET_SIMPLE_NAME_METHOD = new MethodReference(Class.class,
|
||||||
|
"getSimpleName", String.class);
|
||||||
|
private static final MethodReference GET_DECLARING_CLASS_METHOD = new MethodReference(Class.class,
|
||||||
|
"getDeclaringClass", Class.class);
|
||||||
|
private static final MethodReference GET_ENCLOSING_CLASS_METHOD = new MethodReference(Class.class,
|
||||||
|
"getEnclosingClass", Class.class);
|
||||||
|
private static final ClassInfo EMPTY_INFO = new ClassInfo();
|
||||||
|
private Map<String, ClassInfo> requirements = new HashMap<>();
|
||||||
|
|
||||||
|
public ClassMetadataRequirements(DependencyInfo dependencyInfo) {
|
||||||
|
MethodDependencyInfo getNameMethod = dependencyInfo.getMethod(GET_NAME_METHOD);
|
||||||
|
if (getNameMethod != null) {
|
||||||
|
addClassesRequiringName(requirements, getNameMethod.getVariable(0).getClassValueNode().getTypes());
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodDependencyInfo getSimpleNameMethod = dependencyInfo.getMethod(GET_SIMPLE_NAME_METHOD);
|
||||||
|
if (getSimpleNameMethod != null) {
|
||||||
|
String[] classNames = getSimpleNameMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
|
addClassesRequiringName(requirements, classNames);
|
||||||
|
for (String className : classNames) {
|
||||||
|
ClassInfo classInfo = requirements.computeIfAbsent(className, k -> new ClassInfo());
|
||||||
|
classInfo.simpleName = true;
|
||||||
|
classInfo.enclosingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodDependencyInfo getDeclaringClassMethod = dependencyInfo.getMethod(GET_DECLARING_CLASS_METHOD);
|
||||||
|
if (getDeclaringClassMethod != null) {
|
||||||
|
String[] classNames = getDeclaringClassMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
|
for (String className : classNames) {
|
||||||
|
requirements.computeIfAbsent(className, k -> new ClassInfo()).declaringClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MethodDependencyInfo getEnclosingClassMethod = dependencyInfo.getMethod(GET_ENCLOSING_CLASS_METHOD);
|
||||||
|
if (getEnclosingClassMethod != null) {
|
||||||
|
String[] classNames = getEnclosingClassMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
|
for (String className : classNames) {
|
||||||
|
requirements.computeIfAbsent(className, k -> new ClassInfo()).enclosingClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Info getInfo(String className) {
|
||||||
|
ClassInfo result = requirements.get(className);
|
||||||
|
if (result == null) {
|
||||||
|
result = EMPTY_INFO;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addClassesRequiringName(Map<String, ClassInfo> target, String[] source) {
|
||||||
|
for (String typeName : source) {
|
||||||
|
if (typeName.startsWith("[")) {
|
||||||
|
if (!typeName.endsWith(";")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int index = 0;
|
||||||
|
while (typeName.charAt(index) == '[') {
|
||||||
|
++index;
|
||||||
|
}
|
||||||
|
typeName = typeName.substring(index, typeName.length() - 1).replace('/', '.');
|
||||||
|
}
|
||||||
|
target.computeIfAbsent(typeName, k -> new ClassInfo()).name = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class ClassInfo implements Info {
|
||||||
|
boolean name;
|
||||||
|
boolean simpleName;
|
||||||
|
boolean declaringClass;
|
||||||
|
boolean enclosingClass;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean simpleName() {
|
||||||
|
return simpleName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean declaringClass() {
|
||||||
|
return declaringClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean enclosingClass() {
|
||||||
|
return enclosingClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Info {
|
||||||
|
boolean name();
|
||||||
|
|
||||||
|
boolean simpleName();
|
||||||
|
|
||||||
|
boolean declaringClass();
|
||||||
|
|
||||||
|
boolean enclosingClass();
|
||||||
|
}
|
||||||
|
}
|
|
@ -208,6 +208,9 @@ public final class GC {
|
||||||
if (cls.canonicalName != null) {
|
if (cls.canonicalName != null) {
|
||||||
mark(cls.canonicalName);
|
mark(cls.canonicalName);
|
||||||
}
|
}
|
||||||
|
if (cls.nameCache != null) {
|
||||||
|
mark(cls.nameCache);
|
||||||
|
}
|
||||||
classPtr = classPtr.add(Address.sizeOf());
|
classPtr = classPtr.add(Address.sizeOf());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,6 +585,9 @@ public final class GC {
|
||||||
if (cls.canonicalName != null) {
|
if (cls.canonicalName != null) {
|
||||||
cls.canonicalName = updatePointer(cls.canonicalName.toAddress()).toStructure();
|
cls.canonicalName = updatePointer(cls.canonicalName.toAddress()).toStructure();
|
||||||
}
|
}
|
||||||
|
if (cls.nameCache != null) {
|
||||||
|
cls.nameCache = updatePointer(cls.nameCache.toAddress()).toStructure();
|
||||||
|
}
|
||||||
classPtr = classPtr.add(Address.sizeOf());
|
classPtr = classPtr.add(Address.sizeOf());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,6 +48,7 @@ public class RuntimeClass extends RuntimeObject {
|
||||||
public int tag;
|
public int tag;
|
||||||
public int canary;
|
public int canary;
|
||||||
public RuntimeObjectPtr name;
|
public RuntimeObjectPtr name;
|
||||||
|
public RuntimeObject nameCache;
|
||||||
public RuntimeClass itemType;
|
public RuntimeClass itemType;
|
||||||
public RuntimeClass arrayType;
|
public RuntimeClass arrayType;
|
||||||
public RuntimeClass declaringClass;
|
public RuntimeClass declaringClass;
|
||||||
|
|
|
@ -28,6 +28,7 @@ typedef struct TeaVM_Class {
|
||||||
int32_t tag;
|
int32_t tag;
|
||||||
int32_t canary;
|
int32_t canary;
|
||||||
TeaVM_Object** name;
|
TeaVM_Object** name;
|
||||||
|
TeaVM_Object* nameCache;
|
||||||
struct TeaVM_Class* itemType;
|
struct TeaVM_Class* itemType;
|
||||||
struct TeaVM_Class* arrayType;
|
struct TeaVM_Class* arrayType;
|
||||||
struct TeaVM_Class* declaringClass;
|
struct TeaVM_Class* declaringClass;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user