diff --git a/core/src/main/java/org/teavm/backend/lowlevel/transform/CoroutineTransformation.java b/core/src/main/java/org/teavm/backend/lowlevel/transform/CoroutineTransformation.java index 754746c84..9bdd7bb39 100644 --- a/core/src/main/java/org/teavm/backend/lowlevel/transform/CoroutineTransformation.java +++ b/core/src/main/java/org/teavm/backend/lowlevel/transform/CoroutineTransformation.java @@ -120,8 +120,8 @@ public class CoroutineTransformation { processBlock(program.basicBlockAt(i)); } splitter.fixProgram(); - new PhiUpdater().updatePhis(program, methodReference.parameterCount() + 1); processIrreducibleCfg(); + new PhiUpdater().updatePhis(program, methodReference.parameterCount() + 1); } private void createSplitPrologue() { @@ -475,7 +475,6 @@ public class CoroutineTransformation { weights[i] = program.basicBlockAt(i).instructionCount(); } GraphUtils.splitIrreducibleGraph(graph, weights, splittingBackend); - new PhiUpdater().updatePhis(program, parameterCount + 1); } class SplittingBackend implements GraphSplittingBackend { diff --git a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java index 178f30441..1f33f731d 100644 --- a/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java +++ b/core/src/main/java/org/teavm/backend/wasm/WasmTarget.java @@ -37,6 +37,7 @@ import org.teavm.backend.lowlevel.analyze.LowLevelInliningFilterFactory; import org.teavm.backend.lowlevel.dependency.StringsDependencyListener; import org.teavm.backend.lowlevel.generate.NameProvider; import org.teavm.backend.lowlevel.generate.NameProviderWithSpecialNames; +import org.teavm.backend.lowlevel.transform.CoroutineTransformation; import org.teavm.backend.wasm.binary.BinaryWriter; import org.teavm.backend.wasm.generate.WasmClassGenerator; import org.teavm.backend.wasm.generate.WasmDependencyListener; @@ -154,6 +155,7 @@ import org.teavm.model.optimization.InliningFilterFactory; import org.teavm.model.transformation.BoundCheckInsertion; import org.teavm.model.transformation.ClassPatch; import org.teavm.model.transformation.NullCheckInsertion; +import org.teavm.model.util.AsyncMethodFinder; import org.teavm.runtime.Allocator; import org.teavm.runtime.EventQueue; import org.teavm.runtime.ExceptionHandling; @@ -194,6 +196,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { private int minHeapSize = 2 * 1024 * 1024; private int maxHeapSize = 128 * 1024 * 1024; private boolean obfuscated; + private Set asyncMethods; + private boolean hasThreads; @Override public void setController(TeaVMTargetController controller) { @@ -380,6 +384,16 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { dependencyAnalyzer.addDependencyListener(new StringsDependencyListener()); } + @Override + public void analyzeBeforeOptimizations(ListableClassReaderSource classSource) { + AsyncMethodFinder asyncFinder = new AsyncMethodFinder(controller.getDependencyInfo().getCallGraph(), + controller.getDependencyInfo()); + asyncFinder.find(classSource); + asyncMethods = new HashSet<>(asyncFinder.getAsyncMethods()); + asyncMethods.addAll(asyncFinder.getAsyncFamilyMethods()); + hasThreads = asyncFinder.hasAsyncMethods(); + } + @Override public void beforeOptimizations(Program program, MethodReader method) { nullCheckInsertion.transformProgram(program, method.getReference()); @@ -390,6 +404,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { public void afterOptimizations(Program program, MethodReader method) { classInitializerEliminator.apply(program); classInitializerTransformer.transform(program); + new CoroutineTransformation(controller.getUnprocessedClassSource(), asyncMethods, hasThreads) + .apply(program, method.getReference()); checkTransformation.apply(program, method.getResultType()); shadowStackTransformer.apply(program, method); writeBarrierInsertion.apply(program); @@ -456,7 +472,8 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost { classGenerator, stringPool, obfuscated); context.addIntrinsic(exceptionHandlingIntrinsic); - WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator, binaryWriter); + WasmGenerator generator = new WasmGenerator(decompiler, classes, context, classGenerator, binaryWriter, + asyncMethods::contains); generateMethods(classes, context, generator, classGenerator, binaryWriter, module); new WasmInteropFunctionGenerator(classGenerator).generateFunctions(module); diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java index b0658276d..50231d419 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerationVisitor.java @@ -126,6 +126,14 @@ import org.teavm.runtime.RuntimeClass; import org.teavm.runtime.ShadowStack; class WasmGenerationVisitor implements StatementVisitor, ExprVisitor { + private static final MethodReference MONITOR_ENTER_SYNC = new MethodReference(Object.class, + "monitorEnterSync", Object.class, void.class); + private static final MethodReference MONITOR_EXIT_SYNC = new MethodReference(Object.class, + "monitorExitSync", Object.class, void.class); + private static final MethodReference MONITOR_ENTER = new MethodReference(Object.class, + "monitorEnter", Object.class, void.class); + private static final MethodReference MONITOR_EXIT = new MethodReference(Object.class, + "monitorExit", Object.class, void.class); private static final int SWITCH_TABLE_THRESHOLD = 256; private WasmGenerationContext context; private WasmClassGenerator classGenerator; @@ -140,10 +148,11 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor { private List> temporaryVariablesByType = new ArrayList<>(); private WasmLocal stackVariable; private BinaryWriter binaryWriter; + private boolean async; WasmExpression result; WasmGenerationVisitor(WasmGenerationContext context, WasmClassGenerator classGenerator, - BinaryWriter binaryWriter, WasmFunction function, int firstVariable) { + BinaryWriter binaryWriter, WasmFunction function, int firstVariable, boolean async) { this.context = context; this.classGenerator = classGenerator; this.binaryWriter = binaryWriter; @@ -154,6 +163,7 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor { temporaryVariablesByType.add(new ArrayDeque<>()); } typeInference = new WasmTypeInference(context); + this.async = async; } private void accept(Expr expr) { @@ -1420,12 +1430,20 @@ class WasmGenerationVisitor implements StatementVisitor, ExprVisitor { @Override public void visit(MonitorEnterStatement statement) { - result = emptyStatement(statement.getLocation()); + WasmCall call = new WasmCall(context.names.forMethod(async ? MONITOR_ENTER : MONITOR_ENTER_SYNC)); + call.setLocation(statement.getLocation()); + statement.getObjectRef().acceptVisitor(this); + call.getArguments().add(result); + result = call; } @Override public void visit(MonitorExitStatement statement) { - result = emptyStatement(statement.getLocation()); + WasmCall call = new WasmCall(context.names.forMethod(async ? MONITOR_EXIT : MONITOR_EXIT_SYNC)); + call.setLocation(statement.getLocation()); + statement.getObjectRef().acceptVisitor(this); + call.getArguments().add(result); + result = call; } @Override diff --git a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java index fbc67643f..f81eeeb15 100644 --- a/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java +++ b/core/src/main/java/org/teavm/backend/wasm/generate/WasmGenerator.java @@ -15,6 +15,7 @@ */ package org.teavm.backend.wasm.generate; +import java.util.function.Predicate; import org.teavm.ast.RegularMethodNode; import org.teavm.ast.VariableNode; import org.teavm.ast.decompilation.Decompiler; @@ -40,15 +41,18 @@ public class WasmGenerator { private WasmClassGenerator classGenerator; private BinaryWriter binaryWriter; private NameProvider names; + private Predicate asyncMethods; public WasmGenerator(Decompiler decompiler, ClassHolderSource classSource, - WasmGenerationContext context, WasmClassGenerator classGenerator, BinaryWriter binaryWriter) { + WasmGenerationContext context, WasmClassGenerator classGenerator, BinaryWriter binaryWriter, + Predicate asyncMethods) { this.decompiler = decompiler; this.classSource = classSource; this.context = context; this.classGenerator = classGenerator; this.binaryWriter = binaryWriter; names = classGenerator.names; + this.asyncMethods = asyncMethods; } public WasmFunction generateDefinition(MethodReference methodReference) { @@ -85,7 +89,7 @@ public class WasmGenerator { } WasmGenerationVisitor visitor = new WasmGenerationVisitor(context, classGenerator, binaryWriter, function, - firstVariable); + firstVariable, asyncMethods.test(methodReference)); methodAst.getBody().acceptVisitor(visitor); if (visitor.result instanceof WasmBlock) { ((WasmBlock) visitor.result).setType(function.getResult());