diff --git a/core/src/main/java/org/teavm/ast/InitClassStatement.java b/core/src/main/java/org/teavm/ast/InitClassStatement.java index 41fd9cde1..e5354ee2c 100644 --- a/core/src/main/java/org/teavm/ast/InitClassStatement.java +++ b/core/src/main/java/org/teavm/ast/InitClassStatement.java @@ -20,6 +20,7 @@ import org.teavm.model.TextLocation; public class InitClassStatement extends Statement { private TextLocation location; private String className; + private boolean async; public String getClassName() { return className; @@ -37,6 +38,14 @@ public class InitClassStatement extends Statement { this.location = location; } + public boolean isAsync() { + return async; + } + + public void setAsync(boolean async) { + this.async = async; + } + @Override public void acceptVisitor(StatementVisitor visitor) { visitor.visit(this); diff --git a/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java b/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java index 927bffc74..c23b9cadc 100644 --- a/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java +++ b/core/src/main/java/org/teavm/ast/decompilation/StatementGenerator.java @@ -328,11 +328,7 @@ class StatementGenerator implements InstructionVisitor { Map> switchMap = new HashMap<>(); for (int i = 0; i < insn.getEntries().size(); ++i) { SwitchTableEntry entry = insn.getEntries().get(i); - List conditions = switchMap.get(entry.getTarget().getIndex()); - if (conditions == null) { - conditions = new ArrayList<>(); - switchMap.put(entry.getTarget().getIndex(), conditions); - } + List conditions = switchMap.computeIfAbsent(entry.getTarget().getIndex(), k -> new ArrayList<>()); conditions.add(entry.getCondition()); } List targets = new ArrayList<>(switchMap.keySet()); @@ -590,6 +586,8 @@ class StatementGenerator implements InstructionVisitor { public void visit(InitClassInstruction insn) { InitClassStatement stmt = Statement.initClass(insn.getClassName()); stmt.setLocation(currentLocation); + stmt.setAsync(async); + async = false; statements.add(stmt); } diff --git a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java index 99a463a71..ba607b3b3 100644 --- a/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java +++ b/core/src/main/java/org/teavm/backend/javascript/rendering/StatementRenderer.java @@ -121,18 +121,10 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor { this.async = async; } - public MethodNode getCurrentMethod() { - return currentMethod; - } - public void setCurrentMethod(MethodNode currentMethod) { this.currentMethod = currentMethod; } - public int getCurrentPart() { - return currentPart; - } - public void setCurrentPart(int currentPart) { this.currentPart = currentPart; } @@ -433,6 +425,9 @@ public class StatementRenderer implements ExprVisitor, StatementVisitor { pushLocation(statement.getLocation()); } writer.appendClass(statement.getClassName()).append("_$callClinit();").softNewLine(); + if (statement.isAsync()) { + emitSuspendChecker(); + } if (statement.getLocation() != null) { popLocation(); } diff --git a/core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java b/core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java index 8ddc6a064..8db3c37c7 100644 --- a/core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java +++ b/core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java @@ -15,17 +15,35 @@ */ package org.teavm.model.util; -import java.util.*; -import org.teavm.common.*; -import org.teavm.model.*; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import org.teavm.common.Graph; +import org.teavm.common.GraphSplittingBackend; +import org.teavm.common.GraphUtils; +import org.teavm.common.IntegerArray; +import org.teavm.model.BasicBlock; +import org.teavm.model.ClassReader; +import org.teavm.model.ClassReaderSource; +import org.teavm.model.Instruction; +import org.teavm.model.MethodDescriptor; +import org.teavm.model.MethodReader; +import org.teavm.model.MethodReference; +import org.teavm.model.Program; +import org.teavm.model.TryCatchBlock; +import org.teavm.model.ValueType; +import org.teavm.model.Variable; +import org.teavm.model.instructions.InitClassInstruction; import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.instructions.JumpInstruction; import org.teavm.model.instructions.MonitorEnterInstruction; -/** - * - * @author Alexey Andreev - */ public class AsyncProgramSplitter { private List parts = new ArrayList<>(); private Map partMap = new HashMap<>(); @@ -68,6 +86,10 @@ public class AsyncProgramSplitter { if (!asyncMethods.contains(findRealMethod(invoke.getMethod()))) { continue; } + } else if (insn instanceof InitClassInstruction) { + if (!isSplittingClassInitializer(((InitClassInstruction) insn).getClassName())) { + continue; + } } else if (!(insn instanceof MonitorEnterInstruction)) { continue; } @@ -164,6 +186,16 @@ public class AsyncProgramSplitter { partMap.clear(); } + private boolean isSplittingClassInitializer(String className) { + ClassReader cls = classSource.get(className); + if (cls == null) { + return false; + } + + MethodReader method = cls.getMethod(new MethodDescriptor("", ValueType.VOID)); + return method != null && asyncMethods.contains(method.getReference()); + } + private MethodReference findRealMethod(MethodReference method) { String clsName = method.getClassName(); while (clsName != null) { @@ -215,10 +247,6 @@ public class AsyncProgramSplitter { return Arrays.copyOf(result, result.length); } - public int getBlockSuccessor(int index, int blockIndex) { - return parts.get(index).blockSuccessors[blockIndex]; - } - public int[] getSplitPoints(int index) { return parts.get(index).splitPoints.clone(); } diff --git a/tests/src/test/java/org/teavm/vm/VMTest.java b/tests/src/test/java/org/teavm/vm/VMTest.java index be749aca3..9765e0887 100644 --- a/tests/src/test/java/org/teavm/vm/VMTest.java +++ b/tests/src/test/java/org/teavm/vm/VMTest.java @@ -121,10 +121,15 @@ public class VMTest { assertEquals(0, initCount); assertEquals("foo", AsyncClinitClass.foo()); assertEquals(1, initCount); - assertEquals(AsyncClinitClass.state, "ok"); + assertEquals("ok", AsyncClinitClass.state); assertEquals("bar", AsyncClinitClass.bar()); assertEquals(1, initCount); - assertEquals(AsyncClinitClass.state, "ok"); + assertEquals("ok", AsyncClinitClass.state); + } + + @Test + public void asyncClinitField() { + assertEquals("ok", AsyncClinitClass.state); } static int initCount = 0;