summaryrefslogtreecommitdiff
path: root/chapter18/src
diff options
context:
space:
mode:
Diffstat (limited to 'chapter18/src')
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/Parser.java12
-rw-r--r--chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java5
-rw-r--r--chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java22
3 files changed, 33 insertions, 6 deletions
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
index 3f4484f5..a6185aa0 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/Parser.java
@@ -694,10 +694,16 @@ public class Parser {
Node expr;
if( match("=") ) {
expr = parseAsgn();
- // `val` is always final
+ // TOP means val and val is always final
xfinal = (t==Type.TOP) ||
- // var is always not-final, final if no Bang AND TMP since primitives are not-final by default
- (t!=Type.BOTTOM && !hasBang && (t instanceof TypeMemPtr));
+ // BOTTOM is var and var is always not-final
+ (t!=Type.BOTTOM &&
+ // no Bang AND
+ !hasBang &&
+ // not-null (expecting null to be set to not-null)
+ expr._type != Type.NIL &&
+ // Pointers are final by default; int/flt are not-final by default.
+ (t instanceof TypeNil));
// var/val, then type comes from expression
if( inferType ) {
if( expr._type==Type.NIL )
diff --git a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
index 5620a2d2..d0d86b79 100644
--- a/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
+++ b/chapter18/src/main/java/com/seaofnodes/simple/node/ScopeNode.java
@@ -209,6 +209,7 @@ public class ScopeNode extends MemMergeNode {
: loop.setDef(v._idx,new PhiNode(v._name, v.lazyGLB(), loop.ctrl(), loop.in(loop.update(v,null)._idx),null).peephole());
setDef(v._idx,old);
}
+ assert !v._final || st==null;
if( st!=null ) setDef(v._idx,st); // Set new value
return v;
}
@@ -258,7 +259,7 @@ public class ScopeNode extends MemMergeNode {
for( int i=2; i<nIns(); i++ )
// For lazy phis on loops we use a sentinel
// that will trigger phi creation on update
- dup.addDef(loop ? this : in(i));
+ dup.addDef(loop && !_vars.at(i)._final ? this : in(i));
return dup;
}
@@ -327,6 +328,8 @@ public class ScopeNode extends MemMergeNode {
// Fill in the backedge of any inserted Phis
void _endLoop( ScopeNode scope, Node back, Node exit ) {
for( int i=2; i<nIns(); i++ ) {
+ if( _vars.at(i)._final ) continue; // Final vars did not get modified in the loop
+ if( _vars.at(i).type().isHighOrConst() ) continue; // Cannot lift higher than a constant, so no Phi
if( back.in(i) != scope ) {
PhiNode phi = (PhiNode)in(i);
assert phi.region()==scope.ctrl() && phi.in(2)==null;
diff --git a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
index 39edb352..8852537b 100644
--- a/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
+++ b/chapter18/src/test/java/com/seaofnodes/simple/Chapter18Test.java
@@ -13,7 +13,7 @@ public class Chapter18Test {
"""
return 0;
""");
- code.parse().opto().typeCheck().GCM();
+ code.parse().opto().typeCheck().GCM().localSched();
assertEquals("return 0;", code._stop.toString());
assertEquals("0", Eval2.eval(code, 0));
}
@@ -179,6 +179,24 @@ return 2;
assertEquals("1", Eval2.eval(code, 0));
}
+ @Test
+ public void testFcn8() {
+ CodeGen code = new CodeGen(
+"""
+{int -> int}? i2i = null;
+var id = {{int->int} f-> return f;};
+for(;;) {
+ if (i2i) return i2i(arg);
+ var x = {int i-> return i;};
+ arg = x(3);
+ i2i = id(x);
+}
+""");
+ code.parse().opto().typeCheck().GCM().localSched();
+ assertEquals("Stop[ return x( Phi(Loop,arg,x( 3))); return Parm_i(x,int,3,Phi_arg); ]", code._stop.toString());
+ assertEquals("3", Eval2.eval(code, 0));
+ }
+
// Function break
@Test
@@ -203,7 +221,7 @@ return 1;
public void testErr2() {
CodeGen code = new CodeGen(
"""
-{int -> int}? i2i = { int i -> return i; };
+{int -> int}? !i2i = { int i -> return i; };
for(;;) {
if (i2i(2) == arg) break;
i2i = null;