mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
This commit is contained in:
parent
41f8e10e24
commit
a4cb94df2f
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
package org.teavm.codegen;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.teavm.model.FieldReference;
|
||||
|
@ -26,6 +27,8 @@ import org.teavm.model.MethodReference;
|
|||
* @author Alexey Andreev
|
||||
*/
|
||||
public class MinifyingAliasProvider implements AliasProvider {
|
||||
private static Set<String> keywords = new HashSet<>(Arrays.asList("do", "if", "else", "for", "case",
|
||||
"goto", "in", "let", "new", "this", "try", "var", "void", "with"));
|
||||
private static String startLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
private static String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
private static String startVirtualLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
@ -38,7 +41,7 @@ public class MinifyingAliasProvider implements AliasProvider {
|
|||
String result;
|
||||
do {
|
||||
result = getNewAlias(lastVirtual++, startVirtualLetters);
|
||||
} while (!usedAliases.add(result));
|
||||
} while (!usedAliases.add(result) || keywords.contains(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -52,7 +55,7 @@ public class MinifyingAliasProvider implements AliasProvider {
|
|||
String result;
|
||||
do {
|
||||
result = getNewAlias(lastVirtual++, startVirtualLetters);
|
||||
} while (!usedAliases.add(result));
|
||||
} while (!usedAliases.add(result) || keywords.contains(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -249,7 +249,7 @@ public class Decompiler {
|
|||
return true;
|
||||
}
|
||||
|
||||
public AsyncMethodNode decompileAsyncCacheMiss(MethodHolder method) {
|
||||
private AsyncMethodNode decompileAsyncCacheMiss(MethodHolder method) {
|
||||
AsyncMethodNode node = new AsyncMethodNode(method.getReference());
|
||||
AsyncProgramSplitter splitter = new AsyncProgramSplitter(classSource, splitMethods);
|
||||
splitter.split(method.getProgram());
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.javascript.ast.AsyncMethodNode;
|
||||
import org.teavm.javascript.ast.AsyncMethodPart;
|
||||
|
@ -23,7 +24,11 @@ import org.teavm.javascript.ast.RegularMethodNode;
|
|||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.util.*;
|
||||
import org.teavm.model.util.AsyncProgramSplitter;
|
||||
import org.teavm.model.util.DefinitionExtractor;
|
||||
import org.teavm.model.util.LivenessAnalyzer;
|
||||
import org.teavm.model.util.ProgramUtils;
|
||||
import org.teavm.model.util.UsageExtractor;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -59,26 +64,23 @@ public class Optimizer {
|
|||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||
liveness.analyze(splitter.getOriginalProgram());
|
||||
|
||||
boolean[] preservedVars = new boolean[method.getVariables().size()];
|
||||
int[][] readFrequencies = new int[splitter.size()][];
|
||||
Graph cfg = ProgramUtils.buildControlFlowGraph(splitter.getOriginalProgram());
|
||||
|
||||
for (int i = 0; i < splitter.size(); ++i) {
|
||||
boolean[] preservedVars = new boolean[method.getVariables().size()];
|
||||
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
||||
stats.analyze(splitter.getProgram(i));
|
||||
readFrequencies[i] = stats.reads;
|
||||
for (int j = 0; j < stats.writes.length; ++j) {
|
||||
if (stats.writes[j] != 1 && stats.reads[j] > 0) {
|
||||
preservedVars[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < splitter.size(); ++i) {
|
||||
boolean[] partPreservedVars = preservedVars.clone();
|
||||
AsyncMethodPart part = method.getBody().get(i);
|
||||
BreakEliminator breakEliminator = new BreakEliminator();
|
||||
breakEliminator.eliminate(part.getStatement());
|
||||
findEscapingLiveVars(liveness, splitter, i, partPreservedVars);
|
||||
OptimizingVisitor optimizer = new OptimizingVisitor(partPreservedVars, readFrequencies[i]);
|
||||
findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars);
|
||||
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.reads);
|
||||
part.getStatement().acceptVisitor(optimizer);
|
||||
part.setStatement(optimizer.resultStmt);
|
||||
}
|
||||
|
@ -97,38 +99,39 @@ public class Optimizer {
|
|||
}
|
||||
}
|
||||
|
||||
private void findEscapingLiveVars(LivenessAnalyzer liveness, AsyncProgramSplitter splitter, int partIndex,
|
||||
boolean[] output) {
|
||||
private void findEscapingLiveVars(LivenessAnalyzer liveness, Graph cfg, AsyncProgramSplitter splitter,
|
||||
int partIndex, boolean[] output) {
|
||||
Program originalProgram = splitter.getOriginalProgram();
|
||||
Graph cfg = ProgramUtils.buildControlFlowGraph(originalProgram);
|
||||
Program program = splitter.getProgram(partIndex);
|
||||
int[] successors = splitter.getBlockSuccessors(partIndex);
|
||||
int[] splitPoints = splitter.getSplitPoints(partIndex);
|
||||
int[] originalBlocks = splitter.getOriginalBlocks(partIndex);
|
||||
|
||||
for (int i = 0; i < originalProgram.basicBlockCount(); ++i) {
|
||||
if (successors[i] < 0) {
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
if (successors[i] < 0 || originalBlocks[i] < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine live-out vars
|
||||
BitSet liveVars = new BitSet();
|
||||
for (int succ : cfg.outgoingEdges(i)) {
|
||||
for (int succ : cfg.outgoingEdges(originalBlocks[i])) {
|
||||
liveVars.or(liveness.liveIn(succ));
|
||||
}
|
||||
|
||||
// Remove from live set all variables that are defined in these blocks
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
UsageExtractor useExtractor = new UsageExtractor();
|
||||
List<Instruction> instructions = originalProgram.basicBlockAt(i).getInstructions();
|
||||
List<Instruction> instructions = originalProgram.basicBlockAt(originalBlocks[i]).getInstructions();
|
||||
int splitPoint = splitPoints[i];
|
||||
for (int j = instructions.size() - 1; j >= splitPoint; --j) {
|
||||
instructions.get(j).acceptVisitor(useExtractor);
|
||||
instructions.get(j).acceptVisitor(defExtractor);
|
||||
for (Variable var : useExtractor.getUsedVariables()) {
|
||||
liveVars.set(var.getIndex());
|
||||
}
|
||||
instructions.get(j).acceptVisitor(useExtractor);
|
||||
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||
liveVars.clear(var.getIndex());
|
||||
}
|
||||
for (Variable var : useExtractor.getUsedVariables()) {
|
||||
liveVars.set(var.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
// Add live variables to output
|
||||
|
|
|
@ -42,12 +42,8 @@ public class AsyncProgramSplitter {
|
|||
this.program = program;
|
||||
parts.clear();
|
||||
Program initialProgram = createStubCopy(program);
|
||||
Part initialPart = new Part();
|
||||
Part initialPart = new Part(program.basicBlockCount());
|
||||
initialPart.program = initialProgram;
|
||||
initialPart.blockSuccessors = new int[program.basicBlockCount()];
|
||||
Arrays.fill(initialPart.blockSuccessors, -1);
|
||||
initialPart.splitPoints = new int[program.basicBlockCount()];
|
||||
Arrays.fill(initialPart.splitPoints, -1);
|
||||
parts.add(initialPart);
|
||||
partMap.put(0L, 0);
|
||||
Step initialStep = new Step();
|
||||
|
@ -63,6 +59,7 @@ public class AsyncProgramSplitter {
|
|||
continue;
|
||||
}
|
||||
BasicBlock sourceBlock = program.basicBlockAt(step.source);
|
||||
step.targetPart.originalBlocks[step.source] = step.source;
|
||||
int last = 0;
|
||||
for (int i = 0; i < sourceBlock.getInstructions().size(); ++i) {
|
||||
Instruction insn = sourceBlock.getInstructions().get(i);
|
||||
|
@ -91,7 +88,7 @@ public class AsyncProgramSplitter {
|
|||
}
|
||||
last = i;
|
||||
|
||||
step.targetPart.splitPoints[step.source] = i;
|
||||
step.targetPart.splitPoints[targetBlock.getIndex()] = i;
|
||||
|
||||
// If this instruction already separates program, end with current block and refer to the
|
||||
// existing part
|
||||
|
@ -103,14 +100,10 @@ public class AsyncProgramSplitter {
|
|||
|
||||
// Create a new part
|
||||
Program nextProgram = createStubCopy(program);
|
||||
Part part = new Part();
|
||||
Part part = new Part(program.basicBlockCount() + 1);
|
||||
part.program = nextProgram;
|
||||
int partId = parts.size();
|
||||
parts.add(part);
|
||||
part.blockSuccessors = new int[program.basicBlockCount() + 1];
|
||||
Arrays.fill(part.blockSuccessors, -1);
|
||||
part.splitPoints = new int[program.basicBlockCount() + 1];
|
||||
Arrays.fill(part.splitPoints, -1);
|
||||
|
||||
// Mark current instruction as a separator and remember which part is in charge.
|
||||
partMap.put(key, partId);
|
||||
|
@ -126,6 +119,7 @@ public class AsyncProgramSplitter {
|
|||
nextProgram));
|
||||
}
|
||||
step.targetPart = part;
|
||||
part.originalBlocks[targetBlock.getIndex()] = step.source;
|
||||
}
|
||||
targetBlock.getInstructions().addAll(ProgramUtils.copyInstructions(sourceBlock,
|
||||
last, sourceBlock.getInstructions().size(), targetBlock.getProgram()));
|
||||
|
@ -153,8 +147,10 @@ public class AsyncProgramSplitter {
|
|||
|
||||
for (Part part : parts) {
|
||||
IntegerArray blockSuccessors = IntegerArray.of(part.blockSuccessors);
|
||||
IntegerArray originalBlocks = IntegerArray.of(part.originalBlocks);
|
||||
IntegerArray splitPoints = IntegerArray.of(part.splitPoints);
|
||||
AsyncProgramSplittingBackend splittingBackend = new AsyncProgramSplittingBackend(
|
||||
new ProgramNodeSplittingBackend(part.program), blockSuccessors);
|
||||
new ProgramNodeSplittingBackend(part.program), blockSuccessors, originalBlocks, splitPoints);
|
||||
Graph graph = ProgramUtils.buildControlFlowGraphWithTryCatch(part.program);
|
||||
int[] weights = new int[graph.size()];
|
||||
for (int i = 0; i < part.program.basicBlockCount(); ++i) {
|
||||
|
@ -162,6 +158,8 @@ public class AsyncProgramSplitter {
|
|||
}
|
||||
GraphUtils.splitIrreducibleGraph(graph, weights, splittingBackend);
|
||||
part.blockSuccessors = splittingBackend.blockSuccessors.getAll();
|
||||
part.originalBlocks = splittingBackend.originalBlocks.getAll();
|
||||
part.splitPoints = splittingBackend.splitPoints.getAll();
|
||||
}
|
||||
partMap.clear();
|
||||
}
|
||||
|
@ -221,10 +219,24 @@ public class AsyncProgramSplitter {
|
|||
return parts.get(index).splitPoints.clone();
|
||||
}
|
||||
|
||||
private static class Part {
|
||||
public int[] getOriginalBlocks(int index) {
|
||||
return parts.get(index).originalBlocks.clone();
|
||||
}
|
||||
|
||||
static class Part {
|
||||
Program program;
|
||||
int[] blockSuccessors;
|
||||
int[] splitPoints;
|
||||
int[] originalBlocks;
|
||||
|
||||
public Part(int blockCount) {
|
||||
blockSuccessors = new int[blockCount];
|
||||
Arrays.fill(blockSuccessors, -1);
|
||||
splitPoints = new int[blockCount];
|
||||
Arrays.fill(splitPoints, -1);
|
||||
originalBlocks = new int[blockCount];
|
||||
Arrays.fill(originalBlocks, -1);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Step {
|
||||
|
@ -235,10 +247,15 @@ public class AsyncProgramSplitter {
|
|||
private static class AsyncProgramSplittingBackend implements GraphSplittingBackend {
|
||||
private GraphSplittingBackend inner;
|
||||
private IntegerArray blockSuccessors;
|
||||
private IntegerArray originalBlocks;
|
||||
private IntegerArray splitPoints;
|
||||
|
||||
public AsyncProgramSplittingBackend(GraphSplittingBackend inner, IntegerArray blockSuccessors) {
|
||||
public AsyncProgramSplittingBackend(GraphSplittingBackend inner, IntegerArray blockSuccessors,
|
||||
IntegerArray originalBlocks, IntegerArray splitPoints) {
|
||||
this.inner = inner;
|
||||
this.blockSuccessors = blockSuccessors;
|
||||
this.originalBlocks = originalBlocks;
|
||||
this.splitPoints = splitPoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -249,8 +266,12 @@ public class AsyncProgramSplitter {
|
|||
int node = nodes[i];
|
||||
if (blockSuccessors.size() <= copy) {
|
||||
blockSuccessors.add(-1);
|
||||
splitPoints.add(-1);
|
||||
originalBlocks.add(-1);
|
||||
}
|
||||
blockSuccessors.set(copy, blockSuccessors.get(node));
|
||||
originalBlocks.set(copy, originalBlocks.get(node));
|
||||
splitPoints.set(copy, splitPoints.get(node));
|
||||
}
|
||||
return copies;
|
||||
}
|
||||
|
|
|
@ -60,6 +60,10 @@ public class RegisterAllocator {
|
|||
for (int i = 0; i < colors.length; ++i) {
|
||||
program.variableAt(i).setRegister(colors[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
program.basicBlockAt(i).getPhis().clear();
|
||||
}
|
||||
}
|
||||
|
||||
private int[] getVariableCategories(ProgramReader program, MethodReference method) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user