/** Performs peephole optimizations on a program's live methods. */ private static void peephole(final BloatContext context) { final Set liveMethods = new TreeSet(new MemberRefComparator()); final CallGraph cg = context.getCallGraph(); liveMethods.addAll(cg.liveMethods()); // Perform peephole optimizations. We do this separately because // some peephole optimizations do things to the stack that // inlining doesn't like. For instance, a peephole optimizations // might make it so that a method has a non-empty stack upon // return. Inlining will barf at the sight of this. BloatBenchmark.tr("Performing peephole optimizations"); final Iterator iter = liveMethods.iterator(); while (BloatBenchmark.PEEPHOLE && iter.hasNext()) { try { final MethodEditor live = context.editMethod((MemberRef) iter.next()); Peephole.transform(live); context.commit(live.methodInfo()); context.release(live.methodInfo()); } catch (final NoSuchMethodException ex314) { BloatBenchmark.err.println("** Could not find method " + ex314.getMessage()); ex314.printStackTrace(System.err); System.exit(1); } } }
/** * Returns the live methods of a program whose root methods are the <tt>main</tt> method of a set * of classes. * * @param classes Names of classes containing root methods * @param context Repository for accessing BLOAT stuff * @return The <tt>MemberRef</tt>s of the live methods */ private static Collection liveMethods(final Collection classes, final BloatContext context) { // Determine the roots of the call graph final Set roots = new HashSet(); Iterator iter = classes.iterator(); while (iter.hasNext()) { final String className = (String) iter.next(); try { final ClassEditor ce = context.editClass(className); final MethodInfo[] methods = ce.methods(); for (int i = 0; i < methods.length; i++) { final MethodEditor me = context.editMethod(methods[i]); if (!me.name().equals("main")) { continue; } BloatBenchmark.tr(" Root " + ce.name() + "." + me.name() + me.type()); roots.add(me.memberRef()); } } catch (final ClassNotFoundException ex1) { BloatBenchmark.err.println("** Could not find class: " + ex1.getMessage()); System.exit(1); } } if (roots.isEmpty()) { BloatBenchmark.err.print("** No main method found in classes: "); iter = classes.iterator(); while (iter.hasNext()) { final String name = (String) iter.next(); BloatBenchmark.err.print(name); if (iter.hasNext()) { BloatBenchmark.err.print(", "); } } BloatBenchmark.err.println(""); } context.setRootMethods(roots); final CallGraph cg = context.getCallGraph(); final Set liveMethods = new TreeSet(new MemberRefComparator()); liveMethods.addAll(cg.liveMethods()); return (liveMethods); }
/** Specializes the live methods in a program. */ private static void specialize(final BloatContext context) { final CallGraph cg = context.getCallGraph(); final Set liveMethods = new TreeSet(new MemberRefComparator()); liveMethods.addAll(cg.liveMethods()); // Specialize all possible methods final InlineStats stats = context.getInlineStats(); if (BloatBenchmark.statsFile != null) { Specialize.STATS = true; stats.setConfigName("BloatBenchmark"); } if (BloatBenchmark.MORPH != -1) { Specialize.MAX_MORPH = BloatBenchmark.MORPH; } final Specialize spec = new Specialize(context); if (Specialize.STATS) { stats.noteLiveMethods(liveMethods.size()); stats.noteLiveClasses(cg.liveClasses().size()); } BloatBenchmark.tr("Specializing live methods"); final Iterator iter = liveMethods.iterator(); for (int count = 0; iter.hasNext(); count++) { try { final MethodEditor live = context.editMethod((MemberRef) iter.next()); if (context.ignoreMethod(live.memberRef())) { // Don't display ignored methods, it's misleading. continue; } BloatBenchmark.tr( " " + count + ") " + live.declaringClass().name() + "." + live.name() + live.type()); spec.specialize(live); } catch (final NoSuchMethodException ex2) { BloatBenchmark.err.println("** Could not find method " + ex2.getMessage()); System.exit(1); } } }
public void go() { Iterator methods = cg.sourceMethods(); while (methods.hasNext()) { SootMethod m = (SootMethod) methods.next(); dfsVisit(m); } }
private void dfsVisit(SootMethod m) { if (visited.contains(m)) return; visited.add(m); Iterator targets = new Targets(cg.edgesOutOf(m)); while (targets.hasNext()) { SootMethod target = (SootMethod) targets.next(); dfsVisit(target); } order.add(m); }
/** Inlines calls to static methods in the live methods of a given program. */ private static void inline(final BloatContext context) { final Set liveMethods = new TreeSet(new MemberRefComparator()); final CallGraph cg = context.getCallGraph(); liveMethods.addAll(cg.liveMethods()); BloatBenchmark.tr("Inlining " + liveMethods.size() + " live methods"); if (BloatBenchmark.CALLEE_SIZE != -1) { Inline.CALLEE_SIZE = BloatBenchmark.CALLEE_SIZE; } final Iterator iter = liveMethods.iterator(); for (int count = 0; BloatBenchmark.INLINE && iter.hasNext(); count++) { try { final MethodEditor live = context.editMethod((MemberRef) iter.next()); if (context.ignoreMethod(live.memberRef())) { // Don't display ignored methods, it's misleading. continue; } BloatBenchmark.tr( " " + count + ") " + live.declaringClass().name() + "." + live.name() + live.type()); final Inline inline = new Inline(context, BloatBenchmark.SIZE); inline.setMaxCallDepth(BloatBenchmark.DEPTH); inline.inline(live); // Commit here in an attempt to conserve memory context.commit(live.methodInfo()); context.release(live.methodInfo()); } catch (final NoSuchMethodException ex3) { BloatBenchmark.err.println("** Could not find method " + ex3.getMessage()); System.exit(1); } } }