mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -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;
|
||||
case "getSimpleNameCacheLowLevel":
|
||||
case "getCanonicalNameCacheLowLevel":
|
||||
case "getNameCacheLowLevel":
|
||||
method.getResult().propagate(agent.getType("java.lang.String"));
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -106,7 +106,21 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
@Unmanaged
|
||||
public String getName() {
|
||||
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 {
|
||||
if (name == null) {
|
||||
name = Platform.getName(platformClass);
|
||||
|
@ -167,6 +181,27 @@ public class TClass<T> extends TObject implements TAnnotatedElement {
|
|||
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() {
|
||||
String result = getCanonicalNameCache();
|
||||
if (result == null) {
|
||||
|
|
|
@ -64,7 +64,8 @@ public class CNameProvider extends LowLevelNameProvider {
|
|||
|
||||
preserveFieldNames(RuntimeClass.class.getName(), "size", "flags", "tag", "canary", "name", "itemType",
|
||||
"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");
|
||||
preserveFieldNames(RuntimeReference.class.getName(), "queue", "object", "next");
|
||||
preserveFieldNames(RuntimeReferenceQueue.class.getName(), "first", "last");
|
||||
|
|
|
@ -58,6 +58,7 @@ import org.teavm.model.MethodReader;
|
|||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.analysis.ClassMetadataRequirements;
|
||||
import org.teavm.model.classes.TagRegistry;
|
||||
import org.teavm.model.classes.VirtualTable;
|
||||
import org.teavm.model.classes.VirtualTableEntry;
|
||||
|
@ -104,6 +105,7 @@ public class ClassGenerator {
|
|||
private MethodNodeCache astCache = EmptyMethodNodeCache.INSTANCE;
|
||||
private AstDependencyExtractor dependencyExtractor = new AstDependencyExtractor();
|
||||
private List<CallSiteDescriptor> callSites;
|
||||
private ClassMetadataRequirements metadataRequirements;
|
||||
|
||||
public ClassGenerator(GenerationContext context, TagRegistry tagRegistry, Decompiler decompiler,
|
||||
CacheStatus cacheStatus) {
|
||||
|
@ -111,6 +113,7 @@ public class ClassGenerator {
|
|||
this.tagRegistry = tagRegistry;
|
||||
this.decompiler = decompiler;
|
||||
this.cacheStatus = cacheStatus;
|
||||
metadataRequirements = new ClassMetadataRequirements(context.getDependencies());
|
||||
}
|
||||
|
||||
public void setAstCache(MethodNodeCache astCache) {
|
||||
|
@ -778,7 +781,10 @@ public class ClassGenerator {
|
|||
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);
|
||||
|
||||
ValueType arrayType = ValueType.arrayOf(type);
|
||||
|
@ -802,7 +808,7 @@ public class ClassGenerator {
|
|||
codeWriter.println(".flags = " + flags + ",");
|
||||
codeWriter.println(".tag = " + tag + ",");
|
||||
codeWriter.println(".canary = 0,");
|
||||
codeWriter.println(".name = (TeaVM_Object**) &TEAVM_GET_STRING(" + nameRef + "),");
|
||||
codeWriter.println(".name = " + nameRef + ",");
|
||||
codeWriter.println(".simpleName = " + simpleName + ",");
|
||||
codeWriter.println(".arrayType = " + arrayTypeExpr + ",");
|
||||
codeWriter.println(".itemType = " + itemTypeExpr + ",");
|
||||
|
@ -1168,7 +1174,7 @@ public class ClassGenerator {
|
|||
return true;
|
||||
}
|
||||
|
||||
public static String nameOfType(ValueType type) {
|
||||
public String nameOfType(ValueType type) {
|
||||
if (type instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) type).getKind()) {
|
||||
case BOOLEAN:
|
||||
|
@ -1191,16 +1197,28 @@ public class ClassGenerator {
|
|||
throw new AssertionError();
|
||||
}
|
||||
} else if (type instanceof ValueType.Array) {
|
||||
return type.toString().replace('/', '.');
|
||||
if (isArrayOfPrimitives(type)) {
|
||||
return type.toString().replace('/', '.');
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (type == ValueType.VOID) {
|
||||
return "void";
|
||||
} 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 {
|
||||
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) {
|
||||
String name = context.getNames().forSupertypeFunction(type);
|
||||
headerWriter.println("extern int32_t " + name + "(TeaVM_Class*);");
|
||||
|
|
|
@ -62,8 +62,11 @@ public class PlatformClassMetadataIntrinsic implements Intrinsic {
|
|||
printFieldAccess(context, invocation, SUPERCLASS_FIELD);
|
||||
break;
|
||||
case "getName":
|
||||
context.writer().print("*");
|
||||
context.writer().print("(");
|
||||
printFieldAccess(context, invocation, NAME_FIELD);
|
||||
context.writer().print(" ? *");
|
||||
printFieldAccess(context, invocation, NAME_FIELD);
|
||||
context.writer().print(" : NULL)");
|
||||
break;
|
||||
case "getSimpleName":
|
||||
context.writer().print("(");
|
||||
|
|
|
@ -45,7 +45,6 @@ import org.teavm.common.ServiceRepository;
|
|||
import org.teavm.debugging.information.DebugInformationEmitter;
|
||||
import org.teavm.debugging.information.DummyDebugInformationEmitter;
|
||||
import org.teavm.dependency.DependencyInfo;
|
||||
import org.teavm.dependency.MethodDependencyInfo;
|
||||
import org.teavm.diagnostics.Diagnostics;
|
||||
import org.teavm.model.ClassReader;
|
||||
import org.teavm.model.ClassReaderSource;
|
||||
|
@ -57,6 +56,7 @@ import org.teavm.model.MethodDescriptor;
|
|||
import org.teavm.model.MethodReader;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.ValueType;
|
||||
import org.teavm.model.analysis.ClassMetadataRequirements;
|
||||
import org.teavm.vm.RenderingException;
|
||||
import org.teavm.vm.TeaVMProgressFeedback;
|
||||
|
||||
|
@ -475,17 +475,17 @@ public class Renderer implements RenderingManager {
|
|||
return;
|
||||
}
|
||||
|
||||
Map<String, RequiredClassMetadata> classesRequiringName = findRequiredClassMetadata();
|
||||
ClassMetadataRequirements metadataRequirements = new ClassMetadataRequirements(context.getDependencyInfo());
|
||||
|
||||
int start = writer.getOffset();
|
||||
try {
|
||||
writer.append("$rt_packages([");
|
||||
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, classesRequiringName);
|
||||
ObjectIntMap<String> packageIndexes = generatePackageMetadata(classes, metadataRequirements);
|
||||
writer.append("]);").newLine();
|
||||
|
||||
for (int i = 0; i < classes.size(); i += 50) {
|
||||
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) {
|
||||
|
@ -496,7 +496,7 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
|
||||
private void renderClassMetadataPortion(List<PreparedClass> classes, ObjectIntMap<String> packageIndexes,
|
||||
Map<String, RequiredClassMetadata> metadataRequirements) throws IOException {
|
||||
ClassMetadataRequirements metadataRequirements) throws IOException {
|
||||
writer.append("$rt_metadata([");
|
||||
boolean first = true;
|
||||
for (PreparedClass cls : classes) {
|
||||
|
@ -507,8 +507,8 @@ public class Renderer implements RenderingManager {
|
|||
debugEmitter.emitClass(cls.getName());
|
||||
writer.appendClass(cls.getName()).append(",").ws();
|
||||
|
||||
RequiredClassMetadata requiredMetadata = metadataRequirements.get(cls.getName());
|
||||
if (requiredMetadata != null && requiredMetadata.name) {
|
||||
ClassMetadataRequirements.Info requiredMetadata = metadataRequirements.getInfo(cls.getName());
|
||||
if (requiredMetadata.name()) {
|
||||
String className = cls.getName();
|
||||
int dotIndex = className.lastIndexOf('.') + 1;
|
||||
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(cls.getClassHolder().getLevel().ordinal()).append(',').ws();
|
||||
|
||||
if (requiredMetadata == null || !(requiredMetadata.enclosingClass
|
||||
|| requiredMetadata.declaringClass || requiredMetadata.simpleName)) {
|
||||
if (!requiredMetadata.enclosingClass() && !requiredMetadata.declaringClass()
|
||||
&& !requiredMetadata.simpleName()) {
|
||||
writer.append("0");
|
||||
} else {
|
||||
writer.append('[');
|
||||
if (requiredMetadata.enclosingClass && cls.getClassHolder().getOwnerName() != null) {
|
||||
if (requiredMetadata.enclosingClass() && cls.getClassHolder().getOwnerName() != null) {
|
||||
writer.appendClass(cls.getClassHolder().getOwnerName());
|
||||
} else {
|
||||
writer.append('0');
|
||||
}
|
||||
writer.append(',');
|
||||
if (requiredMetadata.declaringClass && cls.getClassHolder().getDeclaringClassName() != null) {
|
||||
if (requiredMetadata.declaringClass() && cls.getClassHolder().getDeclaringClassName() != null) {
|
||||
writer.appendClass(cls.getClassHolder().getDeclaringClassName());
|
||||
} else {
|
||||
writer.append('0');
|
||||
}
|
||||
writer.append(',');
|
||||
if (requiredMetadata.simpleName && cls.getClassHolder().getSimpleName() != null) {
|
||||
if (requiredMetadata.simpleName() && cls.getClassHolder().getSimpleName() != null) {
|
||||
writer.append("\"").append(RenderingUtil.escapeString(cls.getClassHolder().getSimpleName()))
|
||||
.append("\"");
|
||||
} else {
|
||||
|
@ -590,13 +590,13 @@ public class Renderer implements RenderingManager {
|
|||
}
|
||||
|
||||
private ObjectIntMap<String> generatePackageMetadata(List<PreparedClass> classes,
|
||||
Map<String, RequiredClassMetadata> metadataRequirements) throws IOException {
|
||||
ClassMetadataRequirements metadataRequirements) throws IOException {
|
||||
PackageNode root = new PackageNode(null);
|
||||
|
||||
for (PreparedClass classNode : classes) {
|
||||
String className = classNode.getName();
|
||||
RequiredClassMetadata requiredMetadata = metadataRequirements.get(className);
|
||||
if (requiredMetadata == null || !requiredMetadata.name) {
|
||||
ClassMetadataRequirements.Info requiredMetadata = metadataRequirements.getInfo(className);
|
||||
if (!requiredMetadata.name()) {
|
||||
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) {
|
||||
Set<MethodDescriptor> implementedMethods = new HashSet<>();
|
||||
implementedMethods.addAll(targetList.stream().map(method -> method.getDescriptor())
|
||||
|
@ -1217,11 +1158,4 @@ public class Renderer implements RenderingManager {
|
|||
private boolean isVirtual(MethodReference 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, /* canary */
|
||||
DataPrimitives.ADDRESS, /* name */
|
||||
DataPrimitives.ADDRESS, /* name cache */
|
||||
DataPrimitives.ADDRESS, /* item type */
|
||||
DataPrimitives.ADDRESS, /* array type */
|
||||
DataPrimitives.ADDRESS, /* declaring class */
|
||||
|
@ -96,16 +97,16 @@ public class WasmClassGenerator {
|
|||
private static final int CLASS_TAG = 3;
|
||||
private static final int CLASS_CANARY = 4;
|
||||
private static final int CLASS_NAME = 5;
|
||||
private static final int CLASS_ITEM_TYPE = 6;
|
||||
private static final int CLASS_ARRAY_TYPE = 7;
|
||||
private static final int CLASS_DECLARING_CLASS = 8;
|
||||
private static final int CLASS_ENCLOSING_CLASS = 9;
|
||||
private static final int CLASS_IS_INSTANCE = 10;
|
||||
private static final int CLASS_INIT = 11;
|
||||
private static final int CLASS_PARENT = 12;
|
||||
private static final int CLASS_ENUM_VALUES = 15;
|
||||
private static final int CLASS_LAYOUT = 16;
|
||||
private static final int CLASS_SIMPLE_NAME = 17;
|
||||
private static final int CLASS_ITEM_TYPE = 7;
|
||||
private static final int CLASS_ARRAY_TYPE = 8;
|
||||
private static final int CLASS_DECLARING_CLASS = 9;
|
||||
private static final int CLASS_ENCLOSING_CLASS = 10;
|
||||
private static final int CLASS_IS_INSTANCE = 11;
|
||||
private static final int CLASS_INIT = 12;
|
||||
private static final int CLASS_PARENT = 13;
|
||||
private static final int CLASS_ENUM_VALUES = 16;
|
||||
private static final int CLASS_LAYOUT = 17;
|
||||
private static final int CLASS_SIMPLE_NAME = 18;
|
||||
|
||||
public WasmClassGenerator(ClassReaderSource processedClassSource, ClassReaderSource classSource,
|
||||
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) {
|
||||
mark(cls.canonicalName);
|
||||
}
|
||||
if (cls.nameCache != null) {
|
||||
mark(cls.nameCache);
|
||||
}
|
||||
classPtr = classPtr.add(Address.sizeOf());
|
||||
}
|
||||
|
||||
|
@ -582,6 +585,9 @@ public final class GC {
|
|||
if (cls.canonicalName != null) {
|
||||
cls.canonicalName = updatePointer(cls.canonicalName.toAddress()).toStructure();
|
||||
}
|
||||
if (cls.nameCache != null) {
|
||||
cls.nameCache = updatePointer(cls.nameCache.toAddress()).toStructure();
|
||||
}
|
||||
classPtr = classPtr.add(Address.sizeOf());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public class RuntimeClass extends RuntimeObject {
|
|||
public int tag;
|
||||
public int canary;
|
||||
public RuntimeObjectPtr name;
|
||||
public RuntimeObject nameCache;
|
||||
public RuntimeClass itemType;
|
||||
public RuntimeClass arrayType;
|
||||
public RuntimeClass declaringClass;
|
||||
|
|
|
@ -28,6 +28,7 @@ typedef struct TeaVM_Class {
|
|||
int32_t tag;
|
||||
int32_t canary;
|
||||
TeaVM_Object** name;
|
||||
TeaVM_Object* nameCache;
|
||||
struct TeaVM_Class* itemType;
|
||||
struct TeaVM_Class* arrayType;
|
||||
struct TeaVM_Class* declaringClass;
|
||||
|
|
Loading…
Reference in New Issue
Block a user