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..f6f5f724d 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java +++ b/teavm-core/src/main/java/org/teavm/javascript/NameFrequencyEstimator.java @@ -75,6 +75,12 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me consumer.consume(method.getReference().getDescriptor()); consumer.consume(method.getReference()); } + if (method.isAsync()) { + consumer.consumeFunction("$rt_nativeThread"); + consumer.consumeFunction("$rt_nativeThread"); + consumer.consumeFunction("$rt_resuming"); + consumer.consumeFunction("$rt_invalidPointer"); + } } // Metadata @@ -99,7 +105,6 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me async = true; for (AsyncMethodPart part : methodNode.getBody()) { part.getStatement().acceptVisitor(this); - consumer.consumeFunction("$rt_guardAsync"); } } @@ -113,6 +118,9 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me statement.getLeftValue().acceptVisitor(this); } statement.getRightValue().acceptVisitor(this); + if (statement.isAsync()) { + consumer.consumeFunction("$rt_suspending"); + } } @Override @@ -162,9 +170,6 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me if (statement.getResult() != null) { statement.getResult().acceptVisitor(this); } - if (async) { - consumer.consumeFunction("$rt_asyncResult"); - } } @Override @@ -197,6 +202,7 @@ public class NameFrequencyEstimator implements StatementVisitor, ExprVisitor, Me MethodReference monitorEnterRef = new MethodReference( Object.class, "monitorEnter", Object.class, void.class); consumer.consume(monitorEnterRef); + consumer.consumeFunction("$rt_suspending"); } else { MethodReference monitorEnterRef = new MethodReference( Object.class, "monitorEnterSync", Object.class, void.class); 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 50ef677a2..0e5d7618a 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -261,7 +261,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext private void renderRuntimeAliases() throws IOException { String[] names = { "$rt_throw", "$rt_compare", "$rt_nullCheck", "$rt_cls", "$rt_createArray", - "$rt_isInstance" }; + "$rt_isInstance", "$rt_nativeThread", "$rt_suspending", "$rt_resuming", "$rt_invalidPointer" }; boolean first = true; for (String name : names) { if (!first) { @@ -685,8 +685,8 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext if (hasTryCatch) { variableNames.add("$je"); } - variableNames.add("$ptr"); - variableNames.add("$tmp"); + variableNames.add(pointerName()); + variableNames.add(tempVarName()); if (!variableNames.isEmpty()) { writer.append("var "); for (int i = 0; i < variableNames.size(); ++i) { @@ -703,31 +703,39 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext firstToSave = 1; } - writer.append("$ptr").ws().append('=').ws().append("0;").softNewLine(); - writer.append("if").ws().append("($rt_resuming())").ws().append("{").indent().softNewLine(); - writer.append("var $T").ws().append('=').ws().append("$rt_nativeThread();").softNewLine(); - writer.append("$ptr").ws().append('=').ws().append("$T.pop();"); + String popName = minifying ? "l" : "pop"; + String pushName = minifying ? "s" : "push"; + writer.append(pointerName()).ws().append('=').ws().append("0;").softNewLine(); + writer.append("if").ws().append("(").appendFunction("$rt_resuming").append("())").ws() + .append("{").indent().softNewLine(); + writer.append("var ").append(threadName()).ws().append('=').ws() + .appendFunction("$rt_nativeThread").append("();").softNewLine(); + writer.append(pointerName()).ws().append('=').ws().append(threadName()).append(".") + .append(popName).append("();"); for (int i = variableCount - 1; i >= firstToSave; --i) { - writer.append(variableName(i)).ws().append('=').ws().append("$T.pop();"); + writer.append(variableName(i)).ws().append('=').ws().append(threadName()).append(".") + .append(popName).append("();"); } writer.softNewLine(); writer.outdent().append("}").softNewLine(); - writer.append("$main:").ws().append("while").ws().append("(true)").ws().append("{").ws(); - writer.append("switch").ws().append("($ptr)").ws().append('{').softNewLine(); + writer.append(mainLoopName()).append(":").ws().append("while").ws().append("(true)") + .ws().append("{").ws(); + writer.append("switch").ws().append("(").append(pointerName()).append(")").ws() + .append('{').softNewLine(); for (int i = 0; i < methodNode.getBody().size(); ++i) { writer.append("case ").append(i).append(":").indent().softNewLine(); AsyncMethodPart part = methodNode.getBody().get(i); part.getStatement().acceptVisitor(Renderer.this); writer.outdent(); } - writer.append("default:").ws().append("throw new Error('Invalid recorded state');").softNewLine(); + writer.append("default:").ws().appendFunction("$rt_invalidPointer").append("();").softNewLine(); writer.append("}}").softNewLine(); - writer.append("$rt_nativeThread()"); + writer.appendFunction("$rt_nativeThread").append("().").append(pushName).append("("); for (int i = firstToSave; i < variableCount; ++i) { - writer.append(".push(").append(variableName(i)).append(")"); + writer.append(variableName(i)).append(',').ws(); } - writer.append(".push($ptr);"); + writer.append(pointerName()).append(");"); writer.softNewLine(); } catch (IOException e) { throw new RenderingException("IO error occured", e); @@ -816,7 +824,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext prevCallSite = debugEmitter.emitCallSite(); if (statement.getLeftValue() != null) { if (statement.isAsync()) { - writer.append("$tmp"); + writer.append(tempVarName()); } else { priority = Priority.COMMA; associativity = Associativity.NONE; @@ -835,7 +843,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext priority = Priority.COMMA; associativity = Associativity.NONE; statement.getLeftValue().acceptVisitor(this); - writer.ws().append("=").ws().append("$tmp;").softNewLine(); + writer.ws().append("=").ws().append(tempVarName()).append(";").softNewLine(); } } if (statement.getLocation() != null) { @@ -1132,6 +1140,22 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } } + private String pointerName() { + return minifying ? "$p" : "$ptr"; + } + + private String mainLoopName() { + return minifying ? "$m" : "$main"; + } + + private String tempVarName() { + return minifying ? "$z" : "$tmp"; + } + + private String threadName() { + return minifying ? "$T" : "$thread"; + } + private void visitBinary(BinaryExpr expr, String op, Priority priority, Associativity associativity) { try { if (expr.getLocation() != null) { @@ -1977,9 +2001,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext @Override public void visit(GotoPartStatement statement) { try { - writer.append("$ptr").ws().append("=").ws().append(statement.getPart()).append(";") + writer.append(pointerName()).ws().append("=").ws().append(statement.getPart()).append(";") .softNewLine(); - writer.append("continue $main;").softNewLine(); + writer.append("continue ").append(mainLoopName()).append(";").softNewLine(); } catch (IOException ex){ throw new RenderingException("IO error occured", ex); } @@ -2008,8 +2032,9 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext } private void emitSuspendChecker() throws IOException { - writer.append("if").ws().append("($rt_suspending())").ws().append("{").indent().softNewLine(); - writer.append("break $main;").softNewLine(); + writer.append("if").ws().append("(").appendFunction("$rt_suspending").append("())").ws() + .append("{").indent().softNewLine(); + writer.append("break ").append(mainLoopName()).append(";").softNewLine(); writer.outdent().append("}").softNewLine(); } diff --git a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js index 22823bf23..02dbe2dc1 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -444,13 +444,17 @@ function TeaVMThread(runner) { this.attribute = null; this.completeCallback = null; } -TeaVMThread.prototype.push = function(value) { - this.stack.push(value); +TeaVMThread.prototype.push = function() { + for (var i = 0; i < arguments.length; ++i) { + this.stack.push(arguments[i]); + } return this; } +TeaVMThread.prototype.s = TeaVMThread.prototype.push; TeaVMThread.prototype.pop = function() { return this.stack.pop(); } +TeaVMThread.prototype.l = TeaVMThread.prototype.pop; TeaVMThread.prototype.isResuming = function() { return this.status == 2; } @@ -518,6 +522,9 @@ var $rt_currentNativeThread = null; function $rt_nativeThread() { return $rt_currentNativeThread; } +function $rt_invalidPointer() { + throw new Error("Invalid recorded state"); +} function $dbg_repr(obj) { return obj.toString ? obj.toString() : "";