00001 package ca.mcgill.sable.soot.jimple;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 import ca.mcgill.sable.soot.*;
00120 import ca.mcgill.sable.util.*;
00121
00122 public class Transformations
00123 {
00124 public static int nodeCount = 0;
00125 public static int aggrCount = 0;
00126
00127
00128
00129
00130
00131
00132
00133 public static void aggregate(StmtBody body)
00134 {
00135 int aggregateCount = 1;
00136
00137 if(Main.isProfilingOptimization)
00138 Main.aggregationTimer.start();
00139 boolean changed = false;
00140
00141 do {
00142 if(Main.isVerbose)
00143 System.out.println("[" + body.getMethod().getName() + "] Aggregating iteration " + aggregateCount + "...");
00144
00145 changed = internalAggregate(body);
00146
00147 aggregateCount++;
00148 } while(changed);
00149
00150 if(Main.isProfilingOptimization)
00151 Main.aggregationTimer.end();
00152
00153 }
00154 public static void assignTypesToLocals(JimpleBody listBody)
00155 {
00156 if(Main.isVerbose)
00157 System.out.println("[" + listBody.getMethod().getName() + "] Assigning types to locals...");
00158
00159
00160
00161 if(!Main.oldTyping)
00162 {
00163 TypeResolver.assignTypesToLocals(listBody);
00164 return;
00165 }
00166
00167 StmtList stmtList = listBody.getStmtList();
00168
00169
00170 {
00171 Iterator localIt = listBody.getLocals().iterator();
00172
00173 while(localIt.hasNext())
00174 ((Local) localIt.next()).setType(UnknownType.v());
00175 }
00176
00177
00178 {
00179 boolean hasChanged = true;
00180 SootClassManager cm = listBody.getMethod().getDeclaringClass().getManager();
00181
00182 while(hasChanged)
00183 {
00184 hasChanged = false;
00185
00186 Iterator stmtIt = stmtList.iterator();
00187
00188 while(stmtIt.hasNext())
00189 {
00190 Stmt s = (Stmt) stmtIt.next();
00191
00192 if(s instanceof DefinitionStmt)
00193 {
00194 DefinitionStmt def = (DefinitionStmt) s;
00195
00196 if(def.getLeftOp() instanceof Local)
00197 {
00198 Local local = (Local) def.getLeftOp();
00199 Type previousType = local.getType();
00200
00201 Type newType = (Type.toMachineType(def.getRightOp().getType()))
00202 .merge(previousType, cm);
00203
00204 if(!previousType.equals(newType))
00205 hasChanged = true;
00206
00207 local.setType(newType);
00208 }
00209 }
00210 }
00211 }
00212 }
00213
00214
00215 {
00216 Iterator localIt = listBody.getLocals().iterator();
00217
00218 while(localIt.hasNext())
00219 {
00220 Local local = (Local) localIt.next();
00221
00222 if(local.getType().equals(UnknownType.v()))
00223 local.setType(RefType.v("java.lang.Object"));
00224 }
00225 }
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 public static void cleanupCode(JimpleBody stmtBody)
00239 {
00240 ConstantAndCopyPropagator.propagateConstantsAndCopies(stmtBody);
00241 DeadCodeEliminator.eliminateDeadCode(stmtBody);
00242
00243
00244 }
00245 private static boolean internalAggregate(StmtBody body)
00246 {
00247 Iterator stmtIt;
00248 LocalUses localUses;
00249 LocalDefs localDefs;
00250 CompleteStmtGraph graph;
00251 boolean hadAggregation = false;
00252 StmtList stmtList = body.getStmtList();
00253
00254
00255 graph = new CompleteStmtGraph(stmtList);
00256 localDefs = new SimpleLocalDefs(graph);
00257 localUses = new SimpleLocalUses(graph, localDefs);
00258
00259 stmtIt = stmtList.iterator();
00260
00261 while (stmtIt.hasNext())
00262 {
00263 Stmt s = (Stmt)(stmtIt.next());
00264
00265
00266 if (!(s instanceof AssignStmt))
00267 continue;
00268
00269 Value lhs = ((AssignStmt)s).getLeftOp();
00270 if (!(lhs instanceof Local))
00271 continue;
00272
00273 List lu = localUses.getUsesOf((AssignStmt)s);
00274 if (lu.size() != 1)
00275 continue;
00276
00277 StmtValueBoxPair usepair = (StmtValueBoxPair)lu.get(0);
00278 Stmt use = usepair.stmt;
00279 ValueBox useBox = usepair.valueBox;
00280
00281 List ld = localDefs.getDefsOfAt((Local)lhs, use);
00282 if (ld.size() != 1)
00283 continue;
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 boolean cantAggr = false;
00294 boolean propagatingInvokeExpr = false;
00295 boolean propagatingFieldRef = false;
00296 FieldRef fieldRef = null;
00297
00298 Value rhs = ((AssignStmt)s).getRightOp();
00299 LinkedList localsUsed = new LinkedList();
00300 for (Iterator useIt = (s.getUseBoxes()).iterator();
00301 useIt.hasNext(); )
00302 {
00303 Value v = ((ValueBox)(useIt.next())).getValue();
00304 if (v instanceof Local)
00305 localsUsed.add(v);
00306 if (v instanceof InvokeExpr)
00307 propagatingInvokeExpr = true;
00308 else if(v instanceof FieldRef)
00309 {
00310 propagatingFieldRef = true;
00311 fieldRef = (FieldRef) v;
00312 }
00313 }
00314
00315
00316
00317
00318 List path = graph.getExtendedBasicBlockPathBetween(s, use);
00319
00320 if (path == null)
00321 continue;
00322
00323 Iterator pathIt = path.iterator();
00324
00325
00326 if (pathIt.hasNext())
00327 pathIt.next();
00328
00329 while (pathIt.hasNext() && !cantAggr)
00330 {
00331 Stmt between = (Stmt)(pathIt.next());
00332
00333 if(between != use)
00334 {
00335
00336
00337 for (Iterator it = between.getDefBoxes().iterator();
00338 it.hasNext(); )
00339 {
00340 Value v = ((ValueBox)(it.next())).getValue();
00341 if (localsUsed.contains(v))
00342 {
00343 cantAggr = true;
00344 break;
00345 }
00346
00347 if (propagatingInvokeExpr || propagatingFieldRef)
00348 {
00349 if (v instanceof FieldRef)
00350 {
00351 if(propagatingInvokeExpr)
00352 {
00353 cantAggr = true;
00354 break;
00355 }
00356 else {
00357
00358
00359
00360 if(((FieldRef) v).getField() == fieldRef.getField())
00361 {
00362 cantAggr = true;
00363 break;
00364 }
00365 }
00366 }
00367 }
00368 }
00369 }
00370
00371
00372 if(propagatingInvokeExpr || propagatingFieldRef)
00373 {
00374 for (Iterator useIt = (between.getUseBoxes()).iterator();
00375 useIt.hasNext(); )
00376 {
00377 ValueBox box = (ValueBox) useIt.next();
00378
00379 if(between == use && box == useBox)
00380 {
00381
00382
00383 break;
00384 }
00385
00386 Value v = box.getValue();
00387
00388 if (v instanceof InvokeExpr)
00389 cantAggr = true;
00390 }
00391 }
00392 }
00393
00394
00395 if (cantAggr)
00396 {
00397 continue;
00398 }
00399
00400
00401
00402 Value aggregatee = ((AssignStmt)s).getRightOp();
00403
00404 if (usepair.valueBox.canContainValue(aggregatee))
00405 {
00406 usepair.valueBox.setValue(aggregatee);
00407 body.eliminateBackPointersTo(s);
00408 stmtIt.remove();
00409 hadAggregation = true;
00410 aggrCount++;
00411 }
00412 else
00413 {
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423 }
00424 }
00425 return hadAggregation;
00426 }
00427 public static void packLocals(StmtBody body)
00428 {
00429 Map localToGroup = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00430 Map groupToColorCount = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00431 Map localToColor = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00432 Map localToNewLocal;
00433
00434
00435 {
00436 Iterator localIt = body.getLocals().iterator();
00437
00438 while(localIt.hasNext())
00439 {
00440 Local l = (Local) localIt.next();
00441 Object g = l.getType();
00442
00443 localToGroup.put(l, g);
00444
00445 if(!groupToColorCount.containsKey(g))
00446 {
00447 groupToColorCount.put(g, new Integer(0));
00448 }
00449 }
00450 }
00451
00452
00453 {
00454 Iterator codeIt = body.getStmtList().iterator();
00455
00456 while(codeIt.hasNext())
00457 {
00458 Stmt s = (Stmt) codeIt.next();
00459
00460 if(s instanceof IdentityStmt &&
00461 ((IdentityStmt) s).getLeftOp() instanceof Local)
00462 {
00463 Local l = (Local) ((IdentityStmt) s).getLeftOp();
00464
00465 Object group = localToGroup.get(l);
00466 int count = ((Integer) groupToColorCount.get(group)).intValue();
00467
00468 localToColor.put(l, new Integer(count));
00469
00470 count++;
00471
00472 groupToColorCount.put(group, new Integer(count));
00473 }
00474 }
00475 }
00476
00477
00478 FastColorer.assignColorsToLocals(body, localToGroup,
00479 localToColor, groupToColorCount);
00480
00481
00482 {
00483 List originalLocals = new ArrayList();
00484 localToNewLocal = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00485 Map groupIntToLocal = new HashMap(body.getLocalCount() * 2 + 1, 0.7f);
00486
00487 originalLocals.addAll(body.getLocals());
00488 body.getLocals().clear();
00489
00490 Iterator localIt = originalLocals.iterator();
00491
00492 while(localIt.hasNext())
00493 {
00494 Local original = (Local) localIt.next();
00495
00496 Object group = localToGroup.get(original);
00497 int color = ((Integer) localToColor.get(original)).intValue();
00498 GroupIntPair pair = new GroupIntPair(group, color);
00499
00500 Local newLocal;
00501
00502 if(groupIntToLocal.containsKey(pair))
00503 newLocal = (Local) groupIntToLocal.get(pair);
00504 else {
00505 newLocal = new Local(original.getName(), (Type) group);
00506 groupIntToLocal.put(pair, newLocal);
00507 body.getLocals().add(newLocal);
00508 }
00509
00510 localToNewLocal.put(original, newLocal);
00511 }
00512 }
00513
00514
00515
00516 {
00517 Iterator codeIt = body.getStmtList().iterator();
00518
00519 while(codeIt.hasNext())
00520 {
00521 Stmt s = (Stmt) codeIt.next();
00522
00523
00524
00525 Iterator boxIt = s.getUseAndDefBoxes().iterator();
00526
00527 while(boxIt.hasNext())
00528 {
00529 ValueBox box = (ValueBox) boxIt.next();
00530
00531
00532
00533 if(box.getValue() instanceof Local)
00534 {
00535 Local l = (Local) box.getValue();
00536 box.setValue((Local) localToNewLocal.get(l));
00537
00538
00539
00540
00541 }
00542 }
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 }
00553 }
00554 }
00555 public static void removeUnusedLocals(StmtBody listBody)
00556 {
00557 StmtList stmtList = listBody.getStmtList();
00558 Set unusedLocals = new HashSet();
00559
00560
00561 unusedLocals.addAll(listBody.getLocals());
00562
00563
00564 {
00565 Iterator stmtIt = stmtList.iterator();
00566
00567 while(stmtIt.hasNext())
00568 {
00569 Stmt s = (Stmt) stmtIt.next();
00570
00571
00572 {
00573 Iterator boxIt = s.getDefBoxes().iterator();
00574
00575 while(boxIt.hasNext())
00576 {
00577 Value value = ((ValueBox) boxIt.next()).getValue();
00578
00579 if(value instanceof Local && unusedLocals.contains(value))
00580 unusedLocals.remove(value);
00581 }
00582 }
00583
00584
00585 {
00586 Iterator boxIt = s.getUseBoxes().iterator();
00587
00588 while(boxIt.hasNext())
00589 {
00590 Value value = ((ValueBox) boxIt.next()).getValue();
00591
00592 if(value instanceof Local && unusedLocals.contains(value))
00593 unusedLocals.remove(value);
00594 }
00595 }
00596 }
00597
00598 }
00599
00600
00601 {
00602 Iterator it = unusedLocals.iterator();
00603 List locals = listBody.getLocals();
00604
00605 while(it.hasNext())
00606 {
00607 Local local = (Local) it.next();
00608
00609 locals.remove(local);
00610 }
00611 }
00612 }
00613 public static void renameLocals(StmtBody body)
00614 {
00615 StmtList stmtList = body.getStmtList();
00616
00617
00618 {
00619 int objectCount = 0;
00620 int intCount = 0;
00621 int longCount = 0;
00622 int floatCount = 0;
00623 int doubleCount = 0;
00624 int addressCount = 0;
00625 int errorCount = 0;
00626 int nullCount = 0;
00627
00628 Iterator localIt = body.getLocals().iterator();
00629
00630 while(localIt.hasNext())
00631 {
00632 Local l = (Local) localIt.next();
00633
00634 if(l.getType().equals(IntType.v()))
00635 l.setName("i" + intCount++);
00636 else if(l.getType().equals(LongType.v()))
00637 l.setName("l" + longCount++);
00638 else if(l.getType().equals(DoubleType.v()))
00639 l.setName("d" + doubleCount++);
00640 else if(l.getType().equals(FloatType.v()))
00641 l.setName("f" + floatCount++);
00642 else if(l.getType().equals(StmtAddressType.v()))
00643 l.setName("a" + addressCount++);
00644 else if(l.getType().equals(ErroneousType.v()) ||
00645 l.getType().equals(UnknownType.v()))
00646 {
00647 l.setName("e" + errorCount++);
00648 }
00649 else if(l.getType().equals(NullType.v()))
00650 l.setName("n" + nullCount++);
00651 else
00652 l.setName("r" + objectCount++);
00653 }
00654 }
00655 }
00656 }