Further work on CPS generator

This commit is contained in:
konsoletyper 2015-02-01 22:08:04 +04:00
parent 3c9acd8fab
commit 62d3e9f40e
4 changed files with 65 additions and 64 deletions

View File

@ -36,14 +36,14 @@ public class ThreadNativeGenerator implements Generator {
} }
private void generateSleep(GeneratorContext context, SourceWriter writer) throws IOException { private void generateSleep(GeneratorContext context, SourceWriter writer) throws IOException {
writer.append("setTimer(function() {").indent().softNewLine(); writer.append("setTimeout(function() {").indent().softNewLine();
writer.append(context.getCompleteContinuation()).append("();").softNewLine(); writer.append(context.getCompleteContinuation()).append("();").softNewLine();
writer.outdent().append(',').ws().append(context.getParameterName(1)).append(");").softNewLine(); writer.outdent().append("},").ws().append(context.getParameterName(1)).append(");").softNewLine();
} }
private void generateYield(GeneratorContext context, SourceWriter writer) throws IOException { private void generateYield(GeneratorContext context, SourceWriter writer) throws IOException {
writer.append("setTimer(function() {").indent().softNewLine(); writer.append("setTimeout(function() {").indent().softNewLine();
writer.append(context.getCompleteContinuation()).append("();").softNewLine(); writer.append(context.getCompleteContinuation()).append("();").softNewLine();
writer.outdent().append(',').ws().append("0);").softNewLine(); writer.outdent().append("},").ws().append("0);").softNewLine();
} }
} }

View File

