wasm gc: implement some Class intrinsics, fix issues with type inference

This commit is contained in:
Alexey Andreev 2024-09-08 20:32:30 +02:00
parent fea62af09a
commit d0226aab88
8 changed files with 73 additions and 10 deletions

View File

@ -164,12 +164,16 @@ public final class TClass<T> extends TObject implements TAnnotatedElement, TType
if (isArray()) { if (isArray()) {
simpleName = getComponentType().getSimpleName() + "[]"; simpleName = getComponentType().getSimpleName() + "[]";
} else if (getEnclosingClass() != null) { } else if (getEnclosingClass() != null) {
simpleName = Platform.getSimpleName(platformClass); simpleName = PlatformDetector.isWebAssemblyGC()
? getSimpleNameCache(this)
: Platform.getSimpleName(platformClass);
if (simpleName == null) { if (simpleName == null) {
simpleName = ""; simpleName = "";
} }
} else { } else {
String name = Platform.getName(platformClass); var name = PlatformDetector.isWebAssemblyGC()
? getName()
: Platform.getName(platformClass);
int lastDollar = name.lastIndexOf('$'); int lastDollar = name.lastIndexOf('$');
if (lastDollar != -1) { if (lastDollar != -1) {
name = name.substring(lastDollar + 1); name = name.substring(lastDollar + 1);

View File

@ -1097,7 +1097,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
conditionalExpr.setConsequent(firstAssignment.getRightValue()); conditionalExpr.setConsequent(firstAssignment.getRightValue());
conditionalExpr.setAlternative(secondAssignment.getRightValue()); conditionalExpr.setAlternative(secondAssignment.getRightValue());
conditionalExpr.setLocation(statement.getCondition().getLocation()); conditionalExpr.setLocation(statement.getCondition().getLocation());
conditionalExpr.setVariableIndex(firstAssignment.getRightValue().getVariableIndex()); conditionalExpr.setVariableIndex(firstAssignment.getLeftValue().getVariableIndex());
AssignmentStatement assignment = new AssignmentStatement(); AssignmentStatement assignment = new AssignmentStatement();
assignment.setLocation(conditionalExpr.getLocation()); assignment.setLocation(conditionalExpr.getLocation());
VariableExpr lhs = new VariableExpr(); VariableExpr lhs = new VariableExpr();

View File

@ -34,9 +34,9 @@ public final class WasmGCUtil {
if (firstPath.get(0) != secondPath.get(0)) { if (firstPath.get(0) != secondPath.get(0)) {
return "java.lang.Object"; return "java.lang.Object";
} }
var min = Math.min(firstPath.size(), secondPath.size()); var min = Math.min(firstPath.size(), secondPath.size()) - 1;
var index = 1; var index = 0;
while (index < min && firstPath.get(index) == secondPath.get(index)) { while (index < min && firstPath.get(index + 1) == secondPath.get(index + 1)) {
++index; ++index;
} }
return index < firstPath.size() ? firstPath.get(index).getName() : secondPath.get(index).getName(); return index < firstPath.size() ? firstPath.get(index).getName() : secondPath.get(index).getName();

View File

@ -119,11 +119,13 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
private int classTagOffset; private int classTagOffset;
private int classFlagsOffset; private int classFlagsOffset;
private int classNameOffset; private int classNameOffset;
private int classSimpleNameOffset;
private int classParentOffset; private int classParentOffset;
private int classArrayOffset; private int classArrayOffset;
private int classArrayItemOffset; private int classArrayItemOffset;
private int classNewArrayOffset; private int classNewArrayOffset;
private int classSupertypeFunctionOffset; private int classSupertypeFunctionOffset;
private int classEnclosingClassOffset;
private int virtualTableFieldOffset; private int virtualTableFieldOffset;
private int arrayLengthOffset = -1; private int arrayLengthOffset = -1;
private int arrayGetOffset = -1; private int arrayGetOffset = -1;
@ -351,12 +353,24 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
return classSupertypeFunctionOffset; return classSupertypeFunctionOffset;
} }
@Override
public int getClassEnclosingClassOffset() {
standardClasses.classClass().getStructure().init();
return classEnclosingClassOffset;
}
@Override @Override
public int getClassNameOffset() { public int getClassNameOffset() {
standardClasses.classClass().getStructure().init(); standardClasses.classClass().getStructure().init();
return classNameOffset; return classNameOffset;
} }
@Override
public int getClassSimpleNameOffset() {
standardClasses.classClass().getStructure().init();
return classSimpleNameOffset;
}
@Override @Override
public int getNewArrayFunctionOffset() { public int getNewArrayFunctionOffset() {
standardClasses.classClass().getStructure().init(); standardClasses.classClass().getStructure().init();
@ -445,12 +459,16 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
if (cls != null) { if (cls != null) {
if (metadataReq.simpleName() && cls.getSimpleName() != null) { if (metadataReq.simpleName() && cls.getSimpleName() != null) {
var namePtr = strings.getStringConstant(cls.getSimpleName()).global; var namePtr = strings.getStringConstant(cls.getSimpleName()).global;
target.add(setClassField(classInfo, classNameOffset, new WasmGetGlobal(namePtr))); target.add(setClassField(classInfo, classSimpleNameOffset, new WasmGetGlobal(namePtr)));
} }
if (cls.getParent() != null && metadataReq.superclass()) { if (cls.getParent() != null && metadataReq.superclass()) {
var parent = getClassInfo(cls.getParent()); var parent = getClassInfo(cls.getParent());
target.add(setClassField(classInfo, classParentOffset, new WasmGetGlobal(parent.pointer))); target.add(setClassField(classInfo, classParentOffset, new WasmGetGlobal(parent.pointer)));
} }
if (cls.getOwnerName() != null && metadataReq.superclass()) {
var owner = getClassInfo(cls.getOwnerName());
target.add(setClassField(classInfo, classEnclosingClassOffset, new WasmGetGlobal(owner.pointer)));
}
} }
if (virtualTable != null && virtualTable.isConcrete()) { if (virtualTable != null && virtualTable.isConcrete()) {
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable); fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable);
@ -960,8 +978,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
classNewArrayOffset = fields.size(); classNewArrayOffset = fields.size();
fields.add(createClassField(newArrayGenerator.getNewArrayFunctionType().getReference().asStorage(), fields.add(createClassField(newArrayGenerator.getNewArrayFunctionType().getReference().asStorage(),
"createArrayInstance")); "createArrayInstance"));
classEnclosingClassOffset = fields.size();
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "enclosingClass"));
classNameOffset = fields.size(); classNameOffset = fields.size();
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "name")); fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "name"));
classSimpleNameOffset = fields.size();
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "simpleNAme"));
virtualTableFieldOffset = fields.size(); virtualTableFieldOffset = fields.size();
} }
} }

