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 {
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;
}

View File

@ -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());
}
}

View File

@ -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 {

View File

@ -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;

View File

@ -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

View File

@ -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());
}

View File

@ -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() {
}

View File

@ -238,12 +238,15 @@ public abstract class BaseTypeInference<T> {
}
}
@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);