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

View File

@ -15,12 +15,11 @@
*/
package org.teavm.javascript;
import java.util.List;
import org.teavm.javascript.ast.AsyncMethodNode;
import org.teavm.javascript.ast.AsyncMethodPart;
import org.teavm.javascript.ast.RegularMethodNode;
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());
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()) {
OptimizingVisitor optimizer = new OptimizingVisitor(stats.copy());
part.getStatement().acceptVisitor(optimizer);
part.setStatement(optimizer.resultStmt);
}

View File

@ -15,6 +15,7 @@
*/
package org.teavm.javascript;
import java.util.Arrays;
import org.teavm.model.*;
import org.teavm.model.util.DefinitionExtractor;
import org.teavm.model.util.UsageExtractor;
@ -27,11 +28,21 @@ class ReadWriteStatsBuilder {
public int[] reads;
public int[] writes;
private ReadWriteStatsBuilder() {
}
public ReadWriteStatsBuilder(int variableCount) {
reads = 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) {
DefinitionExtractor defExtractor = new DefinitionExtractor();
UsageExtractor useExtractor = new UsageExtractor();

View File

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

View File

@ -455,6 +455,15 @@ function $rt_continue(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) {
return obj.toString ? obj.toString() : "";

View File

@ -55,18 +55,5 @@ public final class AsyncProgram {
}
}
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();
}
}