mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
wasm gc: fix some issues and implement intrinsics
* properly cast exception type on catch blocks * generate virtual table structures lazily * fix calculation of types of a.field values
This commit is contained in:
parent
4823109be5
commit
10c3731c43
|
@ -299,6 +299,8 @@ public final class TMath extends TObject {
|
|||
return randomC();
|
||||
} else if (PlatformDetector.isWebAssembly()) {
|
||||
return WasmSupport.random();
|
||||
} else if (PlatformDetector.isWebAssemblyGC()) {
|
||||
return randomWasmGC();
|
||||
} else {
|
||||
return randomImpl();
|
||||
}
|
||||
|
@ -310,6 +312,9 @@ public final class TMath extends TObject {
|
|||
@GeneratedBy(MathNativeGenerator.class)
|
||||
private static native double randomImpl();
|
||||
|
||||
@Import(module = "teavmMath", name = "random")
|
||||
private static native double randomWasmGC();
|
||||
|
||||
public static int min(int a, int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
|
|
@ -401,6 +401,7 @@ class StatementGenerator implements InstructionVisitor {
|
|||
if (insn.getInstance() != null) {
|
||||
AssignmentStatement stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()),
|
||||
Expr.qualify(Expr.var(insn.getInstance().getIndex()), insn.getField()));
|
||||
stmt.getRightValue().setVariableIndex(insn.getReceiver().getIndex());
|
||||
stmt.setLocation(currentLocation);
|
||||
statements.add(stmt);
|
||||
} else {
|
||||
|
|
|
@ -175,7 +175,8 @@ public class WasmGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local) {
|
||||
protected void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local,
|
||||
String exceptionClass) {
|
||||
var call = new WasmCall(context.functions().forStaticMethod(CATCH_METHOD));
|
||||
if (local != null) {
|
||||
var save = new WasmSetLocal(local, call);
|
||||
|
|
|
@ -1300,7 +1300,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
var catchLocal = tryCatch.getExceptionVariable() != null
|
||||
? localVar(tryCatch.getExceptionVariable())
|
||||
: null;
|
||||
catchException(null, catchBlock.getBody(), catchLocal);
|
||||
catchException(null, catchBlock.getBody(), catchLocal, tryCatch.getExceptionType());
|
||||
visitMany(tryCatch.getHandler(), catchBlock.getBody());
|
||||
if (!catchBlock.isTerminating() && catchBlock != outerCatchBlock) {
|
||||
catchBlock.getBody().add(new WasmBreak(outerCatchBlock));
|
||||
|
@ -1313,7 +1313,8 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
|
||||
protected abstract WasmExpression peekException();
|
||||
|
||||
protected abstract void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local);
|
||||
protected abstract void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local,
|
||||
String exceptionClass);
|
||||
|
||||
private void visitMany(List<Statement> statements, List<WasmExpression> target) {
|
||||
var oldTarget = resultConsumer;
|
||||
|
|
|
@ -129,6 +129,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
private WasmFunction arrayLengthObjectFunction;
|
||||
private WasmFunctionType arrayGetType;
|
||||
private WasmFunctionType arrayLengthType;
|
||||
private List<WasmStructure> nonInitializedStructures = new ArrayList<>();
|
||||
|
||||
public WasmGCClassGenerator(WasmModule module, ClassReaderSource classSource,
|
||||
WasmFunctionTypes functionTypes, TagRegistry tagRegistry,
|
||||
|
@ -163,10 +164,22 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
var classInfo = classInfoQueue.remove();
|
||||
classInfo.initializer.accept(initializerFunctionStatements);
|
||||
classInfo.initializer = null;
|
||||
initStructures();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void initStructures() {
|
||||
if (nonInitializedStructures.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
var copy = List.copyOf(nonInitializedStructures);
|
||||
nonInitializedStructures.clear();
|
||||
for (var structure : copy) {
|
||||
structure.init();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contributeToInitializerDefinitions(WasmFunction function) {
|
||||
fillVirtualTableSupertypes();
|
||||
|
@ -269,6 +282,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
classInfo.structure = new WasmStructure(name != null ? names.forClass(name) : null,
|
||||
fields -> fillFields(finalClassInfo, fields, type));
|
||||
module.types.add(classInfo.structure);
|
||||
nonInitializedStructures.add(classInfo.structure);
|
||||
}
|
||||
}
|
||||
if (name != null) {
|
||||
|
@ -698,12 +712,14 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
|
||||
private WasmStructure initRegularClassStructure(String className) {
|
||||
var virtualTable = virtualTables.lookup(className);
|
||||
var structure = new WasmStructure(names.forClassClass(className));
|
||||
var structure = new WasmStructure(names.forClassClass(className), fields -> {
|
||||
addSystemFields(fields);
|
||||
fillSimpleClassFields(fields, "java.lang.Class");
|
||||
addVirtualTableFields(fields, virtualTable);
|
||||
});
|
||||
nonInitializedStructures.add(structure);
|
||||
structure.setSupertype(standardClasses.classClass().getStructure());
|
||||
module.types.add(structure);
|
||||
addSystemFields(structure.getFields());
|
||||
fillSimpleClassFields(structure.getFields(), "java.lang.Class");
|
||||
addVirtualTableFields(structure, virtualTable);
|
||||
return structure;
|
||||
}
|
||||
|
||||
|
@ -716,46 +732,49 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
|
|||
fields.add(monitorField);
|
||||
}
|
||||
|
||||
private void addVirtualTableFields(WasmStructure structure, WasmGCVirtualTable virtualTable) {
|
||||
private void addVirtualTableFields(List<WasmField> fields, WasmGCVirtualTable virtualTable) {
|
||||
for (var entry : virtualTable.getEntries()) {
|
||||
var functionType = typeMapper.getFunctionType(entry.getOrigin().getClassName(), entry.getMethod(), false);
|
||||
var field = new WasmField(functionType.getReference().asStorage());
|
||||
field.setName(names.forVirtualMethod(entry.getMethod()));
|
||||
structure.getFields().add(field);
|
||||
fields.add(field);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public WasmStructure getArrayVirtualTableStructure() {
|
||||
if (arrayVirtualTableStruct == null) {
|
||||
arrayVirtualTableStruct = new WasmStructure(null);
|
||||
arrayVirtualTableStruct = new WasmStructure(null, fields -> {
|
||||
addSystemFields(fields);
|
||||
fillSimpleClassFields(fields, "java.lang.Class");
|
||||
addVirtualTableFields(fields, virtualTables.lookup("java.lang.Object"));
|
||||
if (metadataRequirements.hasArrayLength()) {
|
||||
arrayLengthOffset = fields.size();
|
||||
var arrayLengthType = getArrayLengthType();
|
||||
fields.add(new WasmField(arrayLengthType.getReference().asStorage()));
|
||||
}
|
||||
if (metadataRequirements.hasArrayGet()) {
|
||||
arrayGetOffset = fields.size();
|
||||
var arrayGetType = getArrayGetType();
|
||||
fields.add(new WasmField(arrayGetType.getReference().asStorage()));
|
||||
}
|
||||
});
|
||||
arrayVirtualTableStruct.setSupertype(standardClasses.objectClass().getVirtualTableStructure());
|
||||
module.types.add(arrayVirtualTableStruct);
|
||||
addSystemFields(arrayVirtualTableStruct.getFields());
|
||||
fillSimpleClassFields(arrayVirtualTableStruct.getFields(), "java.lang.Class");
|
||||
addVirtualTableFields(arrayVirtualTableStruct, virtualTables.lookup("java.lang.Object"));
|
||||
|
||||
if (metadataRequirements.hasArrayLength()) {
|
||||
arrayLengthOffset = arrayVirtualTableStruct.getFields().size();
|
||||
var arrayLengthType = getArrayLengthType();
|
||||
arrayVirtualTableStruct.getFields().add(new WasmField(arrayLengthType.getReference().asStorage()));
|
||||
}
|
||||
if (metadataRequirements.hasArrayGet()) {
|
||||
arrayGetOffset = arrayVirtualTableStruct.getFields().size();
|
||||
var arrayGetType = getArrayGetType();
|
||||
arrayVirtualTableStruct.getFields().add(new WasmField(arrayGetType.getReference().asStorage()));
|
||||
}
|
||||
nonInitializedStructures.add(arrayVirtualTableStruct);
|
||||
}
|
||||
return arrayVirtualTableStruct;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArrayLengthOffset() {
|
||||
initStructures();
|
||||
return arrayLengthOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getArrayGetOffset() {
|
||||
initStructures();
|
||||
return arrayGetOffset;
|
||||
}
|
||||
|
||||
|
|
|
@ -372,10 +372,16 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local) {
|
||||
protected void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local,
|
||||
String exceptionClass) {
|
||||
var type = context.classInfoProvider().getClassInfo("java.lang.Throwable").getType();
|
||||
if (local != null) {
|
||||
var save = new WasmSetLocal(local, new WasmGetGlobal(context.exceptionGlobal()));
|
||||
WasmExpression exception = new WasmGetGlobal(context.exceptionGlobal());
|
||||
if (exceptionClass != null && !exceptionClass.equals("java.lang.Throwable")) {
|
||||
exception = new WasmCast(exception, context.classInfoProvider().getClassInfo(exceptionClass)
|
||||
.getStructure().getReference());
|
||||
}
|
||||
var save = new WasmSetLocal(local, exception);
|
||||
save.setLocation(location);
|
||||
target.add(save);
|
||||
}
|
||||
|
@ -511,6 +517,9 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
var fieldType = field.getType();
|
||||
if (fieldType instanceof ValueType.Primitive) {
|
||||
switch (((ValueType.Primitive) fieldType).getKind()) {
|
||||
case BOOLEAN:
|
||||
structGet.setSignedType(WasmSignedType.UNSIGNED);
|
||||
break;
|
||||
case BYTE:
|
||||
structGet.setSignedType(WasmSignedType.SIGNED);
|
||||
break;
|
||||
|
|
|
@ -35,6 +35,7 @@ public class SystemArrayCopyIntrinsic implements WasmGCIntrinsic {
|
|||
public WasmExpression apply(InvocationExpr invocation, WasmGCIntrinsicContext context) {
|
||||
var result = tryGenerateSpecialCase(invocation, context);
|
||||
if (result == null) {
|
||||
tryGenerateSpecialCase(invocation, context);
|
||||
var function = getDefaultFunction(context);
|
||||
result = new WasmCall(function, context.generate(invocation.getArguments().get(0)),
|
||||
context.generate(invocation.getArguments().get(1)),
|
||||
|
|
|
@ -16,7 +16,10 @@
|
|||
package org.teavm.backend.wasm.transformation.gc;
|
||||
|
||||
import org.teavm.backend.wasm.runtime.WasmGCSupport;
|
||||
import org.teavm.interop.Import;
|
||||
import org.teavm.model.AccessLevel;
|
||||
import org.teavm.model.AnnotationHolder;
|
||||
import org.teavm.model.AnnotationValue;
|
||||
import org.teavm.model.ClassHolder;
|
||||
import org.teavm.model.ClassHolderTransformer;
|
||||
import org.teavm.model.ClassHolderTransformerContext;
|
||||
|
@ -86,6 +89,12 @@ public class BaseClassesTransformation implements ClassHolderTransformer {
|
|||
method.setProgram(null);
|
||||
method.getModifiers().add(ElementModifier.NATIVE);
|
||||
break;
|
||||
case "currentTimeMillis": {
|
||||
var annotation = new AnnotationHolder(Import.class.getName());
|
||||
annotation.getValues().put("module", new AnnotationValue("teavm"));
|
||||
annotation.getValues().put("name", new AnnotationValue("currentTimeMillis"));
|
||||
method.getAnnotations().add(annotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,12 @@ TeaVM.wasm = function() {
|
|||
} else {
|
||||
stdout += String.fromCharCode(c);
|
||||
}
|
||||
},
|
||||
currentTimeMillis() {
|
||||
return new Date().getTime();
|
||||
}
|
||||
};
|
||||
imports.teavmMath = Math;
|
||||
}
|
||||
|
||||
function load(path, options) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user