mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: avoid generation of unnecessary supertype functions
This commit is contained in:
parent
8e483245f5
commit
8d276f2efd
|
@ -157,10 +157,13 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
function.getBody().addAll(initializerFunctionStatements);
|
function.getBody().addAll(initializerFunctionStatements);
|
||||||
initializerFunctionStatements.clear();
|
initializerFunctionStatements.clear();
|
||||||
for (var classInfo : classInfoMap.values()) {
|
for (var classInfo : classInfoMap.values()) {
|
||||||
|
var req = metadataRequirements.getInfo(classInfo.getValueType());
|
||||||
|
if (req != null && req.isAssignable()) {
|
||||||
var supertypeFunction = supertypeGenerator.getIsSupertypeFunction(classInfo.getValueType());
|
var supertypeFunction = supertypeGenerator.getIsSupertypeFunction(classInfo.getValueType());
|
||||||
supertypeFunction.setReferenced(true);
|
supertypeFunction.setReferenced(true);
|
||||||
function.getBody().add(setClassField(classInfo, classSupertypeFunctionOffset,
|
function.getBody().add(setClassField(classInfo, classSupertypeFunctionOffset,
|
||||||
new WasmFunctionReference(supertypeFunction)));
|
new WasmFunctionReference(supertypeFunction)));
|
||||||
|
}
|
||||||
function.getBody().add(setClassField(classInfo, CLASS_FIELD_OFFSET,
|
function.getBody().add(setClassField(classInfo, CLASS_FIELD_OFFSET,
|
||||||
new WasmGetGlobal(classClass.pointer)));
|
new WasmGetGlobal(classClass.pointer)));
|
||||||
if (classInfo.initializerPointer != null) {
|
if (classInfo.initializerPointer != null) {
|
||||||
|
@ -265,9 +268,11 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
|
var req = metadataRequirements.getInfo(type);
|
||||||
|
var name = req != null && req.name() ? ReflectionUtil.typeName(type.getKind()) : null;
|
||||||
target.add(fillPrimitiveClass(
|
target.add(fillPrimitiveClass(
|
||||||
classInfo.pointer,
|
classInfo.pointer,
|
||||||
ReflectionUtil.typeName(type.getKind()),
|
name,
|
||||||
kind
|
kind
|
||||||
));
|
));
|
||||||
};
|
};
|
||||||
|
@ -401,10 +406,13 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
||||||
}
|
}
|
||||||
|
|
||||||
private WasmExpression fillPrimitiveClass(WasmGlobal global, String name, int kind) {
|
private WasmExpression fillPrimitiveClass(WasmGlobal global, String name, int kind) {
|
||||||
|
var str = name != null
|
||||||
|
? new WasmGetGlobal(strings.getStringConstant(name).global)
|
||||||
|
: new WasmNullConstant(standardClasses.stringClass().getType());
|
||||||
return new WasmCall(
|
return new WasmCall(
|
||||||
getCreatePrimitiveClassFunction(),
|
getCreatePrimitiveClassFunction(),
|
||||||
new WasmGetGlobal(global),
|
new WasmGetGlobal(global),
|
||||||
new WasmGetGlobal(strings.getStringConstant(name).global),
|
str,
|
||||||
new WasmInt32Constant(kind)
|
new WasmInt32Constant(kind)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import java.util.Map;
|
||||||
import org.teavm.dependency.DependencyInfo;
|
import org.teavm.dependency.DependencyInfo;
|
||||||
import org.teavm.dependency.MethodDependencyInfo;
|
import org.teavm.dependency.MethodDependencyInfo;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
|
import org.teavm.model.ValueType;
|
||||||
|
|
||||||
public class ClassMetadataRequirements {
|
public class ClassMetadataRequirements {
|
||||||
private static final MethodReference GET_NAME_METHOD = new MethodReference(Class.class, "getName", String.class);
|
private static final MethodReference GET_NAME_METHOD = new MethodReference(Class.class, "getName", String.class);
|
||||||
|
@ -27,12 +28,14 @@ public class ClassMetadataRequirements {
|
||||||
"getSimpleName", String.class);
|
"getSimpleName", String.class);
|
||||||
private static final MethodReference GET_SUPERCLASS_METHOD = new MethodReference(Class.class, "getSuperclass",
|
private static final MethodReference GET_SUPERCLASS_METHOD = new MethodReference(Class.class, "getSuperclass",
|
||||||
Class.class);
|
Class.class);
|
||||||
|
private static final MethodReference IS_ASSIGNABLE_METHOD = new MethodReference(Class.class, "isAssignableFrom",
|
||||||
|
Class.class, boolean.class);
|
||||||
private static final MethodReference GET_DECLARING_CLASS_METHOD = new MethodReference(Class.class,
|
private static final MethodReference GET_DECLARING_CLASS_METHOD = new MethodReference(Class.class,
|
||||||
"getDeclaringClass", Class.class);
|
"getDeclaringClass", Class.class);
|
||||||
private static final MethodReference GET_ENCLOSING_CLASS_METHOD = new MethodReference(Class.class,
|
private static final MethodReference GET_ENCLOSING_CLASS_METHOD = new MethodReference(Class.class,
|
||||||
"getEnclosingClass", Class.class);
|
"getEnclosingClass", Class.class);
|
||||||
private static final ClassInfo EMPTY_INFO = new ClassInfo();
|
private static final ClassInfo EMPTY_INFO = new ClassInfo();
|
||||||
private Map<String, ClassInfo> requirements = new HashMap<>();
|
private Map<ValueType, ClassInfo> requirements = new HashMap<>();
|
||||||
|
|
||||||
public ClassMetadataRequirements(DependencyInfo dependencyInfo) {
|
public ClassMetadataRequirements(DependencyInfo dependencyInfo) {
|
||||||
MethodDependencyInfo getNameMethod = dependencyInfo.getMethod(GET_NAME_METHOD);
|
MethodDependencyInfo getNameMethod = dependencyInfo.getMethod(GET_NAME_METHOD);
|
||||||
|
@ -45,7 +48,7 @@ public class ClassMetadataRequirements {
|
||||||
String[] classNames = getSimpleNameMethod.getVariable(0).getClassValueNode().getTypes();
|
String[] classNames = getSimpleNameMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
addClassesRequiringName(requirements, classNames);
|
addClassesRequiringName(requirements, classNames);
|
||||||
for (String className : classNames) {
|
for (String className : classNames) {
|
||||||
ClassInfo classInfo = requirements.computeIfAbsent(className, k -> new ClassInfo());
|
ClassInfo classInfo = requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo());
|
||||||
classInfo.simpleName = true;
|
classInfo.simpleName = true;
|
||||||
classInfo.enclosingClass = true;
|
classInfo.enclosingClass = true;
|
||||||
}
|
}
|
||||||
|
@ -53,9 +56,17 @@ public class ClassMetadataRequirements {
|
||||||
|
|
||||||
var getSuperclassMethod = dependencyInfo.getMethod(GET_SUPERCLASS_METHOD);
|
var getSuperclassMethod = dependencyInfo.getMethod(GET_SUPERCLASS_METHOD);
|
||||||
if (getSuperclassMethod != null) {
|
if (getSuperclassMethod != null) {
|
||||||
String[] classNames = getSuperclassMethod.getVariable(0).getClassValueNode().getTypes();
|
var classNames = getSuperclassMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
for (String className : classNames) {
|
for (var className : classNames) {
|
||||||
requirements.computeIfAbsent(className, k -> new ClassInfo()).declaringClass = true;
|
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).declaringClass = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var isAssignableMethod = dependencyInfo.getMethod(IS_ASSIGNABLE_METHOD);
|
||||||
|
if (isAssignableMethod != null) {
|
||||||
|
var classNames = getSuperclassMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
|
for (var className : classNames) {
|
||||||
|
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).isAssignable = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,7 +74,7 @@ public class ClassMetadataRequirements {
|
||||||
if (getDeclaringClassMethod != null) {
|
if (getDeclaringClassMethod != null) {
|
||||||
String[] classNames = getDeclaringClassMethod.getVariable(0).getClassValueNode().getTypes();
|
String[] classNames = getDeclaringClassMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
for (String className : classNames) {
|
for (String className : classNames) {
|
||||||
requirements.computeIfAbsent(className, k -> new ClassInfo()).declaringClass = true;
|
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).declaringClass = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,12 +82,16 @@ public class ClassMetadataRequirements {
|
||||||
if (getEnclosingClassMethod != null) {
|
if (getEnclosingClassMethod != null) {
|
||||||
String[] classNames = getEnclosingClassMethod.getVariable(0).getClassValueNode().getTypes();
|
String[] classNames = getEnclosingClassMethod.getVariable(0).getClassValueNode().getTypes();
|
||||||
for (String className : classNames) {
|
for (String className : classNames) {
|
||||||
requirements.computeIfAbsent(className, k -> new ClassInfo()).enclosingClass = true;
|
requirements.computeIfAbsent(decodeType(className), k -> new ClassInfo()).enclosingClass = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Info getInfo(String className) {
|
public Info getInfo(String className) {
|
||||||
|
return getInfo(ValueType.object(className));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Info getInfo(ValueType className) {
|
||||||
ClassInfo result = requirements.get(className);
|
ClassInfo result = requirements.get(className);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
result = EMPTY_INFO;
|
result = EMPTY_INFO;
|
||||||
|
@ -84,19 +99,19 @@ public class ClassMetadataRequirements {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addClassesRequiringName(Map<String, ClassInfo> target, String[] source) {
|
private void addClassesRequiringName(Map<ValueType, ClassInfo> target, String[] source) {
|
||||||
for (String typeName : source) {
|
for (String typeName : source) {
|
||||||
|
target.computeIfAbsent(decodeType(typeName), k -> new ClassInfo()).name = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ValueType decodeType(String typeName) {
|
||||||
if (typeName.startsWith("[")) {
|
if (typeName.startsWith("[")) {
|
||||||
if (!typeName.endsWith(";")) {
|
return ValueType.parseIfPossible(typeName);
|
||||||
continue;
|
} else if (typeName.startsWith("~")) {
|
||||||
}
|
return ValueType.parseIfPossible(typeName.substring(1));
|
||||||
int index = 0;
|
} else {
|
||||||
while (typeName.charAt(index) == '[') {
|
return ValueType.object(typeName);
|
||||||
++index;
|
|
||||||
}
|
|
||||||
typeName = typeName.substring(index, typeName.length() - 1).replace('/', '.');
|
|
||||||
}
|
|
||||||
target.computeIfAbsent(typeName, k -> new ClassInfo()).name = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,6 +121,7 @@ public class ClassMetadataRequirements {
|
||||||
boolean declaringClass;
|
boolean declaringClass;
|
||||||
boolean enclosingClass;
|
boolean enclosingClass;
|
||||||
boolean superclass;
|
boolean superclass;
|
||||||
|
boolean isAssignable;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean name() {
|
public boolean name() {
|
||||||
|
@ -131,6 +147,11 @@ public class ClassMetadataRequirements {
|
||||||
public boolean superclass() {
|
public boolean superclass() {
|
||||||
return superclass;
|
return superclass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAssignable() {
|
||||||
|
return isAssignable;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface Info {
|
public interface Info {
|
||||||
|
@ -143,5 +164,7 @@ public class ClassMetadataRequirements {
|
||||||
boolean enclosingClass();
|
boolean enclosingClass();
|
||||||
|
|
||||||
boolean superclass();
|
boolean superclass();
|
||||||
|
|
||||||
|
boolean isAssignable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user