From 92666e8cf09d41d2bb44462cb2655aca11dfb824 Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Fri, 2 Aug 2024 19:11:11 +0200 Subject: [PATCH] wasm gc: trying to fix issues with array covariance --- core/src/main/java/org/teavm/ast/Expr.java | 10 ++++++ .../ast/decompilation/StatementGenerator.java | 7 +++- .../ast/optimization/OptimizingVisitor.java | 6 ++++ .../gc/classes/WasmGCClassGenerator.java | 35 +++++++++++++++++-- .../gc/methods/WasmGCGenerationVisitor.java | 11 +++++- .../gc/methods/WasmGCMethodGenerator.java | 2 +- .../backend/wasm/model/WasmStorageType.java | 4 +-- .../model/analysis/BaseTypeInference.java | 9 +++-- 8 files changed, 73 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/org/teavm/ast/Expr.java b/core/src/main/java/org/teavm/ast/Expr.java index 3e5f42220..50cd4ef90 100644 --- a/core/src/main/java/org/teavm/ast/Expr.java +++ b/core/src/main/java/org/teavm/ast/Expr.java @@ -22,9 +22,18 @@ import org.teavm.model.*; public abstract class Expr implements Cloneable { private TextLocation location; + private int variableIndex = -1; public abstract void acceptVisitor(ExprVisitor visitor); + public int getVariableIndex() { + return variableIndex; + } + + public void setVariableIndex(int variableIndex) { + this.variableIndex = variableIndex; + } + @Override public Expr clone() { return clone(new HashMap<>()); @@ -41,6 +50,7 @@ public abstract class Expr implements Cloneable { public static Expr var(int index) { VariableExpr expr = new VariableExpr(); expr.setIndex(index); + expr.setVariableIndex(index); return expr; } diff --git a/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java b/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java index 39014f4c2..be885aec4 100644 --- a/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java +++ b/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java @@ -211,6 +211,7 @@ class StatementGenerator implements InstructionVisitor { public void visit(CastInstruction insn) { CastExpr expr = new CastExpr(); expr.setLocation(insn.getLocation()); + expr.setVariableIndex(insn.getReceiver().getIndex()); expr.setValue(Expr.var(insn.getValue().getIndex())); expr.setTarget(insn.getTargetType()); assign(expr, insn.getReceiver()); @@ -219,6 +220,8 @@ class StatementGenerator implements InstructionVisitor { @Override public void visit(CastNumberInstruction insn) { PrimitiveCastExpr expr = new PrimitiveCastExpr(); + expr.setLocation(insn.getLocation()); + expr.setVariableIndex(insn.getReceiver().getIndex()); expr.setSource(mapOperandType(insn.getSourceType())); expr.setTarget(mapOperandType(insn.getTargetType())); expr.setValue(Expr.var(insn.getValue().getIndex())); @@ -495,6 +498,7 @@ class StatementGenerator implements InstructionVisitor { } AssignmentStatement stmt; if (insn.getReceiver() != null) { + invocationExpr.setVariableIndex(insn.getReceiver().getIndex()); stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), invocationExpr); } else { stmt = Statement.assign(null, invocationExpr); @@ -518,6 +522,8 @@ class StatementGenerator implements InstructionVisitor { private void assign(Expr source, Variable target) { AssignmentStatement stmt = Statement.assign(Expr.var(target.getIndex()), source); + source.setLocation(currentLocation); + source.setVariableIndex(target.getIndex()); stmt.setLocation(currentLocation); statements.add(stmt); } @@ -647,7 +653,6 @@ class StatementGenerator implements InstructionVisitor { if (insn.getArray() != null) { expr.setArray(Expr.var(insn.getArray().getIndex())); } - expr.setLocation(insn.getLocation()); assign(expr, insn.getReceiver()); } } diff --git a/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java b/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java index 3d004d81e..954967270 100644 --- a/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java +++ b/core/src/main/java/org/teavm/ast/optimization/OptimizingVisitor.java @@ -190,6 +190,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { Expr result = BinaryExpr.binary(expr.getOperation(), comparison.getType(), comparison.getFirstOperand(), comparison.getSecondOperand()); result.setLocation(comparison.getLocation()); + result.setVariableIndex(comparison.getVariableIndex()); if (invert) { result = ExprOptimizer.invert(result); } @@ -294,6 +295,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { ConstantExpr constantExpr = new ConstantExpr(); constantExpr.setValue(constants[index]); constantExpr.setLocation(expr.getLocation()); + constantExpr.setVariableIndex(expr.getVariableIndex()); resultExpr = constantExpr; return; } @@ -483,6 +485,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { args = Arrays.copyOfRange(args, 1, args.length); InvocationExpr constructrExpr = Expr.constructObject(expr.getMethod(), args); constructrExpr.setLocation(expr.getLocation()); + constructrExpr.setVariableIndex(constructed.getVariableIndex()); assignment.setRightValue(constructrExpr); readFrequencies[var.getIndex()]--; return true; @@ -823,6 +826,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { private void applyArrayOptimization(ArrayOptimization optimization) { AssignmentStatement assign = (AssignmentStatement) resultSequence.get(optimization.index); ArrayFromDataExpr arrayFromData = new ArrayFromDataExpr(); + arrayFromData.setVariableIndex(optimization.array.getVariableIndex()); arrayFromData.setLocation(optimization.array.getLocation()); arrayFromData.setType(optimization.array.getType()); arrayFromData.getData().addAll(optimization.elements); @@ -1096,6 +1100,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { AssignmentStatement assignment = new AssignmentStatement(); assignment.setLocation(conditionalExpr.getLocation()); VariableExpr lhs = new VariableExpr(); + lhs.setVariableIndex(firstLhs.getIndex()); lhs.setIndex(firstLhs.getIndex()); assignment.setLeftValue(lhs); assignment.setRightValue(conditionalExpr); @@ -1166,6 +1171,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { if (statement.getCondition() != null) { Expr newCondition = Expr.binary(BinaryOperation.AND, null, statement.getCondition(), ExprOptimizer.invert(cond.getCondition())); + newCondition.setVariableIndex(statement.getCondition().getVariableIndex()); newCondition.setLocation(statement.getCondition().getLocation()); statement.setCondition(newCondition); } else { diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java index 280034643..8f911fc54 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/classes/WasmGCClassGenerator.java @@ -470,7 +470,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit if (type instanceof ValueType.Object) { fillClassFields(fields, ((ValueType.Object) type).getClassName()); } else if (type instanceof ValueType.Array) { - fillArrayField(classInfo, ((ValueType.Array) type).getItemType()); + fillArrayFields(classInfo, ((ValueType.Array) type).getItemType()); } } @@ -516,8 +516,37 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit } } - private void fillArrayField(WasmGCClassInfo classInfo, ValueType elementType) { - var wasmArray = new WasmArray(null, () -> typeMapper.mapStorageType(elementType)); + private void fillArrayFields(WasmGCClassInfo classInfo, ValueType elementType) { + WasmStorageType wasmElementType; + if (elementType instanceof ValueType.Primitive) { + switch (((ValueType.Primitive) elementType).getKind()) { + case BOOLEAN: + case BYTE: + wasmElementType = WasmStorageType.INT8; + break; + case SHORT: + case CHARACTER: + wasmElementType = WasmStorageType.INT16; + break; + case INTEGER: + wasmElementType = WasmType.INT32.asStorage(); + break; + case LONG: + wasmElementType = WasmType.INT64.asStorage(); + break; + case FLOAT: + wasmElementType = WasmType.FLOAT32.asStorage(); + break; + case DOUBLE: + wasmElementType = WasmType.FLOAT64.asStorage(); + break; + default: + throw new IllegalArgumentException(); + } + } else { + wasmElementType = WasmType.Reference.STRUCT.asStorage(); + } + var wasmArray = new WasmArray(null, wasmElementType); module.types.add(wasmArray); classInfo.structure.getFields().add(wasmArray.getReference().asStorage()); classInfo.array = wasmArray; diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java index b0d47a6b2..c1b94804a 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCGenerationVisitor.java @@ -23,6 +23,7 @@ import org.teavm.ast.InvocationExpr; import org.teavm.ast.QualificationExpr; import org.teavm.ast.SubscriptExpr; import org.teavm.ast.UnwrapArrayExpr; +import org.teavm.backend.wasm.gc.PreciseTypeInference; import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationVisitor; import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider; import org.teavm.backend.wasm.model.WasmArray; @@ -63,12 +64,14 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor { private WasmGCGenerationContext context; private WasmGCGenerationUtil generationUtil; private WasmType expectedType; + private PreciseTypeInference types; public WasmGCGenerationVisitor(WasmGCGenerationContext context, MethodReference currentMethod, - WasmFunction function, int firstVariable, boolean async) { + WasmFunction function, int firstVariable, boolean async, PreciseTypeInference types) { super(context, currentMethod, function, firstVariable, async); this.context = context; generationUtil = new WasmGCGenerationUtil(context.classInfoProvider(), tempVars); + this.types = types; } @Override @@ -384,6 +387,12 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor { } arrayGet.setLocation(expr.getLocation()); result = arrayGet; + if (expr.getType() == ArrayType.OBJECT && expr.getVariableIndex() >= 0) { + var targetType = types.typeOf(expr.getVariableIndex()); + if (targetType != null) { + result = new WasmCast(result, (WasmType.Reference) mapType(targetType.valueType)); + } + } } @Override diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java index 084b6c894..5d0851d04 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/gc/methods/WasmGCMethodGenerator.java @@ -250,7 +250,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository { addInitializerErase(method, function); var visitor = new WasmGCGenerationVisitor(getGenerationContext(), method.getReference(), - function, firstVar, false); + function, firstVar, false, typeInference); visitor.generate(ast.getBody(), function.getBody()); } diff --git a/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java b/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java index 523b6de65..11955fd38 100644 --- a/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java +++ b/core/src/main/java/org/teavm/backend/wasm/model/WasmStorageType.java @@ -16,8 +16,8 @@ package org.teavm.backend.wasm.model; public abstract class WasmStorageType { - private static final Packed INT16 = new Packed(WasmPackedType.INT16); - private static final Packed INT8 = new Packed(WasmPackedType.INT8); + public static final Packed INT16 = new Packed(WasmPackedType.INT16); + public static final Packed INT8 = new Packed(WasmPackedType.INT8); private WasmStorageType() { } diff --git a/core/src/main/java/org/teavm/model/analysis/BaseTypeInference.java b/core/src/main/java/org/teavm/model/analysis/BaseTypeInference.java index b127b8661..dfc061355 100644 --- a/core/src/main/java/org/teavm/model/analysis/BaseTypeInference.java +++ b/core/src/main/java/org/teavm/model/analysis/BaseTypeInference.java @@ -238,12 +238,15 @@ public abstract class BaseTypeInference { } } - @SuppressWarnings("unchecked") public T typeOf(Variable variable) { - ensure(); - return (T) types[variable.getIndex()]; + return typeOf(variable.getIndex()); } + @SuppressWarnings("unchecked") + public T typeOf(int index) { + ensure(); + return (T) types[index]; + } protected abstract T mapType(ValueType type);