/** * given a DelayabilityAnalysis and the computations of each unit, calculates the latest * computation-point for each expression.<br> * the <code>equivRhsMap</code> could be calculated on the fly, but it is <b>very</b> likely that * it already exists (as similar maps are used for calculating Earliestness, Delayed,...<br> * the shared set allows more efficient set-operations, when they the computation is merged with * other analyses/computations. * * @param dg a ExceptionalUnitGraph * @param delayed the delayability-analysis of the same graph. * @param equivRhsMap all computations of the graph * @param set the shared flowSet */ public LatestComputation( UnitGraph unitGraph, DelayabilityAnalysis delayed, Map equivRhsMap, BoundedFlowSet set) { unitToLatest = new HashMap<Unit, FlowSet>(unitGraph.size() + 1, 0.7f); Iterator unitIt = unitGraph.iterator(); while (unitIt.hasNext()) { /* create a new Earliest-list for each unit */ Unit currentUnit = (Unit) unitIt.next(); /* basically the latest-set is: * (delayed) INTERSECT (comp UNION (UNION_successors ~Delayed)) = * (delayed) MINUS ((INTERSECTION_successors Delayed) MINUS comp). */ FlowSet delaySet = (FlowSet) delayed.getFlowBefore(currentUnit); /* Calculate (INTERSECTION_successors Delayed) */ FlowSet succCompSet = (FlowSet) set.topSet(); List succList = unitGraph.getSuccsOf(currentUnit); Iterator succIt = succList.iterator(); while (succIt.hasNext()) { Unit successor = (Unit) succIt.next(); succCompSet.intersection((FlowSet) delayed.getFlowBefore(successor), succCompSet); } /* remove the computation of this set: succCompSet is then: * ((INTERSECTION_successors Delayed) MINUS comp) */ if (equivRhsMap.get(currentUnit) != null) succCompSet.remove(equivRhsMap.get(currentUnit)); /* make the difference: */ FlowSet latest = (FlowSet) delaySet.emptySet(); delaySet.difference(succCompSet, latest); unitToLatest.put(currentUnit, latest); } }
protected void flowThrough(Object inValue, Object unit, Object outValue) { FlowSet in = (FlowSet) inValue, out = (FlowSet) outValue; // Perform kill in.difference(unitToKillSet.get(unit), out); // Perform generation out.union(unitToGenerateSet.get(unit), out); }
/** * Traverse the statements in the given body, looking for aggregation possibilities; that is, * given a def d and a use u, d has no other uses, u has no other defs, collapse d and u. * * <p>option: only-stack-locals; if this is true, only aggregate variables starting with $ */ protected void internalTransform(Body b, String phaseName, Map<String, String> options) { StmtBody body = (StmtBody) b; boolean onlyStackVars = PhaseOptions.getBoolean(options, "only-stack-locals"); int aggregateCount = 1; if (Options.v().time()) Timers.v().aggregationTimer.start(); boolean changed = false; Map<ValueBox, Zone> boxToZone = new HashMap<ValueBox, Zone>(body.getUnits().size() * 2 + 1, 0.7f); // Determine the zone of every box { Zonation zonation = new Zonation(body); for (Unit u : body.getUnits()) { Zone zone = zonation.getZoneOf(u); for (ValueBox box : u.getUseBoxes()) { boxToZone.put(box, zone); } for (ValueBox box : u.getDefBoxes()) { boxToZone.put(box, zone); } } } do { if (Options.v().verbose()) G.v() .out .println( "[" + body.getMethod().getName() + "] Aggregating iteration " + aggregateCount + "..."); // body.printTo(new java.io.PrintWriter(G.v().out, true)); changed = internalAggregate(body, boxToZone, onlyStackVars); aggregateCount++; } while (changed); if (Options.v().time()) Timers.v().aggregationTimer.end(); }
protected void buildMaps(PegGraph pg) { exceHandlers.addAll(pg.getExceHandlers()); startToThread.putAll(pg.getStartToThread()); startToAllocNodes.putAll(pg.getStartToAllocNodes()); startToBeginNodes.putAll(pg.getStartToBeginNodes()); waitingNodes.putAll(pg.getWaitingNodes()); notifyAll.putAll(pg.getNotifyAll()); canNotBeCompacted.addAll(pg.getCanNotBeCompacted()); synch.addAll(pg.getSynch()); threadNameToStart.putAll(pg.getThreadNameToStart()); specialJoin.addAll(pg.getSpecialJoin()); joinStmtToThread.putAll(pg.getJoinStmtToThread()); threadAllocSites.addAll(pg.getThreadAllocSites()); allocNodeToThread.putAll(pg.getAllocNodeToThread()); }
/** * given a DelayabilityAnalysis and the computations of each unit, calculates the latest * computation-point for each expression. the <code>equivRhsMap</code> could be calculated on the * fly, but it is <b>very</b> likely that it already exists (as similar maps are used for * calculating Earliestness, Delayed,... * * @param dg a ExceptionalUnitGraph * @param delayed the delayability-analysis of the same graph. * @param equivRhsMap all computations of the graph */ public LatestComputation(UnitGraph unitGraph, DelayabilityAnalysis delayed, Map equivRhsMap) { this( unitGraph, delayed, equivRhsMap, new ArrayPackedSet(new CollectionFlowUniverse(equivRhsMap.values()))); }
protected void internalTransform(Body b, String phaseName, Map<String, String> options) { initialize(options); SootMethod meth = b.getMethod(); if ((methodsToPrint == null) || (meth.getDeclaringClass().getName() == methodsToPrint.get(meth.getName()))) { Body body = ir.getBody((JimpleBody) b); print_cfg(body); } }
protected void testJoinStmtToThread() { System.out.println("=====test JoinStmtToThread"); Set maps = threadNameToStart.entrySet(); for (Iterator iter = maps.iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); Object key = entry.getKey(); System.out.println("---key= " + key); System.out.println("value: " + entry.getValue()); } System.out.println("=========JoinStmtToThread--ends--------"); }
public void computeMonitorObjs() { Set maps = monitor.entrySet(); for (Iterator iter = maps.iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); FlowSet fs = (FlowSet) entry.getValue(); Iterator it = fs.iterator(); while (it.hasNext()) { Object obj = it.next(); if (!monitorObjs.contains(obj)) monitorObjs.add(obj); } } }
/** Prints the given <code>JimpleBody</code> to the specified <code>PrintWriter</code>. */ private void printLocalsInBody(Body body, UnitPrinter up) { // Print out local variables { Map typeToLocals = new DeterministicHashMap(body.getLocalCount() * 2 + 1, 0.7f); // Collect locals { Iterator localIt = body.getLocals().iterator(); while (localIt.hasNext()) { Local local = (Local) localIt.next(); List localList; Type t = local.getType(); if (typeToLocals.containsKey(t)) localList = (List) typeToLocals.get(t); else { localList = new ArrayList(); typeToLocals.put(t, localList); } localList.add(local); } } // Print locals { Iterator typeIt = typeToLocals.keySet().iterator(); while (typeIt.hasNext()) { Type type = (Type) typeIt.next(); List localList = (List) typeToLocals.get(type); Object[] locals = localList.toArray(); up.type(type); up.literal(" "); for (int k = 0; k < locals.length; k++) { if (k != 0) up.literal(", "); up.local((Local) locals[k]); } up.literal(";"); up.newline(); } } if (!typeToLocals.isEmpty()) { up.newline(); } } }
protected void testThreadNameToStart() { System.out.println("=====test ThreadNameToStart"); Set maps = threadNameToStart.entrySet(); for (Iterator iter = maps.iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); Object key = entry.getKey(); System.out.println("---key= " + key); JPegStmt stmt = (JPegStmt) entry.getValue(); Tag tag1 = (Tag) stmt.getTags().get(0); System.out.println("value: " + tag1 + " " + stmt); } System.out.println("=========ThreadNameToStart--ends--------"); }
/** * Computes the analysis given a UnitGraph computed from a method body. It is recommended that a * ExceptionalUnitGraph (or similar) be provided for correct results in the case of exceptional * control flow. * * @param g a graph on which to compute the analysis. * @see ExceptionalUnitGraph */ public SimpleLiveLocals(UnitGraph graph) { if (Options.v().time()) Timers.v().liveTimer.start(); if (Options.v().verbose()) G.v() .out .println( "[" + graph.getBody().getMethod().getName() + "] Constructing SimpleLiveLocals..."); SimpleLiveLocalsAnalysis analysis = new SimpleLiveLocalsAnalysis(graph); if (Options.v().time()) Timers.v().livePostTimer.start(); // Build unitToLocals map { unitToLocalsAfter = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f); unitToLocalsBefore = new HashMap<Unit, List>(graph.size() * 2 + 1, 0.7f); Iterator unitIt = graph.iterator(); while (unitIt.hasNext()) { Unit s = (Unit) unitIt.next(); FlowSet set = (FlowSet) analysis.getFlowBefore(s); unitToLocalsBefore.put(s, Collections.unmodifiableList(set.toList())); set = (FlowSet) analysis.getFlowAfter(s); unitToLocalsAfter.put(s, Collections.unmodifiableList(set.toList())); } } if (Options.v().time()) Timers.v().livePostTimer.end(); if (Options.v().time()) Timers.v().liveTimer.end(); }
public void testMonitor() { System.out.println("=====test monitor size: " + monitor.size()); Set maps = monitor.entrySet(); for (Iterator iter = maps.iterator(); iter.hasNext(); ) { Map.Entry entry = (Map.Entry) iter.next(); String key = (String) entry.getKey(); System.out.println("---key= " + key); FlowSet list = (FlowSet) entry.getValue(); if (list.size() > 0) { System.out.println("**set: " + list.size()); Iterator it = list.iterator(); while (it.hasNext()) { Object obj = it.next(); if (obj instanceof JPegStmt) { JPegStmt stmt = (JPegStmt) obj; Tag tag1 = (Tag) stmt.getTags().get(0); System.out.println(tag1 + " " + stmt); } else { System.out.println("---list---"); Iterator listIt = ((List) obj).iterator(); while (listIt.hasNext()) { Object oo = listIt.next(); if (oo instanceof JPegStmt) { JPegStmt unit = (JPegStmt) oo; Tag tag = (Tag) unit.getTags().get(0); System.out.println(tag + " " + unit); } else System.out.println(oo); } System.out.println("---list--end-"); } } } } System.out.println("=========monitor--ends--------"); }
public List getLiveLocalsAfter(Unit s) { return unitToLocalsAfter.get(s); }
/** * returns the set of expressions, that have their latest computation just before <code>node * </code>. * * @param node an Object of the flow-graph (in our case always a unit). * @return a FlowSet containing the expressions. */ public Object getFlowBefore(Object node) { return unitToLatest.get(node); }
private static boolean internalAggregate( StmtBody body, Map<ValueBox, Zone> boxToZone, boolean onlyStackVars) { LocalUses localUses; LocalDefs localDefs; ExceptionalUnitGraph graph; boolean hadAggregation = false; Chain<Unit> units = body.getUnits(); graph = new ExceptionalUnitGraph(body); localDefs = new SmartLocalDefs(graph, new SimpleLiveLocals(graph)); localUses = new SimpleLocalUses(graph, localDefs); List<Unit> unitList = new PseudoTopologicalOrderer<Unit>().newList(graph, false); for (Unit u : unitList) { if (!(u instanceof AssignStmt)) continue; AssignStmt s = (AssignStmt) u; Value lhs = s.getLeftOp(); if (!(lhs instanceof Local)) continue; Local lhsLocal = (Local) lhs; if (onlyStackVars && !lhsLocal.getName().startsWith("$")) continue; List<UnitValueBoxPair> lu = localUses.getUsesOf(s); if (lu.size() != 1) continue; UnitValueBoxPair usepair = lu.get(0); Unit use = usepair.unit; ValueBox useBox = usepair.valueBox; List<Unit> ld = localDefs.getDefsOfAt(lhsLocal, use); if (ld.size() != 1) continue; // Check to make sure aggregation pair in the same zone if (boxToZone.get(s.getRightOpBox()) != boxToZone.get(usepair.valueBox)) { continue; } /* we need to check the path between def and use */ /* to see if there are any intervening re-defs of RHS */ /* in fact, we should check that this path is unique. */ /* if the RHS uses only locals, then we know what to do; if RHS has a method invocation f(a, b, c) or field access, we must ban field writes, other method calls and (as usual) writes to a, b, c. */ boolean cantAggr = false; boolean propagatingInvokeExpr = false; boolean propagatingFieldRef = false; boolean propagatingArrayRef = false; ArrayList<FieldRef> fieldRefList = new ArrayList<FieldRef>(); LinkedList<Value> localsUsed = new LinkedList<Value>(); for (ValueBox vb : s.getUseBoxes()) { Value v = vb.getValue(); if (v instanceof Local) localsUsed.add(v); else if (v instanceof InvokeExpr) propagatingInvokeExpr = true; else if (v instanceof ArrayRef) propagatingArrayRef = true; else if (v instanceof FieldRef) { propagatingFieldRef = true; fieldRefList.add((FieldRef) v); } } // look for a path from s to use in graph. // only look in an extended basic block, though. List<Unit> path = graph.getExtendedBasicBlockPathBetween(s, use); if (path == null) continue; Iterator<Unit> pathIt = path.iterator(); // skip s. if (pathIt.hasNext()) pathIt.next(); while (pathIt.hasNext() && !cantAggr) { Stmt between = (Stmt) (pathIt.next()); if (between != use) { // Check for killing definitions for (ValueBox vb : between.getDefBoxes()) { Value v = vb.getValue(); if (localsUsed.contains(v)) { cantAggr = true; break; } if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) { if (v instanceof FieldRef) { if (propagatingInvokeExpr) { cantAggr = true; break; } else if (propagatingFieldRef) { // Can't aggregate a field access if passing a definition of a field // with the same name, because they might be aliased for (FieldRef fieldRef : fieldRefList) { if (((FieldRef) v).getField() == fieldRef.getField()) { cantAggr = true; break; } } } } else if (v instanceof ArrayRef) { if (propagatingInvokeExpr) { // Cannot aggregate an invoke expr past an array write cantAggr = true; break; } else if (propagatingArrayRef) { // cannot aggregate an array read past a write // this is somewhat conservative // (if types differ they may not be aliased) cantAggr = true; break; } } } } // Make sure not propagating past a {enter,exit}Monitor if (propagatingInvokeExpr && between instanceof MonitorStmt) cantAggr = true; } // Check for intervening side effects due to method calls if (propagatingInvokeExpr || propagatingFieldRef || propagatingArrayRef) { for (final ValueBox box : between.getUseBoxes()) { if (between == use && box == useBox) { // Reached use point, stop looking for // side effects break; } Value v = box.getValue(); if (v instanceof InvokeExpr || (propagatingInvokeExpr && (v instanceof FieldRef || v instanceof ArrayRef))) { cantAggr = true; break; } } } } // we give up: can't aggregate. if (cantAggr) { continue; } /* assuming that the d-u chains are correct, */ /* we need not check the actual contents of ld */ Value aggregatee = s.getRightOp(); if (usepair.valueBox.canContainValue(aggregatee)) { boolean wasSimpleCopy = isSimpleCopy(usepair.unit); usepair.valueBox.setValue(aggregatee); units.remove(s); hadAggregation = true; // clean up the tags. If s was not a simple copy, the new statement should get // the tags of s. // OK, this fix was wrong. The condition should not be // "If s was not a simple copy", but rather "If usepair.unit // was a simple copy". This way, when there's a load of a constant // followed by an invoke, the invoke gets the tags. if (wasSimpleCopy) { // usepair.unit.removeAllTags(); usepair.unit.addAllTagsOf(s); } } else { /* if(Options.v().verbose()) { G.v().out.println("[debug] failed aggregation"); G.v().out.println("[debug] tried to put "+aggregatee+ " into "+usepair.stmt + ": in particular, "+usepair.valueBox); G.v().out.println("[debug] aggregatee instanceof Expr: " +(aggregatee instanceof Expr)); }*/ } } return hadAggregation; }
public List getLiveLocalsBefore(Unit s) { return unitToLocalsBefore.get(s); }
SimpleLiveLocalsAnalysis(UnitGraph g) { super(g); if (Options.v().time()) Timers.v().liveSetupTimer.start(); emptySet = new ArraySparseSet(); // Create kill sets. { unitToKillSet = new HashMap<Unit, FlowSet>(g.size() * 2 + 1, 0.7f); Iterator unitIt = g.iterator(); while (unitIt.hasNext()) { Unit s = (Unit) unitIt.next(); FlowSet killSet = emptySet.clone(); Iterator boxIt = s.getDefBoxes().iterator(); while (boxIt.hasNext()) { ValueBox box = (ValueBox) boxIt.next(); if (box.getValue() instanceof Local) killSet.add(box.getValue(), killSet); } unitToKillSet.put(s, killSet); } } // Create generate sets { unitToGenerateSet = new HashMap<Unit, FlowSet>(g.size() * 2 + 1, 0.7f); Iterator unitIt = g.iterator(); while (unitIt.hasNext()) { Unit s = (Unit) unitIt.next(); FlowSet genSet = emptySet.clone(); Iterator boxIt = s.getUseBoxes().iterator(); while (boxIt.hasNext()) { ValueBox box = (ValueBox) boxIt.next(); if (box.getValue() instanceof Local) genSet.add(box.getValue(), genSet); } unitToGenerateSet.put(s, genSet); } } if (Options.v().time()) Timers.v().liveSetupTimer.end(); if (Options.v().time()) Timers.v().liveAnalysisTimer.start(); doAnalysis(); if (Options.v().time()) Timers.v().liveAnalysisTimer.end(); }
/** * Parse the command line arguments specific to CFGViewer, and convert them into phase options for * jtp.printcfg. * * @return an array of arguments to pass on to Soot.Main.main(). */ private String[] parse_options(String[] args) { List<String> sootArgs = new ArrayList<String>(args.length); for (int i = 0, n = args.length; i < n; i++) { if (args[i].equals("--alt-classpath") || args[i].equals("--alt-class-path")) { sootArgs.add("-p"); sootArgs.add(phaseFullname); sootArgs.add(altClassPathOptionName + ':' + args[++i]); } else if (args[i].startsWith("--graph=")) { sootArgs.add("-p"); sootArgs.add(phaseFullname); sootArgs.add(graphTypeOptionName + ':' + args[i].substring("--graph=".length())); } else if (args[i].startsWith("--ir=")) { sootArgs.add("-p"); sootArgs.add(phaseFullname); sootArgs.add(irOptionName + ':' + args[i].substring("--ir=".length())); } else if (args[i].equals("--brief")) { sootArgs.add("-p"); sootArgs.add(phaseFullname); sootArgs.add(briefLabelOptionName + ":true"); } else if (args[i].equals("--multipages")) { sootArgs.add("-p"); sootArgs.add(phaseFullname); sootArgs.add(multipageOptionName + ":true"); } else if (args[i].equals("--help")) { return new String[0]; // This is a cheesy method to inveigle // our caller into printing the help // and exiting. } else if (args[i].equals("--soot-class-path") || args[i].equals("-soot-class-path") || args[i].equals("--soot-classpath") || args[i].equals("-soot-classpath") || args[i].equals("--process-dir") || args[i].equals("-process-dir") || args[i].equals("--android-jars") || args[i].equals("-android-jars") || args[i].equals("--force-android-jar") || args[i].equals("-force-android-jar")) { // Pass classpaths without treating ":" as a method specifier. sootArgs.add(args[i]); sootArgs.add(args[++i]); } else if (args[i].equals("-p") || args[i].equals("--phase-option") || args[i].equals("-phase-option")) { // Pass phase options without treating ":" as a method // specifier. sootArgs.add(args[i]); sootArgs.add(args[++i]); sootArgs.add(args[++i]); } else { int smpos = args[i].indexOf(':'); if (smpos == -1) { sootArgs.add(args[i]); } else { String clsname = args[i].substring(0, smpos); sootArgs.add(clsname); String methname = args[i].substring(smpos + 1); if (methodsToPrint == null) { methodsToPrint = new HashMap<String, String>(); } methodsToPrint.put(methname, clsname); } } } String[] sootArgsArray = new String[sootArgs.size()]; return (String[]) sootArgs.toArray(sootArgsArray); }