Return back AST optimization of async methods.

This commit is contained in:
konsoletyper 2015-02-06 00:53:51 +04:00
parent 73721e5b31
commit 5dfc8a3ed6
6 changed files with 38 additions and 29 deletions

View File

@ -202,7 +202,6 @@ public class Decompiler {
AsyncMethodNode node = new AsyncMethodNode(method.getReference()); AsyncMethodNode node = new AsyncMethodNode(method.getReference());
AsyncProgramSplitter splitter = new AsyncProgramSplitter(asyncMethods); AsyncProgramSplitter splitter = new AsyncProgramSplitter(asyncMethods);
splitter.split(method.getProgram()); splitter.split(method.getProgram());
List<Program> partPrograms = new ArrayList<>();
for (int i = 0; i < splitter.size(); ++i) { for (int i = 0; i < splitter.size(); ++i) {
Integer input = null; Integer input = null;
if (i > 0) { if (i > 0) {
@ -214,14 +213,13 @@ public class Decompiler {
AsyncMethodPart part = getRegularMethodStatement(splitter.getProgram(i), splitter.getBlockSuccessors(i), AsyncMethodPart part = getRegularMethodStatement(splitter.getProgram(i), splitter.getBlockSuccessors(i),
input); input);
node.getBody().add(part); node.getBody().add(part);
partPrograms.add(splitter.getProgram(i));
} }
Program program = method.getProgram(); Program program = method.getProgram();
for (int i = 0; i < program.variableCount(); ++i) { for (int i = 0; i < program.variableCount(); ++i) {
node.getVariables().add(program.variableAt(i).getRegister()); node.getVariables().add(program.variableAt(i).getRegister());
} }
Optimizer optimizer = new Optimizer(); Optimizer optimizer = new Optimizer();
optimizer.optimize(node, partPrograms); optimizer.optimize(node, program, splitter);
node.getModifiers().addAll(mapModifiers(method.getModifiers())); node.getModifiers().addAll(mapModifiers(method.getModifiers()));
int paramCount = Math.min(method.getSignature().length, program.variableCount()); int paramCount = Math.min(method.getSignature().length, program.variableCount());
for (int i = 0; i < paramCount; ++i) { for (int i = 0; i < paramCount; ++i) {

View File

@ -15,12 +15,11 @@
*/ */
package org.teavm.javascript; package org.teavm.javascript;
import java.util.List;
import org.teavm.javascript.ast.AsyncMethodNode; import org.teavm.javascript.ast.AsyncMethodNode;
import org.teavm.javascript.ast.AsyncMethodPart; import org.teavm.javascript.ast.AsyncMethodPart;
import org.teavm.javascript.ast.RegularMethodNode; import org.teavm.javascript.ast.RegularMethodNode;
import org.teavm.model.Program; import org.teavm.model.Program;
import org.teavm.model.util.AsyncProgramSplitter;
/** /**
* *
@ -44,13 +43,17 @@ public class Optimizer {
} }
} }
public void optimize(AsyncMethodNode method, List<Program> programs) { public void optimize(AsyncMethodNode method, Program program, AsyncProgramSplitter splitter) {
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size()); ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
for (Program program : programs) {
stats.analyze(program); stats.analyze(program);
for (int i = 0; i < splitter.size(); ++i) {
Integer var = splitter.getInput(i);
if (var != null) {
stats.reads[var]++;
}
} }
OptimizingVisitor optimizer = new OptimizingVisitor(stats);
for (AsyncMethodPart part : method.getBody()) { for (AsyncMethodPart part : method.getBody()) {
OptimizingVisitor optimizer = new OptimizingVisitor(stats.copy());
part.getStatement().acceptVisitor(optimizer); part.getStatement().acceptVisitor(optimizer);
part.setStatement(optimizer.resultStmt); part.setStatement(optimizer.resultStmt);
} }

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.javascript; package org.teavm.javascript;
import java.util.Arrays;
import org.teavm.model.*; import org.teavm.model.*;
import org.teavm.model.util.DefinitionExtractor; import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.UsageExtractor; import org.teavm.model.util.UsageExtractor;
@ -27,11 +28,21 @@ class ReadWriteStatsBuilder {
public int[] reads; public int[] reads;
public int[] writes; public int[] writes;
private ReadWriteStatsBuilder() {
}
public ReadWriteStatsBuilder(int variableCount) { public ReadWriteStatsBuilder(int variableCount) {
reads = new int[variableCount]; reads = new int[variableCount];
writes = new int[variableCount]; writes = new int[variableCount];
} }
public ReadWriteStatsBuilder copy() {
ReadWriteStatsBuilder result = new ReadWriteStatsBuilder();
result.reads = Arrays.copyOf(reads, reads.length);
result.writes = Arrays.copyOf(writes, writes.length);
return result;
}
public void analyze(Program program) { public void analyze(Program program) {
DefinitionExtractor defExtractor = new DefinitionExtractor(); DefinitionExtractor defExtractor = new DefinitionExtractor();
UsageExtractor useExtractor = new UsageExtractor(); UsageExtractor useExtractor = new UsageExtractor();

View File

@ -533,7 +533,11 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
} }
writer.append(")").ws().append("{").softNewLine().indent(); writer.append(")").ws().append("{").softNewLine().indent();
method.acceptVisitor(new MethodBodyRenderer()); method.acceptVisitor(new MethodBodyRenderer());
writer.outdent().append("}").newLine(); writer.outdent().append("}");
if (inner) {
writer.append(';');
}
writer.newLine();
debugEmitter.emitMethod(null); debugEmitter.emitMethod(null);
} }
@ -630,18 +634,15 @@ public class Renderer implements ExprVisitor, StatementVisitor, RenderingContext
writer.append(";").softNewLine(); writer.append(";").softNewLine();
} }
for (int i = 0; i < methodNode.getBody().size(); ++i) { for (int i = 0; i < methodNode.getBody().size(); ++i) {
writer.append("function $part_").append(i).append("("); writer.append("var $part_").append(i).ws().append("=").ws().append("$rt_guardAsync(function(");
if (i > 0) { if (i > 0) {
writer.append("$restore"); writer.append("$restore");
} }
writer.append(")").ws().append('{').indent().softNewLine(); writer.append(")").ws().append("{").indent().softNewLine();
writer.append("try {").indent().softNewLine();
AsyncMethodPart part = methodNode.getBody().get(i); AsyncMethodPart part = methodNode.getBody().get(i);
part.getStatement().acceptVisitor(Renderer.this); part.getStatement().acceptVisitor(Renderer.this);
writer.outdent().append("} catch ($guard) {").indent().softNewLine();
writer.append("return $return($rt_asyncError($guard));").softNewLine(); writer.append("return $return($rt_asyncError($guard));").softNewLine();
writer.outdent().append("}").softNewLine(); writer.outdent().append("},").ws().append("$return);").softNewLine();
writer.outdent().append("}").softNewLine();
} }
writer.append("return $part_0();").softNewLine(); writer.append("return $part_0();").softNewLine();
} catch (IOException e) { } catch (IOException e) {

View File

@ -455,6 +455,15 @@ function $rt_continue(f) {
return f; return f;
} }
} }
function $rt_guardAsync(f, continuation) {
return function() {
try {
return f.apply(this, arguments);
} catch (e) {
return continuation($rt_asyncError(e));
}
}
}
function $dbg_repr(obj) { function $dbg_repr(obj) {
return obj.toString ? obj.toString() : ""; return obj.toString ? obj.toString() : "";

View File

@ -55,18 +55,5 @@ public final class AsyncProgram {
} }
} }
System.out.println("Complete async"); System.out.println("Complete async");
System.out.println("Throwing exception");
try {
throwException();
} catch (IllegalStateException e) {
System.out.println("Exception caught");
}
}
private static void throwException() {
Thread.yield();
System.out.println("Thread.yield called");
throw new IllegalStateException();
} }
} }