From c4a5f9a5af9f814f55c44757b246fc35037ffe9f Mon Sep 17 00:00:00 2001 From: Evan Battaglia Date: Mon, 4 Feb 2008 15:23:33 -0800 Subject: [PATCH] Some more instrumentation, and playing around with chopping (chops when double-click in slice skater) --- .../src/edu/berkeley/cs/bodik/svelte/Slicing.java | 11 +- .../cs/bodik/svelte/csslicer/DepthSlicer.java | 146 ++++++------- .../svelte/csslicer/DepthTabulationSolver.java | 131 +++++++++--- .../autodebug/InstrumentSliceDelegate.java | 4 +- .../autodebug/InstrumentationPoint.java | 116 +++++++++++ .../experimental/autodebug/InstrumentationSet.java | 61 ++++++ .../experimental/autodebug/Instrumenter.java | 103 ++------- .../{Instrumenter.java => OldInstrumenter.java} | 2 +- .../svelte/plugin/CIThinEditorActionDelegate.java | 2 +- .../svelte/plugin/CSThinEditorActionDelegate.java | 2 +- .../cs/bodik/svelte/plugin/CachedSlice.java | 232 +++++++++++++++++++++ .../cs/bodik/svelte/plugin/EclipseUtils.java | 89 +++++++- .../cs/bodik/svelte/plugin/SliceEnvironment.java | 35 +++- .../svelte/plugin/bfsliceview/BFSliceInput.java | 14 +- .../svelte/plugin/bfsliceview/BFSliceView.java | 37 +++- .../bodik/svelte/plugin/cgview/CallGraphSlice.java | 4 +- .../svelte/plugin/sgview/SGViewActionDelegate.java | 5 +- .../cs/bodik/svelte/plugin/sgview/SliceGraph.java | 18 +- .../plugin/treesliceview/TreeSliceInput.java | 3 +- 19 files changed, 792 insertions(+), 223 deletions(-) create mode 100644 Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationPoint.java create mode 100644 Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationSet.java copy Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/{Instrumenter.java => OldInstrumenter.java} (99%) create mode 100644 Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CachedSlice.java diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/Slicing.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/Slicing.java index 283168f..0418a59 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/Slicing.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/Slicing.java @@ -48,6 +48,8 @@ import com.ibm.wala.ipa.slicer.Slicer; import com.ibm.wala.ipa.slicer.Statement; import com.ibm.wala.ipa.slicer.Slicer.ControlDependenceOptions; import com.ibm.wala.ipa.slicer.Slicer.DataDependenceOptions; +import com.ibm.wala.util.collections.Pair; +import com.ibm.wala.util.graph.Graph; import edu.berkeley.cs.bodik.svelte.cislicer.ThinSlicer; import edu.berkeley.cs.bodik.svelte.csslicer.DepthSlicer; @@ -69,6 +71,7 @@ public class Slicing { Collection slice = null; ThinSlicer thinslicer = null; + Graph csDepGraph = null; System.out.println("-------------------- S E E D ------------------------"); for ( Statement s: seed ) @@ -101,8 +104,10 @@ public class Slicing { SDG sdg = new SDG(cg, pa, new AstJavaModRef(), dOptions, cOptions, null); - try { - slice = DepthSlicer.computeBackwardSlice(sdg, seed.getStatements(), depth); + try { + Pair,Graph> pair= DepthSlicer.computeBackwardsSliceAndDepGraph(sdg, seed.getStatements(), depth); + slice = pair.fst; + csDepGraph = pair.snd; } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); @@ -133,7 +138,7 @@ public class Slicing { Slice sliceslice = new Slice(slice); // TODO: FIXME: still pretty much a hack! - SliceEnvironment.setCurrentSliceData(cg, pa, seed, sliceslice, thinslicer); + SliceEnvironment.setCurrentSliceData(cg, pa, seed, sliceslice, thinslicer, csDepGraph); return sliceslice; } diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthSlicer.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthSlicer.java index 8fcdd49..a3dbdea 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthSlicer.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthSlicer.java @@ -10,8 +10,10 @@ *******************************************************************************/ package edu.berkeley.cs.bodik.svelte.csslicer; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.Stack; import com.ibm.wala.dataflow.IFDS.BackwardsSupergraph; @@ -35,7 +37,9 @@ import com.ibm.wala.ipa.slicer.Slicer.ControlDependenceOptions; import com.ibm.wala.ipa.slicer.Slicer.DataDependenceOptions; import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.Iterator2Collection; +import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.debug.Assertions; +import com.ibm.wala.util.graph.Graph; import com.ibm.wala.util.intset.SparseIntSet; /** @@ -61,75 +65,22 @@ public class DepthSlicer { */ public final static int BAIL_OUT = -1; - /** - * @param s a statement of interest - * @param depth - * @return the backward slice of s. - * @throws CancelException - */ - public static Collection computeBackwardSlice(Statement s, CallGraph cg, PointerAnalysis pa, - DataDependenceOptions dOptions, ControlDependenceOptions cOptions, int depth) throws IllegalArgumentException, CancelException { - return computeSlice(new SDG(cg, pa, ModRef.make(), dOptions, cOptions), Collections.singleton(s), true, depth); - } - - /** - * @param s a statement of interest - * @return the forward slice of s. - * @throws CancelException - */ - public static Collection computeForwardSlice(Statement s, CallGraph cg, PointerAnalysis pa, - DataDependenceOptions dOptions, ControlDependenceOptions cOptions, int depth) throws IllegalArgumentException, CancelException { - return computeSlice(new SDG(cg, pa, ModRef.make(), dOptions, cOptions), Collections.singleton(s), false, depth); - } - - /** - * Use the passed-in SDG - * - * @throws CancelException - */ - public static Collection computeBackwardSlice(SDG sdg, Statement s, int depth) - throws IllegalArgumentException, CancelException { - return computeSlice(sdg, Collections.singleton(s), true, depth); + public static Pair,Graph> computeBackwardsSliceAndDepGraph(SDG sdg, Collection ss, int depth) throws IllegalArgumentException, CancelException { + return new DepthSlicer().slice(sdg, ss, true, depth); } - /** - * Use the passed-in SDG - * - * @throws CancelException - */ - public static Collection computeForwardSlice(SDG sdg, Statement s, int depth) - throws IllegalArgumentException, CancelException { - return computeSlice(sdg, Collections.singleton(s), false, depth); - } - - /** - * Use the passed-in SDG - * @param depth - * - * @throws CancelException - */ - public static Collection computeBackwardSlice(SDG sdg, Collection ss, int depth) - throws IllegalArgumentException, CancelException { - return computeSlice(sdg, ss, true, depth); - } + private Graph getDepGraph() { + // TODO Auto-generated method stub + return null; +} - /** - * @param ss a collection of statements of interest - * @param depth - * @throws CancelException - */ - protected static Collection computeSlice(SDG sdg, Collection ss, boolean backward, int depth) throws CancelException { - if (sdg == null) { - throw new IllegalArgumentException("sdg cannot be null"); - } - return new DepthSlicer().slice(sdg, ss, backward, depth); - } + /** * Main driver logic. * @param depth */ - public Collection slice(SDG sdg, Collection ss, boolean backward, int depth) throws CancelException { + public Pair, Graph> slice(SDG sdg, Collection ss, boolean backward, int depth) throws CancelException { if (sdg == null) { throw new IllegalArgumentException("sdg cannot be null"); @@ -138,6 +89,10 @@ public class DepthSlicer { Collection rootsConsidered = HashSetFactory.make(); Stack workList = new Stack(); Collection result = HashSetFactory.make(); + + Graph superDepGraphResult = null; + final ArrayList> depGraphs = new ArrayList>(); + for (Statement s : ss) { workList.push(s); System.out.println("***1seed*** " + s); @@ -182,13 +137,71 @@ public class DepthSlicer { workList.clear(); System.err.println("Bailed out at " + result.size()); } + + depGraphs.add(solver.getDepGraph()); } if (VERBOSE) { System.err.println("Slicer done."); } - return result; + superDepGraphResult = new Graph() { + public void removeNodeAndEdges(Statement N) throws UnsupportedOperationException { } + public void addNode(Statement n) { } + public boolean containsNode(Statement N) { return false; } + public int getNumberOfNodes() {return 0;} + public Iterator iterator() {return null;} + public void removeNode(Statement n) {} + public void addEdge(Statement src, Statement dst) {} + public int getPredNodeCount(Statement N) {return 0;} + public Iterator getPredNodes(Statement N) {return null;} + public int getSuccNodeCount(Statement N) {return 0;} + public boolean hasEdge(Statement src, Statement dst) {return false;} + public void removeAllIncidentEdges(Statement node) throws UnsupportedOperationException {} + public void removeEdge(Statement src, Statement dst) throws UnsupportedOperationException {} + public void removeIncomingEdges(Statement node) throws UnsupportedOperationException { } + public void removeOutgoingEdges(Statement node) throws UnsupportedOperationException { } + public Iterator getSuccNodes(final Statement N) { + return new Iterator() { + Statement nextStatement = null; + int depGraphIndex = -1; + Iterator currentIter = null; + + public boolean hasNext() { + if ( depGraphIndex == -1 ) + return generateNext(); + return ( (currentIter != null && currentIter.hasNext()) || depGraphIndex +1 < depGraphs.size() ); + } + private boolean generateNext() { + if ( currentIter != null && currentIter.hasNext() ) { + nextStatement = currentIter.next(); + return true; + } else { + currentIter = null; + while ( depGraphIndex + 1 < depGraphs.size() ) { + depGraphIndex++; + currentIter = depGraphs.get(depGraphIndex).getSuccNodes(N); + if ( currentIter != null ) { + nextStatement = currentIter.next(); + return true; + } + } + return false; + } + } + public Statement next(){ + if ( depGraphIndex == -1 ) + generateNext(); + Statement result = nextStatement; + generateNext(); + return result; + } + public void remove() { } + }; + } + + }; + return Pair.make(result,superDepGraphResult); } /** @@ -286,15 +299,6 @@ public class DepthSlicer { return result; } - /** - * @param s a statement of interest - * @return the backward slice of s. - * @throws CancelException - */ - public static Collection computeBackwardSlice(Statement s, CallGraph cg, PointerAnalysis pointerAnalysis, int depth) - throws IllegalArgumentException, CancelException { - return computeBackwardSlice(s, cg, pointerAnalysis, DataDependenceOptions.FULL, ControlDependenceOptions.FULL, depth); - } /** * Tabulation problem representing slicing diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthTabulationSolver.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthTabulationSolver.java index cab3a1c..c8a5c48 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthTabulationSolver.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/csslicer/DepthTabulationSolver.java @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.Hashtable; import java.util.Iterator; +import java.util.LinkedList; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -35,12 +36,10 @@ import com.ibm.wala.dataflow.IFDS.IUnaryFlowFunction; import com.ibm.wala.dataflow.IFDS.TabulationProblem; import com.ibm.wala.dataflow.IFDS.LocalPathEdges; import com.ibm.wala.dataflow.IFDS.LocalSummaryEdges; -import com.ibm.wala.dataflow.IFDS.TabulationProblem; import com.ibm.wala.dataflow.IFDS.ISupergraph; import com.ibm.wala.dataflow.IFDS.TabulationResult; import com.ibm.wala.eclipse.util.CancelException; import com.ibm.wala.eclipse.util.MonitorUtil; -import com.ibm.wala.ipa.slicer.HeapStatement; import com.ibm.wala.ipa.slicer.NormalStatement; import com.ibm.wala.ipa.slicer.StatementWithInstructionIndex; import com.ibm.wala.ipa.slicer.HeapStatement.HeapParamCaller; @@ -50,6 +49,7 @@ import com.ibm.wala.util.collections.Heap; import com.ibm.wala.util.collections.Iterator2Collection; import com.ibm.wala.util.collections.ToStringComparator; import com.ibm.wala.util.debug.Assertions; +import com.ibm.wala.util.graph.Graph; import com.ibm.wala.util.graph.traverse.DFS; import com.ibm.wala.util.heapTrace.HeapTracer; import com.ibm.wala.util.intset.IntIterator; @@ -250,7 +250,7 @@ public class DepthTabulationSolver { // this means that we don't want to push the edge. instead, // we'll push the merged fact. a little tricky, but i think should // work. - if ( logPropagate("merge", edge.s_p,edge.n)) + if ( logPropagate("merge", edge.s_p,edge.n)) // should never happen in slicing since we don't use d1, j1 etc (integers indices for the node) propagate(edge.s_p, edge.d1, edge.n, j); } else { if (supergraph.isCall(edge.n)) { @@ -577,7 +577,7 @@ public class DepthTabulationSolver { reached.foreach(new IntSetAction() { public void act(final int d1) { - if (logPropagate("processcall-self", callee, callee)) + if (logPropagate("processcall-self", edge.n, callee)) propagate(callee, d1, callee, d1); // cache the fact that we've flowed -> by a @@ -738,13 +738,13 @@ public class DepthTabulationSolver { } protected PathEdge popFromWorkList() { - return (PathEdge) worklist.take(); + return (PathEdge) worklist.removeLast(); } private PathEdge peekFromWorkList() { // horrible. don't use in performance-critical - PathEdge result = (PathEdge) worklist.take(); - worklist.insert(result); + PathEdge result = (PathEdge) worklist.getLast(); +// worklist.insert(result); return result; } @@ -764,6 +764,99 @@ public class DepthTabulationSolver { } } + public Graph getDepGraph() { + return new Graph() { + + public void removeNodeAndEdges(T N) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void addNode(T n) { + // TODO Auto-generated method stub + + } + + public boolean containsNode(T N) { + // TODO Auto-generated method stub + return false; + } + + public int getNumberOfNodes() { + // TODO Auto-generated method stub + return 0; + } + + public Iterator iterator() { + // TODO Auto-generated method stub + return null; + } + + public void removeNode(T n) { + // TODO Auto-generated method stub + + } + + public void addEdge(T src, T dst) { + // TODO Auto-generated method stub + + } + + public int getPredNodeCount(T N) { + // TODO Auto-generated method stub + return 0; + } + + public Iterator getPredNodes(T N) { + // TODO Auto-generated method stub + return null; + } + + public int getSuccNodeCount(T N) { + // TODO Auto-generated method stub + return 0; + } + + public Iterator getSuccNodes(T N) { + // TODO Auto-generated method stub + EdgesAndDepth ead = edgesandepths.get(N); + if ( ead == null || ead.tonodes == null ) + return null; + return edgesandepths.get(N).tonodes.iterator(); + } + + public boolean hasEdge(T src, T dst) { + // TODO Auto-generated method stub + return false; + } + + public void removeAllIncidentEdges(T node) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void removeEdge(T src, T dst) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void removeIncomingEdges(T node) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void removeOutgoingEdges(T node) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + }; + } /** * @@ -787,9 +880,9 @@ public class DepthTabulationSolver { edgesandepths.put(n,eadDest); } if ( (eadSource.depth+1) < eadDest.depth ) - System.err.println("WARNING!!! DEPTHED CS ALGORITHMS IS BROKEN, statement on lower depth encountered later!"); + System.out.println("***** WARNING!!! DEPTHED CS ALGORITHMS IS BROKEN, statement on lower depth encountered later!"); - System.out.printf("depths %d->%d (%s->%s)\n", eadSource.depth, eadDest.depth, s_p, n); + System.out.printf("depths %d->%d %s (%s->%s)\n", eadSource.depth, eadDest.depth, string, s_p, n); return true; @@ -892,7 +985,7 @@ public class DepthTabulationSolver { } protected void addToWorkList(T s_p, int i, T n, int j) { - worklist.insert(new PathEdge(s_p, i, n, j)); + worklist.addLast(new PathEdge(s_p, i, n, j)); } private LocalPathEdges findOrCreateLocalPathEdges(T s_p) { @@ -1127,23 +1220,7 @@ public class DepthTabulationSolver { return supergraph; } - protected class Worklist extends Heap { - - Worklist() { - super(100); - } - - @Override - protected boolean compareElements(Object elt1, Object elt2) { - PathEdge p1 = (PathEdge) elt1; - PathEdge p2 = (PathEdge) elt2; - if (p1.d2 != p2.d2) { - if (problem.getDomain().isWeakerThan(p1.d2, p2.d2)) { - return true; - } - } - return false; - } + protected class Worklist extends LinkedList { } /** diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentSliceDelegate.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentSliceDelegate.java index 16822fe..ab49797 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentSliceDelegate.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentSliceDelegate.java @@ -25,7 +25,7 @@ public class InstrumentSliceDelegate implements IEditorActionDelegate { public void run(IAction action) { if ( ! (SliceEnvironment.hasCurrent() && SliceEnvironment.getCurrent().getUseShrike()) ) return; - + // STEP 1: go thru slice, record class files we need to update. (make sure no java.* protected stuff) Hashtable> classesToStatements = new Hashtable>(); Slice slice = SliceEnvironment.getCurrent().getSlice(); @@ -53,7 +53,7 @@ public class InstrumentSliceDelegate implements IEditorActionDelegate { // STEP 4: use Shrike to convert these, adding instrumentation try { - Instrumenter.instrument(inputFilenames, outputFilename); +// Instrumenter.instrument(inputFilenames, outputFilename); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationPoint.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationPoint.java new file mode 100644 index 0000000..877d461 --- /dev/null +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationPoint.java @@ -0,0 +1,116 @@ +package edu.berkeley.cs.bodik.svelte.experimental.autodebug; + + + +import com.ibm.wala.ipa.slicer.NormalStatement; +import com.ibm.wala.ipa.slicer.ParamCaller; +import com.ibm.wala.ipa.slicer.Statement; +import com.ibm.wala.ipa.slicer.StatementWithInstructionIndex; +import com.ibm.wala.shrikeBT.ConstantInstruction; +import com.ibm.wala.shrikeBT.MethodEditor; +import com.ibm.wala.shrikeBT.DupInstruction; +import com.ibm.wala.shrikeBT.GetInstruction; +import com.ibm.wala.shrikeBT.InvokeInstruction; +import com.ibm.wala.shrikeBT.MethodEditor; +import com.ibm.wala.shrikeBT.SwapInstruction; +import com.ibm.wala.shrikeBT.IInvokeInstruction.Dispatch; +import com.ibm.wala.shrikeBT.MethodEditor.Output; +import com.ibm.wala.shrikeBT.MethodEditor.Patch; + +public abstract class InstrumentationPoint { + protected Statement statement; + protected int instructionIndex; + + public InstrumentationPoint(Statement s) { + super(); + this.statement = s; + assert ( s instanceof NormalStatement || s instanceof StatementWithInstructionIndex); + if ( s instanceof NormalStatement ) + this.instructionIndex = ((NormalStatement) s).getInstructionIndex(); + else if ( s instanceof StatementWithInstructionIndex ) + this.instructionIndex = ((StatementWithInstructionIndex) s).getInstructionIndex(); + } + public int getInstructionIndex() { + return instructionIndex; + } + + abstract public void instrument(MethodEditor me, String stackTypes[]); + + static class PrintTopOfStackIP extends InstrumentationPoint { + public PrintTopOfStackIP(Statement s) {super(s);} + + @Override + public void instrument(MethodEditor me, String stackTypes[]) { + final String type = stackTypes[0]; + me.insertBefore(instructionIndex, new Patch() { + + @Override + public void emitTo(Output w) { + System.out.println("type of top of stack at "+instructionIndex+"is " + type); + + + + if ( type.startsWith("L") ) { + w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); + w.emit(ConstantInstruction.makeString(statement.getNode().getMethod().getSignature() + ":" + " ")); + w.emit(InvokeInstruction.make("(Ljava/lang/String;)V","Ljava/io/PrintStream;","print",Dispatch.VIRTUAL)); + w.emit(DupInstruction.make(0)); + if ( ! type.equals("Ljava/lang/String;") ) + w.emit(InvokeInstruction.make("()Ljava/lang/String;","Ljava/lang/Object;","toString",Dispatch.VIRTUAL)); + w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); + w.emit(SwapInstruction.make()); + w.emit(InvokeInstruction.make("(Ljava/lang/String;)V","Ljava/io/PrintStream;","println",Dispatch.VIRTUAL)); + } else if ( type.startsWith("I") ) { + w.emit(DupInstruction.make(0)); + w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); + w.emit(SwapInstruction.make()); + w.emit(InvokeInstruction.make("(I)V","Ljava/io/PrintStream;","println",Dispatch.VIRTUAL)); + } // TODO: arrays + } + }); + } + } + + static class ParamCallerIP extends PrintTopOfStackIP { + public ParamCallerIP (Statement s) {super(s);} + + @Override + public void instrument(MethodEditor me, String stackTypes[]) { + assert(statement instanceof ParamCaller); + ParamCaller pc = (ParamCaller) statement; + +// System.out.println ( "VALUE NUMBER!!! " + pc.getValueNumber() ); +// if ( pc.getInstruction().getNumberOfUses() != pc.getValueNumber() ) +// return; // for now, we only handle the case when we care about the last argument. + + super.instrument(me, stackTypes); + + +// final String type = stackTypes[0]; +// me.insertBefore(instructionIndex, new Patch() { +// +// @Override +// public void emitTo(Output w) { +// System.out.println("type of top of stack at "+instructionIndex+"is " + type); +// +// +// +// +// if ( type.startsWith("L") ) { +// w.emit(DupInstruction.make(0)); +// if ( ! type.equals("Ljava/lang/String;") ) +// w.emit(InvokeInstruction.make("()Ljava/lang/String;","Ljava/lang/Object;","toString",Dispatch.VIRTUAL)); +// w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); +// w.emit(SwapInstruction.make()); +// w.emit(InvokeInstruction.make("(Ljava/lang/String;)V","Ljava/io/PrintStream;","println",Dispatch.VIRTUAL)); +// } else if ( type.startsWith("I") ) { +// w.emit(DupInstruction.make(0)); +// w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); +// w.emit(SwapInstruction.make()); +// w.emit(InvokeInstruction.make("(I)V","Ljava/io/PrintStream;","println",Dispatch.VIRTUAL)); +// } // TODO: arrays +// } +// }); + } + } +} \ No newline at end of file diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationSet.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationSet.java new file mode 100644 index 0000000..6026db2 --- /dev/null +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/InstrumentationSet.java @@ -0,0 +1,61 @@ +package edu.berkeley.cs.bodik.svelte.experimental.autodebug; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Hashtable; + +import com.ibm.wala.ipa.slicer.NormalStatement; +import com.ibm.wala.ipa.slicer.ParamCaller; +import com.ibm.wala.ipa.slicer.Statement; +import com.ibm.wala.ssa.SSAInstruction; +import com.ibm.wala.ssa.SSAPutInstruction; +import com.ibm.wala.ssa.SSAReturnInstruction; + +public class InstrumentationSet { + HashSet fullyQualifiedClassNames; + Hashtable> methodsToIPs; + public InstrumentationSet() { + fullyQualifiedClassNames = new HashSet(); + methodsToIPs = new Hashtable>(); + } + + private void addInstrumentationPoint(String methodSignature,InstrumentationPoint ip) { + methodSignature = methodSignature.replace("/","."); + ArrayList methodsIPs = methodsToIPs.get(methodSignature); + if ( methodsIPs == null ) { + methodsIPs = new ArrayList(); + methodsToIPs.put(methodSignature, methodsIPs); + } + methodsIPs.add(ip); + } + + public boolean toBeInstrumented(String methodSignature) { + return methodsToIPs.containsKey(methodSignature.replace("/",".")); + } + + public ArrayList instrumentationPointsForMethod(String methodSignature) { + return methodsToIPs.get(methodSignature.replace("/",".")); + } + + public void addInstrumentationPoint(Statement statement) { + InstrumentationPoint newIP = null; + if ( statement instanceof NormalStatement ) { + SSAInstruction instr = ((NormalStatement)statement).getInstruction(); + if ( instr instanceof SSAPutInstruction || instr instanceof SSAReturnInstruction ) + newIP = new InstrumentationPoint.PrintTopOfStackIP(statement); + + } else if ( statement instanceof ParamCaller ) { + newIP = new InstrumentationPoint.ParamCallerIP(statement); + } + if ( newIP != null ) { + addInstrumentationPoint(statement.getNode().getMethod().getSignature(), newIP); + String classname = statement.getNode().getMethod().getDeclaringClass().getName().toString(); + fullyQualifiedClassNames.add(classname); + } + } + + public Collection getFullyQualifiedClassNames() { + return fullyQualifiedClassNames; + } +} diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/Instrumenter.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/Instrumenter.java index b3bed43..8808ad6 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/Instrumenter.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/Instrumenter.java @@ -124,41 +124,19 @@ package edu.berkeley.cs.bodik.svelte.experimental.autodebug; import java.io.BufferedWriter; import java.io.FileWriter; -import java.io.IOException; -import java.io.OutputStream; -import java.io.OutputStreamWriter; import java.io.PrintStream; -import java.io.PrintWriter; import java.io.Writer; import java.util.ArrayList; import java.util.BitSet; -import com.ibm.wala.shrikeBT.BinaryOpInstruction; -import com.ibm.wala.shrikeBT.ConditionalBranchInstruction; -import com.ibm.wala.shrikeBT.ConstantInstruction; -import com.ibm.wala.shrikeBT.Constants; -import com.ibm.wala.shrikeBT.Disassembler; -import com.ibm.wala.shrikeBT.DupInstruction; -import com.ibm.wala.shrikeBT.GetInstruction; import com.ibm.wala.shrikeBT.Instruction; -import com.ibm.wala.shrikeBT.InvokeInstruction; import com.ibm.wala.shrikeBT.MethodData; import com.ibm.wala.shrikeBT.MethodEditor; -import com.ibm.wala.shrikeBT.ReturnInstruction; -import com.ibm.wala.shrikeBT.SwapInstruction; -import com.ibm.wala.shrikeBT.ThrowInstruction; import com.ibm.wala.shrikeBT.Util; -import com.ibm.wala.shrikeBT.IInvokeInstruction.Dispatch; -import com.ibm.wala.shrikeBT.MethodEditor.Output; -import com.ibm.wala.shrikeBT.MethodEditor.Patch; import com.ibm.wala.shrikeBT.analysis.Verifier; -import com.ibm.wala.shrikeBT.analysis.Analyzer.FailureException; -import com.ibm.wala.shrikeBT.shrikeCT.CTDecoder; import com.ibm.wala.shrikeBT.shrikeCT.ClassInstrumenter; import com.ibm.wala.shrikeBT.shrikeCT.OfflineInstrumenter; -import com.ibm.wala.shrikeCT.ClassReader; import com.ibm.wala.shrikeCT.ClassWriter; -import com.ibm.wala.shrikeCT.InvalidClassFileException; /** * This is a demo class. @@ -176,30 +154,21 @@ import com.ibm.wala.shrikeCT.InvalidClassFileException; * the current directory. */ public class Instrumenter { - private final static boolean disasm = true; - private final static boolean verify = true; private static OfflineInstrumenter instrumenter; - final private static boolean doEntry = true; - private static boolean doExit = false; - private static boolean doException = false; - - public static void main(String[] args) throws Exception { - String[] realargs = { "bogus", "/home/evan/t/shrikeinstrumentation/old/Main.class", "-o", "/home/evan/t/shrikeinstrumentation/new/Main.class" }; - instrument(realargs); - } - public static void instrument(ArrayList input, String outputFilename) throws Exception { + + public static void instrument(ArrayList input, String outputFilename, InstrumentationSet is) throws Exception { ArrayList realargs = new ArrayList(); realargs.add("ignored"); // bogus first arg (name of program), doesn't matter realargs.addAll(input); realargs.add("-o"); realargs.add(outputFilename); - instrument((String[]) realargs.toArray()); + instrument(realargs.toArray(new String[realargs.size()]), is); } - private static void instrument(String[] args) throws Exception { + private static void instrument(String[] args, InstrumentationSet is) throws Exception { for (int i = 0; i < 1; i++) { instrumenter = new OfflineInstrumenter(); @@ -207,19 +176,11 @@ public class Instrumenter { Writer w = new BufferedWriter(new FileWriter("report", false)); args = instrumenter.parseStandardArgs(args); - if (args.length > 0) { - if (args[0].equals("-doexit")) { - doExit = true; - } else if (args[0].equals("-doexception")) { - doExit = true; - doException = true; - } - } instrumenter.setPassUnmodifiedClasses(true); instrumenter.beginTraversal(); ClassInstrumenter ci; while ((ci = instrumenter.nextClass()) != null) { - doClass(ci, w); + doClass(ci, w, is); } instrumenter.close(); } @@ -231,7 +192,7 @@ public class Instrumenter { static final Instruction getSysErr = Util.makeGet(System.class, "err"); static final Instruction callPrintln = Util.makeInvoke(PrintStream.class, "println", new Class[] { String.class }); - private static void doClass(final ClassInstrumenter ci, Writer w) throws Exception { + private static void doClass(final ClassInstrumenter ci, Writer w, InstrumentationSet is) throws Exception { final String className = ci.getReader().getName(); for (int m = 0; m < ci.getReader().getMethodCount(); m++) { @@ -243,56 +204,20 @@ public class Instrumenter { MethodEditor me = new MethodEditor(d); me.beginPass(); - System.out.println(d.getName()+d.getSignature()); - if ( d.getName().equals("main") && d.getSignature().equals("([Ljava/lang/String;)V" ) ) { - System.out.println("messing with main"); - - int putis[] = { 6, 13, 16 }; + String fullSig = className + "." + d.getName() + d.getSignature(); + if ( is.toBeInstrumented(fullSig) ) { +// System.out.println("messing with main"); Verifier v = new Verifier(d); BitSet all = new BitSet(d.getInstructions().length); - for ( int puti: putis ) - all.set(puti, true); + for ( InstrumentationPoint ip: is.instrumentationPointsForMethod(fullSig) ) + all.set(ip.getInstructionIndex(), true); v.computeTypes(null, all, false); - for ( final int puti: putis ) { - final String type = v.getStackTypes()[puti][0]; - - // v.getStackTypes()[13][0] is the type of the data - // if starts with L: just run object.toString() on it and print it - - me.insertBefore(puti, new Patch() { - - @Override - public void emitTo(Output w) { - System.out.println("type of top of stack at "+puti+"is " + type); - - - - if ( type.startsWith("L") ) { - w.emit(DupInstruction.make(0)); - if ( ! type.equals("Ljava/lang/String;") ) - w.emit(InvokeInstruction.make("()Ljava/lang/String;","Ljava/lang/Object;","toString",Dispatch.VIRTUAL)); - w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); - w.emit(SwapInstruction.make()); - w.emit(InvokeInstruction.make("(Ljava/lang/String;)V","Ljava/io/PrintStream;","println",Dispatch.VIRTUAL)); - } else if ( type.startsWith("I") ) { - w.emit(DupInstruction.make(0)); - w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); - w.emit(SwapInstruction.make()); - w.emit(InvokeInstruction.make("(I)V","Ljava/io/PrintStream;","println",Dispatch.VIRTUAL)); - } // TODO: arrays - -// w.emit(BinaryOpInstruction.make("I",BinaryOpInstruction.Operator.ADD)); -// w.emit(GetInstruction.make("Ljava/io/PrintStream;","Ljava/lang/System;","err",true)); -// w.emit(SwapInstruction.make()); -// w.emit(ConstantInstruction.makeString("is there any body .... out there?")); - // how to get the types?! -// w.emit(InvokeInstruction.make("(Ljava/lang/String;)V","Ljava/io/PrintStream;","println",Dispatch.VIRTUAL)); - } - - }); + for ( InstrumentationPoint ip: is.instrumentationPointsForMethod(fullSig) ) { + final String stackTypes[] = v.getStackTypes()[ip.getInstructionIndex()]; + ip.instrument(me, stackTypes); } } me.applyPatches(); diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/Instrumenter.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/OldInstrumenter.java similarity index 99% copy from Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/Instrumenter.java copy to Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/OldInstrumenter.java index b3bed43..c7ccb4a 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/Instrumenter.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/experimental/autodebug/OldInstrumenter.java @@ -175,7 +175,7 @@ import com.ibm.wala.shrikeCT.InvalidClassFileException; * current directory. Disassembled code is written to the file "report" under * the current directory. */ -public class Instrumenter { +public class OldInstrumenter { private final static boolean disasm = true; private final static boolean verify = true; diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CIThinEditorActionDelegate.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CIThinEditorActionDelegate.java index 4283c9f..6a87bcb 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CIThinEditorActionDelegate.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CIThinEditorActionDelegate.java @@ -44,7 +44,7 @@ public class CIThinEditorActionDelegate extends EditorActionDelegate { public void run(IAction action) { // last arg is depth, -1 for infinite. - run(action, Slicing.CI_THIN_SLICE, "edu.berkeley.cs.bodik.svelte.plugin.sliceMarker", 20); + run(action, Slicing.CI_THIN_SLICE, "edu.berkeley.cs.bodik.svelte.plugin.sliceMarker", 2); } } diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CSThinEditorActionDelegate.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CSThinEditorActionDelegate.java index ca35b39..491bf6d 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CSThinEditorActionDelegate.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CSThinEditorActionDelegate.java @@ -42,7 +42,7 @@ import edu.berkeley.cs.bodik.svelte.Slicing; public class CSThinEditorActionDelegate extends EditorActionDelegate { public void run(IAction action) { - run(action, Slicing.CS_THIN_SLICE, "edu.berkeley.cs.bodik.svelte.plugin.sliceMarker", 7); + run(action, Slicing.CS_THIN_SLICE, "edu.berkeley.cs.bodik.svelte.plugin.sliceMarker", 5); } } diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CachedSlice.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CachedSlice.java new file mode 100644 index 0000000..aa27ce8 --- /dev/null +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/CachedSlice.java @@ -0,0 +1,232 @@ +package edu.berkeley.cs.bodik.svelte.plugin; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; + +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.slicer.Statement; +import com.ibm.wala.util.collections.EmptyIterator; +import com.ibm.wala.util.graph.Graph; + +import edu.berkeley.cs.bodik.svelte.Slice; + +/** + * An in-memory graph representing the slice. We can do operations (like chopping) to modify the slice. + * + * @author evan + * + */ +public class CachedSlice implements Graph { + SliceEnvironment env; + Graph origDepGraph; + Collection seeds; + + Hashtable> predEdges; + Hashtable> succEdges; + + + public CachedSlice ( SliceEnvironment env ) { + this.env = env; + this.origDepGraph = env.getDepGraph(); + this.seeds = new ArrayList(); + this.seeds.addAll(env.getSeed().getStatements()); + + generatePredAndSuccNodes(); + + } + + private void generatePredAndSuccNodes() { + // NEVER fix method seed statements here. They should have already been fixed in the seed. + ArrayList worklist = new ArrayList(); + HashSet serviced = new HashSet(); + + predEdges = new Hashtable>(); + succEdges = new Hashtable>(); + + // BFS time, baby + worklist.addAll(seeds); + + // do a BFS and add all statements + int index = -1; + + int level = 0; + int nextlevelindex = worklist.size(); + int depth = env.getDepth(); + + + while ( (index+1) < worklist.size() ) { + index++; +// if ( depth != -1 && index == nextlevelindex ) { +// nextlevelindex = worklist.size(); +// level ++; +// if ( level > depth ) +// break; +// } + + Statement s = worklist.get(index); + + // service it + if ( serviced.contains(s) ) + continue; + serviced.add(s); + + // look thru the succ nodes, if theres any 'return val' ones or something, build the bridge. + Iterator succNodes = origDepGraph.getSuccNodes(s); + + Statement ss; + while ( succNodes.hasNext() ) { + ss = succNodes.next(); + // add succ nodes to worklist if not already serviced. + if ( ! serviced.contains(ss) ) + worklist.add(ss); + + addEdge(succEdges,s,ss); + addEdge(predEdges,ss,s); + } + } + } + + private void addEdge(Hashtable> edges, + Statement from, Statement to) { + ArrayList nodes = edges.get(from); + if ( nodes == null ) { + nodes = new ArrayList(); + edges.put(from,nodes); + } + nodes.add(to); + + } + + public Collection getSeeds() { + return seeds; + } + + public void chop(Collection leaves) { + Hashtable> newPredEdges = new Hashtable>(); + Hashtable> newSuccEdges = new Hashtable>(); + seeds.clear(); + ArrayList worklist = new ArrayList(); + HashSet serviced = new HashSet(); + worklist.addAll(leaves); + + int index = -1; + while ( (index+1) < worklist.size() ) { + index++; + Statement s = worklist.get(index); + + // service it + if ( serviced.contains(s) ) + continue; + serviced.add(s); + + // look thru the succ nodes, if theres any 'return val' ones or something, build the bridge. + ArrayList parents = predEdges.get(s); + if ( parents == null ) + seeds.add(s); // has no parents, must be a seed. + else { + for ( Statement ss: parents ) { + // add parent nodes to worklist if not already serviced. + if ( ! serviced.contains(ss) ) + worklist.add(ss); + + addEdge(newSuccEdges,ss,s); // succ is from parent to child + addEdge(newPredEdges,s,ss); // pred is from child to parent + } + } + } + + System.out.printf("CHOP pred %d/succ %d -> pred %d/succ %d", predEdges.size(), succEdges.size(), newPredEdges.size(), newSuccEdges.size() ); + predEdges = newPredEdges; + succEdges = newSuccEdges; + } + + public Iterator getSuccNodes(Statement N) { + ArrayList succNodes = succEdges.get(N); + if ( succNodes == null ) + return EmptyIterator.instance(); + return succNodes.iterator(); + } + + public void removeNodeAndEdges(Statement N) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void addNode(Statement n) { + // TODO Auto-generated method stub + + } + + public boolean containsNode(Statement N) { + // TODO Auto-generated method stub + return false; + } + + public int getNumberOfNodes() { + // TODO Auto-generated method stub + return 0; + } + + public Iterator iterator() { + // TODO Auto-generated method stub + return null; + } + + public void removeNode(Statement n) { + // TODO Auto-generated method stub + + } + + public void addEdge(Statement src, Statement dst) { + // TODO Auto-generated method stub + + } + + public int getPredNodeCount(Statement N) { + // TODO Auto-generated method stub + return 0; + } + + public Iterator getPredNodes(Statement N) { + // TODO Auto-generated method stub + return null; + } + + public int getSuccNodeCount(Statement N) { + // TODO Auto-generated method stub + return 0; + } + + public boolean hasEdge(Statement src, Statement dst) { + // TODO Auto-generated method stub + return false; + } + + public void removeAllIncidentEdges(Statement node) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void removeEdge(Statement src, Statement dst) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void removeIncomingEdges(Statement node) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } + + public void removeOutgoingEdges(Statement node) + throws UnsupportedOperationException { + // TODO Auto-generated method stub + + } +} diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/EclipseUtils.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/EclipseUtils.java index 1b79932..cdf6c07 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/EclipseUtils.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/EclipseUtils.java @@ -39,6 +39,7 @@ package edu.berkeley.cs.bodik.svelte.plugin; import java.io.File; import java.util.List; +import java.util.jar.JarFile; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; @@ -76,6 +77,9 @@ import org.eclipse.ui.internal.dialogs.DialogUtil; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.ui.texteditor.AbstractTextEditor; +import com.ibm.wala.classLoader.BinaryDirectoryTreeModule; +import com.ibm.wala.classLoader.JarFileModule; +import com.ibm.wala.classLoader.Module; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.slicer.NormalReturnCallee; import com.ibm.wala.ipa.slicer.NormalStatement; @@ -148,7 +152,83 @@ public class EclipseUtils { } return null; } - + + public static String findClassFileForClass(String classname, IJavaProject proj) { + if ( classname == null || proj == null ) + return null; + + // Strip characters after "$" that is after the last "/" (inner classes), and add ".java" + classname = classname.replaceAll("\\.","/"); // java.lang.String -> java/lang/String + Path classfilenamepath = new Path(classname+".class"); + return classPathToFilename(classfilenamepath, proj); + } + + private static String classPathToFilename(Path path, IJavaProject proj) { + IClasspathEntry[] classpaths = null; + + + // see if it's directly in this project's output location. + String inthisbindir; + try { + inthisbindir = ResourcesPlugin.getWorkspace().getRoot().getLocation().append(proj.getOutputLocation()).append(path).toOSString(); + if ( new File(inthisbindir).exists() ) + return inthisbindir; + } catch (JavaModelException e1) { + e1.printStackTrace(); + } + + // otherwise, try it's libraries and projects (recursively) + try { + classpaths = proj.getResolvedClasspath(true); + for ( IClasspathEntry cpe: classpaths ) { + if ( cpe.getEntryKind() == IClasspathEntry.CPE_PROJECT ) { + IProject project = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(cpe.getPath()); + String result = classPathToFilename ( path, JavaCore.create(project) ); + if ( result != null ) + return result; + } else if ( cpe.getEntryKind() == IClasspathEntry.CPE_LIBRARY ) { + // look for it physically + IPath srcpath = ResourcesPlugin.getWorkspace().getRoot().getLocation().append(cpe.getPath()).append(path); + String srcstr = srcpath.toOSString(); + if ( new File(srcpath.toOSString()).exists() ) + return srcstr; + } + } + } catch (JavaModelException e) { + e.printStackTrace(); + } + return null; + } + +// DELETE THIS SET OF COMMENT CODE NOW!!! +//} else if ( cpe.getEntryKind() == IClasspathEntry.CPE_LIBRARY ) { +// // System.out.println("DEBUG: adding CPE_LIBRARY " + makeAbsolute(cpe.getPath()).toOSString()); +// +// File file = makeAbsolute(cpe.getPath()).toFile(); +// Module m = null; +// if ( file.isDirectory() ) +// m = new BinaryDirectoryTreeModule(file); +// else { +// m = new JarFileModule(new JarFile(file)); +// } +// +// // libraries with absolute paths are assumed to be "system" jars +// if ( pathAbsolute ) { +// // System.out.println("(as system)"); +// addSystemModule(m); +// } else { +// // System.out.println("(as compiled)"); +// addCompiledModule(m); +// } +//} else if ( cpe.getEntryKind() == IClasspathEntry.CPE_PROJECT ) { +// // TODO -- add as source if not using shrike, maybe. +// //addClassDir(makeAbsolute(cpe.getPath()).toOSString()); // could add as source +// +// IProject project = (IProject) ResourcesPlugin.getWorkspace().getRoot().findMember(cpe.getPath()); +// addEclipseClasspaths ( JavaCore.create(project), true, true ); +//} + + public static IFile findIFileForFilename(String filename) { if ( filename!= null ) { IWorkspace workspace= ResourcesPlugin.getWorkspace(); @@ -382,5 +462,12 @@ public class EclipseUtils { } } + } + + + public static String findClassFileForClassStripL(String classnamePrefixedByL, + IJavaProject javaProject) { + assert ( classnamePrefixedByL.startsWith("L") ); + return findClassFileForClass(classnamePrefixedByL.substring(1), javaProject); } } diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/SliceEnvironment.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/SliceEnvironment.java index 3364ee7..9052e8d 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/SliceEnvironment.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/SliceEnvironment.java @@ -6,6 +6,8 @@ import org.eclipse.jdt.core.IJavaProject; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; +import com.ibm.wala.ipa.slicer.Statement; +import com.ibm.wala.util.graph.Graph; import edu.berkeley.cs.bodik.svelte.Slice; import edu.berkeley.cs.bodik.svelte.Slicing; @@ -50,6 +52,10 @@ public class SliceEnvironment { private CISlicer cislicer; // only for CI slicing int depth; + + private Graph csDepGraph; + + private Graph depGraph; public SliceEnvironment(IJavaProject javaProject, int slicingType, IFile seedFile, int seedLine, boolean useShrike, int depth) { @@ -63,14 +69,31 @@ public class SliceEnvironment { this.depth = depth; } - public void setSliceData(CallGraph callGraph, PointerAnalysis pointerAnalysis, Slice seed, Slice slice, CISlicer cislicer) { + public void setSliceData(CallGraph callGraph, PointerAnalysis pointerAnalysis, Slice seed, Slice slice, CISlicer cislicer, Graph csDepGraph) { this.callGraph = callGraph; this.pointerAnalysis = pointerAnalysis; this.seed = seed; this.slice = slice; this.cislicer = cislicer; + this.csDepGraph = csDepGraph; + + revertToOriginalDepGraph(); + } + + public void revertToOriginalDepGraph() { + if ( slicingType == Slicing.CI_THIN_SLICE ) + depGraph = cislicer.getDepGraph(); + else + depGraph = csDepGraph; } + public Graph getDepGraph() { + return depGraph; + } + + public Graph getCSDepGraph() { + return csDepGraph; + } public IProject getProject() { return project; } @@ -118,9 +141,9 @@ public class SliceEnvironment { current = se; // should probably run GC here, since statements, a call graph, etc. will probably be made unreachable } - public static void setCurrentSliceData(CallGraph callGraph, PointerAnalysis pointerAnalysis, Slice seed, Slice slice, CISlicer cislicer) { + public static void setCurrentSliceData(CallGraph callGraph, PointerAnalysis pointerAnalysis, Slice seed, Slice slice, CISlicer cislicer, Graph csDepGraph) { if ( current != null ) - current.setSliceData(callGraph, pointerAnalysis, seed, slice, cislicer); + current.setSliceData(callGraph, pointerAnalysis, seed, slice, cislicer, csDepGraph); } public static boolean hasCurrentCI() { @@ -130,7 +153,11 @@ public class SliceEnvironment { return current != null; } - + public void setDepGraph(Graph newDepGraph) { + depGraph = newDepGraph; +// seed = new Slice(((CachedSlice)newDepGraph).seeds); + // shoiuld really change seed, but we have to change it back remember! + } } diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceInput.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceInput.java index 6d467fc..5b55a89 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceInput.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceInput.java @@ -42,9 +42,9 @@ import java.util.Hashtable; import java.util.Iterator; import com.ibm.wala.ipa.slicer.Statement; +import com.ibm.wala.util.graph.Graph; import edu.berkeley.cs.bodik.svelte.Slice; -import edu.berkeley.cs.bodik.svelte.cislicer.CISlicer; interface BFSliceStatement { Statement getStatement(); @@ -73,7 +73,7 @@ interface BFSliceStatement { } public class BFSliceInput { - private CISlicer slicer; + private Graph graph; private Slice seed; private RootStatement root; @@ -113,7 +113,7 @@ public class BFSliceInput { public ArrayList getChildren() { if ( children == null ) { children = new ArrayList(); - Iterator iter = slicer.getDepGraph().getSuccNodes(s); + Iterator iter = graph.getSuccNodes(s); while ( iter.hasNext() ) { children.add(new RealStatement(iter.next(), this)); } @@ -146,7 +146,7 @@ public class BFSliceInput { } public boolean hasChildren() { - return slicer.getDepGraph().getSuccNodes(s).hasNext(); + return graph.getSuccNodes(s).hasNext(); } } @@ -164,7 +164,7 @@ public class BFSliceInput { @Override public int hashCode() { - return slicer.hashCode() + seed.hashCode(); + return graph.hashCode() + seed.hashCode(); } @Override @@ -212,8 +212,8 @@ public class BFSliceInput { } - public BFSliceInput(CISlicer slicer, Slice seed) { - this.slicer = slicer; + public BFSliceInput(Graph graph, Slice seed) { + this.graph = graph; this.seed = seed; this.root = new RootStatement(); } diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceView.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceView.java index ff4aa80..a3cb67c 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceView.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/bfsliceview/BFSliceView.java @@ -38,6 +38,8 @@ package edu.berkeley.cs.bodik.svelte.plugin.bfsliceview; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.Iterator; import org.eclipse.jface.action.Action; @@ -65,6 +67,9 @@ import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import edu.berkeley.cs.bodik.svelte.CallGraphUtils; +import edu.berkeley.cs.bodik.svelte.experimental.autodebug.InstrumentationSet; +import edu.berkeley.cs.bodik.svelte.experimental.autodebug.Instrumenter; +import edu.berkeley.cs.bodik.svelte.plugin.CachedSlice; import edu.berkeley.cs.bodik.svelte.plugin.EclipseUtils; import edu.berkeley.cs.bodik.svelte.plugin.SliceEnvironment; import edu.berkeley.cs.bodik.svelte.plugin.SveltePlugin; @@ -78,10 +83,8 @@ public class BFSliceView extends ViewPart{ } public void createPartControl(Composite parent) { - if ( ! SliceEnvironment.hasCurrentCI() ) - return; viewer = new TreeViewer(parent); - input = new BFSliceInput(SliceEnvironment.getCurrent().getCISlicer(),SliceEnvironment.getCurrent().getSeed()); // need mutex here?! + input = new BFSliceInput(SliceEnvironment.getCurrent().getDepGraph(),SliceEnvironment.getCurrent().getSeed()); // need mutex here?! bfscp = new BFSliceContentProvider(); viewer.setContentProvider(bfscp); viewer.setLabelProvider(new BFSliceLabelProvider(bfscp)); @@ -123,6 +126,34 @@ public class BFSliceView extends ViewPart{ IStructuredSelection selection = (IStructuredSelection) viewer.getSelection(); EclipseUtils.gotoStatement(((BFSliceStatement)selection.getFirstElement()).getStatement()); + /********************** CHOP *********************/ + // it slices dices, minces, rinses, shreds, cuts, chops, beats, blends, frappes, liquifies, ... + SliceEnvironment.getCurrent().revertToOriginalDepGraph(); + CachedSlice cs = new CachedSlice(SliceEnvironment.getCurrent()); + cs.chop(Collections.singleton(((BFSliceStatement)selection.getFirstElement()).getStatement())); + SliceEnvironment.getCurrent().setDepGraph(cs); + /********************** CHOP *********************/ + +// /**************** INSTRUMENTATION ****************/ +// +// InstrumentationSet is = new InstrumentationSet(); +// is.addInstrumentationPoint(((BFSliceStatement)selection.getFirstElement()).getStatement()); +// for (BFSliceStatement bfss: ((BFSliceStatement)selection.getFirstElement()).getChildren() ) { +// is.addInstrumentationPoint(bfss.getStatement()); +// } +// ArrayList filenames = new ArrayList(); +// for (String classname: is.getFullyQualifiedClassNames()) { +// String classfilename = EclipseUtils.findClassFileForClassStripL(classname, SliceEnvironment.getCurrent().getJavaProject()); +// if ( classfilename != null ) +// filenames.add(classfilename); +// } +// try { +// Instrumenter.instrument(filenames, "/tmp/SveltedInstrumented.jar", is); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// /**************** INSTRUMENTATION ****************/ + Statement s = ((BFSliceStatement)selection.getFirstElement()).getStatement(); System.out.println("****IR****\n****IR****\n"+s.getNode().getIR()); diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/cgview/CallGraphSlice.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/cgview/CallGraphSlice.java index 6bb1129..b958f4d 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/cgview/CallGraphSlice.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/cgview/CallGraphSlice.java @@ -58,6 +58,7 @@ import com.ibm.wala.util.graph.Graph; import edu.berkeley.cs.bodik.svelte.Slice; import edu.berkeley.cs.bodik.svelte.StatementUtils; import edu.berkeley.cs.bodik.svelte.cislicer.CISlicer; +import edu.berkeley.cs.bodik.svelte.plugin.SliceEnvironment; public class CallGraphSlice { private CISlicer slicer; @@ -222,7 +223,8 @@ public class CallGraphSlice { // NEVER fix method seed statements here. They should have already been fixed in the seed. - Graph depGraph = slicer.getDepGraph(); +// Graph depGraph = slicer.getDepGraph(); + Graph depGraph = SliceEnvironment.getCurrent().getDepGraph(); ArrayList worklist = new ArrayList(); HashSet serviced = new HashSet(); diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SGViewActionDelegate.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SGViewActionDelegate.java index d157020..2b8bc16 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SGViewActionDelegate.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SGViewActionDelegate.java @@ -53,6 +53,7 @@ import org.eclipse.ui.IEditorPart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; +import edu.berkeley.cs.bodik.svelte.Slicing; import edu.berkeley.cs.bodik.svelte.plugin.EclipseUtils; import edu.berkeley.cs.bodik.svelte.plugin.SliceEnvironment; import edu.berkeley.cs.bodik.svelte.plugin.sgview.SliceGraphView.IClickHandler; @@ -124,8 +125,8 @@ public class SGViewActionDelegate implements IEditorActionDelegate { public void run(IAction action) { // make the slice - SliceEnvironment env = SliceEnvironment.getCurrent(); - cgs = new SliceGraph(env.getCISlicer(),env.getSeed(),env.getDepth()); + SliceEnvironment env = SliceEnvironment.getCurrent(); + cgs = new SliceGraph(env.getDepGraph(),env.getSeed(),env.getDepth()); reload(); } diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SliceGraph.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SliceGraph.java index d764e5f..0418f75 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SliceGraph.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/sgview/SliceGraph.java @@ -71,16 +71,17 @@ import edu.berkeley.cs.bodik.svelte.StatementUtils; import edu.berkeley.cs.bodik.svelte.cislicer.CISlicer; public class SliceGraph { - private CISlicer slicer; + private Graph depGraph; private Slice seed; + private int depth; + // if you want to work on performance, you could try having using CGNode for this instead (need another hash for string lookups) - private Hashtable allnodes = null; - Hashtable classesToIndices; + private Hashtable allnodes = null; + Hashtable classesToIndices; private Hashtable> clusters = null; private Hashtable clusterIndices; - private Hashtable statementIndices; - private int depth; + private Hashtable statementIndices; class Node { boolean drawPredNodes = false; @@ -138,8 +139,8 @@ public class SliceGraph { } - public SliceGraph(CISlicer slicer, Slice seed, int depth) { - this.slicer = slicer; + public SliceGraph(Graph depGraph, Slice seed, int depth) { + this.depGraph = depGraph; this.seed = seed; this.depth = depth; } @@ -147,8 +148,6 @@ public class SliceGraph { public StringBuffer generateDot() { // NEVER fix method seed statements here. They should have already been fixed in the seed. - Graph depGraph = slicer.getDepGraph(); - clusters = new Hashtable>(); clusterIndices = new Hashtable(); statementIndices = new Hashtable(); @@ -164,6 +163,7 @@ public class SliceGraph { int level = 0; int nextlevelindex = worklist.size(); + int depth = 17; while ( (index+1) < worklist.size() ) { index++; diff --git a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/treesliceview/TreeSliceInput.java b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/treesliceview/TreeSliceInput.java index de0a177..772f6b3 100644 --- a/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/treesliceview/TreeSliceInput.java +++ b/Svelte/src/edu/berkeley/cs/bodik/svelte/plugin/treesliceview/TreeSliceInput.java @@ -44,6 +44,7 @@ import com.ibm.wala.ipa.slicer.Statement; import edu.berkeley.cs.bodik.svelte.Slice; import edu.berkeley.cs.bodik.svelte.cislicer.CISlicer; +import edu.berkeley.cs.bodik.svelte.plugin.SliceEnvironment; public class TreeSliceInput { private CISlicer slicer; @@ -67,7 +68,7 @@ public class TreeSliceInput { } public Iterator getChildren(Statement s) { - return slicer.getDepGraph().getSuccNodes(s); + return SliceEnvironment.getCurrent().getDepGraph().getSuccNodes(s); } // public void setListener(Listener l) { -- 2.11.4.GIT