| 1 19 20 25 26 package soot.jimple.toolkits.invoke; 27 28 import soot.*; 29 import soot.jimple.*; 30 import soot.jimple.toolkits.scalar.*; 31 import java.util.*; 32 import soot.util.*; 33 34 35 public class SiteInliner 36 { 37 public String getDefaultOptions() 38 { 39 return "insert-null-checks insert-redundant-casts"; 40 } 41 42 public static void inlineSites(List sites) 43 { 44 inlineSites(sites, new HashMap()); 45 } 46 47 49 public static void inlineSites(List sites, Map options) 50 { 51 Iterator it = sites.iterator(); 52 while (it.hasNext()) 53 { 54 List l = (List)it.next(); 55 SootMethod inlinee = (SootMethod)l.get(0); 56 Stmt toInline = (Stmt)l.get(1); 57 SootMethod container = (SootMethod)l.get(2); 58 59 inlineSite(inlinee, toInline, container, options); 60 } 61 } 62 63 65 public static void inlineSite(SootMethod inlinee, Stmt toInline, 66 SootMethod container) 67 { 68 inlineSite(inlinee, toInline, container, new HashMap()); 69 } 70 71 77 public static List inlineSite(SootMethod inlinee, Stmt toInline, 78 SootMethod container, Map options) 79 { 80 81 boolean enableNullPointerCheckInsertion = PhaseOptions.getBoolean(options, "insert-null-checks"); 82 boolean enableRedundantCastInsertion = PhaseOptions.getBoolean(options, "insert-redundant-casts"); 83 84 Hierarchy hierarchy = Scene.v().getActiveHierarchy(); 85 86 JimpleBody containerB = (JimpleBody)container.getActiveBody(); 87 Chain containerUnits = containerB.getUnits(); 88 89 if (!(inlinee.getDeclaringClass().isApplicationClass() || 90 inlinee.getDeclaringClass().isLibraryClass())) 91 return null; 92 93 Body inlineeB = (JimpleBody)inlinee.getActiveBody(); 94 Chain inlineeUnits = inlineeB.getUnits(); 95 96 InvokeExpr ie = (InvokeExpr)toInline.getInvokeExpr(); 97 98 Value thisToAdd = null; 99 if (ie instanceof InstanceInvokeExpr) 100 thisToAdd = ((InstanceInvokeExpr)ie).getBase(); 101 102 { 104 boolean targetUsesThis = true; 105 if (enableRedundantCastInsertion && ie instanceof InstanceInvokeExpr && targetUsesThis) 106 { 107 SootClass localType, parameterType; 112 localType = ((RefType)((InstanceInvokeExpr)ie).getBase().getType()).getSootClass(); 113 parameterType = inlinee.getDeclaringClass(); 114 115 if (localType.isInterface() || 116 hierarchy.isClassSuperclassOf(localType, parameterType)) 117 { 118 Local castee = Jimple.v().newLocal("__castee", parameterType.getType()); 119 containerB.getLocals().add(castee); 120 containerB.getUnits().insertBefore(Jimple.v().newAssignStmt(castee, 121 Jimple.v().newCastExpr(((InstanceInvokeExpr)ie).getBase(), 122 parameterType.getType())), toInline); 123 thisToAdd = castee; 124 } 125 } 126 } 127 128 { 130 if (enableNullPointerCheckInsertion && ie instanceof InstanceInvokeExpr) 131 { 132 boolean caught = TrapManager.isExceptionCaughtAt 133 (Scene.v().getSootClass("java.lang.NullPointerException"), toInline, containerB); 134 135 136 if (caught) 137 { 138 140 Stmt insertee = Jimple.v().newIfStmt(Jimple.v().newNeExpr(((InstanceInvokeExpr)ie).getBase(), 141 NullConstant.v()), toInline); 142 143 containerB.getUnits().insertBefore(insertee, toInline); 144 145 ((IfStmt)insertee).setTarget(toInline); 147 148 ThrowManager.addThrowAfter(containerB, insertee); 149 } 150 else 151 { 152 Stmt throwPoint = 153 ThrowManager.getNullPointerExceptionThrower(containerB); 154 containerB.getUnits().insertBefore 155 (Jimple.v().newIfStmt(Jimple.v().newEqExpr(((InstanceInvokeExpr)ie).getBase(), 156 NullConstant.v()), throwPoint), toInline); 157 } 158 } 159 } 160 161 { 163 if (inlinee.isSynchronized()) 164 { 165 if (ie instanceof InstanceInvokeExpr) 167 SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, (Local)((InstanceInvokeExpr)ie).getBase()); 168 else 169 { 170 if (!container.getDeclaringClass().isInterface()) 174 { 175 Local l = SynchronizerManager.v().addStmtsToFetchClassBefore(containerB, toInline); 177 SynchronizerManager.v().synchronizeStmtOn(toInline, containerB, l); 178 } 179 } 180 } 181 } 182 183 Stmt exitPoint = (Stmt)containerUnits.getSuccOf(toInline); 184 185 HashMap oldLocalsToNew = new HashMap(); 187 HashMap oldUnitsToNew = new HashMap(); 188 { 189 Stmt cursor = toInline; 190 for( Iterator currIt = inlineeUnits.iterator(); currIt.hasNext(); ) { 191 final Stmt curr = (Stmt) currIt.next(); 192 Stmt currPrime = (Stmt)curr.clone(); 193 if (currPrime == null) 194 throw new RuntimeException ("getting null from clone!"); 195 currPrime.addAllTagsOf(curr); 196 197 containerUnits.insertAfter(currPrime, cursor); 198 cursor = currPrime; 199 200 oldUnitsToNew.put(curr, currPrime); 201 } 202 203 for( Iterator lIt = inlineeB.getLocals().iterator(); lIt.hasNext(); ) { 204 205 final Local l = (Local) lIt.next(); 206 Local lPrime = (Local)l.clone(); 207 if (lPrime == null) 208 throw new RuntimeException ("getting null from local clone!"); 209 210 containerB.getLocals().add(lPrime); 211 oldLocalsToNew.put(l, lPrime); 212 } 213 } 214 215 { 217 Iterator it = containerUnits.iterator 218 (containerUnits.getSuccOf(toInline), 219 containerUnits.getPredOf(exitPoint)); 220 221 while (it.hasNext()) 222 { 223 Stmt patchee = (Stmt)it.next(); 224 225 Iterator duBoxes = patchee.getUseAndDefBoxes().iterator(); 226 while (duBoxes.hasNext()) 227 { 228 ValueBox box = (ValueBox)duBoxes.next(); 229 if (!(box.getValue() instanceof Local)) 230 continue; 231 232 Local lPrime = (Local)(oldLocalsToNew.get(box.getValue())); 233 if (lPrime != null) 234 box.setValue(lPrime); 235 else 236 throw new RuntimeException ("local has no clone!"); 237 } 238 239 Iterator unitBoxes = patchee.getUnitBoxes().iterator(); 240 while (unitBoxes.hasNext()) 241 { 242 UnitBox box = (UnitBox)unitBoxes.next(); 243 Unit uPrime = (Unit)(oldUnitsToNew.get(box.getUnit())); 244 if (uPrime != null) 245 box.setUnit(uPrime); 246 else 247 throw new RuntimeException ("inlined stmt has no clone!"); 248 } 249 } 250 } 251 252 { 254 Iterator trapsIt = inlineeB.getTraps().iterator(); 255 Trap prevTrap = null; 256 257 while (trapsIt.hasNext()) 258 { 259 Trap t = (Trap)trapsIt.next(); 260 Stmt newBegin = (Stmt)oldUnitsToNew.get(t.getBeginUnit()), 261 newEnd = (Stmt)oldUnitsToNew.get(t.getEndUnit()), 262 newHandler = (Stmt)oldUnitsToNew.get(t.getHandlerUnit()); 263 264 if (newBegin == null || newEnd == null || newHandler == null) 265 throw new RuntimeException ("couldn't map trap!"); 266 267 Trap trap = Jimple.v().newTrap(t.getException(), 268 newBegin, newEnd, newHandler); 269 if (prevTrap == null) 270 containerB.getTraps().addFirst(trap); 271 else 272 containerB.getTraps().insertAfter(trap, prevTrap); 273 prevTrap = trap; 274 } 275 } 276 277 { 279 Iterator it = containerUnits.iterator 280 (containerUnits.getSuccOf(toInline), 281 containerUnits.getPredOf(exitPoint)); 282 ArrayList cuCopy = new ArrayList(); 283 284 while (it.hasNext()) 285 { 286 cuCopy.add(it.next()); 287 } 288 289 it = cuCopy.iterator(); 290 while (it.hasNext()) 291 { 292 Stmt s = (Stmt)it.next(); 293 294 if (s instanceof IdentityStmt) 295 { 296 IdentityRef rhs = (IdentityRef)((IdentityStmt)s).getRightOp(); 297 if (rhs instanceof CaughtExceptionRef) 298 continue; 299 else if (rhs instanceof ThisRef) 300 { 301 if (!(ie instanceof InstanceInvokeExpr)) 302 throw new RuntimeException ("thisref with no receiver!"); 303 304 containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt)s).getLeftOp(), 305 thisToAdd)); 306 } 307 else if (rhs instanceof ParameterRef) 308 { 309 ParameterRef pref = (ParameterRef)rhs; 310 containerUnits.swapWith(s, Jimple.v().newAssignStmt(((IdentityStmt)s).getLeftOp(), 311 ie.getArg(pref.getIndex()))); 312 } 313 } 314 else if (s instanceof ReturnStmt) 315 { 316 if (toInline instanceof InvokeStmt) 317 { 318 containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint)); 320 continue; 321 } 322 323 if (!(toInline instanceof AssignStmt)) 324 throw new RuntimeException  325 ("invoking stmt neither InvokeStmt nor AssignStmt!??!?!"); 326 Value ro = ((ReturnStmt)s).getOp(); 327 Value lhs = ((AssignStmt)toInline).getLeftOp(); 328 AssignStmt as = Jimple.v().newAssignStmt(lhs, ro); 329 containerUnits.insertBefore(as, s); 330 containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint)); 331 } 332 else if (s instanceof ReturnVoidStmt) 333 containerUnits.swapWith(s, Jimple.v().newGotoStmt(exitPoint)); 334 } 335 } 336 337 List newStmts = new ArrayList(); 338 for(Iterator i = containerUnits.iterator(containerUnits.getSuccOf(toInline), containerUnits.getPredOf(exitPoint)); i.hasNext();) { 339 newStmts.add(i.next()); 340 } 341 342 containerUnits.remove(toInline); 344 345 LocalNameStandardizer.v().transform(containerB, "ji.lns"); 347 348 return newStmts; 349 } 350 } 351 | Popular Tags |