View File

@ -40,10 +40,14 @@ public interface WasmGCClassInfoProvider {
int getClassSupertypeFunctionOffset(); int getClassSupertypeFunctionOffset();
int getClassEnclosingClassOffset();
int getNewArrayFunctionOffset(); int getNewArrayFunctionOffset();
int getClassNameOffset(); int getClassNameOffset();
int getClassSimpleNameOffset();
int getArrayGetOffset(); int getArrayGetOffset();
int getArrayLengthOffset(); int getArrayLengthOffset();

View File

@ -20,21 +20,34 @@ import org.teavm.backend.wasm.model.expression.WasmExpression;
import org.teavm.backend.wasm.model.expression.WasmStructGet; import org.teavm.backend.wasm.model.expression.WasmStructGet;
import org.teavm.backend.wasm.model.expression.WasmStructSet; import org.teavm.backend.wasm.model.expression.WasmStructSet;
public class ClassIntrinsics implements WasmGCIntrinsic { public class ClassIntrinsic implements WasmGCIntrinsic {
@Override @Override
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) { public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
switch (invocation.getMethod().getName()) { switch (invocation.getMethod().getName()) {
case "getComponentType": case "getComponentType": {
var cls = context.generate(invocation.getArguments().get(0)); var cls = context.generate(invocation.getArguments().get(0));
var clsStruct = context.classInfoProvider().getClassInfo("java.lang.Class").getStructure(); var clsStruct = context.classInfoProvider().getClassInfo("java.lang.Class").getStructure();
var result = new WasmStructGet(clsStruct, cls, var result = new WasmStructGet(clsStruct, cls,
context.classInfoProvider().getClassArrayItemOffset()); context.classInfoProvider().getClassArrayItemOffset());
result.setLocation(invocation.getLocation()); result.setLocation(invocation.getLocation());
return result; return result;
}
case "getEnclosingClass": {
var cls = context.generate(invocation.getArguments().get(0));
var clsStruct = context.classInfoProvider().getClassInfo("java.lang.Class").getStructure();
var result = new WasmStructGet(clsStruct, cls,
context.classInfoProvider().getClassEnclosingClassOffset());
result.setLocation(invocation.getLocation());
return result;
}
case "getNameImpl": case "getNameImpl":
return generateGetName(invocation, context); return generateGetName(invocation, context);
case "setNameImpl": case "setNameImpl":
return generateSetName(invocation, context); return generateSetName(invocation, context);
case "getSimpleNameCache":
return generateGetSimpleName(invocation, context);
case "setSimpleNameCache":
return generateSetSimpleName(invocation, context);
default: default:
throw new IllegalArgumentException("Unsupported invocation method: " + invocation.getMethod()); throw new IllegalArgumentException("Unsupported invocation method: " + invocation.getMethod());
} }
@ -53,4 +66,18 @@ public class ClassIntrinsics implements WasmGCIntrinsic {
return new WasmStructSet(classCls.getStructure(), arg, context.classInfoProvider().getClassNameOffset(), return new WasmStructSet(classCls.getStructure(), arg, context.classInfoProvider().getClassNameOffset(),
value); value);
} }
private WasmExpression generateGetSimpleName(InvocationExpr invocation, WasmGCIntrinsicContext context) {
var classCls = context.classInfoProvider().getClassInfo("java.lang.Class");
var arg = context.generate(invocation.getArguments().get(0));
return new WasmStructGet(classCls.getStructure(), arg, context.classInfoProvider().getClassSimpleNameOffset());
}
private WasmExpression generateSetSimpleName(InvocationExpr invocation, WasmGCIntrinsicContext context) {
var classCls = context.classInfoProvider().getClassInfo("java.lang.Class");
var arg = context.generate(invocation.getArguments().get(0));
var value = context.generate(invocation.getArguments().get(1));
return new WasmStructSet(classCls.getStructure(), arg,
context.classInfoProvider().getClassSimpleNameOffset(), value);
}
} }

