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
0e3fb1f3d2
commit
79d76f9a4d
|
@ -15,11 +15,15 @@
|
|||
*/
|
||||
package org.teavm.javascript;
|
||||
|
||||
import java.util.*;
|
||||
import org.teavm.common.Graph;
|
||||
import org.teavm.javascript.ast.AsyncMethodNode;
|
||||
import org.teavm.javascript.ast.AsyncMethodPart;
|
||||
import org.teavm.javascript.ast.RegularMethodNode;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.util.AsyncProgramSplitter;
|
||||
import org.teavm.model.Variable;
|
||||
import org.teavm.model.util.*;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -52,6 +56,9 @@ public class Optimizer {
|
|||
}
|
||||
|
||||
public void optimize(AsyncMethodNode method, AsyncProgramSplitter splitter) {
|
||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||
liveness.analyze(splitter.getOriginalProgram());
|
||||
|
||||
boolean[] preservedVars = new boolean[method.getVariables().size()];
|
||||
int[][] readFrequencies = new int[splitter.size()][];
|
||||
for (int i = 0; i < splitter.size(); ++i) {
|
||||
|
@ -59,16 +66,19 @@ public class Optimizer {
|
|||
stats.analyze(splitter.getProgram(i));
|
||||
readFrequencies[i] = stats.reads;
|
||||
for (int j = 0; j < stats.writes.length; ++j) {
|
||||
if (stats.readUninitialized[j] || stats.writes[j] != 1 && stats.reads[j] > 0) {
|
||||
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());
|
||||
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, readFrequencies[i]);
|
||||
findEscapingLiveVars(liveness, splitter, i, partPreservedVars);
|
||||
OptimizingVisitor optimizer = new OptimizingVisitor(partPreservedVars, readFrequencies[i]);
|
||||
part.getStatement().acceptVisitor(optimizer);
|
||||
part.setStatement(optimizer.resultStmt);
|
||||
}
|
||||
|
@ -86,4 +96,45 @@ public class Optimizer {
|
|||
method.getVariables().set(i, i);
|
||||
}
|
||||
}
|
||||
|
||||
private void findEscapingLiveVars(LivenessAnalyzer liveness, AsyncProgramSplitter splitter, int partIndex,
|
||||
boolean[] output) {
|
||||
Program originalProgram = splitter.getOriginalProgram();
|
||||
Graph cfg = ProgramUtils.buildControlFlowGraph(originalProgram);
|
||||
int[] successors = splitter.getBlockSuccessors(partIndex);
|
||||
int[] splitPoints = splitter.getSplitPoints(partIndex);
|
||||
|
||||
for (int i = 0; i < originalProgram.basicBlockCount(); ++i) {
|
||||
if (successors[i] < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Determine live-out vars
|
||||
BitSet liveVars = new BitSet();
|
||||
for (int succ : cfg.outgoingEdges(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();
|
||||
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());
|
||||
}
|
||||
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||
liveVars.clear(var.getIndex());
|
||||
}
|
||||
}
|
||||
|
||||
// Add live variables to output
|
||||
for (int j = liveVars.nextSetBit(0); j >= 0; j = liveVars.nextSetBit(j + 1)) {
|
||||
output[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.teavm.model.util.UsageExtractor;
|
|||
class ReadWriteStatsBuilder {
|
||||
public int[] reads;
|
||||
public int[] writes;
|
||||
public boolean[] readUninitialized;
|
||||
|
||||
private ReadWriteStatsBuilder() {
|
||||
}
|
||||
|
@ -39,7 +38,6 @@ class ReadWriteStatsBuilder {
|
|||
public ReadWriteStatsBuilder(int variableCount) {
|
||||
reads = new int[variableCount];
|
||||
writes = new int[variableCount];
|
||||
readUninitialized = new boolean[variableCount];
|
||||
}
|
||||
|
||||
public ReadWriteStatsBuilder copy() {
|
||||
|
@ -67,9 +65,6 @@ class ReadWriteStatsBuilder {
|
|||
}
|
||||
for (Variable var : useExtractor.getUsedVariables()) {
|
||||
reads[var.getIndex()]++;
|
||||
if (writes[var.getIndex()] == 0) {
|
||||
readUninitialized[var.getIndex()] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Phi phi : block.getPhis()) {
|
||||
|
|
|
@ -31,6 +31,7 @@ public class AsyncProgramSplitter {
|
|||
private Map<Long, Integer> partMap = new HashMap<>();
|
||||
private ClassReaderSource classSource;
|
||||
private Set<MethodReference> asyncMethods = new HashSet<>();
|
||||
private Program program;
|
||||
|
||||
public AsyncProgramSplitter(ClassReaderSource classSource, Set<MethodReference> asyncMethods) {
|
||||
this.classSource = classSource;
|
||||
|
@ -38,12 +39,15 @@ public class AsyncProgramSplitter {
|
|||
}
|
||||
|
||||
public void split(Program program) {
|
||||
this.program = program;
|
||||
parts.clear();
|
||||
Program initialProgram = createStubCopy(program);
|
||||
Part initialPart = new Part();
|
||||
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();
|
||||
|
@ -87,6 +91,8 @@ public class AsyncProgramSplitter {
|
|||
}
|
||||
last = i;
|
||||
|
||||
step.targetPart.splitPoints[step.source] = i;
|
||||
|
||||
// If this instruction already separates program, end with current block and refer to the
|
||||
// existing part
|
||||
long key = ((long)step.source << 32) | i;
|
||||
|
@ -103,6 +109,8 @@ public class AsyncProgramSplitter {
|
|||
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);
|
||||
|
@ -192,6 +200,10 @@ public class AsyncProgramSplitter {
|
|||
return parts.size();
|
||||
}
|
||||
|
||||
public Program getOriginalProgram() {
|
||||
return program;
|
||||
}
|
||||
|
||||
public Program getProgram(int index) {
|
||||
return parts.get(index).program;
|
||||
}
|
||||
|
@ -201,9 +213,18 @@ public class AsyncProgramSplitter {
|
|||
return Arrays.copyOf(result, result.length);
|
||||
}
|
||||
|
||||
public int getBlockSuccessor(int index, int blockIndex) {
|
||||
return parts.get(index).blockSuccessors[blockIndex];
|
||||
}
|
||||
|
||||
public int[] getSplitPoints(int index) {
|
||||
return parts.get(index).splitPoints.clone();
|
||||
}
|
||||
|
||||
private static class Part {
|
||||
Program program;
|
||||
int[] blockSuccessors;
|
||||
int[] splitPoints;
|
||||
}
|
||||
|
||||
private static class Step {
|
||||
|
|
|
@ -205,11 +205,11 @@ public class DefinitionExtractor implements InstructionVisitor {
|
|||
|
||||
@Override
|
||||
public void visit(MonitorEnterInstruction insn) {
|
||||
|
||||
definedVariables = new Variable[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(MonitorExitInstruction insn) {
|
||||
|
||||
definedVariables = new Variable[0];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
<targetDirectory>${project.build.directory}/generated/js/teavm</targetDirectory>
|
||||
<mainClass>org.teavm.samples.async.AsyncProgram</mainClass>
|
||||
<runtime>SEPARATE</runtime>
|
||||
<minifying>true</minifying>
|
||||
<minifying>false</minifying>
|
||||
<debugInformationGenerated>true</debugInformationGenerated>
|
||||
<sourceMapsGenerated>true</sourceMapsGenerated>
|
||||
<sourceFilesCopied>true</sourceFilesCopied>
|
||||
|
|
Loading…
Reference in New Issue
Block a user