wasm gc: trying to fix issues with array covariance

This commit is contained in:
Alexey Andreev 2024-08-02 19:11:11 +02:00
parent dd2e4bb001
commit 92666e8cf0
8 changed files with 73 additions and 11 deletions

View File

@ -22,9 +22,18 @@ import org.teavm.model.*;
public abstract class Expr implements Cloneable { public abstract class Expr implements Cloneable {
private TextLocation location; private TextLocation location;
private int variableIndex = -1;
public abstract void acceptVisitor(ExprVisitor visitor); public abstract void acceptVisitor(ExprVisitor visitor);
public int getVariableIndex() {
return variableIndex;
}
public void setVariableIndex(int variableIndex) {
this.variableIndex = variableIndex;
}
@Override @Override
public Expr clone() { public Expr clone() {
return clone(new HashMap<>()); return clone(new HashMap<>());
@ -41,6 +50,7 @@ public abstract class Expr implements Cloneable {
public static Expr var(int index) { public static Expr var(int index) {
VariableExpr expr = new VariableExpr(); VariableExpr expr = new VariableExpr();
expr.setIndex(index); expr.setIndex(index);
expr.setVariableIndex(index);
return expr; return expr;
} }

View File

@ -211,6 +211,7 @@ class StatementGenerator implements InstructionVisitor {
public void visit(CastInstruction insn) { public void visit(CastInstruction insn) {
CastExpr expr = new CastExpr(); CastExpr expr = new CastExpr();
expr.setLocation(insn.getLocation()); expr.setLocation(insn.getLocation());
expr.setVariableIndex(insn.getReceiver().getIndex());
expr.setValue(Expr.var(insn.getValue().getIndex())); expr.setValue(Expr.var(insn.getValue().getIndex()));
expr.setTarget(insn.getTargetType()); expr.setTarget(insn.getTargetType());
assign(expr, insn.getReceiver()); assign(expr, insn.getReceiver());
@ -219,6 +220,8 @@ class StatementGenerator implements InstructionVisitor {
@Override @Override
public void visit(CastNumberInstruction insn) { public void visit(CastNumberInstruction insn) {
PrimitiveCastExpr expr = new PrimitiveCastExpr(); PrimitiveCastExpr expr = new PrimitiveCastExpr();
expr.setLocation(insn.getLocation());
expr.setVariableIndex(insn.getReceiver().getIndex());
expr.setSource(mapOperandType(insn.getSourceType())); expr.setSource(mapOperandType(insn.getSourceType()));
expr.setTarget(mapOperandType(insn.getTargetType())); expr.setTarget(mapOperandType(insn.getTargetType()));
expr.setValue(Expr.var(insn.getValue().getIndex())); expr.setValue(Expr.var(insn.getValue().getIndex()));
@ -495,6 +498,7 @@ class StatementGenerator implements InstructionVisitor {
} }
AssignmentStatement stmt; AssignmentStatement stmt;
if (insn.getReceiver() != null) { if (insn.getReceiver() != null) {
invocationExpr.setVariableIndex(insn.getReceiver().getIndex());
stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), invocationExpr); stmt = Statement.assign(Expr.var(insn.getReceiver().getIndex()), invocationExpr);
} else { } else {
stmt = Statement.assign(null, invocationExpr); stmt = Statement.assign(null, invocationExpr);
@ -518,6 +522,8 @@ class StatementGenerator implements InstructionVisitor {
private void assign(Expr source, Variable target) { private void assign(Expr source, Variable target) {
AssignmentStatement stmt = Statement.assign(Expr.var(target.getIndex()), source); AssignmentStatement stmt = Statement.assign(Expr.var(target.getIndex()), source);
source.setLocation(currentLocation);
source.setVariableIndex(target.getIndex());
stmt.setLocation(currentLocation); stmt.setLocation(currentLocation);
statements.add(stmt); statements.add(stmt);
} }
@ -647,7 +653,6 @@ class StatementGenerator implements InstructionVisitor {
if (insn.getArray() != null) { if (insn.getArray() != null) {
expr.setArray(Expr.var(insn.getArray().getIndex())); expr.setArray(Expr.var(insn.getArray().getIndex()));
} }
expr.setLocation(insn.getLocation());
assign(expr, insn.getReceiver()); assign(expr, insn.getReceiver());
} }
} }

View File

@ -190,6 +190,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
Expr result = BinaryExpr.binary(expr.getOperation(), comparison.getType(), Expr result = BinaryExpr.binary(expr.getOperation(), comparison.getType(),
comparison.getFirstOperand(), comparison.getSecondOperand()); comparison.getFirstOperand(), comparison.getSecondOperand());
result.setLocation(comparison.getLocation()); result.setLocation(comparison.getLocation());
result.setVariableIndex(comparison.getVariableIndex());
if (invert) { if (invert) {
result = ExprOptimizer.invert(result); result = ExprOptimizer.invert(result);
} }
@ -294,6 +295,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
ConstantExpr constantExpr = new ConstantExpr(); ConstantExpr constantExpr = new ConstantExpr();
constantExpr.setValue(constants[index]); constantExpr.setValue(constants[index]);
constantExpr.setLocation(expr.getLocation()); constantExpr.setLocation(expr.getLocation());
constantExpr.setVariableIndex(expr.getVariableIndex());
resultExpr = constantExpr; resultExpr = constantExpr;
return; return;
} }
@ -483,6 +485,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
args = Arrays.copyOfRange(args, 1, args.length); args = Arrays.copyOfRange(args, 1, args.length);
InvocationExpr constructrExpr = Expr.constructObject(expr.getMethod(), args); InvocationExpr constructrExpr = Expr.constructObject(expr.getMethod(), args);
constructrExpr.setLocation(expr.getLocation()); constructrExpr.setLocation(expr.getLocation());
constructrExpr.setVariableIndex(constructed.getVariableIndex());
assignment.setRightValue(constructrExpr); assignment.setRightValue(constructrExpr);
readFrequencies[var.getIndex()]--; readFrequencies[var.getIndex()]--;
return true; return true;
@ -823,6 +826,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
private void applyArrayOptimization(ArrayOptimization optimization) { private void applyArrayOptimization(ArrayOptimization optimization) {
AssignmentStatement assign = (AssignmentStatement) resultSequence.get(optimization.index); AssignmentStatement assign = (AssignmentStatement) resultSequence.get(optimization.index);
ArrayFromDataExpr arrayFromData = new ArrayFromDataExpr(); ArrayFromDataExpr arrayFromData = new ArrayFromDataExpr();
arrayFromData.setVariableIndex(optimization.array.getVariableIndex());
arrayFromData.setLocation(optimization.array.getLocation()); arrayFromData.setLocation(optimization.array.getLocation());
arrayFromData.setType(optimization.array.getType()); arrayFromData.setType(optimization.array.getType());
arrayFromData.getData().addAll(optimization.elements); arrayFromData.getData().addAll(optimization.elements);
@ -1096,6 +1100,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
AssignmentStatement assignment = new AssignmentStatement(); AssignmentStatement assignment = new AssignmentStatement();
assignment.setLocation(conditionalExpr.getLocation()); assignment.setLocation(conditionalExpr.getLocation());
VariableExpr lhs = new VariableExpr(); VariableExpr lhs = new VariableExpr();
lhs.setVariableIndex(firstLhs.getIndex());
lhs.setIndex(firstLhs.getIndex()); lhs.setIndex(firstLhs.getIndex());
assignment.setLeftValue(lhs); assignment.setLeftValue(lhs);
assignment.setRightValue(conditionalExpr); assignment.setRightValue(conditionalExpr);
@ -1166,6 +1171,7 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor {
if (statement.getCondition() != null) { if (statement.getCondition() != null) {
Expr newCondition = Expr.binary(BinaryOperation.AND, null, statement.getCondition(), Expr newCondition = Expr.binary(BinaryOperation.AND, null, statement.getCondition(),
ExprOptimizer.invert(cond.getCondition())); ExprOptimizer.invert(cond.getCondition()));
newCondition.setVariableIndex(statement.getCondition().getVariableIndex());
newCondition.setLocation(statement.getCondition().getLocation()); newCondition.setLocation(statement.getCondition().getLocation());
statement.setCondition(newCondition); statement.setCondition(newCondition);
} else { } else {

View File

@ -470,7 +470,7 @@ public class WasmGCClassGenerator implements WasmGCClassInfoProvider, WasmGCInit
if (type instanceof ValueType.Object) { if (type instanceof ValueType.Object) {
fillClassFields(fields, ((ValueType.Object) type).getClassName()); fillClassFields(fields, ((ValueType.Object) type).getClassName());
} else if (type instanceof ValueType.Array) { } 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) { private void fillArrayFields(WasmGCClassInfo classInfo, ValueType elementType) {
var wasmArray = new WasmArray(null, () -> typeMapper.mapStorageType(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); module.types.add(wasmArray);
classInfo.structure.getFields().add(wasmArray.getReference().asStorage()); classInfo.structure.getFields().add(wasmArray.getReference().asStorage());
classInfo.array = wasmArray; classInfo.array = wasmArray;

View File

@ -23,6 +23,7 @@ import org.teavm.ast.InvocationExpr;
import org.teavm.ast.QualificationExpr; import org.teavm.ast.QualificationExpr;
import org.teavm.ast.SubscriptExpr; import org.teavm.ast.SubscriptExpr;
import org.teavm.ast.UnwrapArrayExpr; 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.common.methods.BaseWasmGenerationVisitor;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider; import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.model.WasmArray; import org.teavm.backend.wasm.model.WasmArray;
@ -63,12 +64,14 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
private WasmGCGenerationContext context; private WasmGCGenerationContext context;
private WasmGCGenerationUtil generationUtil; private WasmGCGenerationUtil generationUtil;
private WasmType expectedType; private WasmType expectedType;
private PreciseTypeInference types;
public WasmGCGenerationVisitor(WasmGCGenerationContext context, MethodReference currentMethod, 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); super(context, currentMethod, function, firstVariable, async);
this.context = context; this.context = context;
generationUtil = new WasmGCGenerationUtil(context.classInfoProvider(), tempVars); generationUtil = new WasmGCGenerationUtil(context.classInfoProvider(), tempVars);
this.types = types;
} }
@Override @Override
@ -384,6 +387,12 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
} }
arrayGet.setLocation(expr.getLocation()); arrayGet.setLocation(expr.getLocation());
result = arrayGet; 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 @Override

View File

@ -250,7 +250,7 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
addInitializerErase(method, function); addInitializerErase(method, function);
var visitor = new WasmGCGenerationVisitor(getGenerationContext(), method.getReference(), var visitor = new WasmGCGenerationVisitor(getGenerationContext(), method.getReference(),
function, firstVar, false); function, firstVar, false, typeInference);
visitor.generate(ast.getBody(), function.getBody()); visitor.generate(ast.getBody(), function.getBody());
} }

View File

@ -16,8 +16,8 @@
package org.teavm.backend.wasm.model; package org.teavm.backend.wasm.model;
public abstract class WasmStorageType { public abstract class WasmStorageType {
private static final Packed INT16 = new Packed(WasmPackedType.INT16); public static final Packed INT16 = new Packed(WasmPackedType.INT16);
private static final Packed INT8 = new Packed(WasmPackedType.INT8); public static final Packed INT8 = new Packed(WasmPackedType.INT8);
private WasmStorageType() { private WasmStorageType() {
} }

View File

@ -238,12 +238,15 @@ public abstract class BaseTypeInference<T> {
} }
} }
@SuppressWarnings("unchecked")
public T typeOf(Variable variable) { public T typeOf(Variable variable) {
ensure(); return typeOf(variable.getIndex());
return (T) types[variable.getIndex()];
} }
@SuppressWarnings("unchecked")
public T typeOf(int index) {
ensure();
return (T) types[index];
}
protected abstract T mapType(ValueType type); protected abstract T mapType(ValueType type);