diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java index 3fb6b2e9a..376c007ea 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TObject.java @@ -127,7 +127,7 @@ public class TObject { o.monitor.enteringThreads.remove().run(); } } - }); + }, false); } else { o.isEmptyMonitor(); } @@ -203,7 +203,7 @@ public class TObject { while (!listeners.isEmpty()) { NotifyListener listener = listeners.remove(); if (!listener.expired()) { - Platform.startThread(listener); + Platform.startThread(listener, false); break; } } @@ -219,7 +219,7 @@ public class TObject { while (!listeners.isEmpty()) { NotifyListener listener = listeners.remove(); if (!listener.expired()) { - Platform.startThread(listener); + Platform.startThread(listener, false); } } } @@ -279,7 +279,7 @@ public class TObject { @Override public void onTimer() { if (!expired()) { - Platform.startThread(this); + Platform.startThread(this, false); } } diff --git a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java index a635bc045..416a5be0d 100644 --- a/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java +++ b/teavm-classlib/src/main/java/org/teavm/classlib/java/lang/TThread.java @@ -71,7 +71,7 @@ public class TThread extends TObject implements TRunnable { setCurrentThread(mainThread); } } - }); + }, true); } static void setCurrentThread(TThread thread) { @@ -116,7 +116,7 @@ public class TThread extends TObject implements TRunnable { setCurrentThread(thread); callback.complete(null); } - }); + }, false); } private static void yieldImpl() { diff --git a/teavm-core/src/main/java/org/teavm/cache/AstIO.java b/teavm-core/src/main/java/org/teavm/cache/AstIO.java index b1ead2777..78264c5ba 100644 --- a/teavm-core/src/main/java/org/teavm/cache/AstIO.java +++ b/teavm-core/src/main/java/org/teavm/cache/AstIO.java @@ -315,10 +315,18 @@ public class AstIO { } @Override - public void visit(MonitorEnterStatement statement) { + public void visit(SaveStatement statement) { try { output.writeByte(18); - output.writeShort(statement.getAsyncTarget() != null ? 0 : statement.getAsyncTarget()); + } catch (IOException e) { + throw new IOExceptionWrapper(e); + } + } + + @Override + public void visit(MonitorEnterStatement statement) { + try { + output.writeByte(19); writeExpr(statement.getObjectRef()); } catch (IOException e) { throw new IOExceptionWrapper(e); @@ -328,7 +336,7 @@ public class AstIO { @Override public void visit(MonitorExitStatement statement) { try { - output.writeByte(19); + output.writeByte(20); writeExpr(statement.getObjectRef()); } catch (IOException e) { throw new IOExceptionWrapper(e); diff --git a/teavm-core/src/main/java/org/teavm/cache/DiskRegularMethodNodeCache.java b/teavm-core/src/main/java/org/teavm/cache/DiskRegularMethodNodeCache.java index bb6d058e0..a08e16bfd 100644 --- a/teavm-core/src/main/java/org/teavm/cache/DiskRegularMethodNodeCache.java +++ b/teavm-core/src/main/java/org/teavm/cache/DiskRegularMethodNodeCache.java @@ -262,6 +262,10 @@ public class DiskRegularMethodNodeCache implements RegularMethodNodeCache { public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { diff --git a/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java b/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java index f80c3f981..6e17963fb 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/BreakToContinueReplacer.java @@ -117,6 +117,10 @@ class BreakToContinueReplacer implements StatementVisitor { public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { } diff --git a/teavm-core/src/main/java/org/teavm/javascript/CertainBlockCountVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/CertainBlockCountVisitor.java index 11702da38..7892d98b4 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/CertainBlockCountVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/CertainBlockCountVisitor.java @@ -112,6 +112,10 @@ class CertainBlockCountVisitor implements StatementVisitor { public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java index 88c3745fb..40ad05685 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java @@ -22,6 +22,7 @@ import org.teavm.javascript.spi.GeneratedBy; import org.teavm.javascript.spi.Generator; import org.teavm.javascript.spi.InjectedBy; import org.teavm.model.*; +import org.teavm.model.instructions.InvokeInstruction; import org.teavm.model.util.AsyncProgramSplitter; import org.teavm.model.util.ProgramUtils; @@ -294,7 +295,6 @@ public class Decompiler { int tmp = indexer.nodeAt(next); generator.nextBlock = tmp >= 0 && next < indexer.size() ? program.basicBlockAt(tmp) : null; generator.statements.clear(); - generator.asyncTarget = null; InstructionLocation lastLocation = null; NodeLocation nodeLocation = null; List instructions = generator.currentBlock.getInstructions(); @@ -307,11 +307,17 @@ public class Decompiler { if (insn.getLocation() != null) { generator.setCurrentLocation(nodeLocation); } - if (targetBlocks[node] >= 0 && j == instructions.size() - 1) { - generator.asyncTarget = targetBlocks[node]; - } insn.acceptVisitor(generator); + if (j == 0 && insn instanceof InvokeInstruction) { + generator.statements.add(new SaveStatement()); + } } + if (targetBlocks[node] >= 0) { + GotoPartStatement stmt = new GotoPartStatement(); + stmt.setPart(targetBlocks[node]); + generator.statements.add(stmt); + } + for (TryCatchBlock tryCatch : generator.currentBlock.getTryCatchBlocks()) { TryCatchStatement tryCatchStmt = new TryCatchStatement(); tryCatchStmt.setExceptionType(tryCatch.getExceptionType()); diff --git a/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java b/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java index fdfade618..20773208e 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java @@ -191,6 +191,10 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { if (async) { diff --git a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java index f155919c4..eb9369618 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/OptimizingVisitor.java @@ -619,6 +619,11 @@ class OptimizingVisitor implements StatementVisitor, ExprVisitor { resultStmt = statement; } + @Override + public void visit(SaveStatement statement) { + resultStmt = statement; + } + @Override public void visit(MonitorEnterStatement statement) { statement.getObjectRef().acceptVisitor(this); diff --git a/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java index c0d240ebd..25c8bd389 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/RedundantLabelEliminator.java @@ -122,6 +122,10 @@ class RedundantLabelEliminator implements StatementVisitor { public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java index 031ca7d2a..d9714e86b 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ReferenceCountingVisitor.java @@ -116,6 +116,10 @@ class ReferenceCountingVisitor implements StatementVisitor { public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java index 78abe9d5a..f5faaeeb3 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -716,6 +716,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.softNewLine(); writer.outdent().append("}").softNewLine(); + writer.append("while").ws().append("(true)").ws().append("{").indent().softNewLine(); writer.append("$main: switch").ws().append("($ptr)").ws().append('{').softNewLine(); for (int i = 0; i < methodNode.getBody().size(); ++i) { writer.append("case ").append(i).append(":").indent().softNewLine(); @@ -724,6 +725,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.outdent(); } writer.append("}").softNewLine(); + writer.outdent().append("}").softNewLine(); } catch (IOException e) { throw new RenderingException("IO error occured", e); } @@ -1956,23 +1958,26 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } } - @Override public void visit(GotoPartStatement statement) { try { - gotoPart(statement.getPart()); + writer.append("$ptr").ws().append("=").ws().append(statement.getPart()).append(";") + .softNewLine(); + writer.append("break $main;").softNewLine(); } catch (IOException ex){ throw new RenderingException("IO error occured", ex); } } - private void gotoPart(int part) throws IOException { - writer.append("$ptr").ws().append("=").ws().append(part).append(";") - .softNewLine(); - writer.append("if").ws().append("($rt_suspending())").ws().append("{").indent().softNewLine(); - writer.append("return $save();").softNewLine(); - writer.outdent().append("}").softNewLine(); - writer.append("break $main;").softNewLine(); + @Override + public void visit(SaveStatement statement) { + try { + writer.append("if").ws().append("($rt_suspending())").ws().append("{").indent().softNewLine(); + writer.append("return $save();").softNewLine(); + writer.outdent().append("}").softNewLine(); + } catch (IOException ex){ + throw new RenderingException("IO error occured", ex); + } } @Override @@ -1984,9 +1989,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext writer.appendMethodBody(monitorEnterRef).append("("); statement.getObjectRef().acceptVisitor(this); writer.append(");").softNewLine(); - if (statement.getAsyncTarget() != null) { - gotoPart(statement.getAsyncTarget()); - } + writer.append("if").ws().append("($rt_suspending())").ws().append("{").indent().softNewLine(); + writer.append("return $save();").softNewLine(); + writer.outdent().append("}").softNewLine(); } else { MethodReference monitorEnterRef = new MethodReference( Object.class, "monitorEnterSync", Object.class, void.class); diff --git a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java index 604bb2f3c..4b9665225 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/StatementGenerator.java @@ -37,7 +37,6 @@ class StatementGenerator implements InstructionVisitor { Program program; ClassHolderSource classSource; private NodeLocation currentLocation; - Integer asyncTarget; public void setCurrentLocation(NodeLocation currentLocation) { this.currentLocation = currentLocation; @@ -557,11 +556,6 @@ class StatementGenerator implements InstructionVisitor { stmt.setLocation(currentLocation); statements.add(stmt); } - if (asyncTarget != null) { - GotoPartStatement gotoStmt = new GotoPartStatement(); - gotoStmt.setPart(asyncTarget); - statements.add(gotoStmt); - } } @Override @@ -662,7 +656,6 @@ class StatementGenerator implements InstructionVisitor { MonitorEnterStatement stmt = new MonitorEnterStatement(); stmt.setLocation(currentLocation); stmt.setObjectRef(Expr.var(insn.getObjectRef().getIndex())); - stmt.setAsyncTarget(asyncTarget); statements.add(stmt); } diff --git a/teavm-core/src/main/java/org/teavm/javascript/TryCatchFinder.java b/teavm-core/src/main/java/org/teavm/javascript/TryCatchFinder.java index 6bc07c4f0..3f65ad2b8 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/TryCatchFinder.java +++ b/teavm-core/src/main/java/org/teavm/javascript/TryCatchFinder.java @@ -115,6 +115,10 @@ class TryCatchFinder implements StatementVisitor { public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { } diff --git a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java index 82c00b82a..b828f31b5 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/UnusedVariableEliminator.java @@ -229,6 +229,10 @@ class UnusedVariableEliminator implements ExprVisitor, StatementVisitor { public void visit(GotoPartStatement statement) { } + @Override + public void visit(SaveStatement statement) { + } + @Override public void visit(MonitorEnterStatement statement) { statement.getObjectRef().acceptVisitor(this); diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/MonitorEnterStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/MonitorEnterStatement.java index 476d7820a..a7479337f 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/MonitorEnterStatement.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/MonitorEnterStatement.java @@ -22,7 +22,6 @@ package org.teavm.javascript.ast; public class MonitorEnterStatement extends Statement { private NodeLocation location; private Expr objectRef; - private Integer asyncTarget; @Override public void acceptVisitor(StatementVisitor visitor) { @@ -44,12 +43,4 @@ public class MonitorEnterStatement extends Statement { public void setObjectRef(Expr objectRef) { this.objectRef = objectRef; } - - public Integer getAsyncTarget() { - return asyncTarget; - } - - public void setAsyncTarget(Integer asyncTarget) { - this.asyncTarget = asyncTarget; - } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java index 1bb1cfccd..db5e26719 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/RenamingVisitor.java @@ -197,12 +197,14 @@ public class RenamingVisitor implements StatementVisitor, ExprVisitor { } @Override - public void visit(MonitorEnterStatement statement) { + public void visit(SaveStatement statement) { + } + @Override + public void visit(MonitorEnterStatement statement) { } @Override public void visit(MonitorExitStatement statement) { - } } diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/SaveStatement.java b/teavm-core/src/main/java/org/teavm/javascript/ast/SaveStatement.java new file mode 100644 index 000000000..8e8c955b1 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/SaveStatement.java @@ -0,0 +1,27 @@ +/* + * Copyright 2015 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.javascript.ast; + +/** + * + * @author Alexey Andreev + */ +public class SaveStatement extends Statement { + @Override + public void acceptVisitor(StatementVisitor visitor) { + visitor.visit(this); + } +} diff --git a/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java b/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java index 7194cdb4e..7c4f6cf9b 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java +++ b/teavm-core/src/main/java/org/teavm/javascript/ast/StatementVisitor.java @@ -49,4 +49,6 @@ public interface StatementVisitor { void visit(MonitorEnterStatement statement); void visit(MonitorExitStatement statement); + + void visit(SaveStatement statement); } diff --git a/teavm-core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java b/teavm-core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java index 81d174be4..e3b3ccde0 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java +++ b/teavm-core/src/main/java/org/teavm/model/util/AsyncProgramSplitter.java @@ -74,7 +74,7 @@ public class AsyncProgramSplitter { // If we met asynchronous invocation... // Copy portion of current block from last occurrence (or from start) to i'th instruction. targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock, - last, i + 1, targetBlock.getProgram())); + last, i, targetBlock.getProgram())); targetBlock.getTryCatchBlocks().addAll(ProgramUtils.copyTryCatches(sourceBlock, targetBlock.getProgram())); for (TryCatchBlock tryCatch : targetBlock.getTryCatchBlocks()) { @@ -85,7 +85,7 @@ public class AsyncProgramSplitter { queue.add(next); } } - last = i + 1; + last = i; // If this instruction already separates program, end with current block and refer to the // existing part diff --git a/teavm-platform/src/main/java/org/teavm/platform/Platform.java b/teavm-platform/src/main/java/org/teavm/platform/Platform.java index cbf6fe506..749b9d0b5 100644 --- a/teavm-platform/src/main/java/org/teavm/platform/Platform.java +++ b/teavm-platform/src/main/java/org/teavm/platform/Platform.java @@ -107,7 +107,7 @@ public final class Platform { @GeneratedBy(PlatformGenerator.class) @PluggableDependency(PlatformGenerator.class) - public static native void startThread(PlatformRunnable runnable); + public static native void startThread(PlatformRunnable runnable, boolean newNativeThread); private static void launchThread(PlatformRunnable runnable) { runnable.run();