mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 00:04:10 -08:00
wasm gc: minor optimizations; make initializer functions Wasm start function; fix compilation; remove debugging output
This commit is contained in:
parent
f95250ddf7
commit
73dda91d35
|
@ -17,17 +17,6 @@ package org.teavm.backend.wasm;
|
|||
|
||||
import org.teavm.backend.wasm.generate.gc.WasmGCDeclarationsGenerator;
|
||||
import org.teavm.backend.wasm.model.WasmFunction;
|
||||
import org.teavm.backend.wasm.model.WasmGlobal;
|
||||
import org.teavm.backend.wasm.model.WasmLocal;
|
||||
import org.teavm.backend.wasm.model.WasmType;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCall;
|
||||
import org.teavm.backend.wasm.model.expression.WasmCallReference;
|
||||
import org.teavm.backend.wasm.model.expression.WasmDrop;
|
||||
import org.teavm.backend.wasm.model.expression.WasmExpression;
|
||||
import org.teavm.backend.wasm.model.expression.WasmFunctionReference;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetGlobal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmGetLocal;
|
||||
import org.teavm.backend.wasm.model.expression.WasmSetGlobal;
|
||||
import org.teavm.backend.wasm.runtime.StringInternPool;
|
||||
import org.teavm.backend.wasm.runtime.gc.WasmGCSupport;
|
||||
import org.teavm.model.MethodReference;
|
||||
|
@ -35,8 +24,6 @@ import org.teavm.model.ValueType;
|
|||
|
||||
public class WasmGCModuleGenerator {
|
||||
private WasmGCDeclarationsGenerator declarationsGenerator;
|
||||
private WasmFunction initializer;
|
||||
private WasmGlobal initializerRef;
|
||||
|
||||
public WasmGCModuleGenerator(WasmGCDeclarationsGenerator declarationsGenerator) {
|
||||
this.declarationsGenerator = declarationsGenerator;
|
||||
|
@ -44,166 +31,66 @@ public class WasmGCModuleGenerator {
|
|||
|
||||
public void generate() {
|
||||
declarationsGenerator.generate();
|
||||
if (initializer != null) {
|
||||
fillInitializer();
|
||||
}
|
||||
createInitializer();
|
||||
}
|
||||
|
||||
private void fillInitializer() {
|
||||
declarationsGenerator.contributeToInitializer(initializer);
|
||||
}
|
||||
|
||||
public WasmFunction generateMainFunction(String entryPoint) {
|
||||
var mainFunction = declarationsGenerator.functions().forStaticMethod(new MethodReference(entryPoint,
|
||||
return declarationsGenerator.functions().forStaticMethod(new MethodReference(entryPoint,
|
||||
"main", ValueType.parse(String[].class), ValueType.VOID));
|
||||
var stringArrayType = declarationsGenerator.typeMapper()
|
||||
.mapType(ValueType.parse(String[].class));
|
||||
var mainFunctionCaller = new WasmFunction(declarationsGenerator.functionTypes.of(null, stringArrayType));
|
||||
var argsLocal = new WasmLocal(stringArrayType, "args");
|
||||
declarationsGenerator.module.functions.add(mainFunctionCaller);
|
||||
mainFunctionCaller.getBody().add(callInitializer());
|
||||
|
||||
var callToMainFunction = new WasmCall(mainFunction, new WasmGetLocal(argsLocal));
|
||||
mainFunctionCaller.getBody().add(callToMainFunction);
|
||||
|
||||
return mainFunctionCaller;
|
||||
}
|
||||
|
||||
public WasmFunction generateCreateStringBuilderFunction() {
|
||||
var function = declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
WasmGCSupport.class, "createStringBuilder", StringBuilder.class));
|
||||
var caller = new WasmFunction(function.getType());
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmCall(function));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
public WasmFunction generateCreateStringArrayFunction() {
|
||||
var function = declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
WasmGCSupport.class, "createStringArray", int.class, String[].class));
|
||||
var caller = new WasmFunction(function.getType());
|
||||
var sizeLocal = new WasmLocal(WasmType.INT32, "length");
|
||||
caller.add(sizeLocal);
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmCall(function, new WasmGetLocal(sizeLocal)));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
public WasmFunction generateAppendCharFunction() {
|
||||
var function = declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
StringBuilder.class, "append", char.class, StringBuilder.class));
|
||||
var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class));
|
||||
var caller = new WasmFunction(declarationsGenerator.functionTypes.of(null, stringBuilderType, WasmType.INT32));
|
||||
var stringBuilderLocal = new WasmLocal(stringBuilderType, "stringBuilder");
|
||||
var codeLocal = new WasmLocal(WasmType.INT32, "charCode");
|
||||
caller.add(stringBuilderLocal);
|
||||
caller.add(codeLocal);
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmDrop(new WasmCall(function, new WasmGetLocal(stringBuilderLocal),
|
||||
new WasmGetLocal(codeLocal))));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
public WasmFunction generateBuildStringFunction() {
|
||||
var function = declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
StringBuilder.class, "toString", String.class));
|
||||
var stringBuilderType = declarationsGenerator.typeMapper().mapType(ValueType.parse(StringBuilder.class));
|
||||
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
|
||||
var caller = new WasmFunction(declarationsGenerator.functionTypes.of(stringType, stringBuilderType));
|
||||
var stringBuilderLocal = new WasmLocal(stringBuilderType, "stringBuilder");
|
||||
caller.add(stringBuilderLocal);
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmCall(function, new WasmGetLocal(stringBuilderLocal)));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
public WasmFunction generateSetToStringArrayFunction() {
|
||||
var function = declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
WasmGCSupport.class, "setToStringArray", String[].class, int.class, String.class, void.class));
|
||||
var stringArrayType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String[].class));
|
||||
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
|
||||
var caller = new WasmFunction(function.getType());
|
||||
var arrayLocal = new WasmLocal(stringArrayType, "array");
|
||||
var indexLocal = new WasmLocal(WasmType.INT32, "index");
|
||||
var valueLocal = new WasmLocal(stringType, "string");
|
||||
caller.add(arrayLocal);
|
||||
caller.add(indexLocal);
|
||||
caller.add(valueLocal);
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmCall(function, new WasmGetLocal(arrayLocal),
|
||||
new WasmGetLocal(indexLocal), new WasmGetLocal(valueLocal)));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
public WasmFunction generateStringLengthFunction() {
|
||||
var function = declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
String.class, "length", int.class));
|
||||
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
|
||||
var caller = new WasmFunction(function.getType());
|
||||
var stringLocal = new WasmLocal(stringType, "string");
|
||||
caller.add(stringLocal);
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmCall(function, new WasmGetLocal(stringLocal)));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
public WasmFunction generateCharAtFunction() {
|
||||
var function = declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forInstanceMethod(new MethodReference(
|
||||
String.class, "charAt", int.class, char.class));
|
||||
var stringType = declarationsGenerator.typeMapper().mapType(ValueType.parse(String.class));
|
||||
var caller = new WasmFunction(function.getType());
|
||||
var stringLocal = new WasmLocal(stringType, "string");
|
||||
var indexLocal = new WasmLocal(WasmType.INT32, "index");
|
||||
caller.add(stringLocal);
|
||||
caller.add(indexLocal);
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmCall(function, new WasmGetLocal(stringLocal),
|
||||
new WasmGetLocal(indexLocal)));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
public WasmFunction generateReportGarbageCollectedStringFunction() {
|
||||
var entryType = ValueType.object(StringInternPool.class.getName() + "$Entry");
|
||||
var function = declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
return declarationsGenerator.functions().forStaticMethod(new MethodReference(
|
||||
StringInternPool.class.getName(),
|
||||
"remove",
|
||||
entryType,
|
||||
ValueType.VOID
|
||||
));
|
||||
var caller = new WasmFunction(function.getType());
|
||||
var entryLocal = new WasmLocal(declarationsGenerator.typeMapper().mapType(entryType));
|
||||
caller.add(entryLocal);
|
||||
caller.getBody().add(callInitializer());
|
||||
caller.getBody().add(new WasmCall(function, new WasmGetLocal(entryLocal)));
|
||||
declarationsGenerator.module.functions.add(caller);
|
||||
return caller;
|
||||
}
|
||||
|
||||
private void createInitializer() {
|
||||
if (initializer != null) {
|
||||
return;
|
||||
}
|
||||
var functionType = declarationsGenerator.functionTypes.of(null);
|
||||
initializer = new WasmFunction(functionType);
|
||||
initializer.setReferenced(true);
|
||||
var initializer = new WasmFunction(functionType);
|
||||
initializer.setName("teavm@initializer");
|
||||
declarationsGenerator.module.functions.add(initializer);
|
||||
initializerRef = new WasmGlobal("teavm@initializerRef", functionType.getNonNullReference(),
|
||||
new WasmFunctionReference(initializer));
|
||||
declarationsGenerator.module.globals.add(initializerRef);
|
||||
initializer.getBody().add(new WasmSetGlobal(initializerRef,
|
||||
new WasmFunctionReference(declarationsGenerator.dummyInitializer())));
|
||||
}
|
||||
|
||||
private WasmExpression callInitializer() {
|
||||
createInitializer();
|
||||
return new WasmCallReference(new WasmGetGlobal(initializerRef), declarationsGenerator.functionTypes.of(null));
|
||||
declarationsGenerator.module.setStartFunction(initializer);
|
||||
declarationsGenerator.contributeToInitializer(initializer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,7 +48,6 @@ public class DebugLinesBuilder extends DebugSectionBuilder implements DebugLines
|
|||
public void location(String file, int line) {
|
||||
if (Objects.equals(file, this.file) && this.ptr != lastWrittenPtr && this.line != line) {
|
||||
if (this.ptr - lastWrittenPtr < 32 && Math.abs(line - this.line) <= 3) {
|
||||
System.out.println(blob.ptr() + indent.toString() + "[user] ptr: " + this.ptr + ", line: " + line);
|
||||
blob.writeByte(DebugConstants.LOC_USER + (this.ptr - lastWrittenPtr) + 32 * (line - this.line + 3));
|
||||
this.line = line;
|
||||
lastWrittenPtr = ptr;
|
||||
|
@ -59,12 +58,10 @@ public class DebugLinesBuilder extends DebugSectionBuilder implements DebugLines
|
|||
flushPtr();
|
||||
this.line = 1;
|
||||
this.file = file;
|
||||
System.out.println(blob.ptr() + indent.toString() + "[file] " + file);
|
||||
blob.writeByte(DebugConstants.LOC_FILE).writeLEB(file != null ? files.filePtr(file) : 0);
|
||||
}
|
||||
if (this.line != line) {
|
||||
flushPtr();
|
||||
System.out.println(blob.ptr() + indent.toString() + "[line] " + line);
|
||||
blob.writeByte(DebugConstants.LOC_LINE).writeSLEB(line - this.line);
|
||||
this.line = line;
|
||||
}
|
||||
|
@ -77,7 +74,6 @@ public class DebugLinesBuilder extends DebugSectionBuilder implements DebugLines
|
|||
|
||||
private void flushPtr() {
|
||||
if (ptr != lastWrittenPtr) {
|
||||
System.out.println(blob.ptr() + indent.toString() + "[ptr] " + ptr);
|
||||
blob.writeLEB(DebugConstants.LOC_PTR);
|
||||
blob.writeLEB(ptr - lastWrittenPtr);
|
||||
lastWrittenPtr = ptr;
|
||||
|
@ -87,7 +83,6 @@ public class DebugLinesBuilder extends DebugSectionBuilder implements DebugLines
|
|||
@Override
|
||||
public void start(MethodReference methodReference) {
|
||||
flushPtr();
|
||||
System.out.println(blob.ptr() + indent.toString() + "[start] method: " + methodReference);
|
||||
indent.append(".");
|
||||
blob.writeLEB(DebugConstants.LOC_START);
|
||||
blob.writeLEB(methods.methodPtr(methodReference));
|
||||
|
@ -100,7 +95,6 @@ public class DebugLinesBuilder extends DebugSectionBuilder implements DebugLines
|
|||
public void end() {
|
||||
flushPtr();
|
||||
indent.setLength(indent.length() - 1);
|
||||
System.out.println(blob.ptr() + indent.toString() + "[end]");
|
||||
blob.writeLEB(DebugConstants.LOC_END);
|
||||
if (!states.isEmpty()) {
|
||||
var state = states.pop();
|
||||
|
|
|
@ -132,6 +132,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
private boolean async;
|
||||
protected WasmExpression result;
|
||||
protected List<WasmExpression> resultConsumer;
|
||||
protected int blockLevel;
|
||||
|
||||
public BaseWasmGenerationVisitor(BaseWasmGenerationContext context, MethodReference currentMethod,
|
||||
WasmFunction function, int firstVariable, boolean async) {
|
||||
|
@ -591,9 +592,11 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
@Override
|
||||
public void visit(ConditionalStatement statement) {
|
||||
accept(statement.getCondition());
|
||||
++blockLevel;
|
||||
var conditional = new WasmConditional(forCondition(result));
|
||||
visitMany(statement.getConsequent(), conditional.getThenBlock().getBody());
|
||||
visitMany(statement.getAlternative(), conditional.getElseBlock().getBody());
|
||||
--blockLevel;
|
||||
resultConsumer.add(conditional);
|
||||
}
|
||||
|
||||
|
@ -616,6 +619,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
.max().orElse(0);
|
||||
|
||||
var defaultBlock = new WasmBlock(false);
|
||||
++blockLevel;
|
||||
breakTargets.put(statement, defaultBlock);
|
||||
var oldBreakTarget = currentBreakTarget;
|
||||
currentBreakTarget = statement;
|
||||
|
@ -651,6 +655,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
breakTargets.remove(statement);
|
||||
currentBreakTarget = oldBreakTarget;
|
||||
|
||||
--blockLevel;
|
||||
resultConsumer.add(wrapper);
|
||||
}
|
||||
|
||||
|
@ -738,6 +743,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
var wrapper = new WasmBlock(false);
|
||||
var loop = new WasmBlock(true);
|
||||
|
||||
++blockLevel;
|
||||
continueTargets.put(statement, loop);
|
||||
breakTargets.put(statement, wrapper);
|
||||
var oldBreakTarget = currentBreakTarget;
|
||||
|
@ -765,6 +771,8 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
} else {
|
||||
resultConsumer.add(loop);
|
||||
}
|
||||
|
||||
--blockLevel;
|
||||
}
|
||||
|
||||
protected WasmExpression invocation(InvocationExpr expr, List<WasmExpression> resultConsumer, boolean willDrop) {
|
||||
|
@ -957,6 +965,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
@Override
|
||||
public void visit(BlockStatement statement) {
|
||||
var block = new WasmBlock(false);
|
||||
++blockLevel;
|
||||
|
||||
if (statement.getId() != null) {
|
||||
breakTargets.put(statement, block);
|
||||
|
@ -969,6 +978,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
}
|
||||
|
||||
resultConsumer.add(block);
|
||||
--blockLevel;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1053,9 +1063,15 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
} else {
|
||||
result = null;
|
||||
}
|
||||
var wasmStatement = new WasmReturn(result);
|
||||
wasmStatement.setLocation(statement.getLocation());
|
||||
resultConsumer.add(wasmStatement);
|
||||
if (blockLevel == 0) {
|
||||
if (result != null) {
|
||||
resultConsumer.add(result);
|
||||
}
|
||||
} else {
|
||||
var wasmStatement = new WasmReturn(result);
|
||||
wasmStatement.setLocation(statement.getLocation());
|
||||
resultConsumer.add(wasmStatement);
|
||||
}
|
||||
}
|
||||
|
||||
protected WasmExpression forceType(WasmExpression expression, ValueType type) {
|
||||
|
@ -1181,6 +1197,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
protected void generateTry(List<TryCatchStatement> tryCatchStatements, List<Statement> protectedBody) {
|
||||
var throwableType = mapType(ValueType.object("java.lang.Throwable"));
|
||||
var innerCatchBlock = new WasmBlock(false);
|
||||
++blockLevel;
|
||||
|
||||
var catchBlocks = new ArrayList<WasmBlock>();
|
||||
for (int i = 0; i < tryCatchStatements.size(); ++i) {
|
||||
|
@ -1247,6 +1264,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp
|
|||
|
||||
resultConsumer.add(outerCatchBlock);
|
||||
tempVars.release(exceptionVar);
|
||||
--blockLevel;
|
||||
}
|
||||
|
||||
protected void checkExceptionType(TryCatchStatement tryCatch, WasmLocal exceptionVar, List<WasmExpression> target,
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.teavm.ast.ArrayType;
|
|||
import org.teavm.ast.BinaryExpr;
|
||||
import org.teavm.ast.CastExpr;
|
||||
import org.teavm.ast.ConditionalExpr;
|
||||
import org.teavm.ast.ConstantExpr;
|
||||
import org.teavm.ast.Expr;
|
||||
import org.teavm.ast.InstanceOfExpr;
|
||||
import org.teavm.ast.InvocationExpr;
|
||||
|
@ -281,20 +282,12 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
if (expr.getType() == null) {
|
||||
switch (expr.getOperation()) {
|
||||
case EQUALS: {
|
||||
accept(expr.getFirstOperand());
|
||||
var first = result;
|
||||
accept(expr.getSecondOperand());
|
||||
var second = result;
|
||||
result = new WasmReferencesEqual(first, second);
|
||||
isReferenceEq(expr);
|
||||
result.setLocation(expr.getLocation());
|
||||
return;
|
||||
}
|
||||
case NOT_EQUALS:
|
||||
accept(expr.getFirstOperand());
|
||||
var first = result;
|
||||
accept(expr.getSecondOperand());
|
||||
var second = result;
|
||||
result = new WasmReferencesEqual(first, second);
|
||||
isReferenceEq(expr);
|
||||
result = new WasmIntUnary(WasmIntType.INT32, WasmIntUnaryOperation.EQZ, result);
|
||||
result.setLocation(expr.getLocation());
|
||||
return;
|
||||
|
@ -305,6 +298,29 @@ public class WasmGCGenerationVisitor extends BaseWasmGenerationVisitor {
|
|||
super.visit(expr);
|
||||
}
|
||||
|
||||
private void isReferenceEq(BinaryExpr expr) {
|
||||
if (isNull(expr.getFirstOperand())) {
|
||||
accept(expr.getSecondOperand());
|
||||
result = new WasmIsNull(result);
|
||||
} else if (isNull(expr.getSecondOperand())) {
|
||||
accept(expr.getFirstOperand());
|
||||
result = new WasmIsNull(result);
|
||||
} else {
|
||||
accept(expr.getFirstOperand());
|
||||
var first = result;
|
||||
accept(expr.getSecondOperand());
|
||||
var second = result;
|
||||
result = new WasmReferencesEqual(first, second);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNull(Expr expr) {
|
||||
if (!(expr instanceof ConstantExpr)) {
|
||||
return false;
|
||||
}
|
||||
return ((ConstantExpr) expr).getValue() == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WasmExpression generateVirtualCall(WasmLocal instance, MethodReference method,
|
||||
List<WasmExpression> arguments) {
|
||||
|
|
|
@ -1406,7 +1406,7 @@ class WasmBinaryRenderingVisitor implements WasmExpressionVisitor {
|
|||
if (debugLines != null) {
|
||||
debugLines.advance(writer.getPosition() + addressOffset);
|
||||
while (!methodStack.isEmpty()) {
|
||||
methodStack.removeLast();
|
||||
methodStack.remove(methodStack.size() - 1);
|
||||
debugLines.end();
|
||||
}
|
||||
debugLines.end();
|
||||
|
|
Loading…
Reference in New Issue
Block a user