diff --git a/com.ibm.wala.cast.js.test.data/examples-src/tests/rename-example.js b/com.ibm.wala.cast.js.test.data/examples-src/tests/rename-example.js new file mode 100644 index 000000000..118b078d4 --- /dev/null +++ b/com.ibm.wala.cast.js.test.data/examples-src/tests/rename-example.js @@ -0,0 +1,24 @@ +function f() { + var x = 10; + var y; + y = x; + if(y == 100) { + return true; + } + return false; +} + +function ff() { + var x = 10; + var y; + y = x; + var z; + z = y; + if(z == 100) { + return true; + } + return false; + } + +var b = f(); +var c = ff(); \ No newline at end of file diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java index ff95bad39..49bc40e8d 100755 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java @@ -15,7 +15,6 @@ import java.util.List; import junit.framework.Assert; -import org.eclipse.core.runtime.IProgressMonitor; import org.junit.Test; import com.ibm.wala.cast.ipa.callgraph.CAstCallGraphUtil; @@ -694,7 +693,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { CAstCallGraphUtil.dumpCG(B.getPointerAnalysis(), CG); } - @Test + @Test public void testTutorialExample() throws IllegalArgumentException, IOException, CancelException, WalaException { PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "tutorial-example.js"); CallGraph CG = B.makeCallGraph(B.getOptions()); @@ -702,4 +701,16 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { // verifyGraphAssertions(CG, assertionsForDateProperty); } + Object[][] renamingAssertions = { + { "tests/rename-example.js/f", new Name[]{ new Name(9, 7, "x"), new Name(9, 7, "y") } }, + { "tests/rename-example.js/ff", new Name[]{ new Name(11, 10, "x"), new Name(11, 10, "y"), new Name(11, 10, "z") } } + }; + + @Test + public void testRenaming() throws IOException, WalaException, IllegalArgumentException, CancelException { + PropagationCallGraphBuilder B = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "rename-example.js"); + CallGraph CG = B.makeCallGraph(B.getOptions()); + verifyNameAssertions(CG, renamingAssertions); + } + } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationFinder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationFinder.java index 18218dd5a..a814a2d2d 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationFinder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationFinder.java @@ -97,22 +97,24 @@ public class CorrelationFinder { if(inst instanceof AbstractReflectivePut) puts.addFirst((AbstractReflectivePut)inst); - instrs: for(SSAInstruction inst : Iterator2Iterable.make(ir.iterateNormalInstructions())) + SSAInstruction insts[] = ir.getInstructions(); + instrs: for(int ii = 0; ii < insts.length; ii++) { + SSAInstruction inst = insts[ii]; if(inst instanceof AbstractReflectiveGet) { AbstractReflectiveGet get = (AbstractReflectiveGet)inst; int index = get.getMemberRef(); - + if(ir.getSymbolTable().isConstant(index)) continue; - + if(ir.getSymbolTable().isParameter(index)) continue; - + // try to determine what "index" is called at the source level - String indexName = getSourceLevelName(astMethod, index); + String indexName = getSourceLevelName(ir, ii, index); if(indexName == null) continue instrs; - + // check that "index" is not accessed in an inner function LexicalInformation lexicalInfo = astMethod.lexicalInfo(); if (lexicalInfo.getExposedNames() != null) { @@ -121,11 +123,11 @@ public class CorrelationFinder { continue instrs; } } - + // if "index" is a numeric variable, it is not worth extracting if(IGNORE_NUMERIC_INDICES && mustBeNumeric(ir, du, index)) continue instrs; - + // set of SSA variables into which the value read by 'get' may flow MutableIntSet reached = new BitVectorIntSet(); reached.add(get.getDef()); @@ -137,6 +139,7 @@ public class CorrelationFinder { Integer i = worklist.pop(); done.add(i); for(SSAInstruction inst2 : Iterator2Iterable.make(du.getUses(i))) { + int i2 = instrIndices.getMappedIndex(inst2); if(inst2 instanceof SSAPhiInstruction) { int def = inst2.getDef(); if(reached.add(def) && !done.contains(def)) @@ -149,7 +152,7 @@ public class CorrelationFinder { if(TRACK_ESCAPES) { for(int j=0;j= sourceNamesForValues.length) + if(sourceNamesForValues == null) return null; - for(String candidateName : sourceNamesForValues[v]) { + for(String candidateName : sourceNamesForValues) { if(indexName != null) { indexName = null; break; @@ -186,10 +190,10 @@ public class CorrelationFinder { return indexName; } - private static Set getSourceLevelNames(AstMethod astMethod, IntSet vs) { + private static Set getSourceLevelNames(IR ir, int index, IntSet vs) { Set res = new HashSet(); for(IntIterator iter=vs.intIterator();iter.hasNext();) { - String name = getSourceLevelName(astMethod, iter.next()); + String name = getSourceLevelName(ir, index, iter.next()); if(name != null) res.add(name); } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/SSAConversion.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/SSAConversion.java index cd31b1f5a..dda9630ef 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/SSAConversion.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/ssa/SSAConversion.java @@ -10,6 +10,7 @@ *****************************************************************************/ package com.ibm.wala.cast.ir.ssa; +import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @@ -29,6 +30,7 @@ import com.ibm.wala.ssa.SSAPhiInstruction; import com.ibm.wala.ssa.SymbolTable; import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.HashSetFactory; +import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.intset.BitVector; import com.ibm.wala.util.intset.BitVectorIntSet; import com.ibm.wala.util.intset.IntSet; @@ -63,6 +65,8 @@ public class SSAConversion extends AbstractSSAConversion { private SSA2LocalMap computedLocalMap; + private Map assignments = HashMapFactory.make(); + // // Copy propagation history // @@ -81,6 +85,11 @@ public class SSAConversion extends AbstractSSAConversion { this.instructionIndex = instructionIndex; } + @Override + public String toString() { + return "[use " + useNumber + " of " + instructionIndex + "]"; + } + @Override public int hashCode() { return useNumber * instructionIndex; @@ -106,6 +115,11 @@ public class SSAConversion extends AbstractSSAConversion { this.useNumber = useNumber; } + @Override + public String toString() { + return "[use " + useNumber + " of " + phiNumber + " of block " + BBnumber + "]"; + } + @Override public int hashCode() { return phiNumber * BBnumber * useNumber; @@ -121,12 +135,24 @@ public class SSAConversion extends AbstractSSAConversion { private class CopyPropagationRecord { final int rhs; + final int lhs; + final int instructionIndex; final Set renamedUses = HashSetFactory.make(2); private final Set childRecords = HashSetFactory.make(1); + @Override + public String toString() { + StringBuffer sb = new StringBuffer(""); + return sb.toString(); + } + @Override public int hashCode() { return instructionIndex; @@ -141,6 +167,7 @@ public class SSAConversion extends AbstractSSAConversion { if (DEBUG_UNDO) System.err.println(("new copy record for instruction #" + instructionIndex + ", rhs value is " + rhs)); this.rhs = rhs; + this.lhs = lhs; this.instructionIndex = instructionIndex; } @@ -242,10 +269,17 @@ public class SSAConversion extends AbstractSSAConversion { public String[] getLocalNames(int pc, int vn) { int v = skip(vn) || vn >= valueMap.length ? vn : valueMap[vn]; String[][] namesData = debugInfo.getSourceNamesForValues(); - if (namesData == null || namesData.length <= v) - return new String[0]; - else - return namesData[v]; + String[] vNames = namesData[v]; + Set x = HashSetFactory.make(); + x.addAll(Arrays.asList(vNames)); + + while (assignments.containsKey(v)) { + v = assignments.get(v); + vNames = namesData[v]; + x.addAll(Arrays.asList(vNames)); + } + + return x.toArray(new String[x.size()]); } private void undoCopyPropagation(int instructionIndex, int useNumber) { @@ -269,6 +303,17 @@ public class SSAConversion extends AbstractSSAConversion { private Map getCopyHistory() { return copyPropagationMap; } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer( super.toString() ); + + for(Map.Entry x : copyPropagationMap.entrySet()) { + sb.append(x.getKey().toString() + " --> " + x.getValue().toString() + "\n"); + } + + return sb.toString(); + } } private CopyPropagationRecord topR(int v) { @@ -382,8 +427,8 @@ public class SSAConversion extends AbstractSSAConversion { int lhs = getDef(inst, 0); int rhs = getUse(inst, 0); - copyNames(rhs, lhs); - + assignments.put(rhs, lhs); + CopyPropagationRecord rec = new CopyPropagationRecord(index, lhs, newRhs); R[lhs].push(rec); if (topR(rhs) != null) { @@ -510,22 +555,6 @@ public class SSAConversion extends AbstractSSAConversion { return v; } - private void copyNames(int to, int from) { - String[][] namesData = debugInfo.getSourceNamesForValues(); - if (namesData != null && namesData.length > from && namesData[from] != null) { - if (namesData[to] == null) { - namesData[to] = namesData[from]; - } else { - Set newNames = HashSetFactory.make(); - for(String fromName : namesData[from]) - newNames.add(fromName); - for(String toName : namesData[to]) - newNames.add(toName); - namesData[to] = newNames.toArray(new String[newNames.size()]); - } - } - } - @Override protected void initializeVariables() { for (int V = 1; V <= getMaxValueNumber(); V++) {