summaryrefslogtreecommitdiff
path: root/chapter18/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'chapter18/src/main/java')
-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
2 files changed, 13 insertions, 4 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;