mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-03 05:44:10 -08:00
Fixing bugs in nullness analyzer
This commit is contained in:
parent
5fd95f21cb
commit
aef1e2e206
|
@ -70,4 +70,8 @@ public class Variable implements VariableReader {
|
|||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public String getDisplayLabel() {
|
||||
return label != null ? label : String.valueOf(index);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,9 +84,9 @@ class NullnessInformationBuilder {
|
|||
}
|
||||
|
||||
private void extendProgram() {
|
||||
notNullVariables.set(0);
|
||||
insertAdditionalVariables();
|
||||
|
||||
notNullVariables.set(0);
|
||||
Variable[] parameters = new Variable[methodDescriptor.parameterCount() + 1];
|
||||
for (int i = 0; i < parameters.length; ++i) {
|
||||
parameters[i] = program.variableAt(i);
|
||||
|
@ -123,7 +123,7 @@ class NullnessInformationBuilder {
|
|||
for (BasicBlock block : program.getBasicBlocks()) {
|
||||
for (Phi phi : block.getPhis()) {
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
builder.addEdge(incoming.getSource().getIndex(), phi.getReceiver().getIndex());
|
||||
builder.addEdge(incoming.getValue().getIndex(), phi.getReceiver().getIndex());
|
||||
}
|
||||
}
|
||||
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||
|
@ -183,6 +183,7 @@ class NullnessInformationBuilder {
|
|||
continue;
|
||||
}
|
||||
visited[node] = true;
|
||||
notNullVariables.set(node);
|
||||
for (int successor : assignmentGraph.outgoingEdges(node)) {
|
||||
if (sccIndexes[successor] == 0 || sccIndexes[successor] != sccIndexes[node]) {
|
||||
if (--notNullPredecessorsLeft[successor] == 0) {
|
||||
|
@ -203,6 +204,10 @@ class NullnessInformationBuilder {
|
|||
public State visit(BasicBlock block) {
|
||||
currentState = new State();
|
||||
|
||||
if (block.getExceptionVariable() != null) {
|
||||
notNullVariables.set(block.getIndex());
|
||||
}
|
||||
|
||||
currentBlock = block;
|
||||
if (nullSuccessors.containsKey(block.getIndex())) {
|
||||
int varIndex = nullSuccessors.remove(block.getIndex());
|
||||
|
|
|
@ -488,7 +488,7 @@ public class PhiUpdater {
|
|||
private Variable use(Variable var) {
|
||||
Variable mappedVar = variableMap[var.getIndex()];
|
||||
if (mappedVar == null) {
|
||||
throw new AssertionError("Variable used before definition: " + var.getIndex());
|
||||
throw new AssertionError("Variable used before definition: " + var.getDisplayLabel());
|
||||
}
|
||||
usedPhis.set(mappedVar.getIndex());
|
||||
return mappedVar;
|
||||
|
|
|
@ -60,6 +60,21 @@ public class NullnessAnalysisTest {
|
|||
test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void phiPropagation() {
|
||||
test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void tryCatchJoint() {
|
||||
test();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void loop() {
|
||||
test();
|
||||
}
|
||||
|
||||
private void test() {
|
||||
String baseName = "model/analysis/nullness/" + name.getMethodName();
|
||||
String originalResourceName = baseName + ".original.txt";
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@first := field `Foo.first` @this as `LBar;`
|
||||
@checkedFirst := nullCheck @first
|
||||
goto $head
|
||||
$head
|
||||
@current := phi @checkedFirst from $start, @checkedNext from $body
|
||||
@isLast := field `Bar.last` @current as Z
|
||||
@current_2 := nullCheck @current
|
||||
if @isLast == 0 then goto $exit else goto $body
|
||||
$body
|
||||
@next := field `Bar.next` @current_2 as `LBar;`
|
||||
@checkedNext := nullCheck @next
|
||||
goto $head
|
||||
$exit
|
||||
@value := field `Bar.value` @current_2 as `Ljava/lang/Object;`
|
||||
return @value
|
||||
|
||||
// NOT_NULL current
|
||||
// NOT_NULL current_2
|
|
@ -0,0 +1,17 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@first := field `Foo.first` @this as `LBar;`
|
||||
@checkedFirst := nullCheck @first
|
||||
goto $head
|
||||
$head
|
||||
@current := phi @checkedFirst from $start, @checkedNext from $body
|
||||
@isLast := field `Bar.last` @current as Z
|
||||
if @isLast == 0 then goto $exit else goto $body
|
||||
$body
|
||||
@next := field `Bar.next` @current as `LBar;`
|
||||
@checkedNext := nullCheck @next
|
||||
goto $head
|
||||
$exit
|
||||
@value := field `Bar.value` @current as `Ljava/lang/Object;`
|
||||
return @value
|
|
@ -1,4 +1,7 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@cond := invokeStatic `Cond.get()Ljava/lang/Object;`
|
||||
if @cond === null then goto $ifNull else goto $ifNotNull
|
||||
$ifNull
|
||||
@cond_1 := null
|
||||
|
@ -14,8 +17,8 @@ $join
|
|||
@d := phi @a from $ifNull, @b_1 from $ifNotNull
|
||||
return @c
|
||||
|
||||
// NULLABLE: b
|
||||
// NOT_NULL: b_1
|
||||
// NOT_NULL: a
|
||||
// NULLABLE: c
|
||||
// NOT_NULL: d
|
||||
// NULLABLE b
|
||||
// NOT_NULL b_1
|
||||
// NOT_NULL a
|
||||
// NULLABLE c
|
||||
// NOT_NULL d
|
|
@ -1,4 +1,7 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@cond := invokeStatic `Cond.get()Ljava/lang/Object;`
|
||||
if @cond === null then goto $ifNull else goto $ifNotNull
|
||||
$ifNull
|
||||
@a := 'qwe'
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@a := invokeStatic `Value.extract()Ljava/lang/String;`
|
||||
@cond := invokeStatic `Cond.invoke()I`
|
||||
if @cond == 0 then goto $if0 else goto $else
|
||||
$if0
|
||||
@len := invokeStatic `Value.extractLen()I`
|
||||
if @len == 0 then goto $ifEmpty else goto $ifNotEmpty
|
||||
$ifEmpty
|
||||
invokeStatic `Foo.f(Ljava/lang/String;)V` @a
|
||||
goto $joinIf0
|
||||
$ifNotEmpty
|
||||
invokeVirtual `java.lang.String.trim()Ljava/lang/String;` @a
|
||||
@a_1 := nullCheck @a
|
||||
goto $joinIf0
|
||||
$joinIf0
|
||||
@a_2 := phi @a from $ifEmpty, @a_1 from $ifNotEmpty
|
||||
invokeStatic `Foo.g(Ljava/lang/String;)V` @a_2
|
||||
goto $join
|
||||
$else
|
||||
invokeStatic `Foo.bar(Ljava/lang/String;)V` @a
|
||||
goto $join
|
||||
$join
|
||||
@a_3 := phi @a_2 from $joinIf0, @a from $else
|
||||
invokeStatic `Foo.baz(Ljava/lang/String;)V` @a_3
|
||||
return
|
|
@ -0,0 +1,24 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@a := invokeStatic `Value.extract()Ljava/lang/String;`
|
||||
@cond := invokeStatic `Cond.invoke()I`
|
||||
if @cond == 0 then goto $if0 else goto $else
|
||||
$if0
|
||||
@len := invokeStatic `Value.extractLen()I`
|
||||
if @len == 0 then goto $ifEmpty else goto $ifNotEmpty
|
||||
$ifEmpty
|
||||
invokeStatic `Foo.f(Ljava/lang/String;)V` @a
|
||||
goto $joinIf0
|
||||
$ifNotEmpty
|
||||
invokeVirtual `java.lang.String.trim()Ljava/lang/String;` @a
|
||||
goto $joinIf0
|
||||
$joinIf0
|
||||
invokeStatic `Foo.g(Ljava/lang/String;)V` @a
|
||||
goto $join
|
||||
$else
|
||||
invokeStatic `Foo.bar(Ljava/lang/String;)V` @a
|
||||
goto $join
|
||||
$join
|
||||
invokeStatic `Foo.baz(Ljava/lang/String;)V` @a
|
||||
return
|
|
@ -0,0 +1,29 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@bar := invokeVirtual `Foo.bar()LBar;` @this
|
||||
@cond := invokeVirtual `Foo.cond()I` @this
|
||||
if @cond == 0 then goto $if0 else goto $else
|
||||
$if0
|
||||
invokeVirtual `Bar.baz()LBar;` @bar
|
||||
@bar_1 := nullCheck @bar
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $if0Handler
|
||||
@bar_2 := ephi @bar, @bar_1
|
||||
$if0Handler
|
||||
goto $join
|
||||
$else
|
||||
invokeVirtual `Bar.baz()LBar;` @bar
|
||||
@bar_3 := nullCheck @bar
|
||||
goto $else1
|
||||
$else1
|
||||
invokeVirtual `Bar.baz2()LBar;` @bar_3
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $elseHandler
|
||||
$elseHandler
|
||||
goto $join
|
||||
$join
|
||||
@bar_4 := phi @bar_1 from $if0, @bar_2 from $if0Handler, @bar_3 from $else1, @bar_3 from $elseHandler
|
||||
return @bar_4
|
||||
|
||||
// NULLABLE bar_2
|
|
@ -0,0 +1,23 @@
|
|||
var @this as this
|
||||
|
||||
$start
|
||||
@bar := invokeVirtual `Foo.bar()LBar;` @this
|
||||
@cond := invokeVirtual `Foo.cond()I` @this
|
||||
if @cond == 0 then goto $if0 else goto $else
|
||||
$if0
|
||||
invokeVirtual `Bar.baz()LBar;` @bar
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $if0Handler
|
||||
$if0Handler
|
||||
goto $join
|
||||
$else
|
||||
invokeVirtual `Bar.baz()LBar;` @bar
|
||||
goto $else1
|
||||
$else1
|
||||
invokeVirtual `Bar.baz2()LBar;` @bar
|
||||
goto $join
|
||||
catch java.lang.RuntimeException goto $elseHandler
|
||||
$elseHandler
|
||||
goto $join
|
||||
$join
|
||||
return @bar
|
Loading…
Reference in New Issue
Block a user