mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Further work on CPS generator
This commit is contained in:
parent
3c9acd8fab
commit
62d3e9f40e
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user