From 73dda91d35002a2a70d6dd0fb5eb552854bb017e Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Sun, 6 Oct 2024 17:29:27 +0200 Subject: [PATCH] wasm gc: minor optimizations; make initializer functions Wasm start function; fix compilation; remove debugging output --- .../backend/wasm/WasmGCModuleGenerator.java | 139 ++---------------- .../backend/wasm/debug/DebugLinesBuilder.java | 6 - .../methods/BaseWasmGenerationVisitor.java | 24 ++- .../gc/methods/WasmGCGenerationVisitor.java | 36 +++-- .../render/WasmBinaryRenderingVisitor.java | 2 +- 5 files changed, 61 insertions(+), 146 deletions(-) diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java b/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java index a84752214..a500fefec 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmGCModuleGenerator.java @@ -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); } } diff --git a/core/src/main/java/org/teavm/backend/wasm/debug/DebugLinesBuilder.java b/core/src/main/java/org/teavm/backend/wasm/debug/DebugLinesBuilder.java index 41759552b..ace0c8249 100644 --- a/core/src/main/java/org/teavm/backend/wasm/debug/DebugLinesBuilder.java +++ b/core/src/main/java/org/teavm/backend/wasm/debug/DebugLinesBuilder.java @@ -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(); diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java index ada6a2c67..9ef03adc9 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/common/methods/BaseWasmGenerationVisitor.java @@ -132,6 +132,7 @@ public abstract class BaseWasmGenerationVisitor implements StatementVisitor, Exp private boolean async; protected WasmExpression result; protected List 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 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 tryCatchStatements, List protectedBody) { var throwableType = mapType(ValueType.object("java.lang.Throwable")); var innerCatchBlock = new WasmBlock(false); + ++blockLevel; var catchBlocks = new ArrayList(); 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 target, 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 a111be046..d77006d35 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 @@ -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 arguments) { diff --git a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java index 5894ceb46..302789f1a 100644 --- a/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/render/WasmBinaryRenderingVisitor.java @@ -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();