/****************************************************************************** * Copyright (c) 2009 - 2015 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ package com.ibm.wala.memsat.frontEnd.slicer; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import com.ibm.wala.cast.java.ipa.modref.AstJavaModRef; import com.ibm.wala.cast.java.ipa.slicer.AstJavaSlicer; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.impl.PartialCallGraph; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.slicer.PDG; import com.ibm.wala.ipa.slicer.SDG; import com.ibm.wala.ipa.slicer.Statement; import com.ibm.wala.memsat.frontEnd.FieldSSATable; import com.ibm.wala.memsat.frontEnd.fieldssa.FieldNameSSAConversion; import com.ibm.wala.memsat.frontEnd.fieldssa.IPFieldAccessesResult; import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.ISSABasicBlock; import com.ibm.wala.ssa.SSACFG; import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.util.Predicate; import com.ibm.wala.util.collections.ComposedIterator; import com.ibm.wala.util.collections.CompoundIterator; import com.ibm.wala.util.collections.FilterIterator; import com.ibm.wala.util.collections.MapIterator; import com.ibm.wala.util.collections.ObjectArrayMapping; import com.ibm.wala.util.functions.Function; import com.ibm.wala.util.graph.Acyclic; import com.ibm.wala.util.graph.Graph; import kodkod.util.ints.IndexedEntry; public class PartialSlice extends AstJavaSlicer { public static Collection<Statement> compute(CallGraph CG, PointerAnalysis<InstanceKey> pa, Set<CGNode> partialRoots, Collection<Statement> ss) throws com.ibm.wala.util.CancelException { CallGraph pcg = PartialCallGraph.make(CG, partialRoots); SDG sdg = new SDG(pcg, pa, new AstJavaModRef(), DataDependenceOptions.FULL, ControlDependenceOptions.FULL); return computeBackwardSlice(sdg, ss); } public static FieldSSATable sliceFieldSSA(final CGNode node, PointerAnalysis<InstanceKey> pa, IClassHierarchy cha, IPFieldAccessesResult ipaFieldAccesses, final SDG sdg, final Collection<Statement> slice) { IR ir = node.getIR(); FieldNameSSAConversion c = new FieldNameSSAConversion( ir, new FieldNameSSAConversion.IPFieldAccesses( true, node, pa, cha, ipaFieldAccesses.getFieldAccesses(node))) { protected SSAInstruction[] getInstructions(IR ir) { SSAInstruction[] allInstrs = ir.getInstructions(); Map<SSAInstruction,Integer> indicesMap = PDG.computeInstructionIndices(ir); SSAInstruction[] x = new SSAInstruction[ allInstrs.length ]; for(int i = 0; i < allInstrs.length; i++) { if (allInstrs[i] == null) { continue; } if (slice.contains( PDG.ssaInstruction2Statement(node, allInstrs[i], indicesMap, ir))) { x[i] = allInstrs[i]; } } return x; } }; return c.convert(); } private static <T> void order(Graph<T> G, T node, List<T> order) { if (! order.contains(node)) { for(Iterator<T> ps = G.getPredNodes(node); ps.hasNext(); ) { T p = ps.next(); order(G, p, order); } order.add(node); } } public static class InstructionEntry implements IndexedEntry<SSAInstruction> { private final SSAInstruction inst; private final int index; private final SSACFG.BasicBlock bb; private InstructionEntry(SSACFG.BasicBlock bb, int index, SSAInstruction inst) { this.inst = inst; this.bb = bb; this.index = index; } public SSAInstruction value() { return inst; } public int index() { return index; } public SSACFG.BasicBlock bb() { return bb; } public int hashCode() { return index() * value().hashCode(); } public boolean equals(Object o) { return (o instanceof InstructionEntry) && ((InstructionEntry)o).index() == index() && ((InstructionEntry)o).value().equals(value()); } } public static Iterator<InstructionEntry> relevantInstructions(final CGNode node, final FieldSSATable fieldSSA, SDG sdg, final Collection<Statement> slice) { final IR ir = node.getIR(); final Map<SSAInstruction, Integer> indicesMap = PDG.computeInstructionIndices(ir); final ObjectArrayMapping<SSAInstruction> instructionIndices = new ObjectArrayMapping<SSAInstruction>(ir.getInstructions()); SSACFG cfg = ir.getControlFlowGraph(); List<ISSABasicBlock> order = new ArrayList<ISSABasicBlock>(cfg.getNumberOfNodes()); assert Acyclic.isAcyclic(cfg, cfg.entry()); order(cfg, ir.getExitBlock(), order); return new ComposedIterator(order.iterator()) { public Iterator makeInner(Object outer) { final SSACFG.BasicBlock block = (SSACFG.BasicBlock)outer; return new CompoundIterator( new MapIterator( fieldSSA.getPhiNodes(block), new Function<SSAInstruction,InstructionEntry>() { public InstructionEntry apply(SSAInstruction x) { return new InstructionEntry(block, -1, x); } } ), new MapIterator( new FilterIterator( block.iterator(), new Predicate() { private boolean sliceContainsInstruction(SSAInstruction s) { return slice.contains( PDG.ssaInstruction2Statement(node, s, indicesMap, ir)); } public boolean test(Object o) { return sliceContainsInstruction((SSAInstruction)o); } } ), new Function<SSAInstruction,InstructionEntry>() { public InstructionEntry apply(SSAInstruction x) { int index = -1; if (instructionIndices.hasMappedIndex(x)) { index = instructionIndices.getMappedIndex(x); } return new InstructionEntry(block, index, (SSAInstruction)x); } } ) ); } }; } }