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()) {
simpleName = getComponentType().getSimpleName() + "[]";
} else if (getEnclosingClass() != null) {
simpleName = Platform.getSimpleName(platformClass);
simpleName = PlatformDetector.isWebAssemblyGC()
? getSimpleNameCache(this)
: Platform.getSimpleName(platformClass);
if (simpleName == null) {
simpleName = "";
}
} else {
String name = Platform.getName(platformClass);
var name = PlatformDetector.isWebAssemblyGC()
? getName()
: Platform.getName(platformClass);
int lastDollar = name.lastIndexOf('$');
if (lastDollar != -1) {
name = name.substring(lastDollar + 1);

View File

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

View File

@ -34,9 +34,9 @@ public final class WasmGCUtil {
if (firstPath.get(0) != secondPath.get(0)) {
return "java.lang.Object";
}
var min = Math.min(firstPath.size(), secondPath.size());
var index = 1;
while (index < min && firstPath.get(index) == secondPath.get(index)) {
var min = Math.min(firstPath.size(), secondPath.size()) - 1;
var index = 0;
while (index < min && firstPath.get(index + 1) == secondPath.get(index + 1)) {
++index;
}
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 classFlagsOffset;
private int classNameOffset;
private int classSimpleNameOffset;
private int classParentOffset;
private int classArrayOffset;
private int classArrayItemOffset;
private int classNewArrayOffset;
private int classSupertypeFunctionOffset;
private int classEnclosingClassOffset;
private int virtualTableFieldOffset;
private int arrayLengthOffset = -1;
private int arrayGetOffset = -1;
@ -351,12 +353,24 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
return classSupertypeFunctionOffset;
}
@Override
public int getClassEnclosingClassOffset() {
standardClasses.classClass().getStructure().init();
return classEnclosingClassOffset;
}
@Override
public int getClassNameOffset() {
standardClasses.classClass().getStructure().init();
return classNameOffset;
}
@Override
public int getClassSimpleNameOffset() {
standardClasses.classClass().getStructure().init();
return classSimpleNameOffset;
}
@Override
public int getNewArrayFunctionOffset() {
standardClasses.classClass().getStructure().init();
@ -445,12 +459,16 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
if (cls != null) {
if (metadataReq.simpleName() && cls.getSimpleName() != null) {
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()) {
var parent = getClassInfo(cls.getParent());
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()) {
fillVirtualTableMethods(target, classStructure, classInfo.pointer, virtualTable);
@ -960,8 +978,12 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
classNewArrayOffset = fields.size();
fields.add(createClassField(newArrayGenerator.getNewArrayFunctionType().getReference().asStorage(),
"createArrayInstance"));
classEnclosingClassOffset = fields.size();
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "enclosingClass"));
classNameOffset = fields.size();
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "name"));
classSimpleNameOffset = fields.size();
fields.add(createClassField(standardClasses.stringClass().getType().asStorage(), "simpleNAme"));
virtualTableFieldOffset = fields.size();
}
}

View File

@ -40,10 +40,14 @@ public interface WasmGCClassInfoProvider {
int getClassSupertypeFunctionOffset();
int getClassEnclosingClassOffset();
int getNewArrayFunctionOffset();
int getClassNameOffset();
int getClassSimpleNameOffset();
int getArrayGetOffset();
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.WasmStructSet;
public class ClassIntrinsics implements WasmGCIntrinsic {
public class ClassIntrinsic implements WasmGCIntrinsic {
@Override
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
switch (invocation.getMethod().getName()) {
case "getComponentType":
case "getComponentType": {
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().getClassArrayItemOffset());
result.setLocation(invocation.getLocation());
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":
return generateGetName(invocation, context);
case "setNameImpl":
return generateSetName(invocation, context);
case "getSimpleNameCache":
return generateGetSimpleName(invocation, context);
case "setSimpleNameCache":
return generateSetSimpleName(invocation, context);
default:
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(),
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() {
var intrinsic = new ClassIntrinsics();
var intrinsic = new ClassIntrinsic();
add(new MethodReference(Class.class, "getComponentType", Class.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, "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() {

View File

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