mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Fix bug in liveness analysis when running on non-SSA IR
This commit is contained in:
parent
1d19562c49
commit
67c86b089f
|
@ -68,12 +68,15 @@ public class Optimizer {
|
|||
|
||||
public void optimize(AsyncMethodNode method, AsyncProgramSplitter splitter, boolean friendlyToDebugger) {
|
||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||
liveness.analyze(splitter.getOriginalProgram());
|
||||
liveness.analyze(splitter.getOriginalProgram(), method.getReference().getDescriptor());
|
||||
|
||||
Graph cfg = ProgramUtils.buildControlFlowGraph(splitter.getOriginalProgram());
|
||||
boolean[] preservedVars = new boolean[method.getVariables().size()];
|
||||
for (int i = 0; i < splitter.size(); ++i) {
|
||||
findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars);
|
||||
}
|
||||
|
||||
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));
|
||||
applyParametersToWriteStats(stats, method.getReference());
|
||||
|
@ -81,7 +84,6 @@ public class Optimizer {
|
|||
AsyncMethodPart part = method.getBody().get(i);
|
||||
BreakEliminator breakEliminator = new BreakEliminator();
|
||||
breakEliminator.eliminate(part.getStatement());
|
||||
findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars);
|
||||
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads,
|
||||
stats.constants, friendlyToDebugger);
|
||||
part.getStatement().acceptVisitor(optimizer);
|
||||
|
|
|
@ -112,7 +112,7 @@ public class CoroutineTransformation {
|
|||
parameterCount = methodReference.parameterCount();
|
||||
returnType = methodReference.getReturnType();
|
||||
variableTypes.inferTypes(program, methodReference);
|
||||
livenessAnalysis.analyze(program);
|
||||
livenessAnalysis.analyze(program, methodReference.getDescriptor());
|
||||
splitter = new BasicBlockSplitter(program);
|
||||
int basicBlockCount = program.basicBlockCount();
|
||||
createSplitPrologue();
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.teavm.model.BasicBlock;
|
|||
import org.teavm.model.FieldReference;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
|
@ -95,7 +96,7 @@ public class EscapeAnalysis {
|
|||
escapingVars[definitionClasses[i]] = true;
|
||||
}
|
||||
}
|
||||
analyzePhis(program);
|
||||
analyzePhis(program, methodReference.getDescriptor());
|
||||
|
||||
propagateFields(program, visitor.fields);
|
||||
fields = packFields(visitor.fields);
|
||||
|
@ -114,9 +115,9 @@ public class EscapeAnalysis {
|
|||
return varFields != null ? varFields.clone() : null;
|
||||
}
|
||||
|
||||
private void analyzePhis(Program program) {
|
||||
private void analyzePhis(Program program, MethodDescriptor methodDescriptor) {
|
||||
LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
|
||||
livenessAnalyzer.analyze(program);
|
||||
livenessAnalyzer.analyze(program, methodDescriptor);
|
||||
|
||||
GraphBuilder graphBuilder = new GraphBuilder(program.variableCount());
|
||||
IntDeque queue = new IntArrayDeque();
|
||||
|
|
|
@ -134,7 +134,7 @@ public class GCShadowStackContributor {
|
|||
List<Map<Instruction, BitSet>> liveInInformation = new ArrayList<>();
|
||||
|
||||
LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
|
||||
livenessAnalyzer.analyze(program);
|
||||
livenessAnalyzer.analyze(program, method.getDescriptor());
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
UsageExtractor useExtractor = new UsageExtractor();
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.model.util;
|
|||
import com.carrotsearch.hppc.IntHashSet;
|
||||
import com.carrotsearch.hppc.IntSet;
|
||||
import com.carrotsearch.hppc.IntStack;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import org.teavm.common.DominatorTree;
|
||||
import org.teavm.common.Graph;
|
||||
|
@ -25,6 +26,7 @@ import org.teavm.common.GraphUtils;
|
|||
import org.teavm.model.BasicBlock;
|
||||
import org.teavm.model.Incoming;
|
||||
import org.teavm.model.Instruction;
|
||||
import org.teavm.model.MethodDescriptor;
|
||||
import org.teavm.model.Phi;
|
||||
import org.teavm.model.Program;
|
||||
import org.teavm.model.Variable;
|
||||
|
@ -45,7 +47,11 @@ public class LivenessAnalyzer {
|
|||
return (BitSet) liveOutVars[block].clone();
|
||||
}
|
||||
|
||||
public void analyze(Program program) {
|
||||
public void analyze(Program program, MethodDescriptor descriptor) {
|
||||
analyze(program, descriptor.parameterCount() + 1);
|
||||
}
|
||||
|
||||
public void analyze(Program program, int parameterCount) {
|
||||
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||
DominatorTree dominatorTree = GraphUtils.buildDominatorTree(cfg);
|
||||
liveVars = new BitSet[program.basicBlockCount()];
|
||||
|
@ -58,32 +64,28 @@ public class LivenessAnalyzer {
|
|||
UsageExtractor usageExtractor = new UsageExtractor();
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
IntStack stack = new IntStack();
|
||||
int[] definitions = new int[program.variableCount()];
|
||||
IntSet[] definitionsBuilder = new IntSet[program.variableCount()];
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
BasicBlock block = program.basicBlockAt(i);
|
||||
|
||||
if (block.getExceptionVariable() != null) {
|
||||
definitions[block.getExceptionVariable().getIndex()] = i;
|
||||
addDefinition(definitionsBuilder, block.getExceptionVariable().getIndex(), i);
|
||||
}
|
||||
|
||||
for (Instruction insn : block) {
|
||||
insn.acceptVisitor(usageExtractor);
|
||||
IntSet usedVars = new IntHashSet();
|
||||
for (Variable var : usageExtractor.getUsedVariables()) {
|
||||
stack.push(i);
|
||||
stack.push(var.getIndex());
|
||||
usedVars.add(var.getIndex());
|
||||
}
|
||||
insn.acceptVisitor(defExtractor);
|
||||
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||
if (!usedVars.contains(var.getIndex())) {
|
||||
definitions[var.getIndex()] = i;
|
||||
}
|
||||
addDefinition(definitionsBuilder, var.getIndex(), i);
|
||||
}
|
||||
}
|
||||
|
||||
for (Phi phi : block.getPhis()) {
|
||||
definitions[phi.getReceiver().getIndex()] = i;
|
||||
addDefinition(definitionsBuilder, phi.getReceiver().getIndex(), i);
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
stack.push(incoming.getSource().getIndex());
|
||||
stack.push(incoming.getValue().getIndex());
|
||||
|
@ -91,15 +93,39 @@ public class LivenessAnalyzer {
|
|||
}
|
||||
}
|
||||
|
||||
while (!stack.isEmpty()) {
|
||||
int[][] definitions = new int[program.variableCount()][];
|
||||
for (int i = 0; i < definitions.length; ++i) {
|
||||
IntSet definitionsByVar = definitionsBuilder[i];
|
||||
if (definitionsByVar == null) {
|
||||
definitions[i] = new int[0];
|
||||
} else {
|
||||
definitions[i] = definitionsByVar.toArray();
|
||||
Arrays.sort(definitions[i]);
|
||||
}
|
||||
}
|
||||
|
||||
worklist: while (!stack.isEmpty()) {
|
||||
int variable = stack.pop();
|
||||
int block = stack.pop();
|
||||
BitSet blockLiveVars = liveVars[block];
|
||||
if (blockLiveVars.get(variable) || definitions[variable] == block
|
||||
|| !dominatorTree.dominates(definitions[variable], block)) {
|
||||
if (blockLiveVars.get(variable)) {
|
||||
continue;
|
||||
}
|
||||
liveVars[block].set(variable, true);
|
||||
|
||||
boolean hasDominatingDefinition = variable < parameterCount;
|
||||
for (int definedAt : definitions[variable]) {
|
||||
if (definedAt == block) {
|
||||
continue worklist;
|
||||
}
|
||||
if (!hasDominatingDefinition && dominatorTree.dominates(definedAt, block)) {
|
||||
hasDominatingDefinition = true;
|
||||
}
|
||||
}
|
||||
if (!hasDominatingDefinition) {
|
||||
continue;
|
||||
}
|
||||
|
||||
blockLiveVars.set(variable, true);
|
||||
for (int pred : cfg.incomingEdges(block)) {
|
||||
stack.push(pred);
|
||||
stack.push(variable);
|
||||
|
@ -118,4 +144,13 @@ public class LivenessAnalyzer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void addDefinition(IntSet[] definitions, int v, int block) {
|
||||
IntSet definitionsByVar = definitions[v];
|
||||
if (definitionsByVar == null) {
|
||||
definitionsByVar = new IntHashSet();
|
||||
definitions[v] = definitionsByVar;
|
||||
}
|
||||
definitionsByVar.add(block);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public class RegisterAllocator {
|
|||
insertPhiArgumentsCopies(program);
|
||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||
liveness.analyze(program);
|
||||
liveness.analyze(program, method.getDescriptor());
|
||||
List<MutableGraphNode> interferenceGraph = interferenceBuilder.build(
|
||||
program, method.parameterCount(), liveness);
|
||||
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
|
||||
|
|
Loading…
Reference in New Issue
Block a user