mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
Fix issues related to sigma nodes in phi updater
This commit is contained in:
parent
8038d68963
commit
9768a86378
|
@ -22,6 +22,9 @@ import org.teavm.jso.JSBody;
|
||||||
public class JSStderrPrintStream extends JsConsolePrintStream {
|
public class JSStderrPrintStream extends JsConsolePrintStream {
|
||||||
@Override
|
@Override
|
||||||
public void print(String s) {
|
public void print(String s) {
|
||||||
|
if (s == null) {
|
||||||
|
s = "null";
|
||||||
|
}
|
||||||
if (PlatformDetector.isWebAssemblyGC()) {
|
if (PlatformDetector.isWebAssemblyGC()) {
|
||||||
for (int i = 0; i < s.length(); ++i) {
|
for (int i = 0; i < s.length(); ++i) {
|
||||||
WasmGCSupport.putCharStderr(s.charAt(i));
|
WasmGCSupport.putCharStderr(s.charAt(i));
|
||||||
|
|
|
@ -101,6 +101,7 @@ public class PhiUpdater {
|
||||||
private Sigma[][] sigmas;
|
private Sigma[][] sigmas;
|
||||||
private Predicate<Instruction> sigmaPredicate = instruction -> false;
|
private Predicate<Instruction> sigmaPredicate = instruction -> false;
|
||||||
private int[][][] frontierVariableCache;
|
private int[][][] frontierVariableCache;
|
||||||
|
private Variable[][] pendingVariableMap;
|
||||||
|
|
||||||
public int getSourceVariable(int var) {
|
public int getSourceVariable(int var) {
|
||||||
if (var >= variableToSourceMap.size()) {
|
if (var >= variableToSourceMap.size()) {
|
||||||
|
@ -139,8 +140,8 @@ public class PhiUpdater {
|
||||||
phisByReceiver.clear();
|
phisByReceiver.clear();
|
||||||
cfg = ProgramUtils.buildControlFlowGraph(program);
|
cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||||
domTree = GraphUtils.buildDominatorTree(cfg);
|
domTree = GraphUtils.buildDominatorTree(cfg);
|
||||||
domFrontiers = new int[cfg.size()][];
|
|
||||||
domGraph = GraphUtils.buildDominatorGraph(domTree, program.basicBlockCount());
|
domGraph = GraphUtils.buildDominatorGraph(domTree, program.basicBlockCount());
|
||||||
|
pendingVariableMap = new Variable[program.basicBlockCount()][];
|
||||||
|
|
||||||
variableMap = new Variable[program.variableCount()];
|
variableMap = new Variable[program.variableCount()];
|
||||||
usedDefinitions = new boolean[program.variableCount()];
|
usedDefinitions = new boolean[program.variableCount()];
|
||||||
|
@ -207,11 +208,7 @@ public class PhiUpdater {
|
||||||
Sigma sigma = new Sigma(block, variables[j]);
|
Sigma sigma = new Sigma(block, variables[j]);
|
||||||
sigmasInBlock[j] = sigma;
|
sigmasInBlock[j] = sigma;
|
||||||
for (BasicBlock target : targets) {
|
for (BasicBlock target : targets) {
|
||||||
Variable outgoingVar = program.createVariable();
|
Outgoing outgoing = new Outgoing(variables[j], target);
|
||||||
variableToSourceMap.add(sigma.getValue().getIndex());
|
|
||||||
outgoingVar.setDebugName(sigma.getValue().getDebugName());
|
|
||||||
outgoingVar.setLabel(sigma.getValue().getLabel());
|
|
||||||
Outgoing outgoing = new Outgoing(outgoingVar, target);
|
|
||||||
sigma.getOutgoings().add(outgoing);
|
sigma.getOutgoings().add(outgoing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -231,42 +228,28 @@ public class PhiUpdater {
|
||||||
int i = stack.removeLast();
|
int i = stack.removeLast();
|
||||||
currentBlock = program.basicBlockAt(i);
|
currentBlock = program.basicBlockAt(i);
|
||||||
|
|
||||||
for (int predecessor : cfg.incomingEdges(i)) {
|
|
||||||
if (sigmas[predecessor] == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (domTree.immediateDominatorOf(i) != predecessor) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Sigma sigma : sigmas[predecessor]) {
|
|
||||||
for (Outgoing outgoing : sigma.getOutgoings()) {
|
|
||||||
if (outgoing.getTarget() == currentBlock) {
|
|
||||||
markAssignment(sigma.getValue());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentBlock.getExceptionVariable() != null) {
|
if (currentBlock.getExceptionVariable() != null) {
|
||||||
markAssignment(currentBlock.getExceptionVariable());
|
markAssignment(currentBlock.getExceptionVariable(), currentBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Phi phi : currentBlock.getPhis()) {
|
for (Phi phi : currentBlock.getPhis()) {
|
||||||
markAssignment(phi.getReceiver());
|
markAssignment(phi.getReceiver(), currentBlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Instruction insn : currentBlock) {
|
for (Instruction insn : currentBlock) {
|
||||||
currentBlock = program.basicBlockAt(i);
|
currentBlock = program.basicBlockAt(i);
|
||||||
insn.acceptVisitor(definitionExtractor);
|
insn.acceptVisitor(definitionExtractor);
|
||||||
for (Variable var : definitionExtractor.getDefinedVariables()) {
|
for (Variable var : definitionExtractor.getDefinedVariables()) {
|
||||||
markAssignment(var);
|
markAssignment(var, currentBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sigmas[i] != null) {
|
var sigmasAtBlock = sigmas[i];
|
||||||
for (Sigma sigma : sigmas[i]) {
|
if (sigmasAtBlock != null) {
|
||||||
markAssignment(sigma.getValue());
|
for (var sigma : sigmasAtBlock) {
|
||||||
|
for (var outgoing : sigma.getOutgoings()) {
|
||||||
|
markAssignment(outgoing.getValue(), outgoing.getTarget());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,7 +275,6 @@ public class PhiUpdater {
|
||||||
var sigmas = getSigmasAt(block.getIndex());
|
var sigmas = getSigmasAt(block.getIndex());
|
||||||
if (sigmas != null) {
|
if (sigmas != null) {
|
||||||
for (var sigma : sigmas) {
|
for (var sigma : sigmas) {
|
||||||
increaseDefinitionCount(sigma.getValue());
|
|
||||||
for (var i = 0; i < sigma.getOutgoings().size(); ++i) {
|
for (var i = 0; i < sigma.getOutgoings().size(); ++i) {
|
||||||
increaseDefinitionCount(sigma.getValue());
|
increaseDefinitionCount(sigma.getValue());
|
||||||
}
|
}
|
||||||
|
@ -307,31 +289,22 @@ public class PhiUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Task {
|
|
||||||
Variable[] variables;
|
|
||||||
BasicBlock block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renameVariables() {
|
private void renameVariables() {
|
||||||
Deque<Task> stack = new ArrayDeque<>();
|
Deque<BasicBlock> stack = new ArrayDeque<>();
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
if (domGraph.incomingEdgesCount(i) == 0) {
|
if (domGraph.incomingEdgesCount(i) == 0) {
|
||||||
Task task = new Task();
|
stack.push(program.basicBlockAt(i));
|
||||||
task.block = program.basicBlockAt(i);
|
pendingVariableMap[i] = variableMap.clone();
|
||||||
task.variables = variableMap.clone();
|
|
||||||
stack.push(task);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
|
|
||||||
|
|
||||||
while (!stack.isEmpty()) {
|
while (!stack.isEmpty()) {
|
||||||
Collections.fill(definedVersions, null);
|
Collections.fill(definedVersions, null);
|
||||||
Task task = stack.pop();
|
|
||||||
|
|
||||||
currentBlock = task.block;
|
currentBlock = stack.pop();
|
||||||
int index = currentBlock.getIndex();
|
int index = currentBlock.getIndex();
|
||||||
variableMap = task.variables.clone();
|
variableMap = pendingVariableMap[index];
|
||||||
|
pendingVariableMap[index] = null;
|
||||||
|
|
||||||
if (currentBlock.getExceptionVariable() != null) {
|
if (currentBlock.getExceptionVariable() != null) {
|
||||||
currentBlock.setExceptionVariable(define(currentBlock.getExceptionVariable()));
|
currentBlock.setExceptionVariable(define(currentBlock.getExceptionVariable()));
|
||||||
|
@ -355,30 +328,20 @@ public class PhiUpdater {
|
||||||
|
|
||||||
int[] successors = domGraph.outgoingEdges(index);
|
int[] successors = domGraph.outgoingEdges(index);
|
||||||
|
|
||||||
for (Incoming output : phiOutputs.get(index)) {
|
Sigma[] nextSigmas = sigmas[index];
|
||||||
Variable var = output.getValue();
|
if (nextSigmas != null) {
|
||||||
Variable sigmaVar = applySigmaRename(output.getPhi().getBasicBlock(), var);
|
for (Sigma sigma : sigmas[index]) {
|
||||||
var = sigmaVar != var ? sigmaVar : use(var);
|
sigma.setValue(use(sigma.getValue()));
|
||||||
output.setValue(var);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sigma[] nextSigmas = sigmas[index];
|
var oldVariableMap = variableMap;
|
||||||
for (int j = successors.length - 1; j >= 0; --j) {
|
for (int j = successors.length - 1; j >= 0; --j) {
|
||||||
int successor = successors[j];
|
int successor = successors[j];
|
||||||
Task next = new Task();
|
var variables = oldVariableMap.clone();
|
||||||
next.variables = variableMap.clone();
|
pendingVariableMap[successor] = variables;
|
||||||
next.block = program.basicBlockAt(successor);
|
stack.push(program.basicBlockAt(successor));
|
||||||
if (nextSigmas != null) {
|
variableMap = variables;
|
||||||
for (Sigma sigma : nextSigmas) {
|
|
||||||
for (Outgoing outgoing : sigma.getOutgoings()) {
|
|
||||||
if (outgoing.getTarget().getIndex() == successor) {
|
|
||||||
next.variables[sigma.getValue().getIndex()] = outgoing.getValue();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stack.push(next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IntSet exceptionHandlingSuccessors = new IntHashSet();
|
IntSet exceptionHandlingSuccessors = new IntHashSet();
|
||||||
|
@ -387,14 +350,20 @@ public class PhiUpdater {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int successor : cfg.outgoingEdges(index)) {
|
for (int successor : cfg.outgoingEdges(index)) {
|
||||||
|
variableMap = domTree.immediateDominatorOf(successor) == currentBlock.getIndex()
|
||||||
|
? pendingVariableMap[successor]
|
||||||
|
: oldVariableMap.clone();
|
||||||
|
if (nextSigmas != null) {
|
||||||
|
for (var sigma : nextSigmas) {
|
||||||
|
for (var outgoing : sigma.getOutgoings()) {
|
||||||
|
if (outgoing.getTarget().getIndex() == successor) {
|
||||||
|
outgoing.setValue(define(outgoing.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
renameOutgoingPhis(successor, exceptionHandlingSuccessors.contains(successor));
|
renameOutgoingPhis(successor, exceptionHandlingSuccessors.contains(successor));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sigmas[index] != null) {
|
|
||||||
for (Sigma sigma : sigmas[index]) {
|
|
||||||
sigma.setValue(use(sigma.getValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,7 +414,6 @@ public class PhiUpdater {
|
||||||
|
|
||||||
for (int j = 0; j < phis.size(); ++j) {
|
for (int j = 0; j < phis.size(); ++j) {
|
||||||
Phi phi = phis.get(j);
|
Phi phi = phis.get(j);
|
||||||
Variable originalVar = program.variableAt(phiIndexes[j]);
|
|
||||||
Variable var = variableMap[phiIndexes[j]];
|
Variable var = variableMap[phiIndexes[j]];
|
||||||
if (var != null) {
|
if (var != null) {
|
||||||
List<Variable> versions = definedVersions.get(phiIndexes[j]);
|
List<Variable> versions = definedVersions.get(phiIndexes[j]);
|
||||||
|
@ -458,42 +426,38 @@ public class PhiUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable sigmaVar = applySigmaRename(program.basicBlockAt(successor), originalVar);
|
|
||||||
Incoming incoming = new Incoming();
|
Incoming incoming = new Incoming();
|
||||||
incoming.setSource(currentBlock);
|
incoming.setSource(currentBlock);
|
||||||
incoming.setValue(sigmaVar != originalVar ? sigmaVar : var);
|
incoming.setValue(var);
|
||||||
phi.getIncomings().add(incoming);
|
phi.getIncomings().add(incoming);
|
||||||
phi.getReceiver().setDebugName(var.getDebugName());
|
phi.getReceiver().setDebugName(var.getDebugName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (var phi : program.basicBlockAt(successor).getPhis()) {
|
||||||
|
for (var incoming : phi.getIncomings()) {
|
||||||
|
if (incoming.getSource() == currentBlock) {
|
||||||
|
var value = variableMap[incoming.getValue().getIndex()];
|
||||||
|
if (value != null) {
|
||||||
|
incoming.setValue(value);
|
||||||
|
usedPhis.set(value.getIndex());
|
||||||
|
} else {
|
||||||
|
usedPhis.set(incoming.getValue().getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Variable applySigmaRename(BasicBlock target, Variable var) {
|
private void markAssignment(Variable var, BasicBlock targetBlock) {
|
||||||
Sigma[] blockSigmas = sigmas[currentBlock.getIndex()];
|
|
||||||
if (blockSigmas == null) {
|
|
||||||
return var;
|
|
||||||
}
|
|
||||||
for (Sigma sigma : blockSigmas) {
|
|
||||||
if (sigma.getValue() != var) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Outgoing outgoing : sigma.getOutgoings()) {
|
|
||||||
if (outgoing.getTarget() == target) {
|
|
||||||
return outgoing.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return var;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void markAssignment(Variable var) {
|
|
||||||
if (variableDefinitionCount[var.getIndex()] < 2) {
|
if (variableDefinitionCount[var.getIndex()] < 2) {
|
||||||
variableDefined[var.getIndex()] = true;
|
variableDefined[var.getIndex()] = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Deque<BasicBlock> worklist = new ArrayDeque<>();
|
Deque<BasicBlock> worklist = new ArrayDeque<>();
|
||||||
worklist.push(currentBlock);
|
worklist.push(targetBlock);
|
||||||
|
var isCurrentlyFrontier = currentBlock != targetBlock && cfg.incomingEdgesCount(targetBlock.getIndex()) > 1;
|
||||||
|
|
||||||
if (variableDefined[var.getIndex()]) {
|
if (variableDefined[var.getIndex()]) {
|
||||||
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
||||||
|
@ -505,7 +469,8 @@ public class PhiUpdater {
|
||||||
|
|
||||||
while (!worklist.isEmpty()) {
|
while (!worklist.isEmpty()) {
|
||||||
BasicBlock block = worklist.pop();
|
BasicBlock block = worklist.pop();
|
||||||
int[] frontiers = domFrontiers[block.getIndex()];
|
var frontiers = isCurrentlyFrontier ? new int[] { block.getIndex() } : domFrontiers[block.getIndex()];
|
||||||
|
isCurrentlyFrontier = false;
|
||||||
|
|
||||||
if (frontiers != null) {
|
if (frontiers != null) {
|
||||||
for (int frontier : frontiers) {
|
for (int frontier : frontiers) {
|
||||||
|
|
|
@ -29,7 +29,6 @@ import java.io.InputStreamReader;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.rules.TestName;
|
import org.junit.rules.TestName;
|
||||||
|
@ -86,9 +85,6 @@ public class NullnessAnalysisTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
// Fix this issue and un-ignore
|
|
||||||
// Also, un-ignore TestYear.test_isLeap
|
|
||||||
public void nonDominatedBranch2() {
|
public void nonDominatedBranch2() {
|
||||||
test();
|
test();
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,11 +7,11 @@ $ifNonNull
|
||||||
@b := invokeStatic `Foo.g()LBar;`
|
@b := invokeStatic `Foo.g()LBar;`
|
||||||
if @b !== null then goto $joint else goto $ifNull
|
if @b !== null then goto $joint else goto $ifNull
|
||||||
$ifNull
|
$ifNull
|
||||||
return @a_2
|
return @a_1
|
||||||
$joint
|
$joint
|
||||||
@c := phi @a_1 from $start, @b_1 from $ifNonNull
|
@c := phi @a_2 from $start, @b_2 from $ifNonNull
|
||||||
return @c
|
return @c
|
||||||
|
|
||||||
// NULLABLE c
|
// NULLABLE c
|
||||||
// NULL a_1
|
// NULL a_2
|
||||||
// NOT_NULL a_2
|
// NOT_NULL a_1
|
|
@ -1,10 +1,12 @@
|
||||||
var @this as this // 0
|
var @this as this // 0
|
||||||
$0
|
|
||||||
|
$start
|
||||||
@a := invokeStatic `Foo.f()LBar;`
|
@a := invokeStatic `Foo.f()LBar;`
|
||||||
if @a === null then goto $2 else goto $1
|
if @a === null then goto $joint else goto $ifNonNull
|
||||||
$1
|
$ifNonNull
|
||||||
goto $2
|
goto $joint
|
||||||
$2
|
$joint
|
||||||
@c := phi @a_1 from $0, @a_2 from $1
|
@c := phi @a_2 from $start, @a_1 from $ifNonNull
|
||||||
@d := @a
|
@a_3 := phi @a_2 from $start, @a_1 from $ifNonNull
|
||||||
|
@d := @a_3
|
||||||
return @c
|
return @c
|
||||||
|
|
|
@ -76,7 +76,6 @@ import java.time.temporal.TemporalQueries;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.teavm.classlib.java.time.AbstractDateTimeTest;
|
import org.teavm.classlib.java.time.AbstractDateTimeTest;
|
||||||
import org.teavm.junit.SkipPlatform;
|
import org.teavm.junit.SkipPlatform;
|
||||||
|
@ -332,8 +331,6 @@ public class TestYear extends AbstractDateTimeTest {
|
||||||
// isLeap()
|
// isLeap()
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
|
||||||
// Fails due to bug in nullness analysis
|
|
||||||
public void test_isLeap() {
|
public void test_isLeap() {
|
||||||
assertEquals(Year.of(1999).isLeap(), false);
|
assertEquals(Year.of(1999).isLeap(), false);
|
||||||
assertEquals(Year.of(2000).isLeap(), true);
|
assertEquals(Year.of(2000).isLeap(), true);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user