View File

@ -78,10 +78,13 @@ public class WasmGCIntrinsics implements WasmGCIntrinsicProvider {
} }
private void fillClass() { private void fillClass() {
var intrinsic = new ClassIntrinsics(); var intrinsic = new ClassIntrinsic();
add(new MethodReference(Class.class, "getComponentType", Class.class), intrinsic); add(new MethodReference(Class.class, "getComponentType", Class.class), intrinsic);
add(new MethodReference(Class.class, "getNameImpl", String.class), intrinsic); add(new MethodReference(Class.class, "getNameImpl", String.class), intrinsic);
add(new MethodReference(Class.class, "setNameImpl", String.class, void.class), intrinsic); add(new MethodReference(Class.class, "setNameImpl", String.class, void.class), intrinsic);
add(new MethodReference(Class.class, "getEnclosingClass", Class.class), intrinsic);
add(new MethodReference(Class.class, "getSimpleNameCache", Class.class, String.class), intrinsic);
add(new MethodReference(Class.class, "setSimpleNameCache", Class.class, String.class, void.class), intrinsic);
} }
private void fillSystem() { private void fillSystem() {

View File

@ -77,6 +77,9 @@ public class BaseClassesTransformation implements ClassHolderTransformer {
switch (method.getName()) { switch (method.getName()) {
case "getComponentType": case "getComponentType":
case "isInstance": case "isInstance":
case "getEnclosingClass":
case "getSimpleNameCache":
case "setSimpleNameCache":
method.setProgram(null); method.setProgram(null);
method.getModifiers().add(ElementModifier.NATIVE); method.getModifiers().add(ElementModifier.NATIVE);
break; break;