diff options
Diffstat (limited to 'chapter25/src/main/java')
3 files changed, 37 insertions, 22 deletions
diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java index ff52c93b..975bce3d 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeFunPtr.java @@ -59,9 +59,19 @@ public class TypeFunPtr extends TypeNil { if( f2==fun ) return fun; return VISIT.isEmpty() ? f2.free(fun) : f2.delayFree(fun); } - public static TypeFunPtr make( boolean nil, Type[] sig, Type ret ) { return make((byte)(nil ? 3 : 2),true,sig,ret, XInt.FULL); } + // Trim trailing args which match the default. + private static TypeFunPtr makeAdjusted( byte nil, boolean open, Type[] sig, Type ret, int[] fidxs ) { + Type def = open ? TypeScalar.BOT : TypeScalar.TOP; + int nargs = sig.length; + while( nargs > 0 && sig[nargs-1] == def ) + nargs--; + if( nargs != sig.length ) + sig = nargs == 0 ? ARG_EMPTY : Arrays.copyOf(sig,nargs); + return make(nil,open,sig,ret,fidxs); + } + public static TypeFunPtr make( boolean nil, Type[] sig, Type ret ) { return makeAdjusted((byte)(nil ? 3 : 2),true,sig,ret, XInt.FULL); } public static TypeFunPtr make1( byte nil, boolean open, Type[] sig, Type ret, int fidx ) { - return make(nil,open,sig,ret,XInt.make(fidx)); + return makeAdjusted(nil,open,sig,ret,XInt.make(fidx)); } @@ -94,6 +104,12 @@ public class TypeFunPtr extends TypeNil { ts.add(CALLOC); ts.add(make((byte)2,false,TINT,TypeInteger.I32, XInt.SET1)); ts.add(make((byte)2,true ,TINT,TypeInteger.BOT, XInt.SET3)); + ts.add(make1((byte)2,true, + new Type[]{TypeInteger.BOT}, + TypeInteger.BOT, 65)); + ts.add(make1((byte)2,true, + new Type[]{TypeInteger.BOT, TypeScalar.BOT}, + TypeInteger.BOT, 65)); } private static final Type[] ARG_EMPTY = new Type[0]; diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java index 420dea55..106dee49 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/TypeMem.java @@ -111,6 +111,8 @@ public class TypeMem extends Type { ts.add(BOT); ts.add(SELF_MEM); ts.add(START); + ts.add(make(2,TypeInteger.ZERO,true,false,true,XInt.EMPTY,XInt.make(2))); + ts.add(make(2,TypeInteger.BOT,false,false,false,XInt.EMPTY,XInt.FULL)); } @Override @@ -128,16 +130,11 @@ public class TypeMem extends Type { Type mt = _t.meet(that._t); int[] fidxs = XInt.meet( _escFs, that._escFs ); int[] aliases= XInt.meet( _escAs, that._escAs ); - // Singleton & class facts are kept only when both sides agree. - - // Final is kept if either side is final, merging a final & non-final - // memory can be argued either way here: - - // - Keep it: merging a final & non-final memory means a later Store - // update will be flagged as an error. - // - Lose it: merging a final & non-final memory means a later Load - // cannot be promised the memory is unchanging. - return make(alias, mt, _one & that._one, _clz & that._clz, _final | that._final, fidxs, aliases); + // Singleton and class facts are kept only when both sides agree. + // Finality is a low-side fact, and flips on the dual side. + boolean highAlias1 = (this._alias==1 && this._t.isHigh()) || (that._alias==1 && that._t.isHigh()); + boolean xfinal = highAlias1 ? (_final & that._final) : (_final | that._final); + return make(alias, mt, _one & that._one, _clz & that._clz, xfinal, fidxs, aliases); } @Override diff --git a/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java b/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java index e3054a73..752c1419 100644 --- a/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java +++ b/chapter25/src/main/java/com/seaofnodes/simple/type/XInt.java @@ -166,22 +166,24 @@ public abstract class XInt { if( xs==ys ) return xs; boolean isX=true, isY=true; int min = Math.min(xs.length,ys.length); - for( int i=1; i<min; i++ ) { - if( (xs[i] | ys[i])!=xs[i] ) isX=false; - if( (xs[i] | ys[i])!=ys[i] ) isY=false; + int max = Math.max(xs.length,ys.length); + for( int i=1; i<max; i++ ) { + int x = i < xs.length ? xs[i] : isHigh(xs) ? -1 : 0; + int y = i < ys.length ? ys[i] : isHigh(ys) ? -1 : 0; + if( (x | y)!=x ) isX=false; + if( (x | y)!=y ) isY=false; } - if( !isHigh(xs) && min < ys.length ) - isX = false; // YS has *some* more bits set, and XS does not - if( !isHigh(ys) && min < xs.length ) - isY = false; // XS has *some* more bits set, and YS does not if( isX ) return xs; if( isY ) return ys; // Get a free one - int[] ms = free(Math.max(xs.length,ys.length)); + int[] ms = free(max); for( int i=1; i<min; i++ ) ms[i] = xs[i] | ys[i]; - if( min < xs.length ) System.arraycopy(xs,min,ms,min,xs.length-min); - if( min < ys.length ) System.arraycopy(ys,min,ms,min,ys.length-min); + for( int i=min; i<ms.length; i++ ) { + int x = i < xs.length ? xs[i] : isHigh(xs) ? -1 : 0; + int y = i < ys.length ? ys[i] : isHigh(ys) ? -1 : 0; + ms[i] = x | y; + } return intern(ms); } |
