mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
wasm gc: optimize null checks, casts and try/catch using branching instructions
This commit is contained in:
parent
9aee15fa0f
commit
a503333c1b
|
@ -143,7 +143,7 @@ public class DisassemblyCodeListener extends BaseDisassemblyListener implements
|
||||||
writer.write(" ");
|
writer.write(" ");
|
||||||
writeType(sourceType);
|
writeType(sourceType);
|
||||||
writer.write(" ");
|
writer.write(" ");
|
||||||
writeType(sourceType);
|
writeType(targetType);
|
||||||
writer.eol();
|
writer.eol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -179,16 +179,6 @@ public class WasmGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local,
|
|
||||||
String exceptionClass, WasmLocal exceptionVar) {
|
|
||||||
if (local != null) {
|
|
||||||
var save = new WasmSetLocal(local, new WasmGetLocal(exceptionVar));
|
|
||||||
save.setLocation(location);
|
|
||||||
target.add(save);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WasmType mapType(ValueType type) {
|
protected WasmType mapType(ValueType type) {
|
||||||
return WasmGeneratorUtil.mapType(type);
|
return WasmGeneratorUtil.mapType(type);
|
||||||
|
|
|
@ -1300,12 +1300,16 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
for (int i = tryCatchStatements.size() - 1; i >= 0; --i) {
|
for (int i = tryCatchStatements.size() - 1; i >= 0; --i) {
|
||||||
var tryCatch = tryCatchStatements.get(i);
|
var tryCatch = tryCatchStatements.get(i);
|
||||||
var catchBlock = catchBlocks.get(i);
|
var catchBlock = catchBlocks.get(i);
|
||||||
|
var blockType = mapType(tryCatch.getExceptionType() != null
|
||||||
|
? ValueType.object(tryCatch.getExceptionType())
|
||||||
|
: ValueType.object("java.lang.Throwable"));
|
||||||
|
currentBlock.setType(blockType);
|
||||||
if (tryCatch.getExceptionType() != null && !tryCatch.getExceptionType().equals(Throwable.class.getName())) {
|
if (tryCatch.getExceptionType() != null && !tryCatch.getExceptionType().equals(Throwable.class.getName())) {
|
||||||
var exceptionType = ValueType.object(tryCatch.getExceptionType());
|
checkExceptionType(tryCatch, exceptionVar, innerCatchBlock.getBody(), currentBlock);
|
||||||
var isMatched = generateInstanceOf(new WasmGetLocal(exceptionVar), exceptionType);
|
|
||||||
innerCatchBlock.getBody().add(new WasmBranch(isMatched, currentBlock));
|
|
||||||
} else {
|
} else {
|
||||||
innerCatchBlock.getBody().add(new WasmBreak(currentBlock));
|
var br = new WasmBreak(currentBlock);
|
||||||
|
br.setResult(new WasmGetLocal(exceptionVar));
|
||||||
|
innerCatchBlock.getBody().add(br);
|
||||||
catchesAll = true;
|
catchesAll = true;
|
||||||
}
|
}
|
||||||
currentBlock = catchBlock;
|
currentBlock = catchBlock;
|
||||||
|
@ -1320,12 +1324,16 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
for (int i = tryCatchStatements.size() - 1; i >= 0; --i) {
|
for (int i = tryCatchStatements.size() - 1; i >= 0; --i) {
|
||||||
var tryCatch = tryCatchStatements.get(i);
|
var tryCatch = tryCatchStatements.get(i);
|
||||||
var catchBlock = catchBlocks.get(i);
|
var catchBlock = catchBlocks.get(i);
|
||||||
catchBlock.getBody().add(currentBlock);
|
|
||||||
|
|
||||||
var catchLocal = tryCatch.getExceptionVariable() != null
|
var catchLocal = tryCatch.getExceptionVariable() != null
|
||||||
? localVar(tryCatch.getExceptionVariable())
|
? localVar(tryCatch.getExceptionVariable())
|
||||||
: null;
|
: null;
|
||||||
catchException(null, catchBlock.getBody(), catchLocal, tryCatch.getExceptionType(), exceptionVar);
|
if (catchLocal != null) {
|
||||||
|
var save = new WasmSetLocal(localVar(tryCatch.getExceptionVariable()), currentBlock);
|
||||||
|
catchBlock.getBody().add(save);
|
||||||
|
} else {
|
||||||
|
catchBlock.getBody().add(new WasmDrop(currentBlock));
|
||||||
|
}
|
||||||
visitMany(tryCatch.getHandler(), catchBlock.getBody());
|
visitMany(tryCatch.getHandler(), catchBlock.getBody());
|
||||||
if (!catchBlock.isTerminating() && catchBlock != outerCatchBlock) {
|
if (!catchBlock.isTerminating() && catchBlock != outerCatchBlock) {
|
||||||
catchBlock.getBody().add(new WasmBreak(outerCatchBlock));
|
catchBlock.getBody().add(new WasmBreak(outerCatchBlock));
|
||||||
|
@ -1337,8 +1345,12 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
||||||
tempVars.release(exceptionVar);
|
tempVars.release(exceptionVar);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local,
|
protected void checkExceptionType(TryCatchStatement tryCatch, WasmLocal exceptionVar, List<WasmExpression> target,
|
||||||
String exceptionClass, WasmLocal exceptionVar);
|
WasmBlock targetBlock) {
|
||||||
|
var exceptionType = ValueType.object(tryCatch.getExceptionType());
|
||||||
|
var isMatched = generateInstanceOf(new WasmGetLocal(exceptionVar), exceptionType);
|
||||||
|
target.add(new WasmBranch(isMatched, targetBlock));
|
||||||
|
}
|
||||||
|
|
||||||
private void visitMany(List<Statement> statements, List<WasmExpression> target) {
|
private void visitMany(List<Statement> statements, List<WasmExpression> target) {
|
||||||
var oldTarget = resultConsumer;
|
var oldTarget = resultConsumer;
|
||||||
|
|
|
@ -19,12 +19,15 @@ import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import org.teavm.ast.ArrayType;
|
import org.teavm.ast.ArrayType;
|
||||||
import org.teavm.ast.BinaryExpr;
|
import org.teavm.ast.BinaryExpr;
|
||||||
|
import org.teavm.ast.CastExpr;
|
||||||
import org.teavm.ast.ConditionalExpr;
|
import org.teavm.ast.ConditionalExpr;
|
||||||
import org.teavm.ast.Expr;
|
import org.teavm.ast.Expr;
|
||||||
|
import org.teavm.ast.InstanceOfExpr;
|
||||||
import org.teavm.ast.InvocationExpr;
|
import org.teavm.ast.InvocationExpr;
|
||||||
import org.teavm.ast.InvocationType;
|
import org.teavm.ast.InvocationType;
|
||||||
import org.teavm.ast.QualificationExpr;
|
import org.teavm.ast.QualificationExpr;
|
||||||
import org.teavm.ast.SubscriptExpr;
|
import org.teavm.ast.SubscriptExpr;
|
||||||
|
import org.teavm.ast.TryCatchStatement;
|
||||||
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
|
||||||
import org.teavm.backend.wasm.WasmFunctionTypes;
|
import org.teavm.backend.wasm.WasmFunctionTypes;
|
||||||
import org.teavm.backend.wasm.gc.PreciseTypeInference;
|
import org.teavm.backend.wasm.gc.PreciseTypeInference;
|
||||||
|
@ -50,6 +53,8 @@ import org.teavm.backend.wasm.model.expression.WasmBlock;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmCast;
|
import org.teavm.backend.wasm.model.expression.WasmCast;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCastBranch;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmCastCondition;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||||
|
@ -68,9 +73,11 @@ import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
import org.teavm.backend.wasm.model.expression.WasmStructGet;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
import org.teavm.backend.wasm.model.expression.WasmStructNewDefault;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
import org.teavm.backend.wasm.model.expression.WasmStructSet;
|
||||||
|
import org.teavm.backend.wasm.model.expression.WasmTest;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
import org.teavm.backend.wasm.model.expression.WasmThrow;
|
||||||
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
import org.teavm.backend.wasm.model.expression.WasmUnreachable;
|
||||||
import org.teavm.model.ClassHierarchy;
|
import org.teavm.model.ClassHierarchy;
|
||||||
|
import org.teavm.model.ElementModifier;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.TextLocation;
|
import org.teavm.model.TextLocation;
|
||||||
|
@ -245,18 +252,14 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
}
|
}
|
||||||
result.acceptVisitor(typeInference);
|
result.acceptVisitor(typeInference);
|
||||||
block.setType(typeInference.getResult());
|
block.setType(typeInference.getResult());
|
||||||
var cachedValue = exprCache.create(result, typeInference.getResult(), location, block.getBody());
|
var check = new WasmNullBranch(WasmNullCondition.NOT_NULL, result, block);
|
||||||
|
block.getBody().add(check);
|
||||||
var check = new WasmNullBranch(WasmNullCondition.NOT_NULL, cachedValue.expr(), block);
|
|
||||||
check.setResult(cachedValue.expr());
|
|
||||||
block.getBody().add(new WasmDrop(check));
|
|
||||||
|
|
||||||
var callSiteId = generateCallSiteId(location);
|
var callSiteId = generateCallSiteId(location);
|
||||||
callSiteId.generateRegister(block.getBody(), location);
|
callSiteId.generateRegister(block.getBody(), location);
|
||||||
generateThrowNPE(location, block.getBody());
|
generateThrowNPE(location, block.getBody());
|
||||||
callSiteId.generateThrow(block.getBody(), location);
|
callSiteId.generateThrow(block.getBody(), location);
|
||||||
|
|
||||||
cachedValue.release();
|
|
||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -382,6 +385,59 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
return supertypeCall;
|
return supertypeCall;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(InstanceOfExpr expr) {
|
||||||
|
var type = expr.getType();
|
||||||
|
if (canCastNatively(type)) {
|
||||||
|
var wasmType = context.classInfoProvider().getClassInfo(type).getStructure().getNonNullReference();
|
||||||
|
acceptWithType(expr.getExpr(), type);
|
||||||
|
var wasmValue = result;
|
||||||
|
result.acceptVisitor(typeInference);
|
||||||
|
|
||||||
|
result = new WasmTest(wasmValue, wasmType);
|
||||||
|
result.setLocation(expr.getLocation());
|
||||||
|
} else {
|
||||||
|
super.visit(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visit(CastExpr expr) {
|
||||||
|
var type = expr.getTarget();
|
||||||
|
if (!expr.isWeak() && canCastNatively(type)) {
|
||||||
|
var wasmType = context.classInfoProvider().getClassInfo(type).getType();
|
||||||
|
var block = new WasmBlock(false);
|
||||||
|
acceptWithType(expr.getValue(), type);
|
||||||
|
var wasmValue = result;
|
||||||
|
result.acceptVisitor(typeInference);
|
||||||
|
var sourceWasmType = (WasmType.Reference) typeInference.getResult();
|
||||||
|
if (sourceWasmType == null || !validateCastTypes(sourceWasmType, wasmType, expr.getLocation())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
block.setType(wasmType);
|
||||||
|
block.setLocation(expr.getLocation());
|
||||||
|
block.getBody().add(new WasmCastBranch(WasmCastCondition.SUCCESS, wasmValue, sourceWasmType,
|
||||||
|
wasmType, block));
|
||||||
|
generateThrowCCE(expr.getLocation(), block.getBody());
|
||||||
|
result = block;
|
||||||
|
} else {
|
||||||
|
super.visit(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canCastNatively(ValueType type) {
|
||||||
|
if (type instanceof ValueType.Array) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var className = ((ValueType.Object) type).getClassName();
|
||||||
|
var cls = context.classes().get(className);
|
||||||
|
if (cls == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !cls.hasModifier(ElementModifier.INTERFACE);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WasmExpression generateCast(WasmExpression value, WasmType targetType) {
|
protected WasmExpression generateCast(WasmExpression value, WasmType targetType) {
|
||||||
return new WasmCast(value, (WasmType.Reference) targetType);
|
return new WasmCast(value, (WasmType.Reference) targetType);
|
||||||
|
@ -435,18 +491,13 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void catchException(TextLocation location, List<WasmExpression> target, WasmLocal local,
|
protected void checkExceptionType(TryCatchStatement tryCatch, WasmLocal exceptionVar, List<WasmExpression> target,
|
||||||
String exceptionClass, WasmLocal exceptionVar) {
|
WasmBlock targetBlock) {
|
||||||
if (local != null) {
|
var wasmType = context.classInfoProvider().getClassInfo(tryCatch.getExceptionType()).getType();
|
||||||
WasmExpression exception = new WasmGetLocal(exceptionVar);
|
var wasmSourceType = context.classInfoProvider().getClassInfo("java.lang.Throwable").getType();
|
||||||
if (exceptionClass != null && !exceptionClass.equals("java.lang.Throwable")) {
|
var br = new WasmCastBranch(WasmCastCondition.SUCCESS, new WasmGetLocal(exceptionVar),
|
||||||
exception = new WasmCast(exception, context.classInfoProvider().getClassInfo(exceptionClass)
|
wasmSourceType, wasmType, targetBlock);
|
||||||
.getStructure().getNonNullReference());
|
target.add(br);
|
||||||
}
|
|
||||||
var save = new WasmSetLocal(local, exception);
|
|
||||||
save.setLocation(location);
|
|
||||||
target.add(save);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -30,6 +30,7 @@ public class WasmCastBranch extends WasmExpression {
|
||||||
WasmType.Reference type, WasmBlock target) {
|
WasmType.Reference type, WasmBlock target) {
|
||||||
this.condition = Objects.requireNonNull(condition);
|
this.condition = Objects.requireNonNull(condition);
|
||||||
this.value = Objects.requireNonNull(value);
|
this.value = Objects.requireNonNull(value);
|
||||||
|
this.sourceType = Objects.requireNonNull(sourceType);
|
||||||
this.type = Objects.requireNonNull(type);
|
this.type = Objects.requireNonNull(type);
|
||||||
this.target = Objects.requireNonNull(target);
|
this.target = Objects.requireNonNull(target);
|
||||||
}
|
}
|
||||||
|
|
|
@ -816,9 +816,9 @@ public class CodeParser extends BaseSectionParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseCastBranch(boolean success) {
|
private void parseCastBranch(boolean success) {
|
||||||
|
var flags = reader.data[reader.ptr++];
|
||||||
var depth = readLEB();
|
var depth = readLEB();
|
||||||
var target = blockStack.get(blockStack.size() - depth - 1);
|
var target = blockStack.get(blockStack.size() - depth - 1);
|
||||||
var flags = reader.data[reader.ptr++];
|
|
||||||
var sourceType = reader.readHeapType((flags & 1) != 0);
|
var sourceType = reader.readHeapType((flags & 1) != 0);
|
||||||
var targetType = reader.readHeapType((flags & 2) != 0);
|
var targetType = reader.readHeapType((flags & 2) != 0);
|
||||||
codeListener.castBranch(success, depth, target.token, sourceType, targetType);
|
codeListener.castBranch(success, depth, target.token, sourceType, targetType);
|
||||||
|
|
|
@ -236,7 +236,6 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
writer.writeByte(25);
|
writer.writeByte(25);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
writeLabel(expression.getTarget());
|
|
||||||
var flags = 0;
|
var flags = 0;
|
||||||
if (expression.getSourceType().isNullable()) {
|
if (expression.getSourceType().isNullable()) {
|
||||||
flags |= 1;
|
flags |= 1;
|
||||||
|
@ -245,6 +244,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
||||||
flags |= 2;
|
flags |= 2;
|
||||||
}
|
}
|
||||||
writer.writeByte(flags);
|
writer.writeByte(flags);
|
||||||
|
writeLabel(expression.getTarget());
|
||||||
writer.writeHeapType(expression.getSourceType(), module);
|
writer.writeHeapType(expression.getSourceType(), module);
|
||||||
writer.writeHeapType(expression.getType(), module);
|
writer.writeHeapType(expression.getType(), module);
|
||||||
popLocation();
|
popLocation();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user