1 cananian 1.1.2.1 // SCC.java, created Fri Sep 18 17:45:07 1998 by cananian 2 cananian 1.1.2.1 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Analysis.SizeOpt; 5 cananian 1.1.2.1 6 cananian 1.1.2.2 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.3 import harpoon.Analysis.Context; 8 cananian 1.3 import harpoon.Analysis.GenericContextFactory; 9 cananian 1.1.2.1 import harpoon.Analysis.Maps.ConstMap; 10 cananian 1.1.2.1 import harpoon.Analysis.Maps.ExactTypeMap; 11 cananian 1.1.2.1 import harpoon.Analysis.Maps.ExecMap; 12 cananian 1.1.2.1 import harpoon.Analysis.Maps.UseDefMap; 13 cananian 1.1.2.17 import harpoon.Analysis.Quads.DefiniteInitOracle; 14 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 15 cananian 1.1.2.1 import harpoon.ClassFile.HCode; 16 cananian 1.1.2.1 import harpoon.ClassFile.HCodeEdge; 17 cananian 1.1.2.1 import harpoon.ClassFile.HCodeElement; 18 cananian 1.1.2.2 import harpoon.ClassFile.HCodeFactory; 19 cananian 1.1.2.1 import harpoon.ClassFile.HField; 20 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 21 cananian 1.1.2.1 import harpoon.ClassFile.Linker; 22 cananian 1.1.2.1 import harpoon.IR.Quads.AGET; 23 cananian 1.1.2.1 import harpoon.IR.Quads.ALENGTH; 24 cananian 1.1.2.1 import harpoon.IR.Quads.ANEW; 25 cananian 1.1.2.1 import harpoon.IR.Quads.ASET; 26 cananian 1.1.2.1 import harpoon.IR.Quads.CALL; 27 cananian 1.1.2.1 import harpoon.IR.Quads.CJMP; 28 cananian 1.1.2.1 import harpoon.IR.Quads.COMPONENTOF; 29 cananian 1.1.2.1 import harpoon.IR.Quads.CONST; 30 cananian 1.1.2.1 import harpoon.IR.Quads.Edge; 31 cananian 1.1.2.1 import harpoon.IR.Quads.FOOTER; 32 cananian 1.1.2.1 import harpoon.IR.Quads.GET; 33 cananian 1.1.2.1 import harpoon.IR.Quads.HEADER; 34 cananian 1.1.2.1 import harpoon.IR.Quads.INSTANCEOF; 35 cananian 1.1.2.1 import harpoon.IR.Quads.METHOD; 36 cananian 1.1.2.1 import harpoon.IR.Quads.MONITORENTER; 37 cananian 1.1.2.1 import harpoon.IR.Quads.MONITOREXIT; 38 cananian 1.1.2.1 import harpoon.IR.Quads.MOVE; 39 cananian 1.1.2.1 import harpoon.IR.Quads.NEW; 40 cananian 1.1.2.1 import harpoon.IR.Quads.NOP; 41 cananian 1.1.2.1 import harpoon.IR.Quads.OPER; 42 cananian 1.1.2.1 import harpoon.IR.Quads.OperVisitor; 43 cananian 1.1.2.1 import harpoon.IR.Quads.PHI; 44 cananian 1.1.2.1 import harpoon.IR.Quads.Qop; 45 cananian 1.1.2.1 import harpoon.IR.Quads.Quad; 46 cananian 1.1.2.2 import harpoon.IR.Quads.QuadFactory; 47 cananian 1.1.2.1 import harpoon.IR.Quads.QuadSSI; 48 cananian 1.1.2.1 import harpoon.IR.Quads.QuadVisitor; 49 cananian 1.1.2.1 import harpoon.IR.Quads.RETURN; 50 cananian 1.1.2.1 import harpoon.IR.Quads.SET; 51 cananian 1.1.2.1 import harpoon.IR.Quads.SIGMA; 52 cananian 1.1.2.1 import harpoon.IR.Quads.SWITCH; 53 cananian 1.1.2.1 import harpoon.IR.Quads.THROW; 54 cananian 1.1.2.1 import harpoon.IR.Quads.TYPESWITCH; 55 cananian 1.1.2.1 import harpoon.Temp.Temp; 56 cananian 1.1.2.1 import harpoon.Temp.TempMap; 57 cananian 1.9 import net.cscott.jutil.Default; 58 cananian 1.1.2.1 import harpoon.Util.HClassUtil; 59 cananian 1.1.2.9 import harpoon.Util.ParseUtil; 60 cananian 1.1.2.20 import harpoon.Util.Collections.WorkSet; 61 cananian 1.1.2.2 import harpoon.Util.Worklist; 62 cananian 1.9 import net.cscott.jutil.AggregateMapFactory; 63 cananian 1.9 import net.cscott.jutil.AggregateSetFactory; 64 cananian 1.9 import net.cscott.jutil.Factories; 65 cananian 1.9 import net.cscott.jutil.GenericMultiMap; 66 cananian 1.9 import net.cscott.jutil.MapSet; 67 cananian 1.9 import net.cscott.jutil.MultiMap; 68 cananian 1.9 import net.cscott.jutil.MultiMapSet; 69 cananian 1.1.2.1 70 cananian 1.1.2.2 import java.lang.reflect.Modifier; 71 cananian 1.1.2.4 import java.util.Arrays; 72 cananian 1.1.2.3 import java.util.ArrayList; 73 cananian 1.1.2.2 import java.util.Collection; 74 cananian 1.1.2.1 import java.util.HashMap; 75 cananian 1.1.2.1 import java.util.HashSet; 76 cananian 1.1.2.2 import java.util.Iterator; 77 cananian 1.1.2.3 import java.util.List; 78 cananian 1.1.2.1 import java.util.Map; 79 cananian 1.1.2.1 import java.util.Set; 80 cananian 1.9 81 cananian 1.9 import net.cscott.jutil.Util; 82 cananian 1.1.2.1 /** 83 cananian 1.1.2.1 * <code>BitWidthAnalysis</code> implements Sparse Conditional Constant 84 cananian 1.1.2.1 * Propagation, with extensions to allow type and bitwidth analysis. 85 cananian 1.1.2.1 * It combines the intraprocedural SCC analysis with an interprocedural 86 cananian 1.1.2.1 * driver to infer the widths of object fields. 87 cananian 1.1.2.1 * <p>Only works with quads in SSI form. 88 cananian 1.1.2.1 * 89 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 90 cananian 1.10 * @version $Id: BitWidthAnalysis.java,v 1.10 2004/02/08 03:20:22 cananian Exp $ 91 cananian 1.1.2.1 */ 92 cananian 1.1.2.1 93 cananian 1.1.2.1 public class BitWidthAnalysis implements ExactTypeMap, ConstMap, ExecMap { 94 cananian 1.1.2.14 final static int CONTEXT_SENSITIVITY = 95 cananian 1.1.2.14 Integer.parseInt(System.getProperty("harpoon.sizeopt.context", "0")); 96 cananian 1.1.2.5 final static boolean DEBUG = false; 97 cananian 1.1.2.1 final Linker linker; 98 cananian 1.1.2.2 final HCodeFactory hcf; 99 cananian 1.1.2.2 final ClassHierarchy ch; 100 cananian 1.1.2.17 final DefiniteInitOracle dio; 101 cananian 1.1.2.1 102 cananian 1.1.2.9 public BitWidthAnalysis(Linker linker, HCodeFactory hcf, 103 cananian 1.1.2.9 ClassHierarchy ch, Set roots, String resourceName){ 104 cananian 1.1.2.9 this(linker, hcf, ch, roots, parseResource(linker, resourceName)); 105 cananian 1.1.2.9 } 106 cananian 1.1.2.1 /** Creates a <code>BitWidthAnalysis</code>. */ 107 cananian 1.1.2.2 public BitWidthAnalysis(Linker linker, HCodeFactory hcf, 108 cananian 1.1.2.9 ClassHierarchy ch, Set roots, Set fieldRoots) { 109 cananian 1.4.2.1 assert hcf.getCodeName().equals(QuadSSI.codename); 110 cananian 1.1.2.2 this.linker = linker; 111 cananian 1.1.2.2 this.hcf = hcf; 112 cananian 1.1.2.2 this.ch = ch; 113 cananian 1.1.2.17 this.dio = new DefiniteInitOracle(hcf, ch); 114 cananian 1.1.2.9 analyze(roots, fieldRoots); 115 cananian 1.1.2.5 /* accounting: */ 116 cananian 1.1.2.5 long before=0, before8=0, after=0, after8=0; 117 cananian 1.10 for (Object hfO : Vf.keySet()) { 118 cananian 1.10 HField hf = (HField) hfO; 119 cananian 1.1.2.5 HClass ty = hf.getType(); 120 cananian 1.1.2.5 if (ty==HClass.Byte) { before+=8+7; before8+=1; } 121 cananian 1.1.2.5 else if (ty==HClass.Short) { before+=16+15; before8+=2; } 122 cananian 1.1.2.5 else if (ty==HClass.Char) { before+=0+16; before8+=2; } 123 cananian 1.1.2.5 else if (ty==HClass.Boolean) { before+=0+1; before8+=1; } 124 cananian 1.1.2.5 else if (ty==HClass.Int) { before+=32+31; before8+=4; } 125 cananian 1.1.2.5 else if (ty==HClass.Long) { before+=64+63; before8+=8; } 126 cananian 1.1.2.5 else continue; // not an integer type. 127 cananian 1.1.2.5 xBitWidth small= extractWidth((LatticeVal) Vf.get(hf)); 128 cananian 1.1.2.5 after+=small.plusWidth()+small.minusWidth(); 129 cananian 1.1.2.5 // round to byte allocations. 130 cananian 1.1.2.5 int bytes = (Math.max(small.minusWidth(),small.plusWidth())+7)/8; 131 cananian 1.1.2.5 after8 += bytes==3 ? 4 : bytes; 132 cananian 1.1.2.5 } 133 cananian 1.1.2.10 System.out.println("BITWIDTH RESULTS: "+after+"/"+before+" bits; "+ 134 cananian 1.1.2.10 after8+"/"+before8+" bytes"); 135 cananian 1.1.2.6 HashSet flds = new HashSet(5*ch.classes().size()); 136 cananian 1.1.2.6 for (Iterator it=ch.classes().iterator(); it.hasNext(); ) 137 cananian 1.1.2.6 flds.addAll(Arrays.asList(((HClass)it.next()).getFields())); 138 cananian 1.1.2.6 for (Iterator it=flds.iterator(); it.hasNext(); ) 139 cananian 1.1.2.6 if (((HField)it.next()).isStatic()) it.remove(); 140 cananian 1.1.2.6 int ttl = flds.size(); 141 cananian 1.1.2.6 flds.retainAll(fieldMap.keySet()); 142 cananian 1.1.2.6 int lft = flds.size(); 143 cananian 1.1.2.6 for (Iterator it=flds.iterator(); it.hasNext(); ) 144 cananian 1.1.2.6 if (isConst((HField)it.next())) it.remove(); 145 cananian 1.1.2.6 int lss = flds.size(); 146 cananian 1.1.2.6 System.out.println("BITWIDTH RESULTS: "+lss+"/"+lft+"/"+ttl+" unread fields"); 147 cananian 1.1.2.22 System.out.println("TOTAL CLASSES: "+ch.classes().size()); 148 cananian 1.1.2.1 } 149 cananian 1.1.2.1 150 cananian 1.1.2.1 /*-----------------------------*/ 151 cananian 1.1.2.1 // Class state. 152 cananian 1.1.2.14 /** Base Context */ 153 cananian 1.3 final Context base = 154 cananian 1.3 new GenericContextFactory(CONTEXT_SENSITIVITY, true) 155 cananian 1.3 .makeEmptyContext(); 156 cananian 1.1.2.14 /** Set of all executable [edge,context] pairs. */ 157 cananian 1.1.2.14 final MultiMapSet Ee = (MultiMapSet) 158 cananian 1.1.2.14 new GenericMultiMap(new AggregateSetFactory()).entrySet(); 159 cananian 1.1.2.14 /** Set of all executable [quad,context] pairs. */ 160 cananian 1.1.2.14 final MultiMapSet Eq = (MultiMapSet) 161 cananian 1.1.2.14 new GenericMultiMap(new AggregateSetFactory()).entrySet(); 162 cananian 1.1.2.14 /** Mapping from <code>Temp</code>s to [context,lattice value] pairs. */ 163 cananian 1.1.2.14 final MultiMap V = new GenericMultiMap 164 cananian 1.1.2.14 (Factories.mapSetFactory(new AggregateMapFactory())); 165 cananian 1.1.2.2 /** Mapping from <code>HField</code>s to lattice values. */ 166 cananian 1.1.2.2 final Map Vf = new HashMap(); 167 cananian 1.1.2.2 /** Mapping from <code>Temp</code>s to <code>Quad</code>s which use them.*/ 168 cananian 1.1.2.2 final MultiMap useMap = new GenericMultiMap(Factories.arrayListFactory); 169 cananian 1.1.2.14 /** Mapping from <code>HField</code>s to 170 cananian 1.1.2.14 * [<code>Quad</code>,<code>Context</code>]) pairs which read them. */ 171 cananian 1.1.2.2 final MultiMap fieldMap = new GenericMultiMap(new AggregateSetFactory()); 172 cananian 1.1.2.9 /** Set of root fields */ 173 cananian 1.1.2.9 final Set fieldRoots = new HashSet(); 174 cananian 1.1.2.3 /** Mapping from <code>HMethod</code>s to <code>METHOD</code>s. */ 175 cananian 1.1.2.3 final Map methodMap = new HashMap(); 176 cananian 1.1.2.14 /** Mapping from [<code>HMethod</code>s, callee context] to 177 cananian 1.1.2.14 * [<code>CALL</code> quad, caller context] pairs which may invoke 178 cananian 1.1.2.14 * them (with the specified callee context). */ 179 cananian 1.1.2.3 final MultiMap callMap = new GenericMultiMap(new AggregateSetFactory()); 180 cananian 1.1.2.14 /** Mapping from [<code>HMethod</code>,callee context] pairs to all 181 cananian 1.1.2.14 * executable <code>RETURN</code>s in that context. */ 182 cananian 1.1.2.6 final MultiMap returnMap = new GenericMultiMap(new AggregateSetFactory()); 183 cananian 1.1.2.14 /** Mapping from [<code>HMethod</code>,callee context] pairs to all 184 cananian 1.1.2.14 * executable <code>THROW</code>s in that context. */ 185 cananian 1.1.2.6 final MultiMap throwMap = new GenericMultiMap(new AggregateSetFactory()); 186 cananian 1.8 /** Keep a list around of all the 'definitely initialized' fields 187 cananian 1.8 * we're asked about. Some of these may need to be thunked with 188 cananian 1.8 * a value because their declaring class ends up never instantiated. 189 cananian 1.8 */ 190 cananian 1.8 final Set diFields = new HashSet(); 191 cananian 1.1.2.1 192 cananian 1.1.2.1 /*---------------------------*/ 193 cananian 1.1.2.1 // public information accessor methods. 194 cananian 1.1.2.1 195 cananian 1.1.2.6 /** Determine whether the given <code>HField</code> is ever read. */ 196 cananian 1.1.2.6 public boolean isRead(HField hf) { 197 cananian 1.1.2.9 return fieldMap.containsKey(hf) || fieldRoots.contains(hf); 198 cananian 1.1.2.6 } 199 cananian 1.1.2.1 /** Determine whether <code>Quad</code> <code>q</code> 200 cananian 1.1.2.1 * is executable. */ 201 cananian 1.1.2.1 public boolean execMap(HCodeElement quad) { 202 cananian 1.1.2.14 return Eq.asMultiMap().containsKey(quad); 203 cananian 1.1.2.1 } 204 cananian 1.1.2.1 /** Determine whether <code>Edge</code> <code>e</code> 205 cananian 1.1.2.1 * is executable. */ 206 cananian 1.1.2.1 public boolean execMap(HCodeEdge edge) { 207 cananian 1.1.2.14 return Ee.asMultiMap().containsKey(edge); 208 cananian 1.1.2.14 } 209 cananian 1.1.2.14 /** Merge types for <code>Temp</code> t over all contexts in which it 210 cananian 1.1.2.14 * is defined. */ 211 cananian 1.1.2.14 private LatticeVal VforAllContexts(Temp t) { 212 cananian 1.1.2.14 // merge over v's type in all contexts. 213 cananian 1.1.2.14 LatticeVal v=null; // start. 214 cananian 1.1.2.14 // V is a map from t to a map from context to value. 215 cananian 1.1.2.14 // get all values for t 216 cananian 1.1.2.14 for (Iterator it=((MapSet)V.getValues(t)).asMap().values().iterator(); 217 cananian 1.1.2.14 it.hasNext(); ) { 218 cananian 1.1.2.14 // merge the values. 219 cananian 1.1.2.14 if (v==null) v = (LatticeVal) it.next(); 220 cananian 1.1.2.14 else v = v.merge((LatticeVal) it.next()); 221 cananian 1.1.2.14 } 222 cananian 1.1.2.14 // return merged value, or null if there were no values. 223 cananian 1.1.2.14 return v; 224 cananian 1.1.2.1 } 225 cananian 1.1.2.1 /** Determine the static type of <code>Temp</code> <code>t</code> in 226 cananian 1.1.2.1 * <code>HMethod</code> <code>m</code>. */ 227 cananian 1.1.2.1 public HClass typeMap(HCodeElement hce, Temp t) { 228 cananian 1.1.2.14 LatticeVal v = VforAllContexts(t); 229 cananian 1.1.2.1 if (v instanceof xClass) return ((xClass)v).type(); 230 cananian 1.1.2.1 return null; 231 cananian 1.1.2.1 } 232 cananian 1.1.2.6 /** Determine the static type of <code>Temp</code> <code>t</code> in 233 cananian 1.1.2.6 * <code>HMethod</code> <code>m</code>. */ 234 cananian 1.1.2.6 public HClass typeMap(HField hf) { 235 cananian 1.1.2.6 LatticeVal v = get( hf ); 236 cananian 1.1.2.6 if (v instanceof xClass) return ((xClass)v).type(); 237 cananian 1.1.2.6 return null; 238 cananian 1.1.2.6 } 239 cananian 1.1.2.1 /** Determine whether the static type of <code>Temp</code> <code>t</code> 240 cananian 1.1.2.1 * defined at <code>hce</code> is exact (or whether the runtime type 241 cananian 1.1.2.1 * could be a subclass of the static type). */ 242 cananian 1.1.2.1 public boolean isExactType(HCodeElement hce, Temp t) { 243 cananian 1.1.2.1 // ignore hce 244 cananian 1.1.2.14 return VforAllContexts(t) instanceof xClassExact; 245 cananian 1.1.2.1 } 246 cananian 1.1.2.1 /** Determine whether the given <code>Temp</code> can possibly be 247 cananian 1.1.2.1 * <code>null</code>. */ 248 cananian 1.1.2.1 public boolean isPossiblyNull(HCodeElement hce, Temp t) { 249 cananian 1.1.2.14 return !(VforAllContexts(t) instanceof xClassNonNull); 250 cananian 1.1.2.1 } 251 cananian 1.1.2.1 /** Determine whether <code>Temp</code> <code>t</code> 252 cananian 1.1.2.1 * has a constant value. */ 253 cananian 1.1.2.1 public boolean isConst(HCodeElement hce, Temp t) { 254 cananian 1.1.2.1 // ignore hce -- this is SSA form 255 cananian 1.1.2.14 return (VforAllContexts(t) instanceof xConstant); 256 cananian 1.1.2.1 } 257 cananian 1.1.2.1 /** Determine the constant value of <code>Temp</code> <code>t</code>. 258 cananian 1.1.2.1 * @exception Error if <code>Temp</code> <code>t</code> is not a constant. 259 cananian 1.1.2.1 */ 260 cananian 1.1.2.1 public Object constMap(HCodeElement hce, Temp t) { 261 cananian 1.1.2.1 // ignore hce -- this is SSA form. 262 cananian 1.1.2.14 LatticeVal v = VforAllContexts(t); 263 cananian 1.1.2.1 if (v instanceof xConstant) return ((xConstant)v).constValue(); 264 cananian 1.1.2.1 throw new Error(t.toString() + " not a constant"); 265 cananian 1.1.2.1 } 266 cananian 1.1.2.6 /** Determine whether <code>HField</code> <code>hf</code> 267 cananian 1.1.2.6 * has a constant value. */ 268 cananian 1.1.2.6 public boolean isConst(HField hf) { 269 cananian 1.1.2.6 return (get(hf) instanceof xConstant); 270 cananian 1.1.2.6 } 271 cananian 1.1.2.6 /** Determine the constant value of <code>HField</code> <code>hf</code>. 272 cananian 1.1.2.6 * @exception Error if <code>HField</code> <code>hf</code> is not a 273 cananian 1.1.2.6 * constant. 274 cananian 1.1.2.6 */ 275 cananian 1.1.2.6 public Object constMap(HField hf) { 276 cananian 1.1.2.6 LatticeVal v = get(hf); 277 cananian 1.1.2.6 if (v instanceof xConstant) return ((xConstant)v).constValue(); 278 cananian 1.1.2.6 throw new Error(hf + " not a constant"); 279 cananian 1.1.2.6 } 280 cananian 1.1.2.1 281 cananian 1.1.2.1 /** Determine the positive bit width of <code>Temp</code> <code>t</code>. 282 cananian 1.1.2.1 */ 283 cananian 1.1.2.1 public int plusWidthMap(HCodeElement hce, Temp t) { 284 cananian 1.1.2.1 // ignore hce -- this is SSA form 285 cananian 1.1.2.14 LatticeVal v = VforAllContexts(t); 286 cananian 1.1.2.1 if (v==null) throw new Error("Unknown "+t); 287 cananian 1.1.2.1 xBitWidth bw = extractWidth(v); 288 cananian 1.1.2.1 return bw.plusWidth(); 289 cananian 1.1.2.1 } 290 cananian 1.1.2.1 /** Determine the negative bit width of <code>Temp</code> <code>t</code>. 291 cananian 1.1.2.1 */ 292 cananian 1.1.2.1 public int minusWidthMap(HCodeElement hce, Temp t) { 293 cananian 1.1.2.1 // ignore hce -- this is SSA form. 294 cananian 1.1.2.14 LatticeVal v = VforAllContexts(t); 295 cananian 1.1.2.1 if (v==null) throw new Error("Unknown "+t); 296 cananian 1.1.2.1 xBitWidth bw = extractWidth(v); 297 cananian 1.1.2.1 return bw.minusWidth(); 298 cananian 1.1.2.1 } 299 cananian 1.1.2.6 /** Determine the positive bit width of <code>HField</code> 300 cananian 1.1.2.6 * <code>hf</code>. 301 cananian 1.1.2.6 */ 302 cananian 1.1.2.6 public int plusWidthMap(HField hf) { 303 cananian 1.1.2.6 LatticeVal v = get( hf ); 304 cananian 1.1.2.6 if (v==null) throw new Error("Unknown "+hf); 305 cananian 1.1.2.6 xBitWidth bw = extractWidth(v); 306 cananian 1.1.2.6 return bw.plusWidth(); 307 cananian 1.1.2.6 } 308 cananian 1.1.2.6 /** Determine the negative bit width of <code>HField</code> 309 cananian 1.1.2.6 * <code>hf</code>. 310 cananian 1.1.2.6 */ 311 cananian 1.1.2.6 public int minusWidthMap(HField hf) { 312 cananian 1.1.2.6 LatticeVal v = get( hf ); 313 cananian 1.1.2.6 if (v==null) throw new Error("Unknown "+hf); 314 cananian 1.1.2.6 xBitWidth bw = extractWidth(v); 315 cananian 1.1.2.6 return bw.minusWidth(); 316 cananian 1.1.2.6 } 317 cananian 1.1.2.1 318 cananian 1.1.2.3 /** Create methodMap, useMap */ 319 cananian 1.1.2.3 private void scan_one(HMethod hm) { 320 cananian 1.1.2.2 HCode hc = hcf.convert(hm); 321 cananian 1.1.2.2 if (hc==null) return; // abstract method. 322 cananian 1.1.2.3 if (DEBUG) System.out.println("SCAN_ONE: "+hm); 323 cananian 1.1.2.2 for (Iterator it=hc.getElementsI(); it.hasNext(); ) { 324 cananian 1.1.2.2 Quad q = (Quad) it.next(); 325 cananian 1.1.2.2 // add entries to useMap. 326 cananian 1.1.2.2 Temp[] used = q.use(); 327 cananian 1.1.2.2 for (int i=0; i<used.length; i++) 328 cananian 1.1.2.2 useMap.add(used[i], q); 329 cananian 1.1.2.3 // add entry to methodMap 330 cananian 1.1.2.3 if (q instanceof METHOD) 331 cananian 1.1.2.3 methodMap.put(hm, q); 332 cananian 1.1.2.2 } 333 cananian 1.1.2.2 } 334 cananian 1.1.2.2 335 cananian 1.1.2.1 /*---------------------------*/ 336 cananian 1.1.2.1 // Analysis code. 337 cananian 1.1.2.1 338 cananian 1.1.2.1 /** Main analysis method. */ 339 cananian 1.1.2.9 private void analyze(Set roots, Set my_fieldRoots) { 340 cananian 1.1.2.1 // Initialize worklists. 341 cananian 1.1.2.1 Worklist Wv = new WorkSet(); // variable worklist. 342 cananian 1.1.2.1 Worklist Wq = new WorkSet(); // block worklist. 343 cananian 1.1.2.2 Worklist Wf = new WorkSet(); // field worklist. 344 cananian 1.1.2.1 345 cananian 1.1.2.1 // Make instance of visitor class. 346 cananian 1.1.2.2 SCCVisitor visitor = new SCCVisitor(Wv, Wq, Wf); 347 cananian 1.1.2.1 348 cananian 1.1.2.3 // make root methods set (ignore classes) 349 cananian 1.1.2.3 List root_methods = new ArrayList(roots); 350 cananian 1.1.2.3 for (Iterator it=root_methods.iterator(); it.hasNext(); ) 351 cananian 1.1.2.3 if (!(it.next() instanceof HMethod)) 352 cananian 1.1.2.3 it.remove(); 353 cananian 1.1.2.3 // all static initializers to root methods set 354 cananian 1.1.2.3 for (Iterator it=ch.classes().iterator(); it.hasNext(); ) { 355 cananian 1.1.2.3 HMethod hm = ((HClass)it.next()).getClassInitializer(); 356 cananian 1.1.2.3 if (hm!=null) root_methods.add(hm); 357 cananian 1.1.2.3 } 358 cananian 1.1.2.3 // put all root methods on the worklist & mark as executable. 359 cananian 1.10 for (Object hmO : root_methods) { 360 cananian 1.10 HMethod hm = (HMethod) hmO; 361 cananian 1.1.2.3 scan_one(hm); 362 cananian 1.1.2.3 METHOD method = (METHOD) methodMap.get(hm); 363 cananian 1.1.2.3 if (method==null) continue; // native method in root set. 364 cananian 1.1.2.14 Wq.push(Default.pair(base, method)); 365 cananian 1.1.2.14 Eq.add(Default.entry(method,base)); 366 cananian 1.1.2.3 // set up parameters. 367 cananian 1.1.2.3 int j=0; 368 cananian 1.1.2.3 if ( !hm.isStatic() ) // raise 'this' variable (non-null!) 369 cananian 1.1.2.14 raiseV(V, Wv, base, method.params(j++), 370 cananian 1.1.2.3 new xClassNonNull( hm.getDeclaringClass() ) ); 371 cananian 1.1.2.3 HClass[] pt = hm.getParameterTypes(); 372 cananian 1.1.2.3 for (int k=0; k < pt.length; j++, k++) 373 cananian 1.1.2.14 raiseV(V, Wv, base, method.params(j), 374 cananian 1.1.2.3 pt[k].isPrimitive() ? 375 cananian 1.1.2.3 new xClassNonNull( toInternal(pt[k]) ) : 376 cananian 1.1.2.3 new xClass( pt[k] ) ); 377 cananian 1.1.2.3 } 378 cananian 1.1.2.3 // XXX: main method *could* use xClassExact on String[] arg. 379 cananian 1.1.2.1 380 cananian 1.1.2.9 // raise field root types. 381 cananian 1.10 for (Object hfO : my_fieldRoots) { 382 cananian 1.10 HField hf = (HField) hfO; 383 cananian 1.1.2.9 HClass ty = hf.getType(); 384 cananian 1.1.2.14 mergeV(Wf, hf, ty.isPrimitive() ? 385 cananian 1.1.2.9 new xClassNonNull( toInternal(ty) ) : 386 cananian 1.1.2.9 new xClass( ty ) ); 387 cananian 1.1.2.9 this.fieldRoots.add(hf); 388 cananian 1.1.2.6 } 389 cananian 1.1.2.6 390 cananian 1.1.2.2 // Iterate until worklists are empty. 391 cananian 1.8 do { 392 cananian 1.1.2.2 while (! (Wq.isEmpty() && Wv.isEmpty() && Wf.isEmpty()) ) { 393 cananian 1.1.2.1 394 cananian 1.1.2.1 if (!Wq.isEmpty()) { // grab statement from We if we can. 395 cananian 1.1.2.14 List pair = (List) Wq.pull(); 396 cananian 1.1.2.14 Context c = (Context) pair.get(0); 397 cananian 1.1.2.14 Quad q = (Quad) pair.get(1); 398 cananian 1.1.2.1 // Rule 2: for any executable block with 399 cananian 1.1.2.1 // only one successor C, set edge leading to C executable. 400 cananian 1.1.2.7 if (q.nextLength()==1) { 401 cananian 1.1.2.14 raiseE(Ee, Eq, Wq, c, q.nextEdge(0)); 402 cananian 1.1.2.1 } 403 cananian 1.1.2.1 // check conditions 3-8 for q. 404 cananian 1.1.2.14 visitor.context = c; 405 cananian 1.1.2.1 q.accept(visitor); 406 cananian 1.1.2.1 } 407 cananian 1.1.2.1 408 cananian 1.1.2.2 if (!Wv.isEmpty()) { // grab temp from Wv if possible. 409 cananian 1.1.2.14 List pair = (List) Wv.pull(); 410 cananian 1.1.2.14 Context c = (Context) pair.get(0); 411 cananian 1.1.2.14 Temp t = (Temp) pair.get(1); 412 cananian 1.1.2.1 // for every use of t... 413 cananian 1.1.2.14 for (Iterator it=useMap.getValues(t).iterator();it.hasNext();){ 414 cananian 1.1.2.1 // check conditions 3-8 415 cananian 1.1.2.14 visitor.context = c; 416 cananian 1.1.2.2 ((Quad) it.next()).accept(visitor); 417 cananian 1.1.2.14 } 418 cananian 1.1.2.2 } 419 cananian 1.1.2.2 420 cananian 1.1.2.2 if (!Wf.isEmpty()) { // grab field from Wf if possible. 421 cananian 1.1.2.2 HField hf = (HField) Wf.pull(); 422 cananian 1.1.2.2 // for every read of hf... 423 cananian 1.10 for (Object pairO : fieldMap.getValues(hf)) { 424 cananian 1.10 List pair = (List) pairO; 425 cananian 1.1.2.14 visitor.context = (Context) pair.get(0); 426 cananian 1.1.2.2 // check conditions 3-8 427 cananian 1.1.2.14 ((Quad) pair.get(1)).accept(visitor); 428 cananian 1.1.2.14 } 429 cananian 1.1.2.1 } 430 cananian 1.1.2.1 } // end while loop. 431 cananian 1.8 432 cananian 1.8 // OKAY, sometimes we get in a weird spot: we've left definitely 433 cananian 1.8 // intialized fields at bottom, but then their declaring fields 434 cananian 1.8 // end up uninstantiated (this analysis tells us their constructors 435 cananian 1.8 // are never called; but the classhierarchy wasn't smart enough 436 cananian 1.8 // to know this). Now the uses of those fields are left hanging 437 cananian 1.8 // around, still waiting for a value from the definite initializer. 438 cananian 1.8 // We're going to let a separate class hierarchy analysis figure 439 cananian 1.8 // out that the class is uninstantiated LATER, for now we're just 440 cananian 1.8 // going to hack some values into its fields to keep things going. 441 cananian 1.8 // NOTE that these values will never be used at runtime. 442 cananian 1.8 boolean changed = false; 443 cananian 1.10 for (Object hfO : diFields) { 444 cananian 1.10 HField hf = (HField) hfO; 445 cananian 1.8 if (get(hf)==null) { // STILL BOTTOM! 446 cananian 1.8 System.err.println("INFO: "+hf.getDeclaringClass()+ 447 cananian 1.8 " is uninstantiated!"); 448 cananian 1.8 // set to zero value. 449 cananian 1.8 changed = true; 450 cananian 1.8 HClass type = hf.getType(); 451 cananian 1.8 if (!type.isPrimitive()) 452 cananian 1.8 mergeV(Wf, hf, new xNullConstant()); 453 cananian 1.8 else if (type==HClass.Float) 454 cananian 1.8 mergeV(Wf, hf, new xFloatConstant(type, new Float(0.0))); 455 cananian 1.8 else if (type == HClass.Double) 456 cananian 1.8 mergeV(Wf, hf, new xFloatConstant(type, new Double(0.0))); 457 cananian 1.8 else if (type == HClass.Int || type==HClass.Long) 458 cananian 1.8 mergeV(Wf, hf, new xIntConstant(type, 0 )); 459 cananian 1.8 else throw new Error("Unknown field type: "+type); 460 cananian 1.8 } 461 cananian 1.8 } 462 cananian 1.8 diFields.clear(); 463 cananian 1.8 // wouldn't a goto statement be so much clearer? 464 cananian 1.8 if (!changed) break; 465 cananian 1.8 } while (true); // go up and do it all again. 466 cananian 1.1.2.1 } // end analysis. 467 cananian 1.1.2.1 468 cananian 1.1.2.1 /*----------------------------------------*/ 469 cananian 1.1.2.1 // raising values in the lattice: 470 cananian 1.1.2.1 471 cananian 1.1.2.1 /** Raise edge e in Ee/Eq, adding target q to Wq if necessary. */ 472 cananian 1.1.2.14 void raiseE(Set Ee, Set Eq, Worklist Wq, Context c, Edge e) { 473 cananian 1.1.2.1 Quad q = (Quad) e.to(); 474 cananian 1.1.2.21 if (Ee.add(Default.entry(e, c))) { 475 cananian 1.1.2.21 // if making this edge executable for the first time, verify 476 cananian 1.1.2.21 // that destination 'q' is marked executable, and add q to the 477 cananian 1.1.2.21 // work list to be looked at (may be a PHI, needs to be re-eval). 478 cananian 1.1.2.21 // NOTE that this works even if: quad's already been added 479 cananian 1.1.2.21 // to Eq (this may happen for PHIs) and even if this edge leads 480 cananian 1.1.2.21 // to itself (infinite loop in the program). 481 cananian 1.1.2.21 Eq.add(Default.entry(q,c)); 482 cananian 1.1.2.21 Wq.push(Default.pair(c, q)); 483 cananian 1.1.2.21 } 484 cananian 1.1.2.1 } 485 cananian 1.1.2.1 /** Raise element t to a in V, adding t to Wv if necessary. */ 486 cananian 1.1.2.14 void raiseV(MultiMap V, Worklist Wv, Context c, Temp t, LatticeVal a) { 487 cananian 1.4.2.1 assert a!=null; 488 cananian 1.1.2.14 LatticeVal old = get( c, t ); 489 cananian 1.1.2.1 if (corruptor!=null) a=corruptor.corrupt(a); // support incrementalism 490 cananian 1.1.2.1 // only allow raising value in lattice. 491 cananian 1.1.2.4 if (old != null) { 492 cananian 1.1.2.4 a = a.merge(old); 493 cananian 1.1.2.4 if (old.equals(a) && a.equals(old)) return; // same old same old 494 cananian 1.1.2.4 } 495 cananian 1.1.2.14 ((MapSet)V.getValues(t)).asMap().put(c, a); 496 cananian 1.1.2.14 Wv.push(Default.pair(c,t)); 497 cananian 1.1.2.1 } 498 cananian 1.1.2.4 /** Merge a with type of element t in V, adding t to Wv if necessary. */ 499 cananian 1.1.2.14 void mergeV(MultiMap V, Worklist Wv, Context c, Temp t, LatticeVal a) { 500 cananian 1.1.2.14 raiseV(V, Wv, c, t, a); 501 cananian 1.1.2.4 } 502 cananian 1.1.2.4 /** Merge a with type of field hf in Vf, adding reads of hf to Wf if 503 cananian 1.1.2.4 necessary. */ 504 cananian 1.1.2.14 void mergeV(Worklist Wf, HField hf, LatticeVal a) { 505 cananian 1.4.2.1 assert a!=null; 506 cananian 1.1.2.2 LatticeVal old = get( hf ); 507 cananian 1.1.2.2 if (corruptor!=null) a=corruptor.corrupt(a); // support incrementalism 508 cananian 1.1.2.4 if (old != null) { 509 cananian 1.1.2.4 a = a.merge(old); 510 cananian 1.1.2.4 if (old.equals(a) && a.equals(old)) return; // no change. 511 cananian 1.1.2.12 } 512 cananian 1.1.2.12 // careful with small types: limit to what they are defined to hold. 513 cananian 1.1.2.12 if (toInternal(hf.getType())!=hf.getType()) { 514 cananian 1.1.2.12 // trust xBitWidth to properly limit 515 cananian 1.1.2.12 xBitWidth bw = new xBitWidth(hf.getType(), 1000, 1000); 516 cananian 1.1.2.12 xBitWidth aa = extractWidth(a); 517 cananian 1.1.2.12 if (aa.plusWidth() > bw.plusWidth() || 518 cananian 1.1.2.12 aa.minusWidth() > bw.minusWidth()) { 519 cananian 1.1.2.12 // oops: we have to limit the size of a. 520 cananian 1.1.2.12 // xxx: should we ever get a *constant* larger than the 521 cananian 1.1.2.12 // field can hold? 522 cananian 1.4.2.1 assert !(a instanceof xIntConstant); 523 cananian 1.1.2.12 a = new xBitWidth(aa.type(), 524 cananian 1.1.2.12 Math.min(aa.plusWidth(), bw.plusWidth()), 525 cananian 1.1.2.12 Math.min(aa.minusWidth(), bw.minusWidth())); 526 cananian 1.1.2.12 // bail if no change from old value. 527 cananian 1.1.2.12 if (old!=null && old.equals(a) && a.equals(old)) return; 528 cananian 1.1.2.12 } 529 cananian 1.1.2.4 } 530 cananian 1.1.2.2 Vf.put(hf, a); 531 cananian 1.1.2.2 Wf.push(hf); 532 cananian 1.1.2.2 } 533 cananian 1.1.2.2 534 cananian 1.1.2.2 // utility functions. 535 cananian 1.1.2.14 LatticeVal get(Context c, Temp t) { 536 cananian 1.1.2.14 return (LatticeVal) ((MapSet)V.getValues(t)).asMap().get(c); 537 cananian 1.1.2.14 } 538 cananian 1.1.2.2 LatticeVal get(HField hf) { 539 cananian 1.1.2.2 // if value in cache, use it. 540 cananian 1.1.2.2 if (Vf.containsKey(hf)) return (LatticeVal) Vf.get(hf); 541 cananian 1.1.2.2 HClass type = toInternal(hf.getType()); 542 cananian 1.1.2.2 // deal with constant fields. 543 cananian 1.1.2.2 if (hf.isConstant()) { 544 cananian 1.1.2.2 Object val = hf.getConstant(); 545 cananian 1.1.2.2 if (type == linker.forName("java.lang.String")) 546 cananian 1.1.2.2 return new xStringConstant(type, val); 547 cananian 1.1.2.2 else if (type == HClass.Float || type == HClass.Double ) 548 cananian 1.1.2.2 return new xFloatConstant(type, val); 549 cananian 1.1.2.2 else if (type == HClass.Int || type == HClass.Long) 550 cananian 1.1.2.2 return new xIntConstant(type,((Number)val).longValue() ); 551 cananian 1.1.2.2 else throw new Error("Unknown constant field type: "+type); 552 cananian 1.1.2.2 } 553 cananian 1.1.2.2 // final fields will be explicitly initialized. 554 cananian 1.1.2.2 if (Modifier.isFinal(hf.getModifiers())) 555 cananian 1.1.2.2 return null; // bottom 556 cananian 1.1.2.17 // definitely initialized fields can be bottom until initialization. 557 cananian 1.8 if (dio.isDefinitelyInitialized(hf)) { 558 cananian 1.8 diFields.add(hf); // remember this for later. 559 cananian 1.1.2.17 return null; // bottom 560 cananian 1.8 } 561 cananian 1.1.2.2 // else assume that field is set to zero upon object creation. 562 cananian 1.1.2.2 if (!type.isPrimitive()) return new xNullConstant(); 563 cananian 1.1.2.2 if (type==HClass.Float) 564 cananian 1.1.2.2 return new xFloatConstant(type, new Float(0.0)); 565 cananian 1.1.2.2 if (type == HClass.Double) 566 cananian 1.1.2.2 return new xFloatConstant(type, new Double(0.0)); 567 cananian 1.1.2.2 if (type == HClass.Int || type==HClass.Long) 568 cananian 1.1.2.2 return new xIntConstant(type, 0 ); 569 cananian 1.1.2.2 else throw new Error("Unknown field type: "+type); 570 cananian 1.1.2.2 } 571 cananian 1.1.2.2 572 cananian 1.1.2.1 /*------------------------------------------------------------*/ 573 cananian 1.1.2.1 // VISITOR CLASS (the real guts of the routine) 574 cananian 1.1.2.1 class SCCVisitor extends QuadVisitor { 575 cananian 1.1.2.1 // local references to worklists. 576 cananian 1.1.2.2 final Worklist Wv, Wq, Wf; 577 cananian 1.1.2.1 // give us an OperVisitor class to go along with this. 578 cananian 1.1.2.2 final OperVisitor opVisitor = new SCCOpVisitor(); 579 cananian 1.1.2.14 // current context. 580 cananian 1.1.2.14 Context context; 581 cananian 1.1.2.1 582 cananian 1.1.2.2 SCCVisitor(Worklist Wv, Worklist Wq, Worklist Wf) { 583 cananian 1.1.2.2 this.Wv = Wv; this.Wq = Wq; this.Wf = Wf; 584 cananian 1.1.2.1 } 585 cananian 1.1.2.1 586 cananian 1.1.2.14 // implicit context! 587 cananian 1.1.2.14 void raiseE(Set Ee, Set Eq, Worklist Wq, Edge e) { 588 cananian 1.1.2.14 raiseE(Ee, Eq, Wq, context, e); 589 cananian 1.1.2.14 } 590 cananian 1.1.2.14 void raiseV(MultiMap V, Worklist Wv, Temp t, LatticeVal a) { 591 cananian 1.1.2.14 raiseV(V, Wv, context, t, a); 592 cananian 1.1.2.14 } 593 cananian 1.1.2.14 void mergeV(MultiMap V, Worklist Wv, Temp t, LatticeVal a) { 594 cananian 1.1.2.14 raiseV(V, Wv, context, t, a); 595 cananian 1.1.2.14 } 596 cananian 1.1.2.14 LatticeVal get(Temp t) { 597 cananian 1.1.2.14 return get(context, t); 598 cananian 1.1.2.14 } 599 cananian 1.1.2.14 // yuck, this is broken, but the inner class declarations shadow 600 cananian 1.1.2.14 // the outer declarations (even though method params are distinct!) 601 cananian 1.1.2.14 void raiseE(Set Ee, Set Eq, Worklist Wq, Context c, Edge e) { 602 cananian 1.1.2.14 BitWidthAnalysis.this.raiseE(Ee, Eq, Wq, c, e); 603 cananian 1.1.2.14 } 604 cananian 1.1.2.14 void raiseV(MultiMap V, Worklist Wv, Context c, Temp t, LatticeVal a) { 605 cananian 1.1.2.14 BitWidthAnalysis.this.raiseV(V, Wv, c, t, a); 606 cananian 1.1.2.14 } 607 cananian 1.1.2.14 void mergeV(MultiMap V, Worklist Wv, Context c, Temp t, LatticeVal a) { 608 cananian 1.1.2.14 BitWidthAnalysis.this.raiseV(V, Wv, c, t, a); 609 cananian 1.1.2.14 } 610 cananian 1.1.2.14 LatticeVal get(Context c, Temp t) { 611 cananian 1.1.2.14 return BitWidthAnalysis.this.get(c, t); 612 cananian 1.1.2.14 } 613 cananian 1.1.2.14 LatticeVal get(HField hf) { 614 cananian 1.1.2.14 return BitWidthAnalysis.this.get(hf); 615 cananian 1.1.2.14 } 616 cananian 1.1.2.14 void mergeV(Worklist Wf, HField hf, LatticeVal a) { 617 cananian 1.1.2.14 BitWidthAnalysis.this.mergeV(Wf, hf, a); 618 cananian 1.1.2.14 } 619 cananian 1.1.2.14 620 cananian 1.1.2.4 void handleSigmas(CJMP q, boolean falseTaken, boolean trueTaken) { 621 cananian 1.1.2.4 // for every sigma source: 622 cananian 1.1.2.4 for (int i=0; i < q.numSigmas(); i++) { 623 cananian 1.1.2.4 LatticeVal v = get( q.src(i) ); 624 cananian 1.1.2.4 if (v == null) continue; // skip: insufficient info. 625 cananian 1.1.2.4 // check if this is the CJMP condition. 626 cananian 1.1.2.4 if (useSigmas && q.test() == q.src(i)) { 627 cananian 1.1.2.4 // we know that the conditional is zero on the false leg 628 cananian 1.1.2.4 if (falseTaken) 629 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,0), 630 cananian 1.1.2.4 new xIntConstant(toInternal(HClass.Boolean),0)); 631 cananian 1.1.2.4 // CJMP test is possibly non-boolean, so we don't in fact 632 cananian 1.1.2.4 // know the value of the true side (except that it is 633 cananian 1.1.2.4 // non-zero) 634 cananian 1.1.2.4 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 635 cananian 1.1.2.4 } else { 636 cananian 1.1.2.4 // fall back. 637 cananian 1.1.2.4 if (falseTaken) raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 638 cananian 1.1.2.4 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 639 cananian 1.1.2.4 } 640 cananian 1.1.2.4 } 641 cananian 1.1.2.4 } 642 cananian 1.1.2.4 void handleSigmas(CJMP q, xInstanceofResult io, 643 cananian 1.1.2.4 boolean falseTaken, boolean trueTaken) { 644 cananian 1.1.2.1 // for every sigma source: 645 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 646 cananian 1.1.2.1 // check if this is the CJMP condition. 647 cananian 1.1.2.1 if (q.test() == q.src(i)) { // known value after branch 648 cananian 1.1.2.4 if (falseTaken) raiseV(V, Wv, q.dst(i,0), 649 cananian 1.1.2.4 io.makeKnown(false).rename(q,0)); 650 cananian 1.1.2.4 if (trueTaken) raiseV(V, Wv, q.dst(i,1), 651 cananian 1.1.2.4 io.makeKnown(true).rename(q,1)); 652 cananian 1.1.2.1 continue; // go on. 653 cananian 1.1.2.1 } 654 cananian 1.1.2.1 655 cananian 1.1.2.1 LatticeVal v = get( q.src(i) ); 656 cananian 1.1.2.1 if (v == null) continue; // skip: insufficient info. 657 cananian 1.1.2.1 658 cananian 1.1.2.1 // check to see if this is the temp tested by INSTANCEOF 659 cananian 1.1.2.1 if (q.src(i) == io.tested()) { 660 cananian 1.1.2.1 // no new info on false branch. 661 cananian 1.1.2.4 if (falseTaken) 662 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 663 cananian 1.1.2.1 // we know q.dst[i][1] is INSTANCEOF def.hclass 664 cananian 1.1.2.1 // secret inside info: INSTANCEOF src is always non-null. 665 cananian 1.1.2.5 HClass hcI = io.def().hclass(); 666 cananian 1.1.2.5 HClass hcV = ((xClass)v).type(); 667 cananian 1.1.2.5 // use more specific type 668 cananian 1.1.2.5 if (!hcI.isInterface() && !hcV.isInterface() && 669 cananian 1.1.2.5 hcI.isSuperclassOf(hcV)) 670 cananian 1.1.2.5 hcI = hcV; 671 cananian 1.1.2.5 LatticeVal nv = new xClassNonNull(hcI); 672 cananian 1.1.2.5 // use more specific of original class, instanceof. 673 cananian 1.1.2.5 if (v.isLowerThan(nv)) nv = v; 674 cananian 1.1.2.4 if (trueTaken) 675 cananian 1.1.2.5 raiseV(V, Wv, q.dst(i,1), nv); 676 cananian 1.1.2.1 } else { 677 cananian 1.1.2.1 // fall back. 678 cananian 1.1.2.4 if (falseTaken) raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 679 cananian 1.1.2.4 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 680 cananian 1.1.2.1 } 681 cananian 1.1.2.1 } 682 cananian 1.1.2.1 } 683 cananian 1.1.2.4 void handleSigmas(CJMP q, xOperBooleanResult or, 684 cananian 1.1.2.4 boolean falseTaken, boolean trueTaken) { 685 cananian 1.1.2.1 int opc = or.def().opcode(); 686 cananian 1.1.2.1 int opa = or.operands().length; 687 cananian 1.1.2.1 LatticeVal left = opa<1?null:get(or.operands()[0]); 688 cananian 1.1.2.1 LatticeVal right= opa<2?null:get(or.operands()[1]); 689 cananian 1.1.2.1 690 cananian 1.1.2.1 // for every sigma source: 691 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 692 cananian 1.1.2.1 // check if this is the CJMP condition. 693 cananian 1.1.2.1 if (q.test() == q.src(i)) { 694 cananian 1.1.2.4 if (falseTaken) raiseV(V, Wv, q.dst(i,0), 695 cananian 1.1.2.4 or.makeKnown(false).rename(q,0)); 696 cananian 1.1.2.4 if (trueTaken) raiseV(V, Wv, q.dst(i,1), 697 cananian 1.1.2.4 or.makeKnown(true).rename(q,1)); 698 cananian 1.1.2.1 continue; // go on. 699 cananian 1.1.2.1 } 700 cananian 1.1.2.1 701 cananian 1.1.2.1 LatticeVal v = get( q.src(i) ); 702 cananian 1.1.2.1 if (v == null) continue; // skip: insufficient info. 703 cananian 1.1.2.1 704 cananian 1.1.2.1 // check to see if it comes from the OPER defining the boolean. 705 cananian 1.1.2.1 boolean handled = false; 706 cananian 1.1.2.4 boolean leftIsSource = false, swapped = false; 707 cananian 1.1.2.1 if (q.src(i) == or.operands()[0]) { // left is source. 708 cananian 1.1.2.4 leftIsSource = true; 709 cananian 1.1.2.4 } else if (q.src(i) == or.operands()[1]) { // right is source. 710 cananian 1.1.2.4 LatticeVal t = left; left = right; right = t; 711 cananian 1.1.2.4 leftIsSource = true; swapped = true; 712 cananian 1.1.2.4 } 713 cananian 1.1.2.4 if (leftIsSource) { 714 cananian 1.1.2.1 if (opc == Qop.ACMPEQ && 715 cananian 1.1.2.1 left instanceof xClass && // not already xClassNonNull 716 cananian 1.1.2.4 (!(left instanceof xNullConstant)) && 717 cananian 1.1.2.1 right instanceof xNullConstant) { 718 cananian 1.1.2.4 if (falseTaken) 719 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,0), // false branch: non-null 720 cananian 1.1.2.4 new xClassNonNull( ((xClass)left).type() )); 721 cananian 1.1.2.4 if (trueTaken) 722 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,1), // true branch: null 723 cananian 1.1.2.4 new xNullConstant() ); 724 cananian 1.1.2.1 handled = true; 725 cananian 1.1.2.1 } else if ((opc == Qop.ICMPEQ || opc == Qop.LCMPEQ || 726 cananian 1.1.2.1 opc == Qop.FCMPEQ || opc == Qop.DCMPEQ) && 727 cananian 1.1.2.1 right instanceof xConstant) { 728 cananian 1.1.2.4 if (falseTaken) 729 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,0), // false branch: no info 730 cananian 1.1.2.4 left.rename(q, 0)); 731 cananian 1.1.2.4 if (trueTaken) 732 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,1), // true branch: constant! 733 cananian 1.1.2.4 right.rename(q, 1)); 734 cananian 1.1.2.1 handled = true; 735 cananian 1.1.2.4 } else if ((opc == Qop.ICMPGT || opc == Qop.LCMPGT ) && 736 cananian 1.1.2.1 right instanceof xBitWidth) { 737 cananian 1.1.2.1 xBitWidth bw = (xBitWidth) right; 738 cananian 1.1.2.4 xBitWidth sr = extractWidth(left); 739 cananian 1.1.2.4 xBitWidth lessThan = new xBitWidth 740 cananian 1.1.2.4 (sr.type(), 741 cananian 1.1.2.4 sr.minusWidth(), 742 cananian 1.1.2.4 Math.min(sr.plusWidth(), bw.plusWidth()) ); 743 cananian 1.1.2.4 xBitWidth greaterThan = new xBitWidth 744 cananian 1.1.2.4 (sr.type(), 745 cananian 1.1.2.4 Math.min(sr.minusWidth(),bw.minusWidth()), 746 cananian 1.1.2.4 sr.plusWidth() ); 747 cananian 1.1.2.5 // use more specific of original class, xBitWidth. 748 cananian 1.1.2.5 if (left.isLowerThan(lessThan)) 749 cananian 1.1.2.5 lessThan = (xBitWidth) left; 750 cananian 1.1.2.5 if (left.isLowerThan(greaterThan)) 751 cananian 1.1.2.5 greaterThan = (xBitWidth) left; 752 cananian 1.1.2.1 // false branch: 753 cananian 1.1.2.4 if (falseTaken) 754 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,0), 755 cananian 1.1.2.4 swapped ? greaterThan : lessThan); 756 cananian 1.1.2.1 // true branch. 757 cananian 1.1.2.4 if (trueTaken) 758 cananian 1.1.2.4 raiseV(V, Wv, q.dst(i,1), 759 cananian 1.1.2.4 swapped ? lessThan : greaterThan); 760 cananian 1.1.2.1 handled = true; 761 cananian 1.1.2.1 } 762 cananian 1.1.2.1 } 763 cananian 1.1.2.1 // fall back. 764 cananian 1.1.2.1 if (!handled) { 765 cananian 1.1.2.4 if (falseTaken) raiseV(V, Wv, q.dst(i,0), v.rename(q, 0)); 766 cananian 1.1.2.4 if (trueTaken) raiseV(V, Wv, q.dst(i,1), v.rename(q, 1)); 767 cananian 1.1.2.1 } 768 cananian 1.1.2.1 } 769 cananian 1.1.2.1 } 770 cananian 1.1.2.1 771 cananian 1.1.2.1 // visitation. 772 cananian 1.1.2.1 public void visit(Quad q) { /* do nothing. */ } 773 cananian 1.1.2.1 public void visit(AGET q) { 774 cananian 1.1.2.1 LatticeVal v = get( q.objectref() ); 775 cananian 1.1.2.4 if (corruptor==null) 776 cananian 1.4.2.1 assert v==null || v instanceof xClassNonNull; 777 cananian 1.1.2.1 if (v instanceof xClass) 778 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 779 cananian 1.1.2.1 new xClass( toInternal( ((xClass)v).type().getComponentType() ) ) ); 780 cananian 1.1.2.1 } 781 cananian 1.1.2.1 public void visit(ALENGTH q) { 782 cananian 1.1.2.1 LatticeVal v = get( q.objectref() ); 783 cananian 1.1.2.4 if (corruptor==null) 784 cananian 1.4.2.1 assert v==null || v instanceof xClassNonNull; 785 cananian 1.1.2.1 if (v instanceof xClassArray) 786 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 787 cananian 1.1.2.1 new xIntConstant(HClass.Int, 788 cananian 1.1.2.1 ((xClassArray)v).length() ) ); 789 cananian 1.1.2.1 else if (v instanceof xClass) // length is non-negative. 790 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(HClass.Int, 0, 32) ); 791 cananian 1.1.2.1 } 792 cananian 1.1.2.1 public void visit(ANEW q) { // dst of ANEW is non-null. 793 cananian 1.1.2.1 if (q.dimsLength()==1) { 794 cananian 1.1.2.1 LatticeVal v = get( q.dims(0) ); 795 cananian 1.1.2.1 if (v instanceof xIntConstant) { 796 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 797 cananian 1.1.2.1 new xClassArray(q.hclass(), 798 cananian 1.1.2.1 (int) ((xIntConstant)v).value()) ); 799 cananian 1.1.2.1 return; 800 cananian 1.1.2.1 } else if (v == null) return; // bottom. 801 cananian 1.1.2.1 } 802 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClassExact(q.hclass()) ); 803 cananian 1.1.2.1 } 804 cananian 1.1.2.4 public void visit(ASET q) { 805 cananian 1.1.2.4 LatticeVal v = get( q.objectref() ); 806 cananian 1.1.2.4 if (corruptor==null) 807 cananian 1.4.2.1 assert v==null || v instanceof xClassNonNull; 808 cananian 1.1.2.4 /* do nothing. */ 809 cananian 1.1.2.4 } 810 cananian 1.1.2.1 public void visit(CALL q) { 811 cananian 1.1.2.4 if (corruptor==null) 812 cananian 1.4.2.1 assert (q.isVirtual() ? 813 cananian 1.1.2.4 get( q.params(0) )==null || 814 cananian 1.4.2.1 get( q.params(0) ) instanceof xClassNonNull : true) : q; 815 cananian 1.1.2.3 // don't analyze this quad until all params are known. 816 cananian 1.1.2.3 for (int i=0; i<q.paramsLength(); i++) 817 cananian 1.1.2.3 if (get(q.params(i))==null) 818 cananian 1.1.2.3 return; 819 cananian 1.1.2.3 // find methods callable from this site. 820 cananian 1.1.2.3 HMethod hm = q.method(); 821 cananian 1.1.2.3 List callable = new ArrayList(4); 822 cananian 1.1.2.3 if (q.isVirtual()) { // need type info for virtual methods. 823 cananian 1.4.2.1 assert !hm.isStatic(); 824 cananian 1.1.2.3 LatticeVal v = get( q.params(0) ); 825 cananian 1.1.2.3 HClass ty = ((xClass) v).type(); 826 cananian 1.4.2.1 assert !ty.isPrimitive() : v; 827 cananian 1.1.2.3 // when hm.getDeclaringClass() is an interface, the 828 cananian 1.1.2.3 // implementations may not share a common superclass which 829 cananian 1.1.2.3 // implements that interface. 830 cananian 1.1.2.3 if (!ty.isInstanceOf(hm.getDeclaringClass())) 831 cananian 1.1.2.3 ty = hm.getDeclaringClass(); // always safe to fall back. 832 cananian 1.1.2.3 hm = ty.getMethod(hm.getName(), hm.getDescriptor()); 833 cananian 1.1.2.3 if (!(v instanceof xClassExact)) 834 cananian 1.1.2.3 callable.addAll(ch.overrides(ty,hm,true)); 835 cananian 1.1.2.3 } 836 cananian 1.1.2.3 callable.add(hm); 837 cananian 1.1.2.13 // weird special stuff for possible calls to Thread.start(): 838 cananian 1.1.2.13 // they cause calls to Thread.run() 839 cananian 1.1.2.13 if (callable.contains(linker.forName("java.lang.Thread") 840 cananian 1.1.2.13 .getMethod("start", "()V"))) { 841 cananian 1.1.2.13 // do a virtual dispatch to Thread.run() as well. 842 cananian 1.1.2.13 LatticeVal v = get( q.params(0) ); 843 cananian 1.1.2.13 HClass ty = ((xClass) v).type(); 844 cananian 1.4.2.1 assert ty.isInstanceOf 845 cananian 1.4.2.1 (linker.forName("java.lang.Thread")) : v; 846 cananian 1.1.2.13 hm = ty.getMethod("run", "()V"); 847 cananian 1.1.2.13 if (!(v instanceof xClassExact)) 848 cananian 1.1.2.13 callable.addAll(ch.overrides(ty,hm,true)); 849 cananian 1.1.2.13 callable.add(hm); 850 cananian 1.1.2.13 } 851 cananian 1.1.2.3 // for every callable method, raise its Vparam. 852 cananian 1.1.2.3 // flag if any callable methods are native. 853 cananian 1.1.2.6 boolean anyNative = false; 854 cananian 1.1.2.3 Temp[] myparams = q.params(); 855 cananian 1.10 for (Object hmmO : callable) { 856 cananian 1.10 HMethod hmm = (HMethod) hmmO; 857 cananian 1.1.2.14 // create new context (using this call site) 858 cananian 1.1.2.14 Context nc = context.addElement(q); 859 cananian 1.1.2.14 // keep callMap updated. 860 cananian 1.1.2.14 callMap.add(Default.pair(nc, hmm), Default.pair(context, q)); 861 cananian 1.1.2.14 // okay, raise types of METHOD for this context. 862 cananian 1.1.2.3 if (Modifier.isNative(hmm.getModifiers())) anyNative = true; 863 cananian 1.1.2.3 if (!methodMap.containsKey(hmm)) scan_one(hmm); 864 cananian 1.1.2.3 METHOD method = (METHOD) methodMap.get(hmm); 865 cananian 1.1.2.3 if (method==null) continue; // abstract or native method. 866 cananian 1.1.2.18 int i=0; 867 cananian 1.1.2.18 if (!hmm.isStatic()) { 868 cananian 1.1.2.18 // 'this' parameter gets narrowed by the call. 869 cananian 1.1.2.18 mergeV(V, Wv, nc, method.params(i), 870 cananian 1.1.2.18 narrowThis(hmm.getDeclaringClass(), 871 cananian 1.1.2.18 get(myparams[i])) ); 872 cananian 1.1.2.18 i++; 873 cananian 1.1.2.18 } 874 cananian 1.1.2.18 // handle all the non-'this' parameters. 875 cananian 1.1.2.18 for ( ; i<myparams.length; i++) 876 cananian 1.1.2.14 mergeV(V, Wv, nc, method.params(i), get( myparams[i] )); 877 cananian 1.1.2.3 // also mark "method" executable. 878 cananian 1.1.2.14 raiseE(Ee, Eq, Wq, nc, method.prevEdge(0)); 879 cananian 1.1.2.3 // analysis of "method" (in particular, the RETURN/THROW 880 cananian 1.1.2.3 // quads) will raiseE on appropriate outgoing edge and 881 cananian 1.1.2.3 // raiseV on retval/retex. 882 cananian 1.1.2.14 // (only interested in returns with given callee context) 883 cananian 1.10 for (Object rO : returnMap.getValues(Default.pair(nc,hmm)) 884 cananian 1.10 ) { 885 cananian 1.10 RETURN r = (RETURN) rO; 886 cananian 1.1.2.7 if (r.retval()!=null) { 887 cananian 1.1.2.14 LatticeVal v = get( nc, r.retval() ); 888 cananian 1.1.2.7 if (v==null) continue; 889 cananian 1.1.2.7 mergeV(V, Wv, q.retval(), v); 890 cananian 1.1.2.7 } 891 cananian 1.1.2.6 raiseE(Ee, Eq, Wq, q.nextEdge(0) ); 892 cananian 1.1.2.6 } 893 cananian 1.10 for (Object tO : throwMap.getValues(Default.pair(nc,hmm)) 894 cananian 1.10 ) { 895 cananian 1.10 THROW t = (THROW) tO; 896 cananian 1.1.2.14 LatticeVal v = get( nc, t.throwable() ); 897 cananian 1.1.2.6 if (v==null) continue; 898 cananian 1.1.2.6 mergeV(V, Wv, q.retex(), v); 899 cananian 1.1.2.6 raiseE(Ee, Eq, Wq, q.nextEdge(1) ); 900 cananian 1.1.2.6 } 901 cananian 1.1.2.3 } 902 cananian 1.1.2.6 if (anyNative) { 903 cananian 1.1.2.3 // if *native* method in callable methods set, then use 904 cananian 1.1.2.3 // conservative retval/retex/edge assumptions. 905 cananian 1.1.2.1 if (q.retval() != null) { 906 cananian 1.1.2.1 // in the bytecode world, everything's an int. 907 cananian 1.1.2.1 HClass ty = q.method().getReturnType(); 908 cananian 1.1.2.1 LatticeVal v = new xClass(toInternal(ty)); 909 cananian 1.1.2.1 if (ty==HClass.Byte) 910 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Byte), 8, 7); 911 cananian 1.1.2.1 else if (ty==HClass.Short) 912 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Short), 16, 15); 913 cananian 1.1.2.1 else if (ty==HClass.Char) 914 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Char), 0, 16); 915 cananian 1.1.2.1 else if (ty==HClass.Boolean) 916 cananian 1.1.2.1 v = new xBitWidth(toInternal(HClass.Boolean),0, 1); 917 cananian 1.1.2.1 else if (ty.isPrimitive()) 918 cananian 1.1.2.1 v = new xClassNonNull(toInternal(ty)); 919 cananian 1.1.2.4 mergeV(V, Wv, q.retval(), v); 920 cananian 1.1.2.1 } 921 cananian 1.1.2.4 mergeV(V, Wv, q.retex(), 922 cananian 1.1.2.1 new xClassNonNull( linker.forName("java.lang.Throwable") )); 923 cananian 1.1.2.1 // both outgoing edges are potentially executable. 924 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(1) ); 925 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(0) ); 926 cananian 1.1.2.6 } 927 cananian 1.1.2.1 // handle SIGMAs 928 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 929 cananian 1.1.2.1 // no q.src(x) should equal retval or retex... 930 cananian 1.1.2.1 // not that it would particularly break anything if it 931 cananian 1.1.2.1 // did. 932 cananian 1.1.2.1 LatticeVal v2 = get ( q.src(i) ); 933 cananian 1.1.2.6 if (v2 == null) continue; 934 cananian 1.1.2.6 if (execMap(q.nextEdge(0))) 935 cananian 1.1.2.1 raiseV(V, Wv, q.dst(i, 0), v2.rename(q, 0)); 936 cananian 1.1.2.6 if (execMap(q.nextEdge(1))) 937 cananian 1.1.2.1 raiseV(V, Wv, q.dst(i, 1), v2.rename(q, 1)); 938 cananian 1.1.2.1 } 939 cananian 1.1.2.18 } 940 cananian 1.1.2.18 /** private helper method to narrow the type of a 'this' pointer 941 cananian 1.1.2.18 * down to the given class (which defines the class method we're 942 cananian 1.1.2.18 * going to invoke). */ 943 cananian 1.1.2.18 private LatticeVal narrowThis(HClass hc, LatticeVal v) { 944 cananian 1.4.2.1 assert v instanceof xClassNonNull : "'this' pointer should always be known non-null."; 945 cananian 1.1.2.18 xClassNonNull vv = (xClassNonNull) v; 946 cananian 1.4.2.1 assert !hc.isInterface(); // hc comes from method decl. 947 cananian 1.1.2.18 // vv can be interface, in which case we *do* want to narrow. 948 cananian 1.1.2.18 // but an interface can never be an instanceof a non-interface. 949 cananian 1.1.2.18 if (vv.type().isInstanceOf(hc)) return vv; 950 cananian 1.4.2.1 assert !(v instanceof xClassExact) : "how can 'this' be exact when it needs narrowing?"; 951 cananian 1.1.2.18 return new xClassNonNull(hc); 952 cananian 1.1.2.1 } 953 cananian 1.1.2.1 public void visit(CJMP q) { 954 cananian 1.1.2.1 // is test constant? 955 cananian 1.1.2.1 LatticeVal v = get( q.test() ); 956 cananian 1.1.2.1 if (v instanceof xIntConstant) { 957 cananian 1.1.2.1 boolean test = ((xIntConstant)v).value()!=0; 958 cananian 1.1.2.1 959 cananian 1.1.2.1 if (test) 960 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(1) ); // true edge. 961 cananian 1.1.2.1 else 962 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(0) ); // false edge. 963 cananian 1.1.2.1 // handle sigmas. 964 cananian 1.1.2.4 if (useSigmas && v instanceof xOperBooleanResult) 965 cananian 1.1.2.4 handleSigmas((CJMP) q, (xOperBooleanResult)v, 966 cananian 1.1.2.4 !test, test); 967 cananian 1.1.2.4 else if (useSigmas && v instanceof xInstanceofResult) 968 cananian 1.1.2.4 handleSigmas((CJMP) q, (xInstanceofResult) v, 969 cananian 1.1.2.4 !test, test); 970 cananian 1.1.2.4 else // fallback. 971 cananian 1.1.2.4 handleSigmas((CJMP) q, !test, test); 972 cananian 1.1.2.1 return; // done. 973 cananian 1.1.2.1 } else if (v instanceof xClass) { // ie, not bottom. 974 cananian 1.1.2.1 // both edges are potentially executable. 975 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(1) ); 976 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(0) ); 977 cananian 1.1.2.1 978 cananian 1.1.2.1 // look at definition of boolean condition. 979 cananian 1.1.2.1 if (useSigmas && v instanceof xOperBooleanResult) 980 cananian 1.1.2.4 handleSigmas((CJMP) q, (xOperBooleanResult)v, true, true); 981 cananian 1.1.2.1 else if (useSigmas && v instanceof xInstanceofResult) 982 cananian 1.1.2.4 handleSigmas((CJMP) q, (xInstanceofResult) v, true, true); 983 cananian 1.1.2.1 else // fallback. 984 cananian 1.1.2.4 handleSigmas((CJMP) q, true, true); 985 cananian 1.1.2.1 } 986 cananian 1.1.2.1 } 987 cananian 1.1.2.1 public void visit(COMPONENTOF q) { 988 cananian 1.1.2.1 // we're guaranteed that q.arrayref is non-null here. 989 cananian 1.1.2.1 LatticeVal vA = get( q.arrayref() ); 990 cananian 1.1.2.1 LatticeVal vO = get( q.objectref() ); 991 cananian 1.1.2.1 if (vA instanceof xClass && vO instanceof xClass) { 992 cananian 1.1.2.1 HClass hcA = ((xClass) vA).type().getComponentType() ; 993 cananian 1.1.2.1 HClass hcO = ((xClass) vO).type(); 994 cananian 1.1.2.1 if (hcA==null) { // can't prove type is array; usually this 995 cananian 1.1.2.1 // means we've turned useSigmas off. 996 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(toInternal(HClass.Boolean),0,1)); 997 cananian 1.1.2.1 return; 998 cananian 1.1.2.1 } 999 cananian 1.1.2.1 hcA = toInternal(hcA); // normalize external types. 1000 cananian 1.1.2.1 // special case when q.objectref is null 1001 cananian 1.1.2.1 if (hcO == HClass.Void) // always true. 1002 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),1)); 1003 cananian 1.1.2.5 else if (vA instanceof xClassExact && 1004 cananian 1.1.2.5 hcO.isInstanceOf(hcA)) // always true 1005 cananian 1.1.2.5 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),1)); 1006 cananian 1.1.2.5 else if (vO instanceof xClassExact && 1007 cananian 1.1.2.5 !hcO.isInstanceOf(hcA)) // always false 1008 cananian 1.1.2.5 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),0)); 1009 cananian 1.7 else if (hcA.isInterface() || 1010 cananian 1.7 hcO.isInterface() || 1011 cananian 1.7 hcO.isInstanceOf(hcA) || 1012 cananian 1.1.2.1 hcA.isInstanceOf(hcO)) // unknowable. 1013 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(toInternal(HClass.Boolean),0,1)); 1014 cananian 1.1.2.1 else // always false. 1015 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xIntConstant(toInternal(HClass.Boolean),0)); 1016 cananian 1.1.2.1 } 1017 cananian 1.1.2.1 } 1018 cananian 1.1.2.1 public void visit(CONST q) { 1019 cananian 1.1.2.1 if (q.type() == HClass.Void) // null constant 1020 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), new xNullConstant() ); 1021 cananian 1.1.2.1 else if (q.type()==linker.forName("java.lang.String"))// string constant 1022 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), new xStringConstant(q.type(),q.value())); 1023 cananian 1.1.2.1 else if (q.type()==HClass.Float || q.type()==HClass.Double) // f-p 1024 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), new xFloatConstant(q.type(),q.value()) ); 1025 cananian 1.1.2.1 else if (q.type()==HClass.Int || q.type() == HClass.Long) 1026 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), 1027 cananian 1.1.2.1 new xIntConstant(q.type(), 1028 cananian 1.1.2.1 ((Number)q.value()).longValue())); 1029 cananian 1.1.2.1 else if (q.type()==linker.forName("java.lang.Class") || 1030 cananian 1.1.2.1 q.type()==linker.forName("java.lang.reflect.Field") || 1031 cananian 1.1.2.1 q.type()==linker.forName("java.lang.reflect.Method")) 1032 cananian 1.1.2.1 raiseV(V,Wv, q.dst(), new xClassNonNull( q.type() ) ); 1033 cananian 1.1.2.1 else throw new Error("Unknown CONST type: "+q.type()); 1034 cananian 1.1.2.1 } 1035 cananian 1.1.2.1 public void visit(FOOTER q) { /* do nothing. */ } 1036 cananian 1.1.2.1 public void visit(GET q) { 1037 cananian 1.1.2.4 if (corruptor==null) 1038 cananian 1.4.2.1 assert (q.objectref()!=null ? 1039 cananian 1.1.2.4 get(q.objectref())==null || 1040 cananian 1.4.2.1 get(q.objectref()) instanceof xClassNonNull : true) : q; 1041 cananian 1.1.2.7 // add to list of reading quads. 1042 cananian 1.1.2.14 fieldMap.add(q.field(), Default.pair(context, q)); 1043 cananian 1.1.2.2 // variable gets current lattice val of field. 1044 cananian 1.1.2.3 LatticeVal v = get( q.field() ); 1045 cananian 1.1.2.3 if (v==null) return; // wait for field initialization. 1046 cananian 1.1.2.3 raiseV(V, Wv, q.dst(), v); 1047 cananian 1.1.2.3 if (DEBUG) System.out.println("READ OF "+q.field()+" GETS "+get( q.field() )); 1048 cananian 1.1.2.1 } 1049 cananian 1.1.2.1 public void visit(HEADER q) { 1050 cananian 1.4.2.1 assert false; /* we should "skip to the METHOD" */ 1051 cananian 1.1.2.1 } 1052 cananian 1.1.2.1 public void visit(INSTANCEOF q) { 1053 cananian 1.1.2.1 // no guarantee that src is not null. 1054 cananian 1.1.2.1 LatticeVal v = get( q.src() ); 1055 cananian 1.1.2.1 if (v instanceof xNullConstant) // always false. 1056 cananian 1.1.2.4 raiseV(V, Wv, q.dst(), new xInstanceofResultKnown(q,false)); 1057 cananian 1.7 else if (v instanceof xClassExact) { // always known. 1058 cananian 1.7 HClass hcO = ((xClassNonNull)v).type(); 1059 cananian 1.7 assert !hcO.isInterface();//but can be an array type. 1060 cananian 1.7 boolean result = hcO.isInstanceOf(q.hclass()); 1061 cananian 1.7 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,result)); 1062 cananian 1.7 } 1063 cananian 1.1.2.1 else if (v instanceof xClassNonNull) { // analyzable 1064 cananian 1.1.2.1 HClass hcO = ((xClassNonNull)v).type(); 1065 cananian 1.1.2.1 if (hcO.isInstanceOf(q.hclass())) // always true 1066 cananian 1.1.2.4 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,true)); 1067 cananian 1.7 else if (q.hclass().isInterface() || hcO.isInterface() || 1068 cananian 1.7 q.hclass().isInstanceOf(hcO)) // unknowable. 1069 cananian 1.1.2.4 raiseV(V,Wv, q.dst(), new xInstanceofResultUnknown(q)); 1070 cananian 1.1.2.1 else // always false. 1071 cananian 1.1.2.4 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,false)); 1072 cananian 1.1.2.1 } 1073 cananian 1.1.2.1 else if (v instanceof xClass) { // could be null. 1074 cananian 1.1.2.1 HClass hcO = ((xClass)v).type(); 1075 cananian 1.7 if (q.hclass().isInterface() || hcO.isInterface() || 1076 cananian 1.7 q.hclass().isInstanceOf(hcO) || 1077 cananian 1.1.2.1 hcO.isInstanceOf(q.hclass()) ) // unknowable. 1078 cananian 1.1.2.4 raiseV(V,Wv, q.dst(), new xInstanceofResultUnknown(q)); 1079 cananian 1.1.2.1 else // always false (even if src==null) 1080 cananian 1.1.2.4 raiseV(V,Wv, q.dst(), new xInstanceofResultKnown(q,false)); 1081 cananian 1.1.2.1 } 1082 cananian 1.1.2.1 } 1083 cananian 1.1.2.1 public void visit(METHOD q) { 1084 cananian 1.1.2.3 /* do very little */ 1085 cananian 1.4.2.1 assert methodMap.get(q.getFactory().getMethod())==q; 1086 cananian 1.1.2.3 if (DEBUG) System.out.println("METHOD: "+q.getFactory().getMethod()); 1087 cananian 1.1.2.1 } 1088 cananian 1.1.2.4 public void visit(MONITORENTER q) { 1089 cananian 1.1.2.4 LatticeVal v = get( q.lock() ); 1090 cananian 1.4.2.1 assert v==null || v instanceof xClassNonNull; 1091 cananian 1.1.2.4 /* do nothing. */ 1092 cananian 1.1.2.4 } 1093 cananian 1.1.2.4 public void visit(MONITOREXIT q) { 1094 cananian 1.1.2.4 LatticeVal v = get( q.lock() ); 1095 cananian 1.4.2.1 assert v==null || v instanceof xClassNonNull; 1096 cananian 1.1.2.4 /* do nothing. */ 1097 cananian 1.1.2.4 } 1098 cananian 1.1.2.1 public void visit(MOVE q) { 1099 cananian 1.1.2.1 LatticeVal v = get ( q.src() ); 1100 cananian 1.1.2.1 if (v != null) 1101 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), v); 1102 cananian 1.1.2.1 } 1103 cananian 1.1.2.1 public void visit(NEW q) { 1104 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClassExact( q.hclass() ) ); 1105 cananian 1.1.2.1 } 1106 cananian 1.1.2.1 public void visit(NOP q) { /* do nothing. */ } 1107 cananian 1.1.2.1 public void visit(OPER q) { 1108 cananian 1.1.2.1 int opc = q.opcode(); 1109 cananian 1.1.2.1 boolean allConst = true; 1110 cananian 1.1.2.1 boolean allWidth = true; 1111 cananian 1.1.2.1 1112 cananian 1.1.2.1 Object[] op = new Object[q.operandsLength()]; 1113 cananian 1.1.2.1 for (int i=0; i < q.operandsLength(); i++) { 1114 cananian 1.1.2.1 LatticeVal v = get( q.operands(i) ); 1115 cananian 1.1.2.1 if (v==null) return; // can't eval yet. 1116 cananian 1.1.2.1 if (v instanceof xConstant) 1117 cananian 1.1.2.1 op[i] = ((xConstant)v).constValue(); 1118 cananian 1.1.2.1 else if (v instanceof xBitWidth) 1119 cananian 1.1.2.1 allConst = false; 1120 cananian 1.1.2.1 else 1121 cananian 1.1.2.1 allConst = allWidth = false; 1122 cananian 1.1.2.1 } 1123 cananian 1.1.2.1 if (allConst) { 1124 cananian 1.1.2.1 // RULE 3: 1125 cananian 1.1.2.1 HClass ty = q.evalType(); 1126 cananian 1.1.2.1 Object o = q.evalValue(op); 1127 cananian 1.1.2.1 if (ty == HClass.Boolean) 1128 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1129 cananian 1.1.2.4 new xOperBooleanResultKnown 1130 cananian 1.1.2.4 (q,((Boolean)o).booleanValue())); 1131 cananian 1.1.2.1 else if (ty == HClass.Int || ty == HClass.Long) 1132 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1133 cananian 1.1.2.1 new xIntConstant(ty, ((Number)o).longValue() ) ); 1134 cananian 1.1.2.1 else if (ty == HClass.Float || ty == HClass.Double) 1135 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xFloatConstant(ty, o) ); 1136 cananian 1.1.2.1 else throw new Error("Unknown OPER result type: "+ty); 1137 cananian 1.1.2.1 } else if ((allWidth) || 1138 cananian 1.1.2.1 opc == Qop.I2B || opc == Qop.I2C || opc == Qop.I2L || 1139 cananian 1.1.2.1 opc == Qop.I2S || opc == Qop.L2I) { 1140 cananian 1.1.2.1 // do something intelligent with the bitwidths. 1141 cananian 1.1.2.1 q.accept(opVisitor); 1142 cananian 1.1.2.1 } else { // not all constant, not all known widths... 1143 cananian 1.1.2.1 // special-case ACMPEQ x, null 1144 cananian 1.1.2.1 if (opc == Qop.ACMPEQ && 1145 cananian 1.1.2.1 ((get( q.operands(0) ) instanceof xNullConstant && 1146 cananian 1.1.2.1 get( q.operands(1) ) instanceof xClassNonNull) || 1147 cananian 1.1.2.1 (get( q.operands(0) ) instanceof xClassNonNull && 1148 cananian 1.1.2.1 get( q.operands(1) ) instanceof xNullConstant) ) ) 1149 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), // always false. 1150 cananian 1.1.2.4 new xOperBooleanResultKnown(q, false)); 1151 cananian 1.1.2.1 // special case boolean operations. 1152 cananian 1.1.2.1 else if (opc == Qop.ACMPEQ || 1153 cananian 1.1.2.1 opc == Qop.DCMPEQ || opc == Qop.DCMPGE || 1154 cananian 1.1.2.1 opc == Qop.DCMPGT || 1155 cananian 1.1.2.1 opc == Qop.FCMPEQ || opc == Qop.FCMPGE || 1156 cananian 1.1.2.1 opc == Qop.FCMPGT || 1157 cananian 1.1.2.1 opc == Qop.ICMPEQ || opc == Qop.ICMPGT || 1158 cananian 1.1.2.1 opc == Qop.LCMPEQ || opc == Qop.LCMPGT) 1159 cananian 1.1.2.4 raiseV(V, Wv, q.dst(), new xOperBooleanResultUnknown(q)); 1160 cananian 1.1.2.1 else { 1161 cananian 1.1.2.1 // RULE 4: 1162 cananian 1.1.2.1 HClass ty = q.evalType(); 1163 cananian 1.1.2.1 if (ty.isPrimitive()) 1164 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClassNonNull( toInternal(ty) ) ); 1165 cananian 1.1.2.1 else 1166 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClass( ty ) ); 1167 cananian 1.1.2.1 } 1168 cananian 1.1.2.1 } 1169 cananian 1.1.2.1 } 1170 cananian 1.1.2.1 public void visit(PHI q) { 1171 cananian 1.1.2.1 for (int i=0; i<q.numPhis(); i++) { // for each phi-function. 1172 cananian 1.1.2.4 LatticeVal merged = null; 1173 cananian 1.1.2.1 for (int j=0; j < q.arity(); j++) { 1174 cananian 1.1.2.14 if (!Ee.contains( Default.entry(q.prevEdge(j), context) )) 1175 cananian 1.1.2.1 continue; // skip non-executable edges. 1176 cananian 1.1.2.1 LatticeVal v = get ( q.src(i,j) ); 1177 cananian 1.1.2.1 if (v == null) 1178 cananian 1.1.2.1 continue; // skip this arg function. 1179 cananian 1.1.2.4 v = v.rename(q, j); 1180 cananian 1.1.2.4 if (merged == null) 1181 cananian 1.1.2.4 merged = v; // first valid value 1182 cananian 1.1.2.4 else merged = merged.merge(v); 1183 cananian 1.1.2.1 } 1184 cananian 1.1.2.1 // assess results. 1185 cananian 1.1.2.4 if (merged == null) 1186 cananian 1.1.2.1 continue; // nothing to go on. 1187 cananian 1.1.2.4 else raiseV(V, Wv, q.dst(i), merged); 1188 cananian 1.1.2.1 } // for each phi function. 1189 cananian 1.1.2.1 } 1190 cananian 1.1.2.3 public void visit(RETURN q) { 1191 cananian 1.1.2.14 returnMap.add 1192 cananian 1.1.2.14 ( Default.pair(context, q.getFactory().getMethod()), q ); 1193 cananian 1.1.2.7 if (q.retval() != null && get( q.retval() )==null) 1194 cananian 1.1.2.7 return; // wait for definition! 1195 cananian 1.1.2.14 // for all CALLs which may invoke this method in this context... 1196 cananian 1.10 for (Object pairO : callMap.getValues 1197 cananian 1.1.2.14 (Default.pair(context, q.getFactory().getMethod())) 1198 cananian 1.10 ) { 1199 cananian 1.10 List pair = (List) pairO; 1200 cananian 1.1.2.14 Context cc = (Context) pair.get(0); // caller's context 1201 cananian 1.1.2.14 CALL call = (CALL) pair.get(1); 1202 cananian 1.1.2.4 // mergeV on retval. 1203 cananian 1.1.2.3 if (q.retval()!=null) 1204 cananian 1.1.2.14 mergeV(V, Wv, cc, call.retval(), get( q.retval() )); 1205 cananian 1.1.2.3 // raiseE on appropriate outgoing edge. 1206 cananian 1.1.2.14 raiseE(Ee, Eq, Wq, cc, call.nextEdge(0)); 1207 cananian 1.1.2.3 // (don't forget sigmas) 1208 cananian 1.1.2.3 for (int i=0; i < call.numSigmas(); i++) { 1209 cananian 1.1.2.14 LatticeVal v2 = get ( cc, call.src(i) ); 1210 cananian 1.1.2.3 if (v2 != null) 1211 cananian 1.1.2.14 raiseV(V, Wv, cc, call.dst(i, 0), v2.rename(call, 0)); 1212 cananian 1.1.2.3 } 1213 cananian 1.1.2.3 } 1214 cananian 1.1.2.3 } 1215 cananian 1.1.2.2 public void visit(SET q) { 1216 cananian 1.1.2.4 if (corruptor==null) 1217 cananian 1.4.2.1 assert (q.objectref()!=null ? 1218 cananian 1.1.2.4 get(q.objectref())==null || 1219 cananian 1.4.2.1 get(q.objectref()) instanceof xClassNonNull : true) : q; 1220 cananian 1.1.2.2 /* widen type of field */ 1221 cananian 1.1.2.2 LatticeVal v = get( q.src() ); 1222 cananian 1.1.2.2 if (v != null) 1223 cananian 1.1.2.14 mergeV(Wf, q.field(), v); 1224 cananian 1.1.2.3 if (DEBUG) System.out.println("WRITE TO "+q.field()+" OF "+get( q.field() )); 1225 cananian 1.1.2.2 } 1226 cananian 1.1.2.1 public void visit(SWITCH q) { 1227 cananian 1.1.2.1 LatticeVal v = get( q.index() ); 1228 cananian 1.1.2.1 if (v instanceof xIntConstant) { 1229 cananian 1.1.2.1 int index = (int) ((xIntConstant)v).value(); 1230 cananian 1.1.2.1 int i; 1231 cananian 1.1.2.1 for (i=0; i<q.keysLength(); i++) 1232 cananian 1.1.2.1 if (q.keys(i) == index) 1233 cananian 1.1.2.1 break; 1234 cananian 1.1.2.1 // now i has the target index, even for the default case. 1235 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); // executable edge. 1236 cananian 1.1.2.1 // handle sigmas. 1237 cananian 1.1.2.1 for (int j=0; j < q.numSigmas(); j++) { 1238 cananian 1.1.2.1 LatticeVal v2 = get( q.src(j) ); 1239 cananian 1.1.2.1 if (v2 != null) 1240 cananian 1.1.2.1 raiseV(V, Wv, q.dst(j,i), v2.rename(q,i)); 1241 cananian 1.1.2.1 } 1242 cananian 1.1.2.1 } 1243 cananian 1.1.2.1 else if (v != null) { 1244 cananian 1.1.2.5 xBitWidth bw = extractWidth(v); 1245 cananian 1.1.2.5 // mark some edges executable & propagate to all sigmas. 1246 cananian 1.1.2.11 int executable=0; 1247 cananian 1.1.2.5 for (int j=0; j < q.nextEdge().length; j++) { 1248 cananian 1.1.2.11 if (j<q.keysLength()) { // non-default edge. 1249 cananian 1.1.2.5 // learn stuff about cases from bitwidth of v. 1250 cananian 1.1.2.5 int k = q.keys(j); 1251 cananian 1.1.2.5 if (k>0 && Util.fls(k) > bw.plusWidth()) 1252 cananian 1.1.2.5 continue; // key too large to be selected. 1253 cananian 1.1.2.5 if (k<0 && Util.fls(-k) > bw.minusWidth()) 1254 cananian 1.1.2.5 continue; // key too small to be selected. 1255 cananian 1.1.2.11 executable++; 1256 cananian 1.1.2.11 } else { 1257 cananian 1.1.2.11 // pigeon-hole principle: default edge is executable 1258 cananian 1.1.2.11 // iff number of executable edges (so far) is less 1259 cananian 1.1.2.11 // than possible number of cases constrained by 1260 cananian 1.1.2.11 // plusWidth and minusWidth. 1261 cananian 1.1.2.11 // --- bail if plusWidth/minusWidth too large; we 1262 cananian 1.1.2.11 // know (we hope!) that switch can't have this 1263 cananian 1.1.2.11 // many edges. 1264 cananian 1.1.2.11 if (bw.plusWidth<30 && bw.minusWidth<30) { 1265 cananian 1.1.2.11 // number of cases is (2^pw + 2^mw)-1 1266 cananian 1.1.2.11 // (don't count zero twice!) 1267 cananian 1.1.2.11 long cases = -1 + 1268 cananian 1.1.2.11 (1L<<bw.plusWidth()) + (1L<<bw.minusWidth()); 1269 cananian 1.4.2.1 assert executable<=cases; 1270 cananian 1.1.2.11 if (executable==cases) 1271 cananian 1.1.2.11 continue; // default not executable. 1272 cananian 1.1.2.11 } 1273 cananian 1.1.2.5 } 1274 cananian 1.1.2.5 raiseE(Ee, Eq, Wq, q.nextEdge(j) ); 1275 cananian 1.1.2.5 for (int i=0; i < q.numSigmas(); i++) { 1276 cananian 1.1.2.5 LatticeVal v2 = get( q.src(i) ); 1277 cananian 1.1.2.5 if (v2 != null) 1278 cananian 1.1.2.1 raiseV(V, Wv, q.dst(i,j), v2.rename(q,j)); 1279 cananian 1.1.2.5 } 1280 cananian 1.1.2.1 } 1281 cananian 1.1.2.1 } 1282 cananian 1.1.2.1 } 1283 cananian 1.1.2.3 public void visit(THROW q) { 1284 cananian 1.1.2.4 if (corruptor==null) 1285 cananian 1.4.2.1 assert get(q.throwable())==null || 1286 cananian 1.4.2.1 get(q.throwable()) instanceof xClassNonNull; 1287 cananian 1.1.2.14 throwMap.add 1288 cananian 1.1.2.14 ( Default.pair(context, q.getFactory().getMethod()), q ); 1289 cananian 1.1.2.3 if (get( q.throwable() )==null) return; // wait for definition! 1290 cananian 1.1.2.14 // for all CALLs which may invoke this method in this context... 1291 cananian 1.10 for (Object pairO : callMap.getValues 1292 cananian 1.1.2.14 (Default.pair(context, q.getFactory().getMethod())) 1293 cananian 1.10 ) { 1294 cananian 1.10 List pair = (List) pairO; 1295 cananian 1.1.2.14 Context cc = (Context) pair.get(0); //caller's context 1296 cananian 1.1.2.14 CALL call = (CALL) pair.get(1); 1297 cananian 1.1.2.4 // mergeV on retex. 1298 cananian 1.1.2.14 mergeV(V, Wv, cc, call.retex(), get( q.throwable() )); 1299 cananian 1.1.2.3 // raiseE on appropriate outgoing edge. 1300 cananian 1.1.2.14 raiseE(Ee, Eq, Wq, cc, call.nextEdge(1)); 1301 cananian 1.1.2.3 // (don't forget sigmas) 1302 cananian 1.1.2.3 for (int i=0; i < call.numSigmas(); i++) { 1303 cananian 1.1.2.14 LatticeVal v2 = get ( cc, call.src(i) ); 1304 cananian 1.1.2.3 if (v2 != null) 1305 cananian 1.1.2.14 raiseV(V, Wv, cc, call.dst(i, 1), v2.rename(call, 1)); 1306 cananian 1.1.2.3 } 1307 cananian 1.1.2.3 } 1308 cananian 1.1.2.3 } 1309 cananian 1.1.2.1 public void visit(TYPESWITCH q) { 1310 cananian 1.1.2.1 LatticeVal v = get( q.index() ); 1311 cananian 1.1.2.1 if (v instanceof xClass) { 1312 cananian 1.1.2.1 HClass type = ((xClass)v).type(); 1313 cananian 1.1.2.1 boolean catchAll = false; 1314 cananian 1.1.2.1 for (int i=0; i<q.keysLength(); i++) { 1315 cananian 1.1.2.1 if (type.isInstanceOf(q.keys(i))) {// catches all remaining 1316 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); 1317 cananian 1.1.2.1 catchAll = true; 1318 cananian 1.1.2.1 break; 1319 cananian 1.1.2.1 } 1320 cananian 1.7 if (q.keys(i).isInterface() || type.isInterface() || 1321 cananian 1.7 q.keys(i).isInstanceOf(type)) // executable 1322 cananian 1.7 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); 1323 cananian 1.1.2.1 } 1324 cananian 1.1.2.1 if ((!q.hasDefault()) || 1325 cananian 1.1.2.1 (catchAll && v instanceof xClassNonNull)) 1326 cananian 1.1.2.1 /* default edge never taken */; 1327 cananian 1.1.2.1 else // make the default case executable. 1328 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(q.keysLength())); 1329 cananian 1.1.2.1 1330 cananian 1.1.2.1 // handle sigmas. 1331 cananian 1.1.2.1 for (int i=0; i < q.arity(); i++) { 1332 cananian 1.1.2.14 if (!Ee.contains( Default.entry(q.nextEdge(i),context) )) 1333 cananian 1.1.2.14 continue;//only raise exec 1334 cananian 1.1.2.1 for (int j=0; j < q.numSigmas(); j++) { 1335 cananian 1.1.2.1 if (q.src(j)==q.index() && i<q.keysLength()) 1336 cananian 1.1.2.1 raiseV(V, Wv, q.dst(j,i), 1337 cananian 1.1.2.1 new xClassNonNull(q.keys(i))); 1338 cananian 1.1.2.1 else { 1339 cananian 1.1.2.1 LatticeVal v2 = get( q.src(j) ); 1340 cananian 1.1.2.1 if (v2 != null) 1341 cananian 1.1.2.1 raiseV(V, Wv, q.dst(j,i), v2.rename(q,i)); 1342 cananian 1.1.2.1 } 1343 cananian 1.1.2.1 } 1344 cananian 1.1.2.1 } 1345 cananian 1.1.2.1 } 1346 cananian 1.1.2.1 else if (v != null) { 1347 cananian 1.1.2.1 // mark all edges executable & propagate to all sigmas. 1348 cananian 1.1.2.1 for (int i=0; i < q.nextLength(); i++) 1349 cananian 1.1.2.1 raiseE(Ee, Eq, Wq, q.nextEdge(i) ); 1350 cananian 1.1.2.1 for (int i=0; i < q.numSigmas(); i++) { 1351 cananian 1.1.2.1 LatticeVal v2 = get( q.src(i) ); 1352 cananian 1.1.2.1 if (v2 != null) 1353 cananian 1.1.2.1 for (int j=0; j < q.arity(); j++) 1354 cananian 1.1.2.1 raiseV(V, Wv, q.dst(i,j), v2.rename(q,j)); 1355 cananian 1.1.2.1 } 1356 cananian 1.1.2.1 } 1357 cananian 1.1.2.1 } 1358 cananian 1.1.2.1 1359 cananian 1.1.2.1 /*------------------------------------------------------------*/ 1360 cananian 1.1.2.1 // VISITOR CLASS FOR OPER (ugh. lots of cases) 1361 cananian 1.1.2.1 class SCCOpVisitor extends OperVisitor { 1362 cananian 1.1.2.1 1363 cananian 1.1.2.1 public void visit_default(OPER q) { 1364 cananian 1.1.2.1 HClass ty = q.evalType(); 1365 cananian 1.1.2.1 if (ty.isPrimitive()) 1366 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClassNonNull( toInternal(ty) ) ); 1367 cananian 1.1.2.1 else 1368 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xClass( ty ) ); 1369 cananian 1.1.2.1 } 1370 cananian 1.1.2.1 // comparisons 1371 cananian 1.1.2.1 void visit_cmpeq(OPER q) { 1372 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1373 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1374 cananian 1.1.2.1 // comparisons against a constant. 1375 cananian 1.1.2.1 if ((left instanceof xIntConstant &&// left a constant and 1376 cananian 1.1.2.1 ((left.minusWidth()==0 && // right smaller than left. 1377 cananian 1.1.2.1 right.plusWidth() < left.plusWidth()) || 1378 cananian 1.1.2.1 (left.plusWidth()==0 && 1379 cananian 1.1.2.1 right.minusWidth() < left.minusWidth()))) || // or... 1380 cananian 1.1.2.1 (right instanceof xIntConstant &&// right a constant and 1381 cananian 1.1.2.1 ((right.minusWidth()==0 && // left smaller than right. 1382 cananian 1.1.2.1 left.plusWidth() < right.plusWidth()) || 1383 cananian 1.1.2.1 (right.plusWidth()==0 && 1384 cananian 1.1.2.1 left.minusWidth() < right.minusWidth()))) ) 1385 cananian 1.1.2.1 // okay, comparison can never be true. 1386 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1387 cananian 1.1.2.4 new xOperBooleanResultKnown(q,false)); 1388 cananian 1.1.2.1 else // okay, nothing known. 1389 cananian 1.1.2.4 raiseV(V, Wv, q.dst(), new xOperBooleanResultUnknown(q)); 1390 cananian 1.1.2.1 } 1391 cananian 1.1.2.1 public void visit_icmpeq(OPER q) { visit_cmpeq(q); } 1392 cananian 1.1.2.1 public void visit_lcmpeq(OPER q) { visit_cmpeq(q); } 1393 cananian 1.1.2.1 void visit_cmpgt(OPER q) { 1394 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1395 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1396 cananian 1.1.2.1 // comparisons against a non-zero constant. 1397 cananian 1.1.2.1 if ((left instanceof xIntConstant && 1398 cananian 1.1.2.1 ((xIntConstant)left).value()!=0 && 1399 cananian 1.1.2.1 left.plusWidth() > right.plusWidth()) || 1400 cananian 1.1.2.1 (right instanceof xIntConstant && 1401 cananian 1.1.2.1 ((xIntConstant)right).value()!=0 && 1402 cananian 1.1.2.1 right.minusWidth() > left.minusWidth())) 1403 cananian 1.1.2.1 // comparison is always true 1404 cananian 1.1.2.4 raiseV(V,Wv, q.dst(), new xOperBooleanResultKnown(q,true)); 1405 cananian 1.1.2.1 else if ((left instanceof xIntConstant && 1406 cananian 1.1.2.1 ((xIntConstant)left).value()!=0 && 1407 cananian 1.1.2.1 left.minusWidth() > right.minusWidth()) || 1408 cananian 1.1.2.1 (right instanceof xIntConstant && 1409 cananian 1.1.2.1 ((xIntConstant)right).value()!=0 && 1410 cananian 1.1.2.1 right.plusWidth() > left.plusWidth())) 1411 cananian 1.1.2.1 // comparison is always false 1412 cananian 1.1.2.4 raiseV(V,Wv, q.dst(),new xOperBooleanResultKnown(q,false)); 1413 cananian 1.1.2.1 // comparisons against zero. 1414 cananian 1.1.2.1 else if ((left instanceof xIntConstant && 1415 cananian 1.1.2.1 ((xIntConstant)left).value()==0 && 1416 cananian 1.1.2.1 right.minusWidth()==0) || 1417 cananian 1.1.2.1 (right instanceof xIntConstant && 1418 cananian 1.1.2.1 ((xIntConstant)right).value()==0 && 1419 cananian 1.1.2.1 left.plusWidth()==0)) 1420 cananian 1.1.2.1 // comparison is always false. 0 > 0+ or 0- > 0 1421 cananian 1.1.2.4 raiseV(V,Wv, q.dst(),new xOperBooleanResultKnown(q,false)); 1422 cananian 1.1.2.1 else // okay, nothing known. 1423 cananian 1.1.2.4 raiseV(V, Wv, q.dst(), new xOperBooleanResultUnknown(q)); 1424 cananian 1.1.2.1 } 1425 cananian 1.1.2.1 public void visit_icmpgt(OPER q) { visit_cmpgt(q); } 1426 cananian 1.1.2.1 public void visit_lcmpgt(OPER q) { visit_cmpgt(q); } 1427 cananian 1.1.2.1 // conversions 1428 cananian 1.1.2.1 public void visit_i2b(OPER q) { 1429 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 1430 cananian 1.6 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 1431 cananian 1.6 if (bw.plusWidth>=8) 1432 cananian 1.6 mbw = 8; // large + val may become large - val. 1433 cananian 1.6 if (bw.minusWidth()>=8) 1434 cananian 1.6 pbw = 7; // large - val may become large + val. 1435 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1436 cananian 1.1.2.1 new xBitWidth(HClass.Int, 1437 cananian 1.6 Math.min(8, mbw), 1438 cananian 1.6 Math.min(7, pbw) )); 1439 cananian 1.1.2.1 } 1440 cananian 1.1.2.1 public void visit_i2c(OPER q) { 1441 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 1442 cananian 1.6 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 1443 cananian 1.6 if (bw.minusWidth()>0) 1444 cananian 1.6 pbw = 16; // - val may become large + val. 1445 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1446 cananian 1.1.2.1 new xBitWidth(HClass.Int, 0, 1447 cananian 1.6 Math.min(16, pbw) )); 1448 cananian 1.1.2.1 } 1449 cananian 1.1.2.1 public void visit_i2l(OPER q) { 1450 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 1451 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1452 cananian 1.1.2.1 new xBitWidth(HClass.Long, 1453 cananian 1.1.2.1 Math.min(32, bw.minusWidth()), 1454 cananian 1.1.2.1 Math.min(31, bw.plusWidth()) )); 1455 cananian 1.1.2.1 } 1456 cananian 1.1.2.1 public void visit_i2s(OPER q) { 1457 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 1458 cananian 1.6 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 1459 cananian 1.6 if (bw.plusWidth>=16) 1460 cananian 1.6 mbw = 16; // large + val may become large - val. 1461 cananian 1.6 if (bw.minusWidth()>=16) 1462 cananian 1.6 pbw = 15; // large - val may become large + val. 1463 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1464 cananian 1.1.2.1 new xBitWidth(HClass.Int, 1465 cananian 1.6 Math.min(16, mbw), 1466 cananian 1.6 Math.min(15, pbw) )); 1467 cananian 1.1.2.1 } 1468 cananian 1.1.2.1 public void visit_l2i(OPER q) { 1469 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 1470 cananian 1.6 int mbw = bw.minusWidth(), pbw = bw.plusWidth(); 1471 cananian 1.6 if (bw.plusWidth>=32) 1472 cananian 1.6 mbw = 32; // large + val may become large - val. 1473 cananian 1.6 if (bw.minusWidth()>=32) 1474 cananian 1.6 pbw = 31; // large - val may become large + val. 1475 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), 1476 cananian 1.1.2.1 new xBitWidth(HClass.Int, 1477 cananian 1.6 Math.min(32, mbw), 1478 cananian 1.6 Math.min(31, pbw) )); 1479 cananian 1.1.2.1 } 1480 cananian 1.1.2.1 // binops 1481 cananian 1.6 void visit_add(OPER q, int maxbits) { 1482 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1483 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1484 cananian 1.1.2.1 int m = Math.max( left.minusWidth(), right.minusWidth() ); 1485 cananian 1.1.2.1 int p = Math.max( left.plusWidth(), right.plusWidth() ); 1486 cananian 1.1.2.1 // zero plus zero is always zero, but other numbers grow. 1487 cananian 1.6 // also 0+x: x doesn't grow. 1488 cananian 1.6 if (left.minusWidth()>0 && right.minusWidth()>0) m++; 1489 cananian 1.6 if (left.plusWidth()>0 && right.plusWidth()>0) p++; 1490 cananian 1.6 // handle overflow. 1491 cananian 1.6 if (p >= maxbits) 1492 cananian 1.6 m = maxbits; // large + val becomes large - val. 1493 cananian 1.6 if (m >= maxbits) 1494 cananian 1.6 p = maxbits-1; // large - val becomes large + val. 1495 cananian 1.6 // okay, raise it! 1496 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1497 cananian 1.1.2.1 } 1498 cananian 1.6 public void visit_iadd(OPER q) { visit_add(q, 32); } 1499 cananian 1.6 public void visit_ladd(OPER q) { visit_add(q, 64); } 1500 cananian 1.1.2.1 1501 cananian 1.1.2.1 void visit_and(OPER q) { 1502 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1503 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1504 cananian 1.1.2.1 // if there are zero crossings, we have worst-case performance. 1505 cananian 1.1.2.1 int m = Math.max( left.minusWidth(), right.minusWidth() ); 1506 cananian 1.1.2.1 int p = Math.max( left.plusWidth(), right.plusWidth() ); 1507 cananian 1.1.2.1 // check for special positive-number cases. 1508 cananian 1.1.2.1 if (left.minusWidth()==0 && right.minusWidth()==0) 1509 cananian 1.1.2.1 p = Math.min( left.plusWidth(), right.plusWidth() ); 1510 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1511 cananian 1.1.2.1 } 1512 cananian 1.1.2.1 public void visit_iand(OPER q) { visit_and(q); } 1513 cananian 1.1.2.1 public void visit_land(OPER q) { visit_and(q); } 1514 cananian 1.1.2.1 1515 cananian 1.1.2.1 void visit_div(OPER q) { 1516 cananian 1.1.2.1 // we can ignore divide-by-zero. 1517 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1518 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1519 cananian 1.1.2.1 // worst case: either number both pos and neg 1520 cananian 1.1.2.1 int m = Math.max(left.minusWidth(), left.plusWidth()); 1521 cananian 1.1.2.1 int p = Math.max(left.minusWidth(), left.plusWidth()); 1522 cananian 1.1.2.1 // check for special one-quadrant cases. 1523 cananian 1.1.2.1 if (left.minusWidth()==0) { 1524 cananian 1.1.2.1 if (right.minusWidth()==0) m=0; // result positive 1525 cananian 1.1.2.1 if (right.plusWidth()==0) p=0; // result negative 1526 cananian 1.1.2.1 } 1527 cananian 1.1.2.1 if (left.plusWidth()==0) { 1528 cananian 1.1.2.1 if (right.minusWidth()==0) m=0; // result negative 1529 cananian 1.1.2.1 if (right.plusWidth()==0) p=0; // result positive 1530 cananian 1.1.2.1 } 1531 cananian 1.1.2.1 // special case if divisor is a constant. 1532 cananian 1.1.2.1 if (right instanceof xIntConstant) { 1533 cananian 1.1.2.1 if (right.minusWidth()==0) { // a positive constant 1534 cananian 1.1.2.1 m = Math.max(0, left.minusWidth() - right.plusWidth()); 1535 cananian 1.1.2.1 p = Math.max(0, left.plusWidth() - right.plusWidth()); 1536 cananian 1.1.2.1 } 1537 cananian 1.1.2.1 if (right.plusWidth()==0) { // a negative constant 1538 cananian 1.1.2.1 m = Math.max(0, left.minusWidth()-right.minusWidth()); 1539 cananian 1.1.2.1 p = Math.max(0, left.plusWidth() -right.minusWidth()); 1540 cananian 1.1.2.1 } 1541 cananian 1.1.2.1 } 1542 cananian 1.6 // XXX overflow? 1543 cananian 1.1.2.1 // done. 1544 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1545 cananian 1.1.2.1 } 1546 cananian 1.1.2.1 public void visit_idiv(OPER q) { visit_div(q); } 1547 cananian 1.1.2.1 public void visit_ldiv(OPER q) { visit_div(q); } 1548 cananian 1.1.2.1 1549 cananian 1.6 void visit_mul(OPER q, int maxbits) { 1550 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1551 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1552 cananian 1.1.2.1 // worst case: either number both pos and neg 1553 cananian 1.1.2.1 int m = Math.max(left.minusWidth() + right.plusWidth(), 1554 cananian 1.1.2.1 left.plusWidth() + right.minusWidth()); 1555 cananian 1.1.2.1 int p = Math.max(left.minusWidth() + right.minusWidth(), 1556 cananian 1.1.2.1 left.plusWidth() + right.plusWidth()); 1557 cananian 1.1.2.1 // special case multiplication by zero, one, and two. 1558 cananian 1.1.2.16 if (right instanceof xIntConstant) { // switch r and l 1559 cananian 1.1.2.16 xBitWidth temp=left; left=right; right=temp; 1560 cananian 1.1.2.16 } 1561 cananian 1.1.2.1 if (left instanceof xIntConstant) { 1562 cananian 1.1.2.1 long val = ((xIntConstant)left).value(); 1563 cananian 1.1.2.1 if (val==0) { 1564 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), left); return; 1565 cananian 1.1.2.1 } 1566 cananian 1.1.2.1 if (val==1) { 1567 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), right); return; 1568 cananian 1.1.2.1 } 1569 cananian 1.1.2.1 if (val==2) { 1570 cananian 1.1.2.1 m = right.minusWidth()+1; 1571 cananian 1.1.2.1 p = right.plusWidth() +1; 1572 cananian 1.1.2.1 } 1573 cananian 1.1.2.1 } 1574 cananian 1.1.2.1 // XXX special case multiplication by one-bit quantities? 1575 cananian 1.6 // handle overflow. 1576 cananian 1.6 if (p >= maxbits) 1577 cananian 1.6 m = maxbits; // large + val becomes large - val. 1578 cananian 1.6 if (m >= maxbits) 1579 cananian 1.6 p = maxbits-1; // large - val becomes large + val. 1580 cananian 1.1.2.1 // done. 1581 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1582 cananian 1.1.2.1 } 1583 cananian 1.6 public void visit_imul(OPER q) { visit_mul(q,32); } 1584 cananian 1.6 public void visit_lmul(OPER q) { visit_mul(q,64); } 1585 cananian 1.1.2.1 1586 cananian 1.6 void visit_neg(OPER q, int maxbits) { 1587 cananian 1.1.2.1 xBitWidth bw = extractWidth( get( q.operands(0) ) ); 1588 cananian 1.1.2.1 int m = bw.plusWidth(); 1589 cananian 1.1.2.1 int p = bw.minusWidth(); 1590 cananian 1.6 // special case: negating the largest neg num results in neg 1591 cananian 1.6 if (bw.minusWidth() >= maxbits) 1592 cananian 1.6 m = maxbits; // -X = X for largest negative number 1593 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1594 cananian 1.1.2.1 } 1595 cananian 1.6 public void visit_ineg(OPER q) { visit_neg(q, 32); } 1596 cananian 1.6 public void visit_lneg(OPER q) { visit_neg(q, 64); } 1597 cananian 1.1.2.1 1598 cananian 1.1.2.1 void visit_or(OPER q) { 1599 cananian 1.1.2.1 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1600 cananian 1.1.2.1 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1601 cananian 1.1.2.1 // if there are zero crossings, we have worst-case performance. 1602 cananian 1.1.2.1 // XXX: check this "worst-case" computation; might be overly 1603 cananian 1.1.2.1 // conservative. If definitely correct for the 1604 cananian 1.1.2.1 // positive-number-only case. 1605 cananian 1.1.2.1 int m = Math.max( left.minusWidth(), right.minusWidth() ); 1606 cananian 1.1.2.1 int p = Math.max( left.plusWidth(), right.plusWidth() ); 1607 cananian 1.1.2.1 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1608 cananian 1.1.2.1 } 1609 cananian 1.1.2.1 public void visit_ior(OPER q) { visit_or(q); } 1610 cananian 1.1.2.1 public void visit_lor(OPER q) { visit_or(q); } 1611 cananian 1.1.2.16 1612 cananian 1.1.2.16 void visit_rem(OPER q) { 1613 cananian 1.1.2.16 // we don't have to worry about division by zero. 1614 cananian 1.1.2.16 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1615 cananian 1.1.2.16 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1616 cananian 1.1.2.16 // from JLS 15.17.3: "the result of the remainder 1617 cananian 1.1.2.16 // operation can be negative only if the dividend is 1618 cananian 1.1.2.16 // negative, and can be positive only if the dividend 1619 cananian 1.1.2.16 // is positive; moreover, the magnitude of the result 1620 cananian 1.1.2.16 // is always less than the magnitude of the divisor." 1621 cananian 1.1.2.16 if (right instanceof xIntConstant) { 1622 cananian 1.1.2.16 // use the fact that result is strictly less to narrow 1623 cananian 1.1.2.16 long val = ((xIntConstant)right).value(); 1624 cananian 1.1.2.16 right = new xIntConstant(right.type(), val-1 ); 1625 cananian 1.1.2.16 } 1626 cananian 1.1.2.16 int absmag=Math.max(left.minusWidth(), left.plusWidth()); 1627 cananian 1.1.2.16 // abs value of result will also always be smaller than 1628 cananian 1.1.2.16 // abs value of dividend. 1629 cananian 1.1.2.16 int m = Math.min(right.minusWidth(), absmag); 1630 cananian 1.1.2.16 int p = Math.min(right.plusWidth(), absmag); 1631 cananian 1.6 // XXX overflow? 1632 cananian 1.1.2.16 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1633 cananian 1.1.2.16 } 1634 cananian 1.1.2.16 public void visit_irem(OPER q) { visit_rem(q); } 1635 cananian 1.1.2.16 public void visit_lrem(OPER q) { visit_rem(q); } 1636 cananian 1.1.2.16 1637 cananian 1.1.2.16 // SHIFTS. From the JLS, 15.19: "If the promoted type of 1638 cananian 1.1.2.16 // the left-hand operand is int, only the five 1639 cananian 1.1.2.16 // lowest-order bits of the right-hand operand are used as 1640 cananian 1.1.2.16 // the shift distance. It is as if the right-hand operand 1641 cananian 1.1.2.16 // were subjected to a bitwise logical AND operator & 1642 cananian 1.1.2.16 // (15.22.1) with the mask value 0x1f. The shift distance 1643 cananian 1.1.2.16 // actually used is therefore always in the range 0 to 31, 1644 cananian 1.1.2.16 // inclusive. 1645 cananian 1.1.2.16 // 1646 cananian 1.1.2.16 // "If the promoted type of the left-hand operand is long, 1647 cananian 1.1.2.16 // then only the six lowest-order bits of the right-hand 1648 cananian 1.1.2.16 // operand are used as the shift distance. It is as if the 1649 cananian 1.1.2.16 // right-hand operand were subjected to a bitwise logical 1650 cananian 1.1.2.16 // AND operator & (15.22.1) with the mask value 0x3f. The 1651 cananian 1.1.2.16 // shift distance actually used is therefore always in the 1652 cananian 1.1.2.16 // range 0 to 63, inclusive." 1653 cananian 1.1.2.16 1654 cananian 1.1.2.16 void visit_shl(OPER q, boolean isLong) { 1655 cananian 1.1.2.16 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1656 cananian 1.1.2.16 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1657 cananian 1.1.2.16 int shift; 1658 cananian 1.1.2.16 // compute largest possible shift. 1659 cananian 1.1.2.16 if (right instanceof xIntConstant) { 1660 cananian 1.1.2.16 // we know the shift exactly. whoo-hoo! 1661 cananian 1.1.2.16 long val = ((xIntConstant)right).value(); 1662 cananian 1.1.2.16 shift = (int) (val & (isLong ? 0x3F : 0x1F )); 1663 cananian 1.1.2.16 // equivalent to mult by constant 2^shift. 1664 cananian 1.1.2.16 } else if (right.minusWidth()==0 && 1665 cananian 1.1.2.16 right.plusWidth() < (isLong ? 6 : 5)) { 1666 cananian 1.1.2.16 //largest value possible on right is (2^p)-1. 1667 cananian 1.1.2.16 shift = (1<<right.plusWidth())-1; 1668 cananian 1.1.2.16 } else 1669 cananian 1.1.2.16 shift = (isLong) ? 63 : 31; 1670 cananian 1.1.2.16 // okay. nominally widths are width+shift. 1671 cananian 1.1.2.16 int m = left.minusWidth()+shift; 1672 cananian 1.1.2.16 int p = left.plusWidth()+shift; 1673 cananian 1.1.2.16 // zero shifted by anything is still zero, though. 1674 cananian 1.1.2.16 if (left.minusWidth()==0) m=0; 1675 cananian 1.1.2.16 if (left.plusWidth()==0) p=0; 1676 cananian 1.1.2.16 // if we could corrupt the sign bit, all bets are off. 1677 cananian 1.1.2.16 boolean canFrobSign = 1678 cananian 1.1.2.16 /* can leftmost one move into sign bit? */ 1679 cananian 1.1.2.16 ( (left.plusWidth()+shift) >= (isLong?64:32) ) || 1680 cananian 1.1.2.16 /* can leftmost zero move into sign bit? */ 1681 cananian 1.1.2.16 ( (left.minusWidth()+shift) >= (isLong?64:32) ); 1682 cananian 1.1.2.16 if (canFrobSign) { m=1000; p=1000; } 1683 cananian 1.1.2.16 // rely on bitwidth limiting the below. 1684 cananian 1.1.2.16 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1685 cananian 1.1.2.16 } 1686 cananian 1.1.2.16 public void visit_ishl(OPER q) { visit_shl(q, false); } 1687 cananian 1.1.2.16 public void visit_lshl(OPER q) { visit_shl(q, true); } 1688 cananian 1.1.2.16 1689 cananian 1.1.2.16 void visit_shr(OPER q, boolean isSigned, boolean isLong) { 1690 cananian 1.1.2.16 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1691 cananian 1.1.2.16 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1692 cananian 1.1.2.16 int shift; boolean exactlyZero=false; 1693 cananian 1.1.2.16 // compute smallest possible shift. 1694 cananian 1.1.2.16 if (right instanceof xIntConstant) { 1695 cananian 1.1.2.16 // we know the shift exactly. whoo-hoo! 1696 cananian 1.1.2.16 long val = ((xIntConstant)right).value(); 1697 cananian 1.1.2.16 shift = (int) (val & (isLong ? 0x3F : 0x1F )); 1698 cananian 1.1.2.16 if (shift==0) exactlyZero=true; 1699 cananian 1.1.2.16 } else 1700 cananian 1.1.2.16 // smallest possible shift is zero. 1701 cananian 1.1.2.16 shift = 0; 1702 cananian 1.1.2.16 // okay. nominally widths are width-shift. 1703 cananian 1.1.2.16 int m = Math.max(0, left.minusWidth()-shift); 1704 cananian 1.1.2.16 int p = Math.max(0, left.plusWidth()-shift); 1705 cananian 1.1.2.16 // zero shifted by anything is still zero, though. 1706 cananian 1.1.2.16 if (left.minusWidth()==0) m=0; 1707 cananian 1.1.2.16 if (left.plusWidth()==0) p=0; 1708 cananian 1.1.2.16 // if we could corrupt the sign bit, negative numbers 1709 cananian 1.1.2.16 // can become large positive numbers. 1710 cananian 1.1.2.16 if (left.minusWidth()>0 && !isSigned && !exactlyZero) 1711 cananian 1.1.2.16 p=Math.max(p, (isLong?64:32)-shift); 1712 cananian 1.1.2.16 // rely on bitwidth limiting the below. 1713 cananian 1.1.2.16 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1714 cananian 1.1.2.16 } 1715 cananian 1.1.2.16 public void visit_ishr(OPER q) { visit_shr(q, false, false); } 1716 cananian 1.1.2.16 public void visit_lshr(OPER q) { visit_shr(q, false, true); } 1717 cananian 1.1.2.16 public void visit_iushr(OPER q) { visit_shr(q, true, false); } 1718 cananian 1.1.2.16 public void visit_lushr(OPER q) { visit_shr(q, true, true); } 1719 cananian 1.1.2.16 1720 cananian 1.1.2.16 void visit_xor(OPER q) { 1721 cananian 1.1.2.16 xBitWidth left = extractWidth( get( q.operands(0) ) ); 1722 cananian 1.1.2.16 xBitWidth right= extractWidth( get( q.operands(1) ) ); 1723 cananian 1.1.2.16 int mL=left.minusWidth(), pL=left.plusWidth(); 1724 cananian 1.1.2.16 int mR=right.minusWidth(), pR=right.plusWidth(); 1725 cananian 1.1.2.16 int m=0, p=0; 1726 cananian 1.1.2.16 // note that <0,0>=constant zero is included in plus range 1727 cananian 1.1.2.16 // (i.e. all ranges are said to have '+' components (the 0) ) 1728 cananian 1.1.2.16 // <0,pL> xor <0,pR> = <0,MAX(pL,pR)> 1729 cananian 1.1.2.16 if (pL>=0 && pR>=0) 1730 cananian 1.1.2.16 p = Math.max(p, Math.max(pL, pR)); 1731 cananian 1.1.2.16 // <0,pL> xor <mR,0> = <MAX(pL,mR),0> 1732 cananian 1.1.2.16 if (pL>=0 && mR>0) 1733 cananian 1.1.2.16 m = Math.max(m, Math.max(pL, mR)); 1734 cananian 1.1.2.16 // <mL,0> xor <0,pR> = <MAX(mL,pR),0> 1735 cananian 1.1.2.16 if (mL>0 && pR>=0) 1736 cananian 1.1.2.16 m = Math.max(m, Math.max(mL, pR)); 1737 cananian 1.1.2.16 // <mL,0> xor <mR,0> = <0,MAX(mL,mR)> 1738 cananian 1.1.2.16 if (mL>0 && mR>0) 1739 cananian 1.1.2.16 p = Math.max(p, Math.max(mL, mR)); 1740 cananian 1.1.2.16 // ta-da! 1741 cananian 1.1.2.16 raiseV(V, Wv, q.dst(), new xBitWidth(q.evalType(), m, p) ); 1742 cananian 1.1.2.16 } 1743 cananian 1.1.2.16 public void visit_ixor(OPER q) { visit_xor(q); } 1744 cananian 1.1.2.16 public void visit_lxor(OPER q) { visit_xor(q); } 1745 cananian 1.1.2.1 } 1746 cananian 1.1.2.1 } 1747 cananian 1.1.2.1 /*-------------------------------------------------------------*/ 1748 cananian 1.1.2.1 // Extract bitwidth information from unwilling victims. 1749 cananian 1.1.2.1 xBitWidth extractWidth(LatticeVal v) { 1750 cananian 1.1.2.1 if (v instanceof xBitWidth) 1751 cananian 1.1.2.1 return (xBitWidth) v; 1752 cananian 1.1.2.1 if (! (v instanceof xClass) ) 1753 cananian 1.1.2.1 throw new Error("Something's seriously screwed up."); 1754 cananian 1.1.2.1 xClass xc = (xClass) v; 1755 cananian 1.1.2.1 // trust xBitWidth to properly limit. 1756 cananian 1.1.2.1 return new xBitWidth(xc.type(), 1000, 1000); 1757 cananian 1.1.2.1 } 1758 cananian 1.1.2.1 1759 cananian 1.1.2.1 // Deal with the fact that external Byte/Short/Char/Boolean classes 1760 cananian 1.1.2.1 // are represented internally as ints. 1761 cananian 1.1.2.1 1762 cananian 1.1.2.1 static HClass toInternal(HClass c) { 1763 cananian 1.1.2.1 if (c.equals(HClass.Byte) || c.equals(HClass.Short) || 1764 cananian 1.1.2.1 c.equals(HClass.Char) || c.equals(HClass.Boolean)) 1765 cananian 1.1.2.1 return HClass.Int; 1766 cananian 1.1.2.1 return c; 1767 cananian 1.1.2.1 } 1768 cananian 1.1.2.1 1769 cananian 1.1.2.1 /*-------------------------------------------------------------*/ 1770 cananian 1.1.2.1 // Lattice classes. 1771 cananian 1.1.2.1 1772 cananian 1.1.2.1 /** No information obtainable about a temp. */ 1773 cananian 1.1.2.4 static abstract class LatticeVal { 1774 cananian 1.1.2.1 public String toString() { return "Top"; } 1775 cananian 1.1.2.1 public boolean equals(Object o) { return o instanceof LatticeVal; } 1776 cananian 1.1.2.4 // merge. 1777 cananian 1.1.2.4 public abstract LatticeVal merge(LatticeVal v); 1778 cananian 1.1.2.5 // narrow. 1779 cananian 1.1.2.5 public abstract boolean isLowerThan(LatticeVal v); 1780 cananian 1.1.2.1 // by default, the renaming does nothing. 1781 cananian 1.1.2.1 public LatticeVal rename(PHI p, int i) { return this; } 1782 cananian 1.1.2.1 public LatticeVal rename(SIGMA s, int i) { return this; } 1783 cananian 1.1.2.1 } 1784 cananian 1.1.2.1 /** A typed temp. */ 1785 cananian 1.1.2.1 static class xClass extends LatticeVal { 1786 cananian 1.1.2.1 protected HClass type; 1787 cananian 1.1.2.1 public xClass(HClass type) { 1788 cananian 1.4.2.1 assert type!=HClass.Boolean && type!=HClass.Byte && 1789 cananian 1.4.2.1 type!=HClass.Short && type!=HClass.Char : "Not an internal type ("+type+")"; 1790 cananian 1.1.2.1 this.type = type; 1791 cananian 1.1.2.1 } 1792 cananian 1.1.2.1 public HClass type() { return type; } 1793 cananian 1.1.2.1 public String toString() { 1794 cananian 1.1.2.1 return "xClass: " + type; 1795 cananian 1.1.2.1 } 1796 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 1797 cananian 1.1.2.4 private boolean _equals(Object o) { 1798 cananian 1.1.2.1 xClass xc; 1799 cananian 1.1.2.1 try { xc=(xClass) o; } 1800 cananian 1.1.2.1 catch (ClassCastException e) { return false;} 1801 cananian 1.1.2.1 return xc!=null && xc.type.equals(type); 1802 cananian 1.1.2.1 } 1803 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 1804 cananian 1.1.2.4 xClass vv = (xClass) v; 1805 cananian 1.1.2.4 return new xClass(mergeTypes(this.type, vv.type)); 1806 cananian 1.1.2.4 } 1807 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 1808 cananian 1.1.2.5 return !(v instanceof xClass); 1809 cananian 1.1.2.5 } 1810 cananian 1.1.2.4 // Class merge function. 1811 cananian 1.1.2.4 static HClass mergeTypes(HClass a, HClass b) { 1812 cananian 1.4.2.1 assert a!=null && b!=null; 1813 cananian 1.1.2.4 if (a==b) return a; // take care of primitive types. 1814 cananian 1.1.2.4 1815 cananian 1.1.2.4 // Special case 'Void' Hclass, used for null constants. 1816 cananian 1.1.2.4 if (a==HClass.Void) 1817 cananian 1.1.2.4 return b; 1818 cananian 1.1.2.4 if (b==HClass.Void) 1819 cananian 1.1.2.4 return a; 1820 cananian 1.1.2.4 1821 cananian 1.1.2.4 // by this point better be array ref or object, not primitive type. 1822 cananian 1.4.2.1 assert (!a.isPrimitive()) && (!b.isPrimitive()); 1823 cananian 1.1.2.4 return HClassUtil.commonParent(a,b); 1824 cananian 1.1.2.1 } 1825 cananian 1.1.2.1 } 1826 cananian 1.1.2.1 /** A single class type; guaranteed the value is not null. */ 1827 cananian 1.1.2.1 static class xClassNonNull extends xClass { 1828 cananian 1.1.2.1 public xClassNonNull(HClass type) { 1829 cananian 1.1.2.1 super( type ); 1830 cananian 1.4.2.1 assert type!=HClass.Void; 1831 cananian 1.1.2.1 } 1832 cananian 1.1.2.1 public String toString() { 1833 cananian 1.1.2.1 return "xClassNonNull: { " + type + " }"; 1834 cananian 1.1.2.1 } 1835 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 1836 cananian 1.1.2.4 private boolean _equals(Object o) { 1837 cananian 1.1.2.1 return (o instanceof xClassNonNull && super.equals(o)); 1838 cananian 1.1.2.1 } 1839 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 1840 cananian 1.1.2.4 if (!(v instanceof xClassNonNull)) return super.merge(v); 1841 cananian 1.1.2.4 xClassNonNull vv = (xClassNonNull) v; 1842 cananian 1.1.2.4 return new xClassNonNull(mergeTypes(this.type, vv.type)); 1843 cananian 1.1.2.1 } 1844 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 1845 cananian 1.1.2.5 return !(v instanceof xClassNonNull); 1846 cananian 1.1.2.5 } 1847 cananian 1.1.2.1 } 1848 cananian 1.1.2.1 /** An object of the specified *exact* type (not a subtype). */ 1849 cananian 1.1.2.1 static class xClassExact extends xClassNonNull { 1850 cananian 1.1.2.1 public xClassExact(HClass type) { 1851 cananian 1.1.2.1 super(type); 1852 cananian 1.7 assert !type.isInterface(); // interface types can't be exact. 1853 cananian 1.1.2.1 } 1854 cananian 1.1.2.1 public String toString() { 1855 cananian 1.1.2.1 return "xClassExact: { " + type + " }"; 1856 cananian 1.1.2.1 } 1857 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 1858 cananian 1.1.2.4 private boolean _equals(Object o) { 1859 cananian 1.1.2.1 return (o instanceof xClassExact && super.equals(o)); 1860 cananian 1.1.2.1 } 1861 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 1862 cananian 1.1.2.4 if (this._equals(v)) return new xClassExact(type); 1863 cananian 1.1.2.4 return super.merge(v); 1864 cananian 1.1.2.1 } 1865 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 1866 cananian 1.1.2.5 return !(v instanceof xClassExact); 1867 cananian 1.1.2.5 } 1868 cananian 1.1.2.1 } 1869 cananian 1.1.2.1 /** An array with constant length. The array is not null, of course. */ 1870 cananian 1.1.2.1 static class xClassArray extends xClassExact { 1871 cananian 1.1.2.1 protected int length; 1872 cananian 1.1.2.1 public xClassArray(HClass type, int length) { 1873 cananian 1.1.2.1 super(type); 1874 cananian 1.1.2.1 this.length = length; 1875 cananian 1.1.2.1 } 1876 cananian 1.1.2.1 public int length() { return length; } 1877 cananian 1.1.2.1 public String toString() { 1878 cananian 1.1.2.1 return "xClassArray: " + 1879 cananian 1.1.2.1 type.getComponentType() + "["+length+"]"; 1880 cananian 1.1.2.1 } 1881 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 1882 cananian 1.1.2.4 private boolean _equals(Object o) { 1883 cananian 1.1.2.1 xClassArray xca; 1884 cananian 1.1.2.1 try { xca = (xClassArray) o; } 1885 cananian 1.1.2.1 catch (ClassCastException e) { return false; } 1886 cananian 1.1.2.1 return xca!=null && super.equals(xca) && xca.length == length; 1887 cananian 1.1.2.1 } 1888 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 1889 cananian 1.1.2.4 if (this._equals(v)) return new xClassArray(type,length); 1890 cananian 1.1.2.4 return super.merge(v); 1891 cananian 1.1.2.1 } 1892 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 1893 cananian 1.1.2.5 return !(v instanceof xClassArray); 1894 cananian 1.1.2.5 } 1895 cananian 1.1.2.1 } 1896 cananian 1.1.2.1 /** An integer value of the specified bitwidth. */ 1897 cananian 1.1.2.1 static class xBitWidth extends xClassExact { 1898 cananian 1.1.2.1 /** Highest significant bit for positive numbers. */ 1899 cananian 1.1.2.1 protected int plusWidth; 1900 cananian 1.1.2.1 /** Highest significant bit for negative numbers. */ 1901 cananian 1.1.2.1 protected int minusWidth; 1902 cananian 1.1.2.1 /** Constructor. */ 1903 cananian 1.1.2.1 public xBitWidth(HClass type, int minusWidth, int plusWidth) { 1904 cananian 1.1.2.1 super(toInternal(type)); 1905 cananian 1.1.2.1 // limit. 1906 cananian 1.1.2.1 if (type == HClass.Long) { 1907 cananian 1.1.2.1 this.minusWidth = Math.min(64, minusWidth); 1908 cananian 1.1.2.1 this.plusWidth = Math.min(63, plusWidth); 1909 cananian 1.1.2.1 } else if (type == HClass.Int) { 1910 cananian 1.1.2.1 this.minusWidth = Math.min(32, minusWidth); 1911 cananian 1.1.2.1 this.plusWidth = Math.min(31, plusWidth); 1912 cananian 1.1.2.1 } else // NON-CANONICAL TYPES: CAREFUL! (this.type fixed by above) 1913 cananian 1.1.2.1 if (type == HClass.Boolean) { 1914 cananian 1.1.2.1 this.minusWidth = Math.min( 0, minusWidth); 1915 cananian 1.1.2.1 this.plusWidth = Math.min( 1, plusWidth); 1916 cananian 1.1.2.1 } else if (type == HClass.Short) { 1917 cananian 1.1.2.1 this.minusWidth = Math.min(16, minusWidth); 1918 cananian 1.1.2.1 this.plusWidth = Math.min(15, plusWidth); 1919 cananian 1.1.2.1 } else if (type == HClass.Byte) { 1920 cananian 1.1.2.1 this.minusWidth = Math.min( 8, minusWidth); 1921 cananian 1.1.2.1 this.plusWidth = Math.min( 7, plusWidth); 1922 cananian 1.1.2.1 } else if (type == HClass.Char) { 1923 cananian 1.1.2.1 this.minusWidth = Math.min( 0, minusWidth); 1924 cananian 1.1.2.1 this.plusWidth = Math.min(16, plusWidth); 1925 cananian 1.1.2.1 } else throw new Error("Unknown type for xBitWidth: "+type); 1926 cananian 1.1.2.1 } 1927 cananian 1.1.2.1 public int minusWidth() { return minusWidth; } 1928 cananian 1.1.2.1 public int plusWidth () { return plusWidth; } 1929 cananian 1.1.2.1 public String toString() { 1930 cananian 1.1.2.1 return "xBitWidth: " + type + " " + 1931 cananian 1.1.2.1 "-"+minusWidth+"+"+plusWidth+" bits"; 1932 cananian 1.1.2.1 } 1933 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 1934 cananian 1.1.2.4 private boolean _equals(Object o) { 1935 cananian 1.1.2.1 xBitWidth xbw; 1936 cananian 1.1.2.1 try { xbw = (xBitWidth) o; } 1937 cananian 1.1.2.1 catch (ClassCastException e) { return false; } 1938 cananian 1.1.2.1 return xbw!=null && super.equals(xbw) && 1939 cananian 1.1.2.1 xbw.minusWidth == minusWidth && 1940 cananian 1.1.2.1 xbw.plusWidth == plusWidth; 1941 cananian 1.1.2.1 } 1942 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 1943 cananian 1.1.2.4 if (!(v instanceof xBitWidth)) return super.merge(v); 1944 cananian 1.1.2.4 // bitwidth merge 1945 cananian 1.1.2.4 xBitWidth vv = (xBitWidth) v; 1946 cananian 1.1.2.4 if (!this.type.equals(vv.type)) return super.merge(vv); 1947 cananian 1.1.2.4 return new xBitWidth 1948 cananian 1.1.2.4 (this.type, 1949 cananian 1.1.2.4 Math.max(this.minusWidth, vv.minusWidth), 1950 cananian 1.1.2.4 Math.max(this.plusWidth, vv.plusWidth)); 1951 cananian 1.1.2.1 } 1952 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 1953 cananian 1.1.2.5 return !(v instanceof xBitWidth); 1954 cananian 1.1.2.5 } 1955 cananian 1.1.2.1 } 1956 cananian 1.1.2.1 /** An integer value which is the result of an INSTANCEOF. */ 1957 cananian 1.1.2.4 static class xInstanceofResultUnknown extends xBitWidth 1958 cananian 1.1.2.4 implements xInstanceofResult { 1959 cananian 1.1.2.1 Temp tested; 1960 cananian 1.1.2.1 INSTANCEOF q; 1961 cananian 1.1.2.4 public xInstanceofResultUnknown(INSTANCEOF q) { this(q, q.src()); } 1962 cananian 1.1.2.4 xInstanceofResultUnknown(INSTANCEOF q, Temp tested) { 1963 cananian 1.1.2.1 super(toInternal(HClass.Boolean),0,1); 1964 cananian 1.1.2.1 this.q = q; 1965 cananian 1.1.2.1 this.tested = tested; 1966 cananian 1.1.2.1 } 1967 cananian 1.1.2.1 public Temp tested() { return tested; } 1968 cananian 1.1.2.1 public INSTANCEOF def() { return q; } 1969 cananian 1.1.2.1 public String toString() { 1970 cananian 1.1.2.4 return "xInstanceofResultUnknown: " + type + " " +q; 1971 cananian 1.1.2.1 } 1972 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 1973 cananian 1.1.2.4 private boolean _equals(Object o) { 1974 cananian 1.1.2.4 return (o instanceof xInstanceofResultUnknown && super.equals(o) && 1975 cananian 1.1.2.4 ((xInstanceofResultUnknown)o).q == q && 1976 cananian 1.1.2.4 ((xInstanceofResultUnknown)o).tested == tested); 1977 cananian 1.1.2.4 } 1978 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 1979 cananian 1.1.2.4 if (v instanceof xInstanceofResult) 1980 cananian 1.1.2.4 // xInstanceofResultKnown merged with 1981 cananian 1.1.2.4 // xInstanceofResultKnown or xInstanceofResultUnknown 1982 cananian 1.1.2.4 return makeUnknown(); 1983 cananian 1.1.2.4 // all others. 1984 cananian 1.1.2.4 return super.merge(v); 1985 cananian 1.1.2.4 } 1986 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 1987 cananian 1.1.2.5 return !(v instanceof xBitWidth); 1988 cananian 1.1.2.5 } 1989 cananian 1.1.2.4 public xInstanceofResultKnown makeKnown(boolean nvalue) { 1990 cananian 1.1.2.4 return new xInstanceofResultKnown(q,tested,nvalue?1:0); 1991 cananian 1.1.2.4 } 1992 cananian 1.1.2.4 public xInstanceofResultUnknown makeUnknown() { 1993 cananian 1.1.2.4 return new xInstanceofResultUnknown(q,tested); 1994 cananian 1.1.2.1 } 1995 cananian 1.1.2.1 // override renaming functions. 1996 cananian 1.1.2.1 public LatticeVal rename(PHI q, int j) { 1997 cananian 1.1.2.1 for (int i=0; i<q.numPhis(); i++) 1998 cananian 1.1.2.1 if (q.src(i, j)==this.tested) 1999 cananian 1.1.2.4 return new xInstanceofResultUnknown(def(), q.dst(i)); 2000 cananian 1.1.2.1 return this; 2001 cananian 1.1.2.1 } 2002 cananian 1.1.2.1 public LatticeVal rename(SIGMA q, int j) { 2003 cananian 1.1.2.1 for (int i=0; i<q.numSigmas(); i++) 2004 cananian 1.1.2.1 if (q.src(i)==this.tested) 2005 cananian 1.1.2.4 return new xInstanceofResultUnknown(def(), q.dst(i, j)); 2006 cananian 1.1.2.1 return this; 2007 cananian 1.1.2.1 } 2008 cananian 1.1.2.1 } 2009 cananian 1.1.2.4 /** An unknown boolean value which is the result of an OPER. */ 2010 cananian 1.1.2.4 static class xOperBooleanResultUnknown extends xBitWidth 2011 cananian 1.1.2.4 implements xOperBooleanResult { 2012 cananian 1.1.2.1 OPER q; 2013 cananian 1.1.2.1 Temp[] operands; 2014 cananian 1.1.2.4 public xOperBooleanResultUnknown(OPER q) { this(q, q.operands()); } 2015 cananian 1.1.2.4 xOperBooleanResultUnknown(OPER q, Temp[] operands) { 2016 cananian 1.1.2.1 super(toInternal(HClass.Boolean),0,1); 2017 cananian 1.1.2.1 this.q = q; 2018 cananian 1.1.2.1 this.operands = operands; 2019 cananian 1.1.2.1 } 2020 cananian 1.1.2.1 public Temp[] operands() { return operands; } 2021 cananian 1.1.2.1 public OPER def() { return q; } 2022 cananian 1.1.2.1 public String toString() { 2023 cananian 1.1.2.4 return "xOperBooleanResultUnknown: " + type + " " +q; 2024 cananian 1.1.2.1 } 2025 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 2026 cananian 1.1.2.4 private boolean _equals(Object o) { 2027 cananian 1.1.2.1 if (o==this) return true; // common case. 2028 cananian 1.1.2.4 if (!(o instanceof xOperBooleanResultUnknown)) return false; 2029 cananian 1.1.2.1 if (!super.equals(o)) return false; 2030 cananian 1.1.2.4 xOperBooleanResultUnknown oo = (xOperBooleanResultUnknown)o; 2031 cananian 1.1.2.1 if (oo.q != q) return false; 2032 cananian 1.1.2.1 if (oo.operands.length != operands.length) return false; 2033 cananian 1.1.2.1 for (int i=0; i<operands.length; i++) 2034 cananian 1.1.2.1 if (oo.operands[i] != operands[i]) return false; 2035 cananian 1.1.2.1 return true; 2036 cananian 1.1.2.1 } 2037 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 2038 cananian 1.1.2.4 if (v instanceof xOperBooleanResult) 2039 cananian 1.1.2.4 // xOperBooleanResultKnown merged with 2040 cananian 1.1.2.4 // xOperBooleanResultKnown or xOperBooleanResultUnknown 2041 cananian 1.1.2.4 return makeUnknown(); 2042 cananian 1.1.2.4 // all others. 2043 cananian 1.1.2.4 return super.merge(v); 2044 cananian 1.1.2.4 } 2045 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 2046 cananian 1.1.2.5 return !(v instanceof xBitWidth); 2047 cananian 1.1.2.5 } 2048 cananian 1.1.2.4 public xOperBooleanResultKnown makeKnown(boolean nvalue) { 2049 cananian 1.1.2.4 return new xOperBooleanResultKnown(q,operands,nvalue?1:0); 2050 cananian 1.1.2.4 } 2051 cananian 1.1.2.4 public xOperBooleanResultUnknown makeUnknown() { 2052 cananian 1.1.2.4 return new xOperBooleanResultUnknown(q,operands); 2053 cananian 1.1.2.1 } 2054 cananian 1.1.2.1 // override renaming functions. 2055 cananian 1.1.2.1 public LatticeVal rename(PHI q, int j) { 2056 cananian 1.1.2.1 MyTempMap mtm = new MyTempMap(); 2057 cananian 1.1.2.1 for (int i=0; i<q.numPhis(); i++) 2058 cananian 1.1.2.1 mtm.put(q.src(i,j), q.dst(i)); 2059 cananian 1.1.2.4 return new xOperBooleanResultUnknown(def(), mtm.tempMap(operands())); 2060 cananian 1.1.2.1 } 2061 cananian 1.1.2.1 public LatticeVal rename(SIGMA q, int j) { 2062 cananian 1.1.2.1 MyTempMap mtm = new MyTempMap(); 2063 cananian 1.1.2.1 for (int i=0; i<q.numSigmas(); i++) 2064 cananian 1.1.2.1 mtm.put(q.src(i), q.dst(i, j)); 2065 cananian 1.1.2.4 return new xOperBooleanResultUnknown(def(), mtm.tempMap(operands())); 2066 cananian 1.1.2.1 } 2067 cananian 1.1.2.1 private static class MyTempMap extends HashMap implements TempMap { 2068 cananian 1.1.2.1 public Temp tempMap(Temp t) { 2069 pnkfelix 1.1.2.8 return containsKey(t) ? (Temp) super.get(t) : t; 2070 cananian 1.1.2.1 } 2071 cananian 1.1.2.1 public Temp[] tempMap(Temp[] t) { 2072 cananian 1.1.2.1 Temp[] r = new Temp[t.length]; 2073 cananian 1.1.2.1 for (int i=0; i<r.length; i++) 2074 cananian 1.1.2.1 r[i] = tempMap(t[i]); 2075 cananian 1.1.2.1 return r; 2076 cananian 1.1.2.1 } 2077 cananian 1.1.2.1 } 2078 cananian 1.1.2.1 } 2079 cananian 1.1.2.1 /** An integer or boolean constant. */ 2080 cananian 1.1.2.1 static class xIntConstant extends xBitWidth implements xConstant { 2081 cananian 1.1.2.1 protected long value; 2082 cananian 1.1.2.1 public xIntConstant(HClass type, long value) { 2083 cananian 1.1.2.1 super(type, value<0?Util.fls(-value):0, value>0?Util.fls(value):0); 2084 cananian 1.1.2.1 this.value = value; 2085 cananian 1.1.2.1 } 2086 cananian 1.1.2.1 public long value() { return value; } 2087 cananian 1.1.2.1 public Object constValue() { 2088 cananian 1.1.2.1 if (type==HClass.Int) return new Integer((int)value); 2089 cananian 1.1.2.1 if (type==HClass.Long) return new Long((long)value); 2090 cananian 1.1.2.1 //if (type==HClass.Boolean) return new Integer(value!=0?1:0); 2091 cananian 1.1.2.1 throw new Error("Unknown integer constant type."); 2092 cananian 1.1.2.1 } 2093 cananian 1.1.2.1 public String toString() { 2094 cananian 1.1.2.1 return "xIntConstant: " + type + " " + value; 2095 cananian 1.1.2.1 } 2096 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 2097 cananian 1.1.2.4 private boolean _equals(Object o) { 2098 cananian 1.1.2.1 return (o instanceof xIntConstant && super.equals(o) && 2099 cananian 1.1.2.1 ((xIntConstant)o).value == value); 2100 cananian 1.1.2.1 } 2101 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 2102 cananian 1.1.2.4 if (this._equals(v)) return new xIntConstant(type,value); 2103 cananian 1.1.2.4 return super.merge(v); 2104 cananian 1.1.2.4 } 2105 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 2106 cananian 1.1.2.5 return !(v instanceof xIntConstant); 2107 cananian 1.1.2.5 } 2108 cananian 1.1.2.4 } 2109 cananian 1.1.2.4 /** An integer value which is the result of an INSTANCEOF. */ 2110 cananian 1.1.2.4 static class xInstanceofResultKnown extends xIntConstant 2111 cananian 1.1.2.4 implements xInstanceofResult { 2112 cananian 1.1.2.4 Temp tested; 2113 cananian 1.1.2.4 INSTANCEOF q; 2114 cananian 1.1.2.4 public xInstanceofResultKnown(INSTANCEOF q, boolean value) { 2115 cananian 1.1.2.4 this(q, q.src(), value?1:0); 2116 cananian 1.1.2.4 } 2117 cananian 1.1.2.4 private xInstanceofResultKnown(INSTANCEOF q, Temp tested, long value) { 2118 cananian 1.1.2.4 super(toInternal(HClass.Boolean),value); 2119 cananian 1.1.2.4 this.q = q; 2120 cananian 1.1.2.4 this.tested = tested; 2121 cananian 1.4.2.1 assert value==0 || value==1; 2122 cananian 1.1.2.4 } 2123 cananian 1.1.2.4 public Temp tested() { return tested; } 2124 cananian 1.1.2.4 public INSTANCEOF def() { return q; } 2125 cananian 1.1.2.4 public String toString() { 2126 cananian 1.1.2.4 return "xInstanceofResultKnown: " + value + " " +q; 2127 cananian 1.1.2.4 } 2128 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 2129 cananian 1.1.2.4 private boolean _equals(Object o) { 2130 cananian 1.1.2.4 return (o instanceof xInstanceofResultKnown && super.equals(o) && 2131 cananian 1.1.2.4 ((xInstanceofResultKnown)o).q == q && 2132 cananian 1.1.2.4 ((xInstanceofResultKnown)o).tested == tested); 2133 cananian 1.1.2.4 } 2134 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 2135 cananian 1.1.2.4 if (v instanceof xInstanceofResult) 2136 cananian 1.1.2.4 // xInstanceofResultKnown merged with 2137 cananian 1.1.2.4 // xInstanceofResultKnown or xInstanceofResultUnknown 2138 cananian 1.1.2.4 return this._equals(v) ? (LatticeVal) 2139 cananian 1.1.2.4 makeKnown(value!=0) : makeUnknown(); 2140 cananian 1.1.2.4 // all others. 2141 cananian 1.1.2.4 return super.merge(v); 2142 cananian 1.1.2.4 } 2143 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 2144 cananian 1.1.2.5 return !(v instanceof xIntConstant); 2145 cananian 1.1.2.5 } 2146 cananian 1.1.2.4 public xInstanceofResultKnown makeKnown(boolean nvalue) { 2147 cananian 1.1.2.4 return new xInstanceofResultKnown(q,tested,nvalue?1:0); 2148 cananian 1.1.2.4 } 2149 cananian 1.1.2.4 public xInstanceofResultUnknown makeUnknown() { 2150 cananian 1.1.2.4 return new xInstanceofResultUnknown(q,tested); 2151 cananian 1.1.2.4 } 2152 cananian 1.1.2.4 // override renaming functions. 2153 cananian 1.1.2.4 public LatticeVal rename(PHI q, int j) { 2154 cananian 1.1.2.4 for (int i=0; i<q.numPhis(); i++) 2155 cananian 1.1.2.4 if (q.src(i, j)==this.tested) 2156 cananian 1.1.2.4 return new xInstanceofResultKnown(def(), q.dst(i), value); 2157 cananian 1.1.2.4 return this; 2158 cananian 1.1.2.4 } 2159 cananian 1.1.2.4 public LatticeVal rename(SIGMA q, int j) { 2160 cananian 1.1.2.4 for (int i=0; i<q.numSigmas(); i++) 2161 cananian 1.1.2.4 if (q.src(i)==this.tested) 2162 cananian 1.1.2.4 return new xInstanceofResultKnown(def(),q.dst(i, j),value); 2163 cananian 1.1.2.4 return this; 2164 cananian 1.1.2.4 } 2165 cananian 1.1.2.4 } 2166 cananian 1.1.2.4 /** A known boolean value which is the result of an OPER. */ 2167 cananian 1.1.2.4 static class xOperBooleanResultKnown extends xIntConstant 2168 cananian 1.1.2.4 implements xOperBooleanResult { 2169 cananian 1.1.2.4 OPER q; 2170 cananian 1.1.2.4 Temp[] operands; 2171 cananian 1.1.2.4 public xOperBooleanResultKnown(OPER q, boolean value) { 2172 cananian 1.1.2.4 this(q, q.operands(), value?1:0); 2173 cananian 1.1.2.4 } 2174 cananian 1.1.2.4 xOperBooleanResultKnown(OPER q, Temp[] operands, long value) 2175 cananian 1.1.2.4 { 2176 cananian 1.1.2.4 super(toInternal(HClass.Boolean),value); 2177 cananian 1.1.2.4 this.q = q; 2178 cananian 1.1.2.4 this.operands = operands; 2179 cananian 1.4.2.1 assert value==0 || value==1; 2180 cananian 1.1.2.4 } 2181 cananian 1.1.2.4 public Temp[] operands() { return operands; } 2182 cananian 1.1.2.4 public OPER def() { return q; } 2183 cananian 1.1.2.4 public String toString() { 2184 cananian 1.1.2.4 return "xOperBooleanResultKnown: " + value + " " +q; 2185 cananian 1.1.2.4 } 2186 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 2187 cananian 1.1.2.4 private boolean _equals(Object o) { 2188 cananian 1.1.2.4 if (o==this) return true; // common case. 2189 cananian 1.1.2.4 if (!(o instanceof xOperBooleanResultKnown)) return false; 2190 cananian 1.1.2.4 if (!super.equals(o)) return false; 2191 cananian 1.1.2.4 xOperBooleanResultKnown oo = (xOperBooleanResultKnown)o; 2192 cananian 1.1.2.4 if (oo.q != q) return false; 2193 cananian 1.1.2.4 if (oo.operands.length != operands.length) return false; 2194 cananian 1.1.2.4 for (int i=0; i<operands.length; i++) 2195 cananian 1.1.2.4 if (oo.operands[i] != operands[i]) return false; 2196 cananian 1.1.2.1 return true; 2197 cananian 1.1.2.1 } 2198 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 2199 cananian 1.1.2.4 if (v instanceof xOperBooleanResult) 2200 cananian 1.1.2.4 // xOperBooleanResultKnown merged with 2201 cananian 1.1.2.4 // xOperBooleanResultKnown or xOperBooleanResultUnknown 2202 cananian 1.1.2.4 return this._equals(v) ? (LatticeVal) 2203 cananian 1.1.2.4 makeKnown(value!=0) : makeUnknown(); 2204 cananian 1.1.2.4 // all others. 2205 cananian 1.1.2.4 return super.merge(v); 2206 cananian 1.1.2.4 } 2207 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 2208 cananian 1.1.2.5 return !(v instanceof xIntConstant); 2209 cananian 1.1.2.5 } 2210 cananian 1.1.2.4 public xOperBooleanResultKnown makeKnown(boolean nvalue) { 2211 cananian 1.1.2.4 return new xOperBooleanResultKnown(q,operands,nvalue?1:0); 2212 cananian 1.1.2.4 } 2213 cananian 1.1.2.4 public xOperBooleanResultUnknown makeUnknown() { 2214 cananian 1.1.2.4 return new xOperBooleanResultUnknown(q,operands); 2215 cananian 1.1.2.4 } 2216 cananian 1.1.2.4 // override renaming functions. 2217 cananian 1.1.2.4 public LatticeVal rename(PHI q, int j) { 2218 cananian 1.1.2.4 MyTempMap mtm = new MyTempMap(); 2219 cananian 1.1.2.4 for (int i=0; i<q.numPhis(); i++) 2220 cananian 1.1.2.4 mtm.put(q.src(i,j), q.dst(i)); 2221 cananian 1.1.2.4 return new xOperBooleanResultKnown(def(), mtm.tempMap(operands()), 2222 cananian 1.1.2.4 value); 2223 cananian 1.1.2.4 } 2224 cananian 1.1.2.4 public LatticeVal rename(SIGMA q, int j) { 2225 cananian 1.1.2.4 MyTempMap mtm = new MyTempMap(); 2226 cananian 1.1.2.4 for (int i=0; i<q.numSigmas(); i++) 2227 cananian 1.1.2.4 mtm.put(q.src(i), q.dst(i, j)); 2228 cananian 1.1.2.4 return new xOperBooleanResultKnown(def(), mtm.tempMap(operands()), 2229 cananian 1.1.2.4 value); 2230 cananian 1.1.2.4 } 2231 cananian 1.1.2.4 private static class MyTempMap extends HashMap implements TempMap { 2232 cananian 1.1.2.4 public Temp tempMap(Temp t) { 2233 pnkfelix 1.1.2.8 return containsKey(t) ? (Temp) super.get(t) : t; 2234 cananian 1.1.2.4 } 2235 cananian 1.1.2.4 public Temp[] tempMap(Temp[] t) { 2236 cananian 1.1.2.4 Temp[] r = new Temp[t.length]; 2237 cananian 1.1.2.4 for (int i=0; i<r.length; i++) 2238 cananian 1.1.2.4 r[i] = tempMap(t[i]); 2239 cananian 1.1.2.4 return r; 2240 cananian 1.1.2.4 } 2241 cananian 1.1.2.4 } 2242 cananian 1.1.2.1 } 2243 cananian 1.1.2.1 static class xNullConstant extends xClass implements xConstant { 2244 cananian 1.1.2.1 public xNullConstant() { 2245 cananian 1.1.2.1 super(HClass.Void); 2246 cananian 1.1.2.1 } 2247 cananian 1.1.2.1 public Object constValue() { return null; } 2248 cananian 1.1.2.1 public String toString() { 2249 cananian 1.1.2.1 return "xNullConstant: null"; 2250 cananian 1.1.2.1 } 2251 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 2252 cananian 1.1.2.4 private boolean _equals(Object o) { 2253 cananian 1.1.2.1 return (o instanceof xNullConstant); 2254 cananian 1.1.2.1 } 2255 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 2256 cananian 1.1.2.4 if (this._equals(v)) return new xNullConstant(); 2257 cananian 1.1.2.4 return super.merge(v); 2258 cananian 1.1.2.1 } 2259 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 2260 cananian 1.1.2.5 return !(v instanceof xNullConstant); 2261 cananian 1.1.2.5 } 2262 cananian 1.1.2.1 } 2263 cananian 1.1.2.1 static class xFloatConstant extends xClassExact 2264 cananian 1.1.2.1 implements xConstant { 2265 cananian 1.1.2.1 protected Object value; 2266 cananian 1.1.2.1 public xFloatConstant(HClass type, Object value) { 2267 cananian 1.1.2.1 super(type); this.value = value; 2268 cananian 1.1.2.1 } 2269 cananian 1.1.2.1 public Object constValue() { return value; } 2270 cananian 1.1.2.1 public String toString() { 2271 cananian 1.1.2.1 return "xFloatConstant: " + type + " " + value.toString(); 2272 cananian 1.1.2.1 } 2273 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 2274 cananian 1.1.2.4 private boolean _equals(Object o) { 2275 cananian 1.1.2.1 return (o instanceof xFloatConstant && super.equals(o) && 2276 cananian 1.1.2.1 ((xFloatConstant)o).value.equals(value)); 2277 cananian 1.1.2.1 } 2278 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 2279 cananian 1.1.2.4 if (this._equals(v)) return new xFloatConstant(type, value); 2280 cananian 1.1.2.4 return super.merge(v); 2281 cananian 1.1.2.1 } 2282 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 2283 cananian 1.1.2.5 return !(v instanceof xFloatConstant); 2284 cananian 1.1.2.5 } 2285 cananian 1.1.2.1 } 2286 cananian 1.1.2.1 static class xStringConstant extends xClassExact 2287 cananian 1.1.2.1 implements xConstant { 2288 cananian 1.1.2.1 protected Object value; 2289 cananian 1.1.2.1 public xStringConstant(HClass type, Object value) { 2290 cananian 1.1.2.1 super(type); 2291 cananian 1.1.2.1 // note that the string constant objects are intern()ed. 2292 cananian 1.1.2.1 // doing this here ensures that evaluating ACMPEQ with constant 2293 cananian 1.1.2.1 // args works correctly. 2294 cananian 1.1.2.1 this.value = ((String)value).intern(); 2295 cananian 1.1.2.1 } 2296 cananian 1.1.2.1 public Object constValue() { return value; } 2297 cananian 1.1.2.1 public String toString() { 2298 cananian 1.1.2.1 return "xStringConstant: " + 2299 cananian 1.9 "\"" + harpoon.Util.Util.escape(value.toString()) + "\""; 2300 cananian 1.1.2.1 } 2301 cananian 1.1.2.4 public boolean equals(Object o) { return _equals(o); } 2302 cananian 1.1.2.4 private boolean _equals(Object o) { 2303 cananian 1.1.2.1 return (o instanceof xStringConstant && super.equals(o) && 2304 cananian 1.1.2.1 ((xStringConstant)o).value.equals(value)); 2305 cananian 1.1.2.1 } 2306 cananian 1.1.2.4 public LatticeVal merge(LatticeVal v) { 2307 cananian 1.1.2.4 if (this._equals(v)) return new xStringConstant(type, value); 2308 cananian 1.1.2.4 return super.merge(v); 2309 cananian 1.1.2.5 } 2310 cananian 1.1.2.5 public boolean isLowerThan(LatticeVal v) { 2311 cananian 1.1.2.5 return !(v instanceof xStringConstant); 2312 cananian 1.1.2.1 } 2313 cananian 1.1.2.1 } 2314 cananian 1.1.2.1 static interface xConstant { 2315 cananian 1.1.2.1 public Object constValue(); 2316 cananian 1.1.2.1 } 2317 cananian 1.1.2.4 static interface xInstanceofResult { 2318 cananian 1.1.2.4 public Temp tested(); 2319 cananian 1.1.2.4 public INSTANCEOF def(); 2320 cananian 1.1.2.4 public xInstanceofResultKnown makeKnown(boolean value); 2321 cananian 1.1.2.4 public xInstanceofResultUnknown makeUnknown(); 2322 cananian 1.1.2.4 } 2323 cananian 1.1.2.4 static interface xOperBooleanResult { 2324 cananian 1.1.2.4 public Temp[] operands(); 2325 cananian 1.1.2.4 public OPER def(); 2326 cananian 1.1.2.4 public xOperBooleanResultKnown makeKnown(boolean value); 2327 cananian 1.1.2.4 public xOperBooleanResultUnknown makeUnknown(); 2328 cananian 1.1.2.4 } 2329 cananian 1.1.2.1 ///////////////////////////////////////////////////////// 2330 cananian 1.1.2.1 // ways to degrade the analysis to collect statistics. 2331 cananian 1.1.2.1 private final Corruptor corruptor = null; // no corruption. 2332 cananian 1.1.2.1 private final boolean useSigmas = true; 2333 cananian 1.1.2.1 /** A <code>Corruptor</code> lets you 'dumb-down' the analysis 2334 cananian 1.1.2.1 * incrementally, so that we can generate numbers showing that 2335 cananian 1.1.2.1 * every step makes it better and better. */ 2336 cananian 1.1.2.1 static abstract class Corruptor { 2337 cananian 1.1.2.1 /** make this lattice value worse than we know it to be. */ 2338 cananian 1.1.2.1 abstract LatticeVal corrupt(LatticeVal v); 2339 cananian 1.1.2.1 } 2340 cananian 1.1.2.1 static final Corruptor nobitwidth = new Corruptor() { 2341 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 2342 cananian 1.1.2.4 if (v!=null && v.toString().startsWith("xBitWidth:")) 2343 cananian 1.1.2.4 return new xClassExact(((xClassExact)v).type); 2344 cananian 1.1.2.1 return v; 2345 cananian 1.1.2.1 } 2346 cananian 1.1.2.1 }; 2347 cananian 1.1.2.1 static final Corruptor nofixedarray = new Corruptor() { 2348 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 2349 cananian 1.1.2.1 v = nobitwidth.corrupt(v); 2350 cananian 1.1.2.1 if (v instanceof xClassArray) 2351 cananian 1.1.2.1 return new xClassNonNull(((xClassNonNull)v).type); 2352 cananian 1.1.2.1 return v; 2353 cananian 1.1.2.1 } 2354 cananian 1.1.2.1 }; 2355 cananian 1.1.2.1 static final Corruptor nonullpointer = new Corruptor() { 2356 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 2357 cananian 1.1.2.1 if (v instanceof xClassNonNull) 2358 cananian 1.1.2.1 return new xClass(((xClassNonNull)v).type); 2359 cananian 1.1.2.1 return v; 2360 cananian 1.1.2.1 } 2361 cananian 1.1.2.1 }; 2362 cananian 1.1.2.1 static final Corruptor nononint = new Corruptor() { 2363 cananian 1.1.2.1 public LatticeVal corrupt(LatticeVal v) { 2364 cananian 1.1.2.1 v = nonullpointer.corrupt(v); 2365 cananian 1.1.2.1 if (v instanceof xFloatConstant || 2366 cananian 1.1.2.1 v instanceof xStringConstant || 2367 cananian 1.1.2.1 (v instanceof xIntConstant && ((xClass)v).type!=HClass.Int)) 2368 cananian 1.1.2.1 return new xClass(((xClass)v).type); 2369 cananian 1.1.2.1 return v; 2370 cananian 1.1.2.1 } 2371 cananian 1.1.2.1 }; 2372 cananian 1.1.2.14 2373 cananian 1.1.2.9 private static Set parseResource(final Linker l, String resourceName) { 2374 cananian 1.1.2.9 final Set result = new HashSet(); 2375 cananian 1.1.2.9 try { 2376 cananian 1.1.2.9 ParseUtil.readResource(resourceName, new ParseUtil.StringParser() { 2377 cananian 1.1.2.9 public void parseString(String s) 2378 cananian 1.1.2.9 throws ParseUtil.BadLineException { 2379 cananian 1.1.2.9 result.add(ParseUtil.parseField(l, s)); 2380 cananian 1.1.2.9 } 2381 cananian 1.1.2.9 }); 2382 cananian 1.1.2.9 } catch (java.io.IOException ex) { 2383 cananian 1.1.2.9 System.err.println("ERROR READING FIELD ROOTS, SKIPPING REST."); 2384 cananian 1.1.2.9 System.err.println(ex.toString()); 2385 cananian 1.1.2.9 } 2386 cananian 1.1.2.9 // done. 2387 cananian 1.1.2.9 return result; 2388 cananian 1.1.2.9 } 2389 cananian 1.2 }