From 672de2f111de35df10749fbee272a4ad2306b20d Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Sun, 1 Feb 2015 00:02:20 +0400 Subject: [PATCH] Fix errors. Generalize AST optimizer to handle async methods --- .../java/org/teavm/javascript/Decompiler.java | 12 +++++++++ .../java/org/teavm/javascript/Optimizer.java | 25 +++++++++++++++++++ .../java/org/teavm/javascript/Renderer.java | 2 +- .../model/util/AsyncProgramSplitter.java | 1 + .../resources/org/teavm/javascript/runtime.js | 13 ++++++++++ 5 files changed, 52 insertions(+), 1 deletion(-) 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 8319ae223..f60778ad2 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Decompiler.java @@ -214,6 +214,18 @@ public class Decompiler { part.setStatement(getRegularMethodStatement(splitter.getProgram(i), i, splitter.getBlockSuccessors(i))); node.getBody().add(part); } + Program program = method.getProgram(); + for (int i = 0; i < program.variableCount(); ++i) { + node.getVariables().add(program.variableAt(i).getRegister()); + } + Optimizer optimizer = new Optimizer(); + optimizer.optimize(node, method.getProgram()); + node.getModifiers().addAll(mapModifiers(method.getModifiers())); + int paramCount = Math.min(method.getSignature().length, program.variableCount()); + for (int i = 0; i < paramCount; ++i) { + Variable var = program.variableAt(i); + node.getParameterDebugNames().add(new HashSet<>(var.getDebugNames())); + } return node; } diff --git a/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java b/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java index c5174b0ea..5396e0964 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Optimizer.java @@ -15,6 +15,8 @@ */ package org.teavm.javascript; +import org.teavm.javascript.ast.AsyncMethodNode; +import org.teavm.javascript.ast.AsyncMethodPart; import org.teavm.javascript.ast.RegularMethodNode; import org.teavm.model.Program; @@ -40,4 +42,27 @@ public class Optimizer { method.getVariables().set(i, i); } } + + public void optimize(AsyncMethodNode method, Program program) { + ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); + stats.analyze(program); + OptimizingVisitor optimizer = new OptimizingVisitor(stats); + for (AsyncMethodPart part : method.getBody()) { + part.getStatement().acceptVisitor(optimizer); + part.setStatement(optimizer.resultStmt); + } + int paramCount = method.getReference().parameterCount(); + UnusedVariableEliminator unusedEliminator = new UnusedVariableEliminator(paramCount, method.getVariables()); + for (AsyncMethodPart part : method.getBody()) { + part.getStatement().acceptVisitor(unusedEliminator); + } + method.getVariables().subList(unusedEliminator.lastIndex, method.getVariables().size()).clear(); + RedundantLabelEliminator labelEliminator = new RedundantLabelEliminator(); + for (AsyncMethodPart part : method.getBody()) { + part.getStatement().acceptVisitor(labelEliminator); + } + for (int i = 0; i < method.getVariables().size(); ++i) { + method.getVariables().set(i, i); + } + } } 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 393c63733..fb1d11f8f 100644 --- a/teavm-core/src/main/java/org/teavm/javascript/Renderer.java +++ b/teavm-core/src/main/java/org/teavm/javascript/Renderer.java @@ -1455,7 +1455,7 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext break; } if (expr.getAsyncTarget() != null) { - writer.append(',').ws().append("$part_").append(expr.getAsyncTarget()); + writer.append(',').ws().append("$rt_continue($part_").append(expr.getAsyncTarget()).append(')'); } writer.append(')'); if (lastCallSite != null) { 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 0934da48b..3df6610b3 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 @@ -57,6 +57,7 @@ public class AsyncProgramSplitter { int end = step.sourceIndex; boolean asyncOccured = false; for (int i = step.sourceIndex; i < sourceBlock.getInstructions().size(); ++i) { + end = i; Instruction insn = sourceBlock.getInstructions().get(i); if (insn instanceof InvokeInstruction) { InvokeInstruction invoke = (InvokeInstruction)insn; 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 5845769ec..f839305bc 100644 --- a/teavm-core/src/main/resources/org/teavm/javascript/runtime.js +++ b/teavm-core/src/main/resources/org/teavm/javascript/runtime.js @@ -402,6 +402,19 @@ function $rt_stringPool(strings) { function $rt_s(index) { return $rt_stringPool_instance[index]; } +var $rt_continueCounter = 0; +function $rt_continue(f) { + if ($rt_continueCounter++ == 10) { + $rt_continueCounter = 0; + var self = f; + var args = arguments; + setTimeout(function() { + f.apply(self, args); + }, 0); + } else { + return f; + } +} function $dbg_repr(obj) { return obj.toString ? obj.toString() : "";