@ -205,7 +205,7 @@ public class Decompiler {
for (int i = 0; i < splitter.size(); ++i) { for (int i = 0; i < splitter.size(); ++i) {
AsyncMethodPart part = new AsyncMethodPart(); AsyncMethodPart part = new AsyncMethodPart();
part.setInputVariable(splitter.getInput(i)); part.setInputVariable(splitter.getInput(i));
part.setStatement(getRegularMethodStatement(splitter.getProgram(i), i, splitter.getBlockSuccessors(i))); part.setStatement(getRegularMethodStatement(splitter.getProgram(i), splitter.getBlockSuccessors(i)));
node.getBody().add(part); node.getBody().add(part);
} }
Program program = method.getProgram(); Program program = method.getProgram();
@ -226,7 +226,7 @@ public class Decompiler {
public RegularMethodNode decompileRegularCacheMiss(MethodHolder method) { public RegularMethodNode decompileRegularCacheMiss(MethodHolder method) {
RegularMethodNode methodNode = new RegularMethodNode(method.getReference()); RegularMethodNode methodNode = new RegularMethodNode(method.getReference());
Program program = method.getProgram(); Program program = method.getProgram();
methodNode.setBody(getRegularMethodStatement(program, 0, new int[program.basicBlockCount()])); methodNode.setBody(getRegularMethodStatement(program, new int[program.basicBlockCount()]));
for (int i = 0; i < program.variableCount(); ++i) { for (int i = 0; i < program.variableCount(); ++i) {
methodNode.getVariables().add(program.variableAt(i).getRegister()); methodNode.getVariables().add(program.variableAt(i).getRegister());
} }
@ -241,7 +241,7 @@ public class Decompiler {
return methodNode; return methodNode;
} }
private Statement getRegularMethodStatement(Program program, int currentPart, int[] targetBlocks) { private Statement getRegularMethodStatement(Program program, int[] targetBlocks) {
lastBlockId = 1; lastBlockId = 1;
graph = ProgramUtils.buildControlFlowGraph(program); graph = ProgramUtils.buildControlFlowGraph(program);
indexer = new GraphIndexer(graph); indexer = new GraphIndexer(graph);
@ -306,8 +306,8 @@ public class Decompiler {
if (insn.getLocation() != null) { if (insn.getLocation() != null) {
generator.setCurrentLocation(nodeLocation); generator.setCurrentLocation(nodeLocation);
} }
if (targetBlocks[i] != currentPart && j == instructions.size() - 1) { if (targetBlocks[node] >= 0 && j == instructions.size() - 1) {
generator.asyncTarget = targetBlocks[i]; generator.asyncTarget = targetBlocks[node];
} }
insn.acceptVisitor(generator); insn.acceptVisitor(generator);
} }

View File

@ -39,6 +39,7 @@ public class AsyncProgramSplitter {
Part initialPart = new Part(); Part initialPart = new Part();
initialPart.program = initialProgram; initialPart.program = initialProgram;
initialPart.blockSuccessors = new int[program.basicBlockCount()]; initialPart.blockSuccessors = new int[program.basicBlockCount()];
Arrays.fill(initialPart.blockSuccessors, -1);
parts.add(initialPart); parts.add(initialPart);
partMap.put(0L, 0); partMap.put(0L, 0);
Step initialStep = new Step(); Step initialStep = new Step();
@ -47,79 +48,80 @@ public class AsyncProgramSplitter {
Queue<Step> queue = new ArrayDeque<>(); Queue<Step> queue = new ArrayDeque<>();
queue.add(initialStep); queue.add(initialStep);
while (!queue.isEmpty()) { taskLoop: while (!queue.isEmpty()) {
Step step = queue.remove(); Step step = queue.remove();
BasicBlock targetBlock = step.targetPart.program.basicBlockAt(step.source); BasicBlock targetBlock = step.targetPart.program.basicBlockAt(step.source);
if (targetBlock.instructionCount() > 0) { if (targetBlock.instructionCount() > 0) {
continue; continue;
} }
BasicBlock sourceBlock = program.basicBlockAt(step.source); BasicBlock sourceBlock = program.basicBlockAt(step.source);
int end = step.sourceIndex; int last = 0;
boolean asyncOccured = false; for (int i = 0; i < sourceBlock.getInstructions().size(); ++i) {
for (int i = step.sourceIndex; i < sourceBlock.getInstructions().size(); ++i) {
end = i;
Instruction insn = sourceBlock.getInstructions().get(i); Instruction insn = sourceBlock.getInstructions().get(i);
if (insn instanceof InvokeInstruction) { if (insn instanceof InvokeInstruction) {
InvokeInstruction invoke = (InvokeInstruction)insn; InvokeInstruction invoke = (InvokeInstruction)insn;
if (asyncMethods.contains(invoke.getMethod())) { if (!asyncMethods.contains(invoke.getMethod())) {
asyncOccured = true; continue;
long key = ((long)step.source << 32) | i;
if (partMap.containsKey(key)) {
step.targetPart.blockSuccessors[step.sourceIndex] = partMap.get(key);
break;
}
Program nextProgram = createStubCopy(program);
BasicBlock nextBlock = nextProgram.basicBlockAt(step.source);
if (step.source > 0) {
JumpInstruction jumpToNextBlock = new JumpInstruction();
jumpToNextBlock.setTarget(nextBlock);
nextProgram.basicBlockAt(0).getInstructions().add(jumpToNextBlock);
}
Part part = new Part();
part.input = invoke.getReceiver() != null ? invoke.getReceiver().getIndex() : null;
part.program = nextProgram;
int partId = parts.size();
part.blockSuccessors = new int[program.basicBlockCount()];
Arrays.fill(part.blockSuccessors, partId);
partMap.put(key, partId);
step.targetPart.blockSuccessors[step.source] = partId;
parts.add(part);
Step next = new Step();
next.source = step.source;
next.sourceIndex = i + 1;
next.targetPart = part;
queue.add(next);
break;
} }
// If we met asynchronous invocation...
// Copy portion of current block from last occurence (or from start) to i'th instruction.
targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock,
last, i + 1, targetBlock.getProgram()));
ProgramUtils.copyTryCatches(sourceBlock, targetBlock.getProgram());
last = i + 1;
// If this instruction already separates program, end with current block and refer to the
// existing part
long key = ((long)step.source << 32) | i;
if (partMap.containsKey(key)) {
step.targetPart.blockSuccessors[targetBlock.getIndex()] = partMap.get(key);
continue taskLoop;
}
// Create a new part
Program nextProgram = createStubCopy(program);
Part part = new Part();
part.input = invoke.getReceiver() != null ? invoke.getReceiver().getIndex() : null;
part.program = nextProgram;
int partId = parts.size();
parts.add(part);
part.blockSuccessors = new int[program.basicBlockCount() + 1];
Arrays.fill(part.blockSuccessors, -1);
// Mark current instruction as a separator and remember which part is in charge.
partMap.put(key, partId);
step.targetPart.blockSuccessors[targetBlock.getIndex()] = partId;
// Continue with a new block in the new part
targetBlock = nextProgram.createBasicBlock();
if (step.source > 0) {
JumpInstruction jumpToNextBlock = new JumpInstruction();
jumpToNextBlock.setTarget(targetBlock);
nextProgram.basicBlockAt(0).getInstructions().add(jumpToNextBlock);
}
step.targetPart = part;
} }
} }
targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock, step.sourceIndex, end + 1, targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock,
targetBlock.getProgram())); last, sourceBlock.getInstructions().size(), targetBlock.getProgram()));
if (step.sourceIndex == 0) {
targetBlock.getPhis().addAll(ProgramUtils.copyPhis(sourceBlock, targetBlock.getProgram()));
}
ProgramUtils.copyTryCatches(sourceBlock, targetBlock.getProgram());
for (TryCatchBlock tryCatch : targetBlock.getTryCatchBlocks()) { for (TryCatchBlock tryCatch : targetBlock.getTryCatchBlocks()) {
if (tryCatch.getHandler() != null) { if (tryCatch.getHandler() != null) {
Step next = new Step(); Step next = new Step();
next.source = tryCatch.getHandler().getIndex(); next.source = tryCatch.getHandler().getIndex();
next.sourceIndex = 0;
next.targetPart = step.targetPart; next.targetPart = step.targetPart;
queue.add(next); queue.add(next);
} }
} }
if (!asyncOccured) { InstructionTransitionExtractor successorExtractor = new InstructionTransitionExtractor();
InstructionTransitionExtractor successorExtractor = new InstructionTransitionExtractor(); sourceBlock.getLastInstruction().acceptVisitor(successorExtractor);
sourceBlock.getLastInstruction().acceptVisitor(successorExtractor); for (BasicBlock successor : successorExtractor.getTargets()) {
for (BasicBlock successor : successorExtractor.getTargets()) { BasicBlock targetSuccessor = targetBlock.getProgram().basicBlockAt(successor.getIndex());
BasicBlock targetSuccessor = targetBlock.getProgram().basicBlockAt(successor.getIndex()); if (targetSuccessor.instructionCount() == 0) {
if (targetSuccessor.instructionCount() == 0) { Step next = new Step();
Step next = new Step(); next.source = successor.getIndex();
next.source = successor.getIndex(); next.targetPart = step.targetPart;
next.sourceIndex = 0; queue.add(next);
next.targetPart = step.targetPart;
queue.add(next);
}
} }
} }
} }
@ -164,6 +166,5 @@ public class AsyncProgramSplitter {
private static class Step { private static class Step {
Part targetPart; Part targetPart;
int source; int source;
int sourceIndex;
} }
} }

View File

@ -397,7 +397,7 @@ function $rt_asyncAdapter(f) {
var e; var e;
var args = Array.prototype.slice.apply(arguments); var args = Array.prototype.slice.apply(arguments);
var $throw = args.pop(); var $throw = args.pop();
var $return args.pop(); var $return = args.pop();
try { try {
var result = f.apply(this, args); var result = f.apply(this, args);
} catch (e) { } catch (e) {