From 6ff9063a1869d7e37dedc8203e5234959d4f3481 Mon Sep 17 00:00:00 2001 From: sjfink Date: Fri, 9 Dec 2011 19:03:21 +0000 Subject: [PATCH 001/238] suppress compiler warnings from raw types git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4288 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../impl/DefaultFixedPointSystem.java | 58 ++++++++++--------- .../src/com/ibm/wala/viz/DotUtil.java | 6 +- 2 files changed, 33 insertions(+), 31 deletions(-) diff --git a/com.ibm.wala.util/src/com/ibm/wala/fixedpoint/impl/DefaultFixedPointSystem.java b/com.ibm.wala.util/src/com/ibm/wala/fixedpoint/impl/DefaultFixedPointSystem.java index 9926ea0a2..fe61a7e9b 100644 --- a/com.ibm.wala.util/src/com/ibm/wala/fixedpoint/impl/DefaultFixedPointSystem.java +++ b/com.ibm.wala.util/src/com/ibm/wala/fixedpoint/impl/DefaultFixedPointSystem.java @@ -87,11 +87,11 @@ public class DefaultFixedPointSystem> implements IFixedPo return graph.toString(); } - public void removeStatement(IFixedPointStatement s) { + public void removeStatement(IFixedPointStatement s) { graph.removeNodeAndEdges(s); } - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) public Iterator getStatements() { return new FilterIterator(graph.iterator(), new Filter() { public boolean accepts(Object x) { @@ -100,6 +100,7 @@ public class DefaultFixedPointSystem> implements IFixedPo }); } + @SuppressWarnings("rawtypes") public void addStatement(IFixedPointStatement statement) throws IllegalArgumentException, UnimplementedError { if (statement == null) { throw new IllegalArgumentException("statement == null"); @@ -115,12 +116,12 @@ public class DefaultFixedPointSystem> implements IFixedPo } } - public void addStatement(GeneralStatement s) { + public void addStatement(GeneralStatement s) { if (s == null) { throw new IllegalArgumentException("s is null"); } - IVariable[] rhs = s.getRHS(); - IVariable lhs = s.getLHS(); + IVariable[] rhs = s.getRHS(); + IVariable lhs = s.getLHS(); equations.add(s); graph.addNode(s); @@ -130,8 +131,8 @@ public class DefaultFixedPointSystem> implements IFixedPo graph.addEdge(s, lhs); } for (int i = 0; i < rhs.length; i++) { - IVariable v = rhs[i]; - IVariable variable = v; + IVariable v = rhs[i]; + IVariable variable = v; if (variable != null) { variables.add(variable); graph.addNode(variable); @@ -144,12 +145,12 @@ public class DefaultFixedPointSystem> implements IFixedPo } } - public void addStatement(UnaryStatement s) { + public void addStatement(UnaryStatement s) { if (s == null) { throw new IllegalArgumentException("s is null"); } - IVariable lhs = s.getLHS(); - IVariable rhs = s.getRightHandSide(); + IVariable lhs = s.getLHS(); + IVariable rhs = s.getRightHandSide(); graph.addNode(s); if (lhs != null) { @@ -166,11 +167,11 @@ public class DefaultFixedPointSystem> implements IFixedPo } } - public void addStatement(NullaryStatement s) { + public void addStatement(NullaryStatement s) { if (s == null) { throw new IllegalArgumentException("s is null"); } - IVariable lhs = s.getLHS(); + IVariable lhs = s.getLHS(); graph.addNode(s); if (lhs != null) { @@ -184,7 +185,7 @@ public class DefaultFixedPointSystem> implements IFixedPo } } - public void addVariable(IVariable v) { + public void addVariable(T v) { variables.add(v); graph.addNode(v); if (DEBUG) { @@ -192,8 +193,8 @@ public class DefaultFixedPointSystem> implements IFixedPo } } - public AbstractStatement getStep(int number) { - return (AbstractStatement) graph.getNode(number); + public AbstractStatement getStep(int number) { + return (AbstractStatement) graph.getNode(number); } public void reorder() { @@ -206,7 +207,8 @@ public class DefaultFixedPointSystem> implements IFixedPo while (order.hasNext()) { Object elt = order.next(); if (elt instanceof IVariable) { - IVariable v = (IVariable) elt; + @SuppressWarnings("unchecked") + T v = (T) elt; v.setOrderNumber(number++); } } @@ -224,30 +226,30 @@ public class DefaultFixedPointSystem> implements IFixedPo } } - public Iterator getStatementsThatUse(IVariable v) { + public Iterator getStatementsThatUse(T v) { return (graph.containsNode(v) ? graph.getSuccNodes(v) : EmptyIterator.instance()); } - public Iterator getStatementsThatDef(IVariable v) { + public Iterator getStatementsThatDef(T v) { return (graph.containsNode(v) ? graph.getPredNodes(v) : EmptyIterator.instance()); } - public IVariable getVariable(int n) { - return (IVariable) graph.getNode(n); + @SuppressWarnings("unchecked") + public T getVariable(int n) { + return (T) graph.getNode(n); } - public int getNumberOfStatementsThatUse(IVariable v) { + public int getNumberOfStatementsThatUse(T v) { return (graph.containsNode(v) ? graph.getSuccNodeCount(v) : 0); } - public int getNumberOfStatementsThatDef(IVariable v) { + public int getNumberOfStatementsThatDef(T v) { return (graph.containsNode(v) ? graph.getPredNodeCount(v) : 0); } - @SuppressWarnings("unchecked") - public Iterator getVariables() { - return new FilterIterator(graph.iterator(), new Filter() { - public boolean accepts(Object x) { + public Iterator getVariables() { + return new FilterIterator(graph.iterator(), new Filter() { + public boolean accepts(T x) { return x instanceof IVariable; } }); @@ -266,11 +268,11 @@ public class DefaultFixedPointSystem> implements IFixedPo return graph.getPredNodeCount(n); } - public boolean containsStatement(IFixedPointStatement s) { + public boolean containsStatement(IFixedPointStatement s) { return equations.contains(s); } - public boolean containsVariable(IVariable v) { + public boolean containsVariable(T v) { return variables.contains(v); } diff --git a/com.ibm.wala.util/src/com/ibm/wala/viz/DotUtil.java b/com.ibm.wala.util/src/com/ibm/wala/viz/DotUtil.java index 9cbc38574..96d9ab92a 100644 --- a/com.ibm.wala.util/src/com/ibm/wala/viz/DotUtil.java +++ b/com.ibm.wala.util/src/com/ibm/wala/viz/DotUtil.java @@ -205,7 +205,7 @@ public class DotUtil { result.append(fontnameStr); result.append("]; \n"); - Collection dotNodes = computeDotNodes(g); + Collection dotNodes = computeDotNodes(g); outputNodes(labels, result, dotNodes); @@ -225,8 +225,8 @@ public class DotUtil { return result; } - private static void outputNodes(NodeDecorator labels, StringBuffer result, Collection dotNodes) throws WalaException { - for (Iterator it = dotNodes.iterator(); it.hasNext();) { + private static void outputNodes(NodeDecorator labels, StringBuffer result, Collection dotNodes) throws WalaException { + for (Iterator it = dotNodes.iterator(); it.hasNext();) { outputNode(labels, result, it.next()); } } From bd315e7718a1c7f05b5ccd3e549a3ac2e550016a Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Wed, 28 Dec 2011 17:01:56 +0000 Subject: [PATCH 002/238] add a .gitignore file git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4289 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .gitignore | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f3b736a53 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +*/bin/ +com.ibm.wala.cast.js.rhino/lib/ +com.ibm.wala.cast.js/lib/ +com.ibm.wala.cast.java.polyglot/lib/ +com.ibm.wala.cast.java.test.data/src/JLex/ +.metadata/ +*~ +com.ibm.wala.cast.js.test/examples-src/ajaxslt/ +com.ibm.wala.core.testdata/@dot/ +com.ibm.wala.core.testdata/lib/ +com.ibm.wala.core/dat/wala.properties From 59e46916ce1c0ec71760f183978cd57902326f02 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Wed, 28 Dec 2011 17:03:27 +0000 Subject: [PATCH 003/238] Generalize certain IR data structures to be less Java-specific. Generalize annotations code to allow for reading annotation parameters. Various other fixes git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4290 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/java/test/JavaIRTests.java | 2 +- .../translator/JavaCAst2IRTranslator.java | 39 +- .../ibm/wala/cast/js/html/FileMapping.java | 1 + .../wala/cast/js/loader/JavaScriptLoader.java | 14 +- .../com/ibm/wala/cast/js/vis/JsPaPanel.java | 180 +++--- .../com/ibm/wala/cast/js/vis/JsViewer.java | 40 +- .../ipa/callgraph/CrossLanguageCallGraph.java | 4 +- .../wala/core/tests/slicer/SlicerTest.java | 2 + .../ReflectiveInvocationInterpreter.java | 4 +- .../stackMachine/AbstractIntStackMachine.java | 76 ++- .../wala/analysis/typeInference/ConeType.java | 2 +- .../typeInference/TypeAbstraction.java | 2 +- .../analysis/typeInference/TypeInference.java | 20 +- .../src/com/ibm/wala/cfg/AbstractCFG.java | 1 + .../src/com/ibm/wala/cfg/ShrikeCFG.java | 24 +- .../com/ibm/wala/classLoader/ArrayClass.java | 5 +- .../BinaryDirectoryTreeModule.java | 19 +- .../ibm/wala/classLoader/BytecodeClass.java | 6 +- .../ibm/wala/classLoader/ClassFileModule.java | 13 +- .../ibm/wala/classLoader/ClassLoaderImpl.java | 1 - .../wala/classLoader/DirectoryTreeModule.java | 8 +- .../src/com/ibm/wala/classLoader/IClass.java | 2 +- .../src/com/ibm/wala/classLoader/IMethod.java | 10 - .../ibm/wala/classLoader/JavaLanguage.java | 17 +- .../ibm/wala/classLoader/ShrikeIRFactory.java | 2 +- .../ibm/wala/ipa/callgraph/AnalysisScope.java | 4 +- .../callgraph/impl/AbstractRootMethod.java | 4 +- .../com/ibm/wala/ipa/cha/ClassHierarchy.java | 19 +- .../src/com/ibm/wala/ssa/IR.java | 2 +- .../src/com/ibm/wala/ssa/SSABuilder.java | 77 ++- .../ibm/wala/ssa/SSACheckCastInstruction.java | 12 +- .../ibm/wala/ssa/SSAInstructionFactory.java | 8 +- .../src/com/ibm/wala/types/TypeName.java | 6 + .../src/com/ibm/wala/types/TypeReference.java | 6 +- .../wala/types/annotations/Annotation.java | 37 +- .../wala/util/config/AnalysisScopeReader.java | 9 +- .../com/ibm/wala/util/io/FileProvider.java | 18 + .../src/com/ibm/wala/viz/viewer/CgPanel.java | 250 ++++---- .../src/com/ibm/wala/viz/viewer/ChaPanel.java | 208 +++---- .../wala/viz/viewer/DualTreeCellRenderer.java | 140 ++--- .../wala/viz/viewer/IrAndSourceViewer.java | 158 ++--- .../src/com/ibm/wala/viz/viewer/IrViewer.java | 312 +++++----- .../src/com/ibm/wala/viz/viewer/PaPanel.java | 576 +++++++++--------- .../com/ibm/wala/viz/viewer/SourceViewer.java | 178 +++--- .../com/ibm/wala/viz/viewer/WalaViewer.java | 122 ++-- .../src/com/ibm/wala/util/PlatformUtil.java | 7 + 46 files changed, 1378 insertions(+), 1269 deletions(-) diff --git a/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java index 97ee107d4..1d56c5033 100644 --- a/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java +++ b/com.ibm.wala.cast.java.test/src/com/ibm/wala/cast/java/test/JavaIRTests.java @@ -138,7 +138,7 @@ public abstract class JavaIRTests extends IRTests { final IClass iClass = cg.getClassHierarchy().lookupClass(type); Assert.assertNotNull("Could not find class " + typeStr, iClass); - final Collection interfaces = iClass.getDirectInterfaces(); + final Collection interfaces = iClass.getDirectInterfaces(); Assert.assertEquals("Expected one single interface.", interfaces.size(), 1); diff --git a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java index a372c47dc..223e3e96c 100644 --- a/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java +++ b/com.ibm.wala.cast.java/src/com/ibm/wala/cast/java/translator/JavaCAst2IRTranslator.java @@ -316,14 +316,13 @@ public class JavaCAst2IRTranslator extends AstTranslator { } protected boolean visitCast(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext) c; + WalkContext context = (WalkContext)c; int result = context.currentScope().allocateTempValue(); setValue(n, result); return false; } - protected void leaveCast(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext) c; + WalkContext context = (WalkContext)c; int result = getValue(n); CAstType toType = (CAstType) n.getChild(0).getValue(); TypeReference toRef = makeType(toType); @@ -332,29 +331,42 @@ public class JavaCAst2IRTranslator extends AstTranslator { TypeReference fromRef = makeType(fromType); if (toRef.isPrimitiveType()) { - context.cfg().addInstruction(insts.ConversionInstruction(result, getValue(n.getChild(1)), fromRef, toRef, false)); - + context.cfg().addInstruction( + insts.ConversionInstruction( + result, + getValue(n.getChild(1)), + fromRef, + toRef, + false)); + } else { - context.cfg().addInstruction(insts.CheckCastInstruction(result, getValue(n.getChild(1)), toRef)); + context.cfg().addInstruction( + insts.CheckCastInstruction( + result, + getValue(n.getChild(1)), + toRef, + true)); - processExceptions(n, context); +processExceptions(n, context); } } - protected boolean visitInstanceOf(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext) c; + WalkContext context = (WalkContext)c; int result = context.currentScope().allocateTempValue(); setValue(n, result); return false; } - protected void leaveInstanceOf(CAstNode n, Context c, CAstVisitor visitor) { - WalkContext context = (WalkContext) c; + WalkContext context = (WalkContext)c; int result = getValue(n); CAstType type = (CAstType) n.getChild(0).getValue(); - TypeReference ref = makeType(type); - context.cfg().addInstruction(insts.InstanceofInstruction(result, getValue(n.getChild(1)), ref)); + TypeReference ref = makeType( type ); + context.cfg().addInstruction( + insts.InstanceofInstruction( + result, + getValue(n.getChild(1)), + ref)); } protected boolean doVisit(CAstNode n, Context context, CAstVisitor visitor) { @@ -369,7 +381,6 @@ public class JavaCAst2IRTranslator extends AstTranslator { visitor.visit(n.getChild(0), wc, visitor); wc.cfg().addInstruction(insts.MonitorInstruction(getValue(n.getChild(0)), false)); processExceptions(n, wc); - return true; } else { return super.doVisit(n, wc, visitor); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/FileMapping.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/FileMapping.java index e7308c4da..4f983482a 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/FileMapping.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/FileMapping.java @@ -39,4 +39,5 @@ public class FileMapping{ ps.println(line + ": " + fnAndln); } } + } \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java index 6c78cc86d..ceaaae0d0 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java @@ -347,20 +347,22 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader { }; } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types) { + public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI) { throw new UnsupportedOperationException(); } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues) { + public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues, boolean isPEI) { throw new UnsupportedOperationException(); } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue) { - return CheckCastInstruction(result, val, new int[] { typeValue }); + public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue, boolean isPEI) { + assert isPEI; + return CheckCastInstruction(result, val, new int[]{ typeValue }, true); } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type) { - return CheckCastInstruction(result, val, new TypeReference[] { type }); + public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type, boolean isPEI) { + assert isPEI; + return CheckCastInstruction(result, val, new TypeReference[]{ type }, true); } public SSAComparisonInstruction ComparisonInstruction(Operator operator, int result, int val1, int val2) { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsPaPanel.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsPaPanel.java index 06d4150b5..78d6c4b9e 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsPaPanel.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsPaPanel.java @@ -1,90 +1,90 @@ -package com.ibm.wala.cast.js.vis; - -import java.util.ArrayList; -import java.util.List; - -import com.ibm.wala.analysis.pointers.HeapGraph; -import com.ibm.wala.cast.ipa.callgraph.AstGlobalPointerKey; -import com.ibm.wala.cast.ipa.callgraph.ObjectPropertyCatalogKey; -import com.ibm.wala.ipa.callgraph.CGNode; -import com.ibm.wala.ipa.callgraph.CallGraph; -import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; -import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; -import com.ibm.wala.ipa.callgraph.propagation.PointerKey; -import com.ibm.wala.util.intset.MutableMapping; -import com.ibm.wala.util.intset.OrdinalSetMapping; -import com.ibm.wala.viz.viewer.PaPanel; - -/** - * Augments the PaPanel with: 1) global pointer keys at the root level. 2) property catalog key for instance keys. - * @author yinnonh - * - */ -public class JsPaPanel extends PaPanel { - - private static final long serialVersionUID = 1L; - - private MutableMapping> instanceKeyIdToObjectPropertyCatalogKey = MutableMapping.> make(); - private List globalsPointerKeys = new ArrayList(); - - public JsPaPanel(CallGraph cg, PointerAnalysis pa) { - super(cg, pa); - initDataStructures(pa); - } - - private void initDataStructures(PointerAnalysis pa) { - HeapGraph heapGraph = pa.getHeapGraph(); - OrdinalSetMapping instanceKeyMapping = pa.getInstanceKeyMapping(); - for (Object n : heapGraph){ - if (heapGraph.getPredNodeCount(n) == 0){ - if (n instanceof PointerKey){ - if (n instanceof ObjectPropertyCatalogKey){ - ObjectPropertyCatalogKey opck = (ObjectPropertyCatalogKey) n; - InstanceKey instanceKey = opck.getObject(); - int instanceKeyId = instanceKeyMapping.getMappedIndex(instanceKey); - mapUsingMutableMapping(instanceKeyIdToObjectPropertyCatalogKey, instanceKeyId, opck); - } else if (n instanceof AstGlobalPointerKey){ - globalsPointerKeys.add((AstGlobalPointerKey) n); - } - } else { - System.err.println("Non Pointer key root: " + n); - } - } - } - } - - protected List getPointerKeysUnderInstanceKey(InstanceKey ik) { - List ret = new ArrayList(); - ret.addAll(super.getPointerKeysUnderInstanceKey(ik)); - int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik); - ret.addAll(nonNullList(instanceKeyIdToObjectPropertyCatalogKey.getMappedObject(ikIndex))); - return ret; - } - - private String cgNodesRoot = "CGNodes"; - private String globalsRoot = "Globals"; - - @Override - protected List getRootNodes() { - List ret = new ArrayList(2); - ret.add(cgNodesRoot); - ret.add(globalsRoot); - return ret; - } - - @Override - protected List getChildrenFor(Object node) { - List ret = new ArrayList(); - if (node == cgNodesRoot){ - for (int nodeId = 0 ; nodeId < cg.getNumberOfNodes(); nodeId++){ - CGNode cgNode = cg.getNode(nodeId); - ret.add(cgNode); - } - } else if (node == globalsRoot){ - ret.addAll(globalsPointerKeys); - } else { - ret.addAll(super.getChildrenFor(node)); - } - return ret; - } -} +package com.ibm.wala.cast.js.vis; + +import java.util.ArrayList; +import java.util.List; + +import com.ibm.wala.analysis.pointers.HeapGraph; +import com.ibm.wala.cast.ipa.callgraph.AstGlobalPointerKey; +import com.ibm.wala.cast.ipa.callgraph.ObjectPropertyCatalogKey; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; +import com.ibm.wala.ipa.callgraph.propagation.PointerKey; +import com.ibm.wala.util.intset.MutableMapping; +import com.ibm.wala.util.intset.OrdinalSetMapping; +import com.ibm.wala.viz.viewer.PaPanel; + +/** + * Augments the PaPanel with: 1) global pointer keys at the root level. 2) property catalog key for instance keys. + * @author yinnonh + * + */ +public class JsPaPanel extends PaPanel { + + private static final long serialVersionUID = 1L; + + private MutableMapping> instanceKeyIdToObjectPropertyCatalogKey = MutableMapping.> make(); + private List globalsPointerKeys = new ArrayList(); + + public JsPaPanel(CallGraph cg, PointerAnalysis pa) { + super(cg, pa); + initDataStructures(pa); + } + + private void initDataStructures(PointerAnalysis pa) { + HeapGraph heapGraph = pa.getHeapGraph(); + OrdinalSetMapping instanceKeyMapping = pa.getInstanceKeyMapping(); + for (Object n : heapGraph){ + if (heapGraph.getPredNodeCount(n) == 0){ + if (n instanceof PointerKey){ + if (n instanceof ObjectPropertyCatalogKey){ + ObjectPropertyCatalogKey opck = (ObjectPropertyCatalogKey) n; + InstanceKey instanceKey = opck.getObject(); + int instanceKeyId = instanceKeyMapping.getMappedIndex(instanceKey); + mapUsingMutableMapping(instanceKeyIdToObjectPropertyCatalogKey, instanceKeyId, opck); + } else if (n instanceof AstGlobalPointerKey){ + globalsPointerKeys.add((AstGlobalPointerKey) n); + } + } else { + System.err.println("Non Pointer key root: " + n); + } + } + } + } + + protected List getPointerKeysUnderInstanceKey(InstanceKey ik) { + List ret = new ArrayList(); + ret.addAll(super.getPointerKeysUnderInstanceKey(ik)); + int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik); + ret.addAll(nonNullList(instanceKeyIdToObjectPropertyCatalogKey.getMappedObject(ikIndex))); + return ret; + } + + private String cgNodesRoot = "CGNodes"; + private String globalsRoot = "Globals"; + + @Override + protected List getRootNodes() { + List ret = new ArrayList(2); + ret.add(cgNodesRoot); + ret.add(globalsRoot); + return ret; + } + + @Override + protected List getChildrenFor(Object node) { + List ret = new ArrayList(); + if (node == cgNodesRoot){ + for (int nodeId = 0 ; nodeId < cg.getNumberOfNodes(); nodeId++){ + CGNode cgNode = cg.getNode(nodeId); + ret.add(cgNode); + } + } else if (node == globalsRoot){ + ret.addAll(globalsPointerKeys); + } else { + ret.addAll(super.getChildrenFor(node)); + } + return ret; + } +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsViewer.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsViewer.java index 33df35a39..b21ab6d16 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsViewer.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/vis/JsViewer.java @@ -1,20 +1,20 @@ -package com.ibm.wala.cast.js.vis; - -import com.ibm.wala.ipa.callgraph.CallGraph; -import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; -import com.ibm.wala.viz.viewer.PaPanel; -import com.ibm.wala.viz.viewer.WalaViewer; - -public class JsViewer extends WalaViewer{ - - private static final long serialVersionUID = 1L; - - public JsViewer(CallGraph cg, PointerAnalysis pa) { - super(cg, pa); - } - - @Override - protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) { - return new JsPaPanel(cg, pa); - } -} +package com.ibm.wala.cast.js.vis; + +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; +import com.ibm.wala.viz.viewer.PaPanel; +import com.ibm.wala.viz.viewer.WalaViewer; + +public class JsViewer extends WalaViewer{ + + private static final long serialVersionUID = 1L; + + public JsViewer(CallGraph cg, PointerAnalysis pa) { + super(cg, pa); + } + + @Override + protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) { + return new JsPaPanel(cg, pa); + } +} diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CrossLanguageCallGraph.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CrossLanguageCallGraph.java index 6a51ec79f..a02ac2404 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CrossLanguageCallGraph.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/CrossLanguageCallGraph.java @@ -121,10 +121,10 @@ public class CrossLanguageCallGraph extends AstCallGraph { return root.addGetStatic(ref); } - public int addCheckcast(TypeReference[] type, int rv) { + public int addCheckcast(TypeReference[] type, int rv, boolean isPEI) { Atom language = type[0].getClassLoader().getLanguage(); AbstractRootMethod root = getLanguageRoot(language); - return root.addCheckcast(type, rv); + return root.addCheckcast(type, rv, isPEI); } public SSANewInstruction addAllocation(TypeReference type) { diff --git a/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java index e8804377e..9d9b47160 100644 --- a/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java +++ b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java @@ -21,6 +21,7 @@ import java.util.Iterator; import org.junit.AfterClass; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Test; import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil; @@ -220,6 +221,7 @@ public class SlicerTest { * @throws IllegalArgumentException * @throws IOException */ + @Ignore @Test public void testSlice7() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { AnalysisScope scope = findOrCreateAnalysisScope(); diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectiveInvocationInterpreter.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectiveInvocationInterpreter.java index 58842eadb..dc33bc9f0 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectiveInvocationInterpreter.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/ReflectiveInvocationInterpreter.java @@ -150,7 +150,7 @@ public class ReflectiveInvocationInterpreter extends AbstractReflectionInterpret // insert a cast for v2 to filter out bogus types args[0] = nextLocal++; TypeReference type = target.getParameterType(0); - SSACheckCastInstruction cast = insts.CheckCastInstruction(args[0], 2, type); + SSACheckCastInstruction cast = insts.CheckCastInstruction(args[0], 2, type, true); m.addInstruction(null, cast, false); } } @@ -170,7 +170,7 @@ public class ReflectiveInvocationInterpreter extends AbstractReflectionInterpret args[j] = nextLocal++; TypeReference type = target.getParameterType(j); // we insert a cast to filter out bogus types - SSACheckCastInstruction cast = insts.CheckCastInstruction(args[j], temp, type); + SSACheckCastInstruction cast = insts.CheckCastInstruction(args[j], temp, type, true); m.addInstruction(null, cast, false); pc++; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/stackMachine/AbstractIntStackMachine.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/stackMachine/AbstractIntStackMachine.java index 74b8d47bb..913dc41e5 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/stackMachine/AbstractIntStackMachine.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/stackMachine/AbstractIntStackMachine.java @@ -85,16 +85,6 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { */ final private ShrikeCFG cfg; - /** - * The max height of the stack. - */ - final private int maxStackHeight; - - /** - * the max number of locals in play - */ - final protected int maxLocals; - /** * Should uninitialized variables be considered TOP (optimistic) or BOTTOM (pessimistic); */ @@ -104,8 +94,6 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { if (G == null) { throw new IllegalArgumentException("G is null"); } - maxStackHeight = G.getMaxStackHeight(); - maxLocals = G.getMaxLocals(); this.cfg = G; } @@ -394,7 +382,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { // allocate lhs.stack if it's // not already allocated. if (L.stack == null) { - L.allocateStack(); + L.allocateStack(1); L.stackHeight = 1; } @@ -430,8 +418,8 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { // if there's any stack height to meet, allocate lhs.stack if it's // not already allocated. - if (height > -1 && L.stack == null) { - L.allocateStack(); + if (height > -1 && (L.stack == null || L.stack.length < height)) { + L.allocateStack(height); L.stackHeight = height; changed = true; } @@ -441,7 +429,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { int[] R = new int[rhs.length]; for (int j = 0; j < R.length; j++) { MachineState m = (MachineState) rhs[j]; - if (m.stack == null) { + if (m.stack == null || m.stack.length < i+1) { R[j] = TOP; } else { R[j] = m.stack[i]; @@ -478,8 +466,8 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { MachineState L = (MachineState) lhs; // need we allocate lhs.locals? int nLocals = computeMeetNLocals(rhs); - if (nLocals > -1 && L.locals == null) { - L.allocateLocals(); + if (nLocals > -1 && (L.locals == null || L.locals.length < nLocals)) { + L.allocateLocals(nLocals); } // evaluate the element-wise meet over the locals. @@ -577,6 +565,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { void setTOP() { stackHeight = -1; + stack = null; } boolean isTOP() { @@ -584,8 +573,8 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { } public void push(int i) { - if (stack == null) - allocateStack(); + if (stack == null || stackHeight >= stack.length) + allocateStack(stackHeight+1); stack[stackHeight++] = i; } @@ -607,13 +596,30 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { stack[stackHeight - 2] = temp; } - private void allocateStack() { - stack = new int[maxStackHeight + 1]; - stackHeight = 0; + private void allocateStack(int stackHeight) { + if (stack == null) { + stack = new int[stackHeight + 1 ]; + this.stackHeight = 0; + } else { + int[] newStack = new int[ Math.max(stack.length, stackHeight) * 2 + 1 ]; + System.arraycopy(stack, 0, newStack, 0, stack.length); + stack = newStack; + } } - private void allocateLocals() { - locals = allocateNewLocalsArray(); + private void allocateLocals(int maxLocals) { + int[] result = new int[maxLocals]; + int start = 0; + if (locals != null) { + System.arraycopy(locals, 0, result, 0, locals.length); + start = locals.length; + } + + for (int i = start; i < maxLocals; i++) { + result[i] = OPTIMISTIC ? TOP : BOTTOM; + } + + locals = result; } public void clearStack() { @@ -627,11 +633,11 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { * @param j */ public void setLocal(int i, int j) { - if (locals == null) { + if (locals == null || locals.length < i+1) { if (OPTIMISTIC && (j == TOP)) { return; } else { - allocateLocals(); + allocateLocals(i+1); } } locals[i] = j; @@ -642,7 +648,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { * @return the number of the symbol corresponding to local i */ public int getLocal(int i) { - if (locals == null) { + if (locals == null || locals.length < i+1) { if (OPTIMISTIC) { return TOP; } else { @@ -660,7 +666,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { stack[i] = to; if (locals != null) - for (int i = 0; i < maxLocals; i++) + for (int i = 0; i < locals.length; i++) if (locals[i] == from) locals[i] = to; } @@ -672,7 +678,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { return true; if (locals != null) - for (int i = 0; i < maxLocals; i++) + for (int i = 0; i < locals.length; i++) if (locals[i] == val) return true; @@ -692,7 +698,7 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { result.append(array2StringBuffer(stack, stackHeight)); } result.append("L"); - result.append(array2StringBuffer(locals, maxLocals)); + result.append(array2StringBuffer(locals, locals.length)); result.append(">"); return result.toString(); } @@ -775,14 +781,6 @@ public abstract class AbstractIntStackMachine implements FixedPointConstants { } - public int[] allocateNewLocalsArray() { - int[] result = new int[maxLocals]; - for (int i = 0; i < maxLocals; i++) { - result[i] = OPTIMISTIC ? TOP : BOTTOM; - } - return result; - } - /** * Interface which defines a flow function for a basic block */ diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/ConeType.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/ConeType.java index 03fdbc3b0..1261e93d6 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/ConeType.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/ConeType.java @@ -31,7 +31,7 @@ public class ConeType extends TypeAbstraction { if (type == null) { throw new IllegalArgumentException("type is null"); } - assert type.getReference().isReferenceType(); + assert type.getReference().isReferenceType() : type; this.type = type; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeAbstraction.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeAbstraction.java index b639c2ad8..7dcefe377 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeAbstraction.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeAbstraction.java @@ -33,7 +33,7 @@ public abstract class TypeAbstraction implements ContextItem { @Override public String toString() { - return "JavaTypeAbstraction.TOP"; + return "WalaTypeAbstraction.TOP"; } @Override diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeInference.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeInference.java index 0aa9eb810..8a76ce6b9 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeInference.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/typeInference/TypeInference.java @@ -538,7 +538,9 @@ public class TypeInference extends SSAInference implements FixedPo TypeReference type = instruction.getDeclaredFieldType(); if (doPrimitives && type.isPrimitiveType()) { - result = new DeclaredTypeOperator(language.getPrimitive(type)); + PrimitiveType p = language.getPrimitive(type); + assert p != null : "no type for " + type; + result = new DeclaredTypeOperator(p); } else { IClass klass = cha.lookupClass(type); if (klass == null) { @@ -593,10 +595,18 @@ public class TypeInference extends SSAInference implements FixedPo // be pessimistic typeAbs = BOTTOM; } else { - if (typeAbs == null) { - typeAbs = new ConeType(klass); - } else { - typeAbs = typeAbs.meet(new ConeType(klass)); + TypeAbstraction x = null; + if (doPrimitives && type.isPrimitiveType()) { + x = language.getPrimitive(type); + } else if (type.isReferenceType()) { + x = new ConeType(klass); + } + if (x != null) { + if (typeAbs == null) { + typeAbs = x; + } else { + typeAbs = typeAbs.meet(x); + } } } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/cfg/AbstractCFG.java b/com.ibm.wala.core/src/com/ibm/wala/cfg/AbstractCFG.java index 47061248a..c6f25096a 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/cfg/AbstractCFG.java +++ b/com.ibm.wala.core/src/com/ibm/wala/cfg/AbstractCFG.java @@ -663,4 +663,5 @@ public abstract class AbstractCFG> implements Contro } return result; } + } diff --git a/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java b/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java index 1ef2aba1c..24123479a 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java +++ b/com.ibm.wala.core/src/com/ibm/wala/cfg/ShrikeCFG.java @@ -59,7 +59,11 @@ public class ShrikeCFG extends AbstractCFG { */ final private Set exceptionHandlers = HashSetFactory.make(10); - public ShrikeCFG(IBytecodeMethod method) throws IllegalArgumentException { + public static ShrikeCFG make(IBytecodeMethod m) { + return new ShrikeCFG(m); + } + + private ShrikeCFG(IBytecodeMethod method) throws IllegalArgumentException { super(method); if (method == null) { throw new IllegalArgumentException("method cannot be null"); @@ -70,12 +74,12 @@ public class ShrikeCFG extends AbstractCFG { init(); computeI2BMapping(); computeEdges(); - + if (DEBUG) { System.err.println(this); } } - + @Override public IBytecodeMethod getMethod() { return method; @@ -426,7 +430,11 @@ public class ShrikeCFG extends AbstractCFG { // this is the last non-exit block return getInstructions().length - 1; } else { - BasicBlock next = getNode(getNumber() + 1); + int i = 1; + BasicBlock next; + do { + next = getNode(getNumber() + i); + } while (next == null); return next.getFirstInstructionIndex() - 1; } } @@ -502,14 +510,6 @@ public class ShrikeCFG extends AbstractCFG { return s.toString(); } - public int getMaxStackHeight() { - return method.getMaxStackHeight(); - } - - public int getMaxLocals() { - return method.getMaxLocals(); - } - public Set getExceptionHandlers() { return exceptionHandlers; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java index 481cda566..44c6f34e3 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ArrayClass.java @@ -17,7 +17,6 @@ import java.util.HashSet; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.shrikeBT.Constants; -import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.types.Selector; import com.ibm.wala.types.TypeName; import com.ibm.wala.types.TypeReference; @@ -50,7 +49,7 @@ public class ArrayClass implements IClass, Constants { Assertions.UNREACHABLE("caller should not attempt to create an array with type " + type); } } else { - assert loader.getReference().equals(ClassLoaderReference.Primordial); + // assert loader.getReference().equals(ClassLoaderReference.Primordial); } } @@ -123,7 +122,7 @@ public class ArrayClass implements IClass, Constants { * @see com.ibm.wala.classLoader.IClass#getMethod(com.ibm.wala.classLoader.Selector) */ public IMethod getMethod(Selector sig) { - return loader.lookupClass(getClassLoader().getLanguage().getRootType().getName()).getMethod(sig); + return cha.lookupClass(getClassLoader().getLanguage().getRootType()).getMethod(sig); } public IField getField(Atom name) { diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/BinaryDirectoryTreeModule.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/BinaryDirectoryTreeModule.java index 32bed1740..fae27544e 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/BinaryDirectoryTreeModule.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/BinaryDirectoryTreeModule.java @@ -12,6 +12,10 @@ package com.ibm.wala.classLoader; import java.io.File; +import com.ibm.wala.shrikeCT.InvalidClassFileException; +import com.ibm.wala.util.warnings.Warning; +import com.ibm.wala.util.warnings.Warnings; + /** * Module representing a directory of .class files */ @@ -27,8 +31,19 @@ public class BinaryDirectoryTreeModule extends DirectoryTreeModule { } @Override - protected FileModule makeFile(File file) { - return new ClassFileModule(file); + protected FileModule makeFile(final File file) { + try { + return new ClassFileModule(file); + } catch (InvalidClassFileException e) { + Warnings.add(new Warning(Warning.MODERATE) { + + @Override + public String getMsg() { + return "Invalid class file at path " + file.getAbsolutePath(); + } + }); + return null; + } } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java index c385ecd15..445809c0a 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/BytecodeClass.java @@ -279,7 +279,7 @@ public abstract class BytecodeClass implements IClass { /* * @see com.ibm.wala.classLoader.IClass#getDirectInterfaces() */ - public Collection getDirectInterfaces() { + public Collection getDirectInterfaces() { return array2IClassSet(interfaceNames); } @@ -416,9 +416,9 @@ public abstract class BytecodeClass implements IClass { * @return Collection of IClasses, representing the interfaces this class implements. */ protected Collection computeAllInterfacesAsCollection() { - Collection c = getDirectInterfaces(); + Collection c = getDirectInterfaces(); Set result = HashSetFactory.make(); - for (Iterator it = c.iterator(); it.hasNext();) { + for (Iterator it = c.iterator(); it.hasNext();) { IClass klass = it.next(); if (klass.isInterface()) { result.add(klass); diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassFileModule.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassFileModule.java index d5ad4d30c..46d1de63e 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassFileModule.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassFileModule.java @@ -14,7 +14,6 @@ package com.ibm.wala.classLoader; import java.io.File; import com.ibm.wala.shrikeCT.InvalidClassFileException; -import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.shrike.ShrikeClassReaderHandle; import com.ibm.wala.util.strings.ImmutableByteArray; @@ -25,18 +24,10 @@ public class ClassFileModule extends FileModule { private final String className; - public ClassFileModule(File f) { + public ClassFileModule(File f) throws InvalidClassFileException { super(f); - // this is delicate: TODO, clean it up a bit. ShrikeClassReaderHandle reader = new ShrikeClassReaderHandle(this); - ImmutableByteArray name = null; - try { - name = ImmutableByteArray.make(reader.get().getName()); - } catch (InvalidClassFileException e) { - System.err.println("Invalid class file: " + f.getAbsolutePath()); - e.printStackTrace(); - Assertions.UNREACHABLE(); - } + ImmutableByteArray name = ImmutableByteArray.make(reader.get().getName()); className = name.toString(); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassLoaderImpl.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassLoaderImpl.java index 8038781ae..bbdeb9f0f 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassLoaderImpl.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ClassLoaderImpl.java @@ -157,7 +157,6 @@ public class ClassLoaderImpl implements IClassLoader { } TreeSet sortedEntries = new TreeSet(HashCodeComparator.instance()); sortedEntries.addAll(Iterator2Collection.toSet(M.getEntries())); - HashSet result = HashSetFactory.make(); for (Iterator it = sortedEntries.iterator(); it.hasNext();) { ModuleEntry entry = (ModuleEntry) it.next(); diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/DirectoryTreeModule.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/DirectoryTreeModule.java index f429c40f2..110027ff7 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/DirectoryTreeModule.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/DirectoryTreeModule.java @@ -36,6 +36,9 @@ public abstract class DirectoryTreeModule implements Module { } } + /** + * returns null if unsuccessful in creating FileModule + */ protected abstract FileModule makeFile(File file); protected abstract boolean includeFile(File file); @@ -48,7 +51,10 @@ public abstract class DirectoryTreeModule implements Module { if (files[i].isDirectory()) { result.addAll(getEntriesRecursive(files[i])); } else if (includeFile(files[i])) { - result.add(makeFile(files[i])); + FileModule fileModule = makeFile(files[i]); + if (fileModule != null) { + result.add(fileModule); + } } } } else { diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java index 14d82bf5b..9cdd4715f 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/IClass.java @@ -70,7 +70,7 @@ public interface IClass extends IClassHierarchyDweller { * @return Collection of (IClass) interfaces this class directly implements. If this class is an interface, returns the interfaces * it immediately extends. */ - Collection getDirectInterfaces(); + Collection getDirectInterfaces(); /** * @return Collection of (IClass) interfaces this class implements, including all ancestors of interfaces immediately implemented. diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/IMethod.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/IMethod.java index 6ad8fe4c6..bbd810b7a 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/IMethod.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/IMethod.java @@ -82,16 +82,6 @@ public interface IMethod extends IMember, ContextItem { */ MethodReference getReference(); - /** - * @return maximum number of JVM locals used by this method - */ - int getMaxLocals(); - - /** - * @return maximum height of JVM stack used by this method - */ - int getMaxStackHeight(); - /** * @return true iff this method has at least one exception handler */ diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/JavaLanguage.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/JavaLanguage.java index c93c39b87..066c5a0d9 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/JavaLanguage.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/JavaLanguage.java @@ -128,13 +128,14 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons }; } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues) { + public SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues, boolean isPEI) { throw new UnsupportedOperationException(); } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types) { + public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI) { assert types.length == 1; - return new SSACheckCastInstruction(result, val, types) { + assert isPEI; + return new SSACheckCastInstruction(result, val, types, true) { @Override public Collection getExceptionTypes() { return getClassCastException(); @@ -142,12 +143,14 @@ public class JavaLanguage extends LanguageImpl implements BytecodeLanguage, Cons }; } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue) { - return CheckCastInstruction(result, val, new int[]{ typeValue }); + public SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue, boolean isPEI) { + assert isPEI; + return CheckCastInstruction(result, val, new int[]{ typeValue }, true); } - public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type) { - return CheckCastInstruction(result, val, new TypeReference[]{ type }); + public SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type, boolean isPEI) { + assert isPEI; + return CheckCastInstruction(result, val, new TypeReference[]{ type }, true); } public SSAComparisonInstruction ComparisonInstruction(IComparisonInstruction.Operator operator, int result, int val1, int val2) { diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ShrikeIRFactory.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ShrikeIRFactory.java index b7a6a6fa4..7cd119940 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/ShrikeIRFactory.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/ShrikeIRFactory.java @@ -33,7 +33,7 @@ public class ShrikeIRFactory implements IRFactory { public final static boolean buildLocalMap = true; public ControlFlowGraph makeCFG(final IBytecodeMethod method, Context C) { - return new ShrikeCFG(method); + return ShrikeCFG.make(method); } public IR makeIR(final IBytecodeMethod method, Context C, final SSAOptions options) throws IllegalArgumentException { diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisScope.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisScope.java index 3da23e419..5ed280f10 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisScope.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/AnalysisScope.java @@ -35,6 +35,7 @@ import com.ibm.wala.classLoader.Module; import com.ibm.wala.classLoader.SourceDirectoryTreeModule; import com.ibm.wala.classLoader.SourceFileModule; import com.ibm.wala.ipa.callgraph.impl.SetOfClasses; +import com.ibm.wala.shrikeCT.InvalidClassFileException; import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.types.Descriptor; import com.ibm.wala.types.MethodReference; @@ -202,8 +203,9 @@ public class AnalysisScope { /** * Add a class file to the scope for a loader + * @throws InvalidClassFileException */ - public void addClassFileToScope(ClassLoaderReference loader, File file) throws IllegalArgumentException { + public void addClassFileToScope(ClassLoaderReference loader, File file) throws IllegalArgumentException, InvalidClassFileException { List s = MapUtil.findOrCreateList(moduleMap, loader); s.add(new ClassFileModule(file)); } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/AbstractRootMethod.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/AbstractRootMethod.java index f24f8a145..25e71a6dd 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/AbstractRootMethod.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/impl/AbstractRootMethod.java @@ -330,10 +330,10 @@ public abstract class AbstractRootMethod extends SyntheticMethod { return result; } - public int addCheckcast(TypeReference[] types, int rv) { + public int addCheckcast(TypeReference[] types, int rv, boolean isPEI) { int lv = nextLocal++; - statements.add(insts.CheckCastInstruction(lv, rv, types)); + statements.add(insts.CheckCastInstruction(lv, rv, types, isPEI)); return lv; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java index 116a9d114..54816f5ee 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/cha/ClassHierarchy.java @@ -747,13 +747,22 @@ public class ClassHierarchy implements IClassHierarchy { Assertions.UNREACHABLE(); superB = null; } - while (a != null) { - if (superB.contains(a)) { - return a; + IClass aa = a; + while (aa != null) { + if (superB.contains(aa)) { + return aa; } - a = a.getSuperclass(); + aa = aa.getSuperclass(); } - Assertions.UNREACHABLE("getLeastCommonSuperclass " + tempA + " " + b); + Set superA; + try { + superA = getSuperclasses(a); + } catch (ClassHierarchyException e1) { + e1.printStackTrace(); + Assertions.UNREACHABLE(); + superA = null; + } + Assertions.UNREACHABLE("getLeastCommonSuperclass " + tempA + " " + b + ": " + superA + ", " + superB); return null; } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ssa/IR.java b/com.ibm.wala.core/src/com/ibm/wala/ssa/IR.java index 21fcde8b0..3b8d1adc4 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ssa/IR.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ssa/IR.java @@ -125,7 +125,7 @@ public abstract class IR { newSiteMapping.put(((SSANewInstruction) x).getNewSite(), new Integer(i)); } if (x.isPEI()) { - peiMapping.put(new ProgramCounter(cfg.getProgramCounter(i)), new Integer(i)); + peiMapping.put(new ProgramCounter(cfg.getProgramCounter(i)), new Integer(i)); } } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java index 04edbe478..dd72e2940 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java @@ -105,8 +105,8 @@ public class SSABuilder extends AbstractIntStackMachine { private SSABuilder(IBytecodeMethod method, SSACFG cfg, ShrikeCFG scfg, SSAInstruction[] instructions, SymbolTable symbolTable, boolean buildLocalMap, SSAPiNodePolicy piNodePolicy) { super(scfg); - localMap = buildLocalMap ? new SSA2LocalMap(scfg, instructions.length, cfg.getNumberOfNodes(), maxLocals) : null; - init(new SymbolTableMeeter(symbolTable, cfg, instructions, scfg), new SymbolicPropagator(scfg, instructions, symbolTable, + localMap = buildLocalMap ? new SSA2LocalMap(scfg, instructions.length, cfg.getNumberOfNodes()) : null; + init(new SymbolTableMeeter(symbolTable, cfg, scfg), new SymbolicPropagator(scfg, instructions, symbolTable, localMap, cfg, piNodePolicy)); this.method = method; this.symbolTable = symbolTable; @@ -120,15 +120,13 @@ public class SSABuilder extends AbstractIntStackMachine { final SSACFG cfg; - final SSAInstruction[] instructions; final SymbolTable symbolTable; final ShrikeCFG shrikeCFG; - SymbolTableMeeter(SymbolTable symbolTable, SSACFG cfg, SSAInstruction[] instructions, ShrikeCFG shrikeCFG) { + SymbolTableMeeter(SymbolTable symbolTable, SSACFG cfg, ShrikeCFG shrikeCFG) { this.cfg = cfg; - this.instructions = instructions; this.symbolTable = symbolTable; this.shrikeCFG = shrikeCFG; } @@ -328,17 +326,19 @@ public class SSABuilder extends AbstractIntStackMachine { } private void emitInstruction(SSAInstruction s) { - instructions[getCurrentInstructionIndex()] = s; - for (int i = 0; i < s.getNumberOfDefs(); i++) { - if (creators.length < (s.getDef(i) + 1)) { - SSAInstruction[] arr = new SSAInstruction[2 * s.getDef(i)]; - System.arraycopy(creators, 0, arr, 0, creators.length); - creators = arr; - } + if (s != null) { + instructions[getCurrentInstructionIndex()] = s; + for (int i = 0; i < s.getNumberOfDefs(); i++) { + if (creators.length < (s.getDef(i) + 1)) { + SSAInstruction[] arr = new SSAInstruction[2 * s.getDef(i)]; + System.arraycopy(creators, 0, arr, 0, creators.length); + creators = arr; + } - assert s.getDef(i) != -1 : "invalid def " + i + " for " + s; + assert s.getDef(i) != -1 : "invalid def " + i + " for " + s; - creators[s.getDef(i)] = s; + creators[s.getDef(i)] = s; + } } } @@ -451,7 +451,7 @@ public class SSABuilder extends AbstractIntStackMachine { for(int i = 0; i < typeNames.length; i++) { t[i] = ShrikeUtil.makeTypeReference(loader, typeNames[i]); } - emitInstruction(insts.CheckCastInstruction(result, val, t)); + emitInstruction(insts.CheckCastInstruction(result, val, t, instruction.isPEI())); } } @@ -933,20 +933,14 @@ public class SSABuilder extends AbstractIntStackMachine { */ private final int[][] block2LocalState; - /** - * maximum number of locals used at any program point - */ - private final int maxLocals; - /** * @param nInstructions number of instructions in the bytecode for this method * @param nBlocks number of basic blocks in the CFG */ - SSA2LocalMap(ShrikeCFG shrikeCfg, int nInstructions, int nBlocks, int maxLocals) { + SSA2LocalMap(ShrikeCFG shrikeCfg, int nInstructions, int nBlocks) { shrikeCFG = shrikeCfg; localStoreMap = new IntPair[nInstructions]; block2LocalState = new int[nBlocks][]; - this.maxLocals = maxLocals; } /** @@ -954,11 +948,6 @@ public class SSABuilder extends AbstractIntStackMachine { * a particular local number */ void startRange(int pc, int localNumber, int valueNumber) { - int max = shrikeCFG.getMethod().getMaxLocals(); - if (localNumber >= max) { - assert false : "invalid local " + localNumber + ">" + max; - } - localStoreMap[pc] = new IntPair(valueNumber, localNumber); } @@ -1002,6 +991,27 @@ public class SSABuilder extends AbstractIntStackMachine { } } + public int[] allocateNewLocalsArray(int maxLocals) { + int[] result = new int[maxLocals]; + for (int i = 0; i < maxLocals; i++) { + result[i] = OPTIMISTIC ? TOP : BOTTOM; + } + return result; + } + + private int[] setLocal(int[] locals, int localNumber, int valueNumber) { + if (locals == null) { + locals = allocateNewLocalsArray(localNumber + 1); + } else if (locals.length <= localNumber) { + int[] newLocals = allocateNewLocalsArray(2 * Math.max(locals.length, localNumber) + 1); + System.arraycopy(locals, 0, newLocals, 0, locals.length); + locals = newLocals; + } + + locals[localNumber] = valueNumber; + + return locals; + } /** * @param pc a program counter (index into ShrikeBT instruction array) * @param vn a value number @@ -1015,26 +1025,15 @@ public class SSABuilder extends AbstractIntStackMachine { // walk forward from the first instruction to reconstruct the // state of the locals at this pc int[] locals = block2LocalState[bb.getNumber()]; - if (locals == null) { - locals = allocateNewLocalsArray(); - } for (int i = firstInstruction; i <= pc; i++) { if (localStoreMap[i] != null) { IntPair p = localStoreMap[i]; - locals[p.getY()] = p.getX(); + setLocal(locals, p.getY(), p.getX()); } } return extractIndices(locals, vn); } - public int[] allocateNewLocalsArray() { - int[] result = new int[maxLocals]; - for (int i = 0; i < maxLocals; i++) { - result[i] = OPTIMISTIC ? TOP : BOTTOM; - } - return result; - } - /** * @return the indices i s.t. x[i] == y, or null if none found. */ diff --git a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACheckCastInstruction.java b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACheckCastInstruction.java index 1991b0f79..241694f30 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACheckCastInstruction.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSACheckCastInstruction.java @@ -38,16 +38,22 @@ public abstract class SSACheckCastInstruction extends SSAInstruction { */ private final TypeReference[] declaredResultTypes; + /** + * whether the type test throws an exception + */ + private final boolean isPEI; + /** * @param result A new value number def'fed by this instruction when the type check succeeds. * @param val The value being checked by this instruction * @param type The type which this instruction checks */ - protected SSACheckCastInstruction(int result, int val, TypeReference[] types) { + protected SSACheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI) { super(); this.result = result; this.val = val; this.declaredResultTypes = types; + this.isPEI = isPEI; } @Override @@ -58,7 +64,7 @@ public abstract class SSACheckCastInstruction extends SSAInstruction { if (uses != null && uses.length == 0) { throw new IllegalArgumentException("(uses != null) and (uses.length == 0)"); } - return insts.CheckCastInstruction(defs == null ? result : defs[0], uses == null ? val : uses[0], declaredResultTypes); + return insts.CheckCastInstruction(defs == null ? result : defs[0], uses == null ? val : uses[0], declaredResultTypes, isPEI); } @Override @@ -162,7 +168,7 @@ public abstract class SSACheckCastInstruction extends SSAInstruction { */ @Override public boolean isPEI() { - return true; + return isPEI; } /* diff --git a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSAInstructionFactory.java b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSAInstructionFactory.java index 2c37bc72e..e1111b02f 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSAInstructionFactory.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSAInstructionFactory.java @@ -40,13 +40,13 @@ public interface SSAInstructionFactory { SSABinaryOpInstruction BinaryOpInstruction(IBinaryOpInstruction.IOperator operator, boolean overflow, boolean unsigned, int result, int val1, int val2, boolean mayBeInteger); - SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues); + SSACheckCastInstruction CheckCastInstruction(int result, int val, int[] typeValues, boolean isPEI); - SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue); + SSACheckCastInstruction CheckCastInstruction(int result, int val, int typeValue, boolean isPEI); - SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types); + SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference[] types, boolean isPEI); - SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type); + SSACheckCastInstruction CheckCastInstruction(int result, int val, TypeReference type, boolean isPEI); SSAComparisonInstruction ComparisonInstruction(IComparisonInstruction.Operator operator, int result, int val1, int val2); diff --git a/com.ibm.wala.core/src/com/ibm/wala/types/TypeName.java b/com.ibm.wala.core/src/com/ibm/wala/types/TypeName.java index 2e523d509..1d6b22919 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/types/TypeName.java +++ b/com.ibm.wala.core/src/com/ibm/wala/types/TypeName.java @@ -261,7 +261,10 @@ public final class TypeName implements Serializable { } if (!innermostPrimitive) { result.append("L"); + } else if (packageName != null && innermostPrimitive) { + result.append("P"); } + if (packageName != null) { result.append(packageName.toString()); result.append("/"); @@ -279,7 +282,10 @@ public final class TypeName implements Serializable { } if (!innermostPrimitive) { result.append("L"); + } else if (packageName != null && innermostPrimitive) { + result.append("P"); } + if (packageName != null) { result.append(packageName.toUnicodeString()); result.append("/"); diff --git a/com.ibm.wala.core/src/com/ibm/wala/types/TypeReference.java b/com.ibm.wala.core/src/com/ibm/wala/types/TypeReference.java index e527b2703..0d8446de8 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/types/TypeReference.java +++ b/com.ibm.wala.core/src/com/ibm/wala/types/TypeReference.java @@ -329,7 +329,11 @@ public final class TypeReference implements Serializable { public final static TypeReference Unknown = findOrCreate(ClassLoaderReference.Primordial, UnknownName); private static TypeReference makePrimitive(TypeName n) { - TypeReference t = new TypeReference(ClassLoaderReference.Primordial, n); + return makePrimitive(ClassLoaderReference.Primordial, n); + } + + public static TypeReference makePrimitive(ClassLoaderReference cl, TypeName n) { + TypeReference t = new TypeReference(cl, n); primitiveMap.put(t.name, t); return t; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/types/annotations/Annotation.java b/com.ibm.wala.core/src/com/ibm/wala/types/annotations/Annotation.java index 1f601716a..e56e2b996 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/types/annotations/Annotation.java +++ b/com.ibm.wala.core/src/com/ibm/wala/types/annotations/Annotation.java @@ -10,7 +10,10 @@ *******************************************************************************/ package com.ibm.wala.types.annotations; +import java.util.Arrays; + import com.ibm.wala.types.TypeReference; +import com.ibm.wala.util.collections.Pair; /** * Represents a Java 5.0 class file annotation @@ -18,25 +21,40 @@ import com.ibm.wala.types.TypeReference; public class Annotation { private final TypeReference type; + private final Pair[] arguments; - private Annotation(TypeReference type) { + private Annotation(TypeReference type, Pair[] arguments) { this.type = type; + this.arguments = arguments; + } + + public static Annotation make(TypeReference t, Pair[] arguments) { + return new Annotation(t, arguments); } public static Annotation make(TypeReference t) { - return new Annotation(t); + return make(t, null); } @Override public String toString() { - return "Annotation type " + type; + StringBuffer sb = new StringBuffer("Annotation type " + type); + if (arguments != null) { + sb.append("["); + for(Pair arg : arguments) { + sb.append(" " + arg.fst.getName().getClassName() + ":" + arg.snd); + } + sb.append(" ]"); + } + return sb.toString(); } @Override public int hashCode() { - final int PRIME = 31; + final int prime = 31; int result = 1; - result = PRIME * result + ((type == null) ? 0 : type.hashCode()); + result = prime * result + Arrays.hashCode(arguments); + result = prime * result + ((type == null) ? 0 : type.hashCode()); return result; } @@ -48,7 +66,9 @@ public class Annotation { return false; if (getClass() != obj.getClass()) return false; - final Annotation other = (Annotation) obj; + Annotation other = (Annotation) obj; + if (!Arrays.equals(arguments, other.arguments)) + return false; if (type == null) { if (other.type != null) return false; @@ -57,7 +77,10 @@ public class Annotation { return true; } - + public Pair[] getArguments() { + return arguments; + } + public TypeReference getType() { return type; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/util/config/AnalysisScopeReader.java b/com.ibm.wala.core/src/com/ibm/wala/util/config/AnalysisScopeReader.java index f396d1273..187766f83 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/util/config/AnalysisScopeReader.java +++ b/com.ibm.wala.core/src/com/ibm/wala/util/config/AnalysisScopeReader.java @@ -26,6 +26,7 @@ import com.ibm.wala.classLoader.SourceDirectoryTreeModule; import com.ibm.wala.core.plugin.CorePlugin; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.properties.WalaProperties; +import com.ibm.wala.shrikeCT.InvalidClassFileException; import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.io.FileProvider; @@ -108,7 +109,11 @@ public class AnalysisScopeReader { String entryPathname = toks.nextToken(); if ("classFile".equals(entryType)) { File cf = FileProvider.getFile(entryPathname, javaLoader); - scope.addClassFileToScope(walaLoader, cf); + try { + scope.addClassFileToScope(walaLoader, cf); + } catch (InvalidClassFileException e) { + Assertions.UNREACHABLE(e.toString()); + } } else if ("sourceFile".equals(entryType)) { File sf = FileProvider.getFile(entryPathname, javaLoader); scope.addSourceFileToScope(walaLoader, sf, entryPathname); @@ -197,6 +202,8 @@ public class AnalysisScopeReader { } } catch (IOException e) { Assertions.UNREACHABLE(e.toString()); + } catch (InvalidClassFileException e) { + Assertions.UNREACHABLE(e.toString()); } } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/util/io/FileProvider.java b/com.ibm.wala.core/src/com/ibm/wala/util/io/FileProvider.java index 1de734c1c..b15a1a063 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/util/io/FileProvider.java +++ b/com.ibm.wala.core/src/com/ibm/wala/util/io/FileProvider.java @@ -13,6 +13,7 @@ package com.ibm.wala.util.io;// 5724-D15 import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Method; import java.net.JarURLConnection; import java.net.MalformedURLException; @@ -263,6 +264,23 @@ public class FileProvider { } } + /** + * @throws FileNotFoundException + */ + public static InputStream getInputStreamFromClassLoader(String fileName, ClassLoader loader) throws FileNotFoundException { + if (loader == null) { + throw new IllegalArgumentException("null loader"); + } + if (fileName == null) { + throw new IllegalArgumentException("null fileName"); + } + InputStream is = loader.getResourceAsStream(fileName); + if (is == null) { + throw new FileNotFoundException(fileName); + } + return is; + } + /** * @return the jar file packaged with this plug-in of the given name, or null * if not found: wrapped as a JarFileModule or a NestedJarFileModule diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/CgPanel.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/CgPanel.java index c701b9089..abf41eb5c 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/CgPanel.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/CgPanel.java @@ -1,125 +1,125 @@ -package com.ibm.wala.viz.viewer; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTree; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeExpansionListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreePath; - -import com.ibm.wala.classLoader.CallSiteReference; -import com.ibm.wala.ipa.callgraph.CGNode; -import com.ibm.wala.ipa.callgraph.CallGraph; -import com.ibm.wala.ssa.IR; - -public class CgPanel extends JSplitPane{ - - private final CallGraph cg; - - public CgPanel(CallGraph cg) { - this.cg = cg; - this.setDividerLocation(250); - JTree tree = buildTree(); - this.setLeftComponent(new JScrollPane(tree)); - - - final IrAndSourceViewer irViewer = new IrAndSourceViewer(cg); - this.setRightComponent(irViewer.getComponent()); - - tree.addTreeSelectionListener(new TreeSelectionListener() { - public void valueChanged(TreeSelectionEvent e) { - TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); - if (null == newLeadSelectionPath){ - return; - } - DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent(); - Object userObject = treeNode.getUserObject(); - if (userObject instanceof CGNode) { - CGNode node = (CGNode) userObject; - IR ir = node.getIR(); - irViewer.setIR(ir); - } else if (userObject instanceof CallSiteReference){ - CGNode parentNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject(); - IR ir = parentNode.getIR(); - irViewer.setIRAndPc(ir, ((CallSiteReference) userObject).getProgramCounter()); - } - } - }); - - } - - private JTree buildTree() { - - CGNode cgRoot = cg.getFakeRootNode(); - DefaultMutableTreeNode root = new DefaultMutableTreeNode(cgRoot); - - expandNode(root); - JTree tree = new JTree(root); - - tree.addTreeExpansionListener(new TreeExpansionListener() { - - public void treeExpanded(TreeExpansionEvent event) { - TreePath path = event.getPath(); - if (path == null) { - return; - } - DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); - expandNode(lastNode); - } - - public void treeCollapsed(TreeExpansionEvent event) { - - } - }); - - return tree; - } - - private void expandNode(DefaultMutableTreeNode treeNode) { - expandNode(treeNode, 3); - } - - private void expandNode(DefaultMutableTreeNode treeNode, int rec) { - if (rec == 0) { - return; - } - - if (treeNode.getChildCount() == 0) { - List newChilds = new ArrayList(); - Object userObject = treeNode.getUserObject(); - if (userObject instanceof CGNode) { - CGNode cgNode = (CGNode) userObject; - for (Iterator iter = cgNode.iterateCallSites(); iter.hasNext();) { - CallSiteReference csr = iter.next(); - newChilds.add(new DefaultMutableTreeNode(csr)); - } - } else { - assert userObject instanceof CallSiteReference; - CallSiteReference csr = (CallSiteReference) userObject; - CGNode cgNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject(); - Set successors = cg.getPossibleTargets(cgNode, csr); - for (CGNode successor : successors) { - newChilds.add(new DefaultMutableTreeNode(successor)); - } - } - - for (DefaultMutableTreeNode newChild : newChilds) { - treeNode.add(newChild); - } - } - - for (int i = 0; i < treeNode.getChildCount(); i++) { - DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i); - expandNode(child, rec - 1); - } - } - -} +package com.ibm.wala.viz.viewer; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTree; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; + +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ssa.IR; + +public class CgPanel extends JSplitPane{ + + private final CallGraph cg; + + public CgPanel(CallGraph cg) { + this.cg = cg; + this.setDividerLocation(250); + JTree tree = buildTree(); + this.setLeftComponent(new JScrollPane(tree)); + + + final IrAndSourceViewer irViewer = new IrAndSourceViewer(cg); + this.setRightComponent(irViewer.getComponent()); + + tree.addTreeSelectionListener(new TreeSelectionListener() { + public void valueChanged(TreeSelectionEvent e) { + TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); + if (null == newLeadSelectionPath){ + return; + } + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent(); + Object userObject = treeNode.getUserObject(); + if (userObject instanceof CGNode) { + CGNode node = (CGNode) userObject; + IR ir = node.getIR(); + irViewer.setIR(ir); + } else if (userObject instanceof CallSiteReference){ + CGNode parentNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject(); + IR ir = parentNode.getIR(); + irViewer.setIRAndPc(ir, ((CallSiteReference) userObject).getProgramCounter()); + } + } + }); + + } + + private JTree buildTree() { + + CGNode cgRoot = cg.getFakeRootNode(); + DefaultMutableTreeNode root = new DefaultMutableTreeNode(cgRoot); + + expandNode(root); + JTree tree = new JTree(root); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + + public void treeExpanded(TreeExpansionEvent event) { + TreePath path = event.getPath(); + if (path == null) { + return; + } + DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); + expandNode(lastNode); + } + + public void treeCollapsed(TreeExpansionEvent event) { + + } + }); + + return tree; + } + + private void expandNode(DefaultMutableTreeNode treeNode) { + expandNode(treeNode, 3); + } + + private void expandNode(DefaultMutableTreeNode treeNode, int rec) { + if (rec == 0) { + return; + } + + if (treeNode.getChildCount() == 0) { + List newChilds = new ArrayList(); + Object userObject = treeNode.getUserObject(); + if (userObject instanceof CGNode) { + CGNode cgNode = (CGNode) userObject; + for (Iterator iter = cgNode.iterateCallSites(); iter.hasNext();) { + CallSiteReference csr = iter.next(); + newChilds.add(new DefaultMutableTreeNode(csr)); + } + } else { + assert userObject instanceof CallSiteReference; + CallSiteReference csr = (CallSiteReference) userObject; + CGNode cgNode = (CGNode) ((DefaultMutableTreeNode) treeNode.getParent()).getUserObject(); + Set successors = cg.getPossibleTargets(cgNode, csr); + for (CGNode successor : successors) { + newChilds.add(new DefaultMutableTreeNode(successor)); + } + } + + for (DefaultMutableTreeNode newChild : newChilds) { + treeNode.add(newChild); + } + } + + for (int i = 0; i < treeNode.getChildCount(); i++) { + DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i); + expandNode(child, rec - 1); + } + } + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/ChaPanel.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/ChaPanel.java index 5f3c39a55..406768d70 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/ChaPanel.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/ChaPanel.java @@ -1,104 +1,104 @@ -package com.ibm.wala.viz.viewer; - -import java.util.Collection; - -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTree; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeExpansionListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreePath; - -import com.ibm.wala.classLoader.IClass; -import com.ibm.wala.classLoader.IMethod; -import com.ibm.wala.ipa.cha.IClassHierarchy; - -public class ChaPanel extends JSplitPane { - - private final IClassHierarchy cha; - - public ChaPanel(IClassHierarchy cha) { - this.cha = cha; - - this.setDividerLocation(250); - JTree tree = buildTree(); - this.setLeftComponent(new JScrollPane(tree)); - - final DefaultListModel methodListModel = new DefaultListModel(); - JList methodList = new JList(methodListModel); - this.setRightComponent(methodList); - - tree.addTreeSelectionListener(new TreeSelectionListener(){ - public void valueChanged(TreeSelectionEvent e) { - TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); - if (null == newLeadSelectionPath){ - return; - } - DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent(); - IClass klass = (IClass) treeNode.getUserObject(); - methodListModel.clear(); - for (IMethod m : klass.getDeclaredMethods()){ - methodListModel.addElement(m.toString()); - } - } - }); - - } - - private JTree buildTree() { - IClass rootClass = cha.getRootClass(); - DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootClass); - - expandNode(root); - JTree tree = new JTree(root); - - tree.addTreeExpansionListener(new TreeExpansionListener() { - - public void treeExpanded(TreeExpansionEvent event) { - TreePath path = event.getPath(); - if (path == null) { - return; - } - DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); - expandNode(lastNode); - } - - public void treeCollapsed(TreeExpansionEvent event) { - - } - }); - - return tree; - } - - private void expandNode(DefaultMutableTreeNode treeNode) { - expandNode(treeNode, 3); - } - - private void expandNode(DefaultMutableTreeNode treeNode, int rec) { - if (rec == 0) { - return; - } - - if (treeNode.getChildCount() == 0) { - IClass klass = (IClass) treeNode.getUserObject(); - Collection immediateSubclasses = cha.getImmediateSubclasses(klass); - for (IClass immediateSubclass : immediateSubclasses){ - treeNode.add(new DefaultMutableTreeNode(immediateSubclass)); - } - } - - for (int i = 0; i < treeNode.getChildCount(); i++) { - DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i); - expandNode(child, rec - 1); - } - } - - - -} +package com.ibm.wala.viz.viewer; + +import java.util.Collection; + +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTree; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreePath; + +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ipa.cha.IClassHierarchy; + +public class ChaPanel extends JSplitPane { + + private final IClassHierarchy cha; + + public ChaPanel(IClassHierarchy cha) { + this.cha = cha; + + this.setDividerLocation(250); + JTree tree = buildTree(); + this.setLeftComponent(new JScrollPane(tree)); + + final DefaultListModel methodListModel = new DefaultListModel(); + JList methodList = new JList(methodListModel); + this.setRightComponent(methodList); + + tree.addTreeSelectionListener(new TreeSelectionListener(){ + public void valueChanged(TreeSelectionEvent e) { + TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); + if (null == newLeadSelectionPath){ + return; + } + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent(); + IClass klass = (IClass) treeNode.getUserObject(); + methodListModel.clear(); + for (IMethod m : klass.getDeclaredMethods()){ + methodListModel.addElement(m.toString()); + } + } + }); + + } + + private JTree buildTree() { + IClass rootClass = cha.getRootClass(); + DefaultMutableTreeNode root = new DefaultMutableTreeNode(rootClass); + + expandNode(root); + JTree tree = new JTree(root); + + tree.addTreeExpansionListener(new TreeExpansionListener() { + + public void treeExpanded(TreeExpansionEvent event) { + TreePath path = event.getPath(); + if (path == null) { + return; + } + DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); + expandNode(lastNode); + } + + public void treeCollapsed(TreeExpansionEvent event) { + + } + }); + + return tree; + } + + private void expandNode(DefaultMutableTreeNode treeNode) { + expandNode(treeNode, 3); + } + + private void expandNode(DefaultMutableTreeNode treeNode, int rec) { + if (rec == 0) { + return; + } + + if (treeNode.getChildCount() == 0) { + IClass klass = (IClass) treeNode.getUserObject(); + Collection immediateSubclasses = cha.getImmediateSubclasses(klass); + for (IClass immediateSubclass : immediateSubclasses){ + treeNode.add(new DefaultMutableTreeNode(immediateSubclass)); + } + } + + for (int i = 0; i < treeNode.getChildCount(); i++) { + DefaultMutableTreeNode child = (DefaultMutableTreeNode) treeNode.getChildAt(i); + expandNode(child, rec - 1); + } + } + + + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/DualTreeCellRenderer.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/DualTreeCellRenderer.java index 38af41ac2..a54e333df 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/DualTreeCellRenderer.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/DualTreeCellRenderer.java @@ -1,70 +1,70 @@ -package com.ibm.wala.viz.viewer; - -import java.awt.Component; - -import javax.swing.ImageIcon; -import javax.swing.JTree; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.DefaultTreeCellRenderer; -import javax.swing.tree.TreeCellRenderer; - -import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; -import com.ibm.wala.ipa.callgraph.propagation.PointerKey; - -/** - * Renderer for the heap tree. Gives non default icons for pointer keys and instance keys. - * @author yinnonh - * - */ -class DualTreeCellRenderer implements TreeCellRenderer { - - private final DefaultTreeCellRenderer defaultTreeCellRenderer; - private final DefaultTreeCellRenderer ikTreeCellRenderer; - private final DefaultTreeCellRenderer pkTreeCellRenderer; - - public DualTreeCellRenderer() { - defaultTreeCellRenderer = new DefaultTreeCellRenderer(); - - - ikTreeCellRenderer = new DefaultTreeCellRenderer(); - ikTreeCellRenderer.setOpenIcon(createImageIcon("images/ik_open.png")); - ikTreeCellRenderer.setClosedIcon(createImageIcon("images/ik_closed.png")); - ikTreeCellRenderer.setLeafIcon(createImageIcon("images/ik_leaf.png")); - - pkTreeCellRenderer = new DefaultTreeCellRenderer(); - pkTreeCellRenderer.setOpenIcon(createImageIcon("images/pk_open.png")); - pkTreeCellRenderer.setClosedIcon(createImageIcon("images/pk_closed.png")); - pkTreeCellRenderer.setLeafIcon(createImageIcon("images/pk_leaf.png")); - } - - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, - int row, boolean hasFocus) { - TreeCellRenderer delegate = getTreeCellRenderer(value); - return delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); - } - - private TreeCellRenderer getTreeCellRenderer(Object value) { - if (value instanceof DefaultMutableTreeNode){ - value = ((DefaultMutableTreeNode) value).getUserObject(); - } - if (value instanceof PointerKey){ - return pkTreeCellRenderer; - } else if (value instanceof InstanceKey){ - return ikTreeCellRenderer; - } else { - return defaultTreeCellRenderer; - } - } - - /** Returns an ImageIcon, or null if the path was invalid. */ - protected ImageIcon createImageIcon(String path) { - java.net.URL imgURL = DualTreeCellRenderer.class.getResource(path); - if (imgURL != null) { - return new ImageIcon(imgURL); - } else { - System.err.println("Couldn't find file: " + path); - return null; - } - } - -} +package com.ibm.wala.viz.viewer; + +import java.awt.Component; + +import javax.swing.ImageIcon; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeCellRenderer; +import javax.swing.tree.TreeCellRenderer; + +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.callgraph.propagation.PointerKey; + +/** + * Renderer for the heap tree. Gives non default icons for pointer keys and instance keys. + * @author yinnonh + * + */ +class DualTreeCellRenderer implements TreeCellRenderer { + + private final DefaultTreeCellRenderer defaultTreeCellRenderer; + private final DefaultTreeCellRenderer ikTreeCellRenderer; + private final DefaultTreeCellRenderer pkTreeCellRenderer; + + public DualTreeCellRenderer() { + defaultTreeCellRenderer = new DefaultTreeCellRenderer(); + + + ikTreeCellRenderer = new DefaultTreeCellRenderer(); + ikTreeCellRenderer.setOpenIcon(createImageIcon("images/ik_open.png")); + ikTreeCellRenderer.setClosedIcon(createImageIcon("images/ik_closed.png")); + ikTreeCellRenderer.setLeafIcon(createImageIcon("images/ik_leaf.png")); + + pkTreeCellRenderer = new DefaultTreeCellRenderer(); + pkTreeCellRenderer.setOpenIcon(createImageIcon("images/pk_open.png")); + pkTreeCellRenderer.setClosedIcon(createImageIcon("images/pk_closed.png")); + pkTreeCellRenderer.setLeafIcon(createImageIcon("images/pk_leaf.png")); + } + + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, + int row, boolean hasFocus) { + TreeCellRenderer delegate = getTreeCellRenderer(value); + return delegate.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); + } + + private TreeCellRenderer getTreeCellRenderer(Object value) { + if (value instanceof DefaultMutableTreeNode){ + value = ((DefaultMutableTreeNode) value).getUserObject(); + } + if (value instanceof PointerKey){ + return pkTreeCellRenderer; + } else if (value instanceof InstanceKey){ + return ikTreeCellRenderer; + } else { + return defaultTreeCellRenderer; + } + } + + /** Returns an ImageIcon, or null if the path was invalid. */ + protected ImageIcon createImageIcon(String path) { + java.net.URL imgURL = DualTreeCellRenderer.class.getResource(path); + if (imgURL != null) { + return new ImageIcon(imgURL); + } else { + System.err.println("Couldn't find file: " + path); + return null; + } + } + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrAndSourceViewer.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrAndSourceViewer.java index f02595470..fe068cce4 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrAndSourceViewer.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrAndSourceViewer.java @@ -1,79 +1,79 @@ -package com.ibm.wala.viz.viewer; - -import java.awt.Component; -import java.io.File; -import java.net.MalformedURLException; -import java.net.URL; - -import javax.swing.JSplitPane; - -import com.ibm.wala.classLoader.IClassLoader; -import com.ibm.wala.classLoader.IMethod; -import com.ibm.wala.ipa.callgraph.CallGraph; -import com.ibm.wala.ssa.IR; -import com.ibm.wala.viz.viewer.IrViewer.SelectedPcListner; - -public class IrAndSourceViewer { - - private IrViewer irViewer; - private SourceViewer sourceViewer; - - private IR ir; - - public IrAndSourceViewer(CallGraph cg) { - } - - public Component getComponent() { - - - JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); - irViewer = new IrViewer(); - splitPane.setLeftComponent(irViewer); - - sourceViewer = new SourceViewer(); - splitPane.setRightComponent(sourceViewer); - - irViewer.addSelectedPcListner(new SelectedPcListner(){ - - public void valueChanged(int pc) { - IMethod method = ir.getMethod(); - int sourceLineNumber = IrViewer.NA; - String sourceFileName = null; - if (pc != IrViewer.NA){ - try{ - sourceLineNumber = method.getLineNumber(pc); - IClassLoader loader = method.getDeclaringClass().getClassLoader(); - sourceFileName = loader.getSourceFileName(method, pc); - } catch (Exception e){ - e.printStackTrace(); - } - } - if (sourceFileName != null){ - URL url; - try { - url = (new File(sourceFileName)).toURI().toURL(); - sourceViewer.setSource(url, sourceLineNumber); - } catch (MalformedURLException e) { - e.printStackTrace(); - } - } else { - sourceViewer.removeSource(); - } - } - - }); - - return splitPane; - } - - public void setIRAndPc(IR ir, int pc) { - this.ir = ir; - irViewer.setIRAndPc(ir, pc); - } - - public void setIR(IR ir) { - this.ir = ir; - irViewer.setIR(ir); - } - -} +package com.ibm.wala.viz.viewer; + +import java.awt.Component; +import java.io.File; +import java.net.MalformedURLException; +import java.net.URL; + +import javax.swing.JSplitPane; + +import com.ibm.wala.classLoader.IClassLoader; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.viz.viewer.IrViewer.SelectedPcListner; + +public class IrAndSourceViewer { + + private IrViewer irViewer; + private SourceViewer sourceViewer; + + private IR ir; + + public IrAndSourceViewer(CallGraph cg) { + } + + public Component getComponent() { + + + JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT); + irViewer = new IrViewer(); + splitPane.setLeftComponent(irViewer); + + sourceViewer = new SourceViewer(); + splitPane.setRightComponent(sourceViewer); + + irViewer.addSelectedPcListner(new SelectedPcListner(){ + + public void valueChanged(int pc) { + IMethod method = ir.getMethod(); + int sourceLineNumber = IrViewer.NA; + String sourceFileName = null; + if (pc != IrViewer.NA){ + try{ + sourceLineNumber = method.getLineNumber(pc); + IClassLoader loader = method.getDeclaringClass().getClassLoader(); + sourceFileName = loader.getSourceFileName(method, pc); + } catch (Exception e){ + e.printStackTrace(); + } + } + if (sourceFileName != null){ + URL url; + try { + url = (new File(sourceFileName)).toURI().toURL(); + sourceViewer.setSource(url, sourceLineNumber); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } else { + sourceViewer.removeSource(); + } + } + + }); + + return splitPane; + } + + public void setIRAndPc(IR ir, int pc) { + this.ir = ir; + irViewer.setIRAndPc(ir, pc); + } + + public void setIR(IR ir) { + this.ir = ir; + irViewer.setIR(ir); + } + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrViewer.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrViewer.java index 5d9dfeace..48d297d10 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrViewer.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/IrViewer.java @@ -1,156 +1,156 @@ -package com.ibm.wala.viz.viewer; - -import java.awt.BorderLayout; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.StringReader; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; -import javax.swing.ScrollPaneConstants; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; - -import com.ibm.wala.classLoader.IMethod; -import com.ibm.wala.ssa.IR; -import com.ibm.wala.util.collections.HashMapFactory; - -public class IrViewer extends JPanel{ - private JTextField methodName; - private DefaultListModel irLineList = new DefaultListModel(); - private JList irLines; - - // mapping from ir viewer list line to source code line number. - private Map lineToPosition = null; - - // Mapping for pc to line in the ir viewer list. - private Map pcToLine = null; - private Map lineToPc = null; - - public interface SelectedPcListner{ - void valueChanged(int pc); - } - Set selectedPcListners = new HashSet(); - - public IrViewer() { - super(new BorderLayout()); - irLines = new JList(irLineList); - methodName = new JTextField("IR"); - this.add(methodName, BorderLayout.PAGE_START); - this.add(new JScrollPane(irLines, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, - ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER); - - - irLines.addListSelectionListener(new ListSelectionListener() { - public void valueChanged(ListSelectionEvent e) { - int index = irLines.getSelectedIndex(); - Integer pc = lineToPc.get(index); - if (pc == null) { - pc = NA; - } - for (SelectedPcListner selectedPcListner : selectedPcListners) { - selectedPcListner.valueChanged(pc); - } - } - }); - } - - public void setIR(IR ir) { - this.lineToPosition = HashMapFactory.make(); - this.pcToLine = HashMapFactory.make(); - this.lineToPc = HashMapFactory.make(); - - int firstLineWithPosition = NA; - - try { - methodName.setText("IR: " + ir.getMethod()); - irLineList.clear(); - BufferedReader br = new BufferedReader(new StringReader(ir.toString())); - int lineNum = 0; - int position = NA; - String line; - while ((line = br.readLine()) != null) { - irLineList.addElement(line); - int pc = parseIrLine(line); - if (pc != NA) { - IMethod m = ir.getMethod(); - int newPosition = m.getLineNumber(pc); - if (newPosition != -1) { - position = newPosition; - } - lineToPc.put(lineNum, pc); - pcToLine.put(pc, lineNum); - - if (position != NA) { - lineToPosition.put(lineNum, position); - if (firstLineWithPosition == NA){ - firstLineWithPosition = lineNum; - } - } - } - lineNum++; - } - } catch (IOException e) { - // ??? - assert false; - } - - // focusing on the first line with position - if (firstLineWithPosition != NA){ - irLines.setSelectedIndex(firstLineWithPosition); - irLines.ensureIndexIsVisible(firstLineWithPosition); - } - } - - static final int NA = -1; - - private int parseIrLine(String line) { - int firstSpace = line.indexOf(' '); - if (firstSpace > 0) { - String pcString = line.substring(0, firstSpace); - try { - return Integer.parseInt(pcString); - } catch (NumberFormatException e) { - return NA; - } - } else { - return NA; - } - } - - public void addSelectedPcListner(SelectedPcListner selectedPcListner) { - this.selectedPcListners.add(selectedPcListner); - } - - public void setPc(int pc){ - Integer lineNum = pcToLine.get(pc); - if (lineNum != null){ - irLines.ensureIndexIsVisible(lineNum); - irLines.setSelectedIndex(lineNum); - } else { - removeSelection(); - } - } - - public void setIRAndPc(IR ir, int pc) { - setIR(ir); - if (pc != NA){ - setPc(pc); - } else { - removeSelection(); - } - } - - private void removeSelection() { - int curSelectedIndex = irLines.getSelectedIndex(); - irLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex); - } - - -} +package com.ibm.wala.viz.viewer; + +import java.awt.BorderLayout; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; +import javax.swing.ScrollPaneConstants; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.util.collections.HashMapFactory; + +public class IrViewer extends JPanel{ + private JTextField methodName; + private DefaultListModel irLineList = new DefaultListModel(); + private JList irLines; + + // mapping from ir viewer list line to source code line number. + private Map lineToPosition = null; + + // Mapping for pc to line in the ir viewer list. + private Map pcToLine = null; + private Map lineToPc = null; + + public interface SelectedPcListner{ + void valueChanged(int pc); + } + Set selectedPcListners = new HashSet(); + + public IrViewer() { + super(new BorderLayout()); + irLines = new JList(irLineList); + methodName = new JTextField("IR"); + this.add(methodName, BorderLayout.PAGE_START); + this.add(new JScrollPane(irLines, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, + ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER); + + + irLines.addListSelectionListener(new ListSelectionListener() { + public void valueChanged(ListSelectionEvent e) { + int index = irLines.getSelectedIndex(); + Integer pc = lineToPc.get(index); + if (pc == null) { + pc = NA; + } + for (SelectedPcListner selectedPcListner : selectedPcListners) { + selectedPcListner.valueChanged(pc); + } + } + }); + } + + public void setIR(IR ir) { + this.lineToPosition = HashMapFactory.make(); + this.pcToLine = HashMapFactory.make(); + this.lineToPc = HashMapFactory.make(); + + int firstLineWithPosition = NA; + + try { + methodName.setText("IR: " + ir.getMethod()); + irLineList.clear(); + BufferedReader br = new BufferedReader(new StringReader(ir.toString())); + int lineNum = 0; + int position = NA; + String line; + while ((line = br.readLine()) != null) { + irLineList.addElement(line); + int pc = parseIrLine(line); + if (pc != NA) { + IMethod m = ir.getMethod(); + int newPosition = m.getLineNumber(pc); + if (newPosition != -1) { + position = newPosition; + } + lineToPc.put(lineNum, pc); + pcToLine.put(pc, lineNum); + + if (position != NA) { + lineToPosition.put(lineNum, position); + if (firstLineWithPosition == NA){ + firstLineWithPosition = lineNum; + } + } + } + lineNum++; + } + } catch (IOException e) { + // ??? + assert false; + } + + // focusing on the first line with position + if (firstLineWithPosition != NA){ + irLines.setSelectedIndex(firstLineWithPosition); + irLines.ensureIndexIsVisible(firstLineWithPosition); + } + } + + static final int NA = -1; + + private int parseIrLine(String line) { + int firstSpace = line.indexOf(' '); + if (firstSpace > 0) { + String pcString = line.substring(0, firstSpace); + try { + return Integer.parseInt(pcString); + } catch (NumberFormatException e) { + return NA; + } + } else { + return NA; + } + } + + public void addSelectedPcListner(SelectedPcListner selectedPcListner) { + this.selectedPcListners.add(selectedPcListner); + } + + public void setPc(int pc){ + Integer lineNum = pcToLine.get(pc); + if (lineNum != null){ + irLines.ensureIndexIsVisible(lineNum); + irLines.setSelectedIndex(lineNum); + } else { + removeSelection(); + } + } + + public void setIRAndPc(IR ir, int pc) { + setIR(ir); + if (pc != NA){ + setPc(pc); + } else { + removeSelection(); + } + } + + private void removeSelection() { + int curSelectedIndex = irLines.getSelectedIndex(); + irLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex); + } + + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/PaPanel.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/PaPanel.java index c4d639907..184c49e2b 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/PaPanel.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/PaPanel.java @@ -1,288 +1,288 @@ -package com.ibm.wala.viz.viewer; - -import java.awt.BorderLayout; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTextField; -import javax.swing.JTree; -import javax.swing.event.TreeExpansionEvent; -import javax.swing.event.TreeExpansionListener; -import javax.swing.event.TreeSelectionEvent; -import javax.swing.event.TreeSelectionListener; -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; -import javax.swing.tree.TreePath; - -import com.ibm.wala.analysis.pointers.HeapGraph; -import com.ibm.wala.ipa.callgraph.CGNode; -import com.ibm.wala.ipa.callgraph.CallGraph; -import com.ibm.wala.ipa.callgraph.propagation.InstanceFieldPointerKey; -import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; -import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; -import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode; -import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; -import com.ibm.wala.ipa.callgraph.propagation.PointerKey; -import com.ibm.wala.ipa.callgraph.propagation.ReturnValueKey; -import com.ibm.wala.ssa.IR; -import com.ibm.wala.ssa.SSAInstruction; -import com.ibm.wala.util.intset.MutableMapping; -import com.ibm.wala.util.intset.OrdinalSetMapping; - -/** - * Panel for showing the Pointer Analysis results. Shows the heap graph on the left, and the ir viewer on the right. Sets the IR of - * and pc according to the chosen pointer/instance key when possible (e.g., allocation side for NormalAllocationInNode instance - * keys. Can be customized for clients that use different their own pointer / instance keys (see JsPaPanel) - * - * Note the two steps initialization require (calling init()) - * @author yinnonh - * - */ -public class PaPanel extends JSplitPane { - - protected final PointerAnalysis pa; - protected final CallGraph cg; - - private JTextField fullName; - - private IrAndSourceViewer irViewer; - - private MutableMapping> cgNodeIdToLocalPointers = MutableMapping.> make(); - private MutableMapping> cgNodeIdToReturnValue = MutableMapping.> make(); - private MutableMapping> instanceKeyIdToInstanceFieldPointers = MutableMapping.> make(); - - - public PaPanel(CallGraph cg, PointerAnalysis pa) { - super(JSplitPane.HORIZONTAL_SPLIT); - - this.pa = pa; - this.cg = cg; - - initDataStructures(pa); - } - - /** - * Two steps initialization is required here is our deriver can choose the roots for the heap tree. - */ - public void init() { - this.setDividerLocation(250); - - DefaultMutableTreeNode root = new DefaultMutableTreeNode(); - for (Object rootChildNode : getRootNodes()){ - DefaultMutableTreeNode n = new DefaultMutableTreeNode(rootChildNode); - root.add(n); - expandNodeRec(n, 1); - } - - JTree heapTree = new JTree(root); - - heapTree.setCellRenderer(new DualTreeCellRenderer()); - - this.setLeftComponent(new JScrollPane(heapTree)); - JPanel rightPanel = new JPanel(new BorderLayout()); - this.setRightComponent(rightPanel); - fullName = new JTextField(""); - rightPanel.add(fullName, BorderLayout.PAGE_START); - irViewer = new IrAndSourceViewer(cg); - rightPanel.add(irViewer.getComponent(), BorderLayout.CENTER); - - heapTree.addTreeExpansionListener(new TreeExpansionListener() { - - public void treeExpanded(TreeExpansionEvent event) { - TreePath path = event.getPath(); - if (path == null) { - return; - } - DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); - expandNodeRec(lastNode, 2); - } - - public void treeCollapsed(TreeExpansionEvent event) { - } - }); - - heapTree.addTreeSelectionListener(new TreeSelectionListener() { - - public void valueChanged(TreeSelectionEvent e) { - TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); - if (null == newLeadSelectionPath){ - return; - } - DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent(); - Object userObject = treeNode.getUserObject(); - fullName.setText(userObject.toString()); - if (userObject instanceof LocalPointerKey){ - LocalPointerKey lpk = (LocalPointerKey) userObject; - IR ir = lpk.getNode().getIR(); - SSAInstruction def = lpk.getNode().getDU().getDef(lpk.getValueNumber()); - int pc = IrViewer.NA; - if (def != null){ - SSAInstruction[] instructions = ir.getInstructions(); - for (int i = 0; i < instructions.length; i++) { - SSAInstruction instruction = instructions[i]; - if (def == instruction){ - pc = i; - } - } - } - irViewer.setIRAndPc(ir, pc); - } else if (userObject instanceof InstanceFieldPointerKey){ - InstanceKey ik = ((InstanceFieldPointerKey) userObject).getInstanceKey(); - if (ik instanceof NormalAllocationInNode){ - NormalAllocationInNode normalIk = (NormalAllocationInNode) ik; - IR ir = normalIk.getNode().getIR(); - int pc = normalIk.getSite().getProgramCounter(); - irViewer.setIRAndPc(ir, pc); - } - } else if (userObject instanceof NormalAllocationInNode){ - NormalAllocationInNode normalIk = (NormalAllocationInNode) userObject; - IR ir = normalIk.getNode().getIR(); - int pc = normalIk.getSite().getProgramCounter(); - irViewer.setIRAndPc(ir, pc); - } else if (userObject instanceof CGNode){ - irViewer.setIR(((CGNode)userObject).getIR()); - } - - - } - }); - - } - - private void initDataStructures(PointerAnalysis pa) { - HeapGraph heapGraph = pa.getHeapGraph(); - OrdinalSetMapping instanceKeyMapping = pa.getInstanceKeyMapping(); - for (Object n : heapGraph){ - if (heapGraph.getPredNodeCount(n) == 0){ // considering only roots of the heap graph. - if (n instanceof PointerKey){ - if (n instanceof LocalPointerKey){ - LocalPointerKey lpk = (LocalPointerKey) n; - int nodeId = lpk.getNode().getGraphNodeId(); - mapUsingMutableMapping(cgNodeIdToLocalPointers, nodeId, lpk); - } else if (n instanceof ReturnValueKey){ - ReturnValueKey rvk = (ReturnValueKey) n; - int nodeId = rvk.getNode().getGraphNodeId(); - mapUsingMutableMapping(cgNodeIdToReturnValue, nodeId, rvk); - } else if (n instanceof InstanceFieldPointerKey){ - InstanceFieldPointerKey ifpk = (InstanceFieldPointerKey) n; - int instanceKeyId = instanceKeyMapping.getMappedIndex(ifpk.getInstanceKey()); - mapUsingMutableMapping(instanceKeyIdToInstanceFieldPointers, instanceKeyId, ifpk); - } - } else { - System.err.println("Non Pointer key root: " + n); - } - } - } - } - - - /** - * Override if you want different roots for your heap tree. - * @return - */ - protected List getRootNodes(){ - List ret = new ArrayList(); - for (CGNode n : cg){ - ret.add(n); - } - return ret; - } - - /** - * expands the given "treeNode" "rec" levels. - * @param treeNode - * @param rec - */ - private void expandNodeRec(DefaultMutableTreeNode treeNode, int rec) { - if (rec == 0){ - return; - } - - if (treeNode.getChildCount() == 0){ // may be expandable. - List children = getChildrenFor(treeNode.getUserObject()); - for (Object child : children){ - treeNode.add(new DefaultMutableTreeNode(child)); - } - } - - for (int i = 0 ; i < treeNode.getChildCount(); i++){ - TreeNode child = treeNode.getChildAt(i); - expandNodeRec((DefaultMutableTreeNode)child, rec-1); - } - } - - /** - * Used for filling the tree dynamically. Override and handle your own nodes / different links. - * @param node - * @return - */ - protected List getChildrenFor(Object node) { - List ret = new ArrayList(); - if (node instanceof InstanceKey){ - ret.addAll(getPointerKeysUnderInstanceKey((InstanceKey) node)); - } else if (node instanceof PointerKey){ - for (InstanceKey ik : pa.getPointsToSet((PointerKey) node)){ - ret.add(ik); - } - } else if (node instanceof CGNode){ - int nodeId = ((CGNode) node).getGraphNodeId(); - ret.addAll(nonNullList(cgNodeIdToLocalPointers.getMappedObject(nodeId))); - ret.addAll(nonNullList(cgNodeIdToReturnValue.getMappedObject(nodeId))); - } else { - assert false : "Unhandled Node : " + node; - } - return ret; - } - - /** - * Get the set of pointer keys that should be presented below an instance key in the heap tree. Override if you have special - * pointer keys (not just for fields) - * - * @param ik - * @return - */ - protected List getPointerKeysUnderInstanceKey(InstanceKey ik) { - int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik); - List ret; - if (ikIndex <= instanceKeyIdToInstanceFieldPointers.getMaximumIndex()){ - ret = nonNullList(instanceKeyIdToInstanceFieldPointers.getMappedObject(ikIndex)); - } else { - ret = Collections.emptyList(); - } - return ret; - } - - - /** - * Utility method for mutable mapping. map[index] U= o - * @param - * @param map - * @param index - * @param o - */ - protected static void mapUsingMutableMapping(MutableMapping> map, int index, T o){ - List set; - if (index <= map.getMaximumIndex()){ - set = map.getMappedObject(index); - } else { - set = null; - } - if (null == set){ - set = new ArrayList(); - map.put(index, set); - } - set.add(o); - } - - protected List nonNullList(List l){ - if (null == l){ - return Collections.emptyList(); - } else { - return l; - } - } -} +package com.ibm.wala.viz.viewer; + +import java.awt.BorderLayout; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTextField; +import javax.swing.JTree; +import javax.swing.event.TreeExpansionEvent; +import javax.swing.event.TreeExpansionListener; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +import com.ibm.wala.analysis.pointers.HeapGraph; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.propagation.InstanceFieldPointerKey; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; +import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode; +import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; +import com.ibm.wala.ipa.callgraph.propagation.PointerKey; +import com.ibm.wala.ipa.callgraph.propagation.ReturnValueKey; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.ssa.SSAInstruction; +import com.ibm.wala.util.intset.MutableMapping; +import com.ibm.wala.util.intset.OrdinalSetMapping; + +/** + * Panel for showing the Pointer Analysis results. Shows the heap graph on the left, and the ir viewer on the right. Sets the IR of + * and pc according to the chosen pointer/instance key when possible (e.g., allocation side for NormalAllocationInNode instance + * keys. Can be customized for clients that use different their own pointer / instance keys (see JsPaPanel) + * + * Note the two steps initialization require (calling init()) + * @author yinnonh + * + */ +public class PaPanel extends JSplitPane { + + protected final PointerAnalysis pa; + protected final CallGraph cg; + + private JTextField fullName; + + private IrAndSourceViewer irViewer; + + private MutableMapping> cgNodeIdToLocalPointers = MutableMapping.> make(); + private MutableMapping> cgNodeIdToReturnValue = MutableMapping.> make(); + private MutableMapping> instanceKeyIdToInstanceFieldPointers = MutableMapping.> make(); + + + public PaPanel(CallGraph cg, PointerAnalysis pa) { + super(JSplitPane.HORIZONTAL_SPLIT); + + this.pa = pa; + this.cg = cg; + + initDataStructures(pa); + } + + /** + * Two steps initialization is required here is our deriver can choose the roots for the heap tree. + */ + public void init() { + this.setDividerLocation(250); + + DefaultMutableTreeNode root = new DefaultMutableTreeNode(); + for (Object rootChildNode : getRootNodes()){ + DefaultMutableTreeNode n = new DefaultMutableTreeNode(rootChildNode); + root.add(n); + expandNodeRec(n, 1); + } + + JTree heapTree = new JTree(root); + + heapTree.setCellRenderer(new DualTreeCellRenderer()); + + this.setLeftComponent(new JScrollPane(heapTree)); + JPanel rightPanel = new JPanel(new BorderLayout()); + this.setRightComponent(rightPanel); + fullName = new JTextField(""); + rightPanel.add(fullName, BorderLayout.PAGE_START); + irViewer = new IrAndSourceViewer(cg); + rightPanel.add(irViewer.getComponent(), BorderLayout.CENTER); + + heapTree.addTreeExpansionListener(new TreeExpansionListener() { + + public void treeExpanded(TreeExpansionEvent event) { + TreePath path = event.getPath(); + if (path == null) { + return; + } + DefaultMutableTreeNode lastNode = (DefaultMutableTreeNode) path.getLastPathComponent(); + expandNodeRec(lastNode, 2); + } + + public void treeCollapsed(TreeExpansionEvent event) { + } + }); + + heapTree.addTreeSelectionListener(new TreeSelectionListener() { + + public void valueChanged(TreeSelectionEvent e) { + TreePath newLeadSelectionPath = e.getNewLeadSelectionPath(); + if (null == newLeadSelectionPath){ + return; + } + DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) newLeadSelectionPath.getLastPathComponent(); + Object userObject = treeNode.getUserObject(); + fullName.setText(userObject.toString()); + if (userObject instanceof LocalPointerKey){ + LocalPointerKey lpk = (LocalPointerKey) userObject; + IR ir = lpk.getNode().getIR(); + SSAInstruction def = lpk.getNode().getDU().getDef(lpk.getValueNumber()); + int pc = IrViewer.NA; + if (def != null){ + SSAInstruction[] instructions = ir.getInstructions(); + for (int i = 0; i < instructions.length; i++) { + SSAInstruction instruction = instructions[i]; + if (def == instruction){ + pc = i; + } + } + } + irViewer.setIRAndPc(ir, pc); + } else if (userObject instanceof InstanceFieldPointerKey){ + InstanceKey ik = ((InstanceFieldPointerKey) userObject).getInstanceKey(); + if (ik instanceof NormalAllocationInNode){ + NormalAllocationInNode normalIk = (NormalAllocationInNode) ik; + IR ir = normalIk.getNode().getIR(); + int pc = normalIk.getSite().getProgramCounter(); + irViewer.setIRAndPc(ir, pc); + } + } else if (userObject instanceof NormalAllocationInNode){ + NormalAllocationInNode normalIk = (NormalAllocationInNode) userObject; + IR ir = normalIk.getNode().getIR(); + int pc = normalIk.getSite().getProgramCounter(); + irViewer.setIRAndPc(ir, pc); + } else if (userObject instanceof CGNode){ + irViewer.setIR(((CGNode)userObject).getIR()); + } + + + } + }); + + } + + private void initDataStructures(PointerAnalysis pa) { + HeapGraph heapGraph = pa.getHeapGraph(); + OrdinalSetMapping instanceKeyMapping = pa.getInstanceKeyMapping(); + for (Object n : heapGraph){ + if (heapGraph.getPredNodeCount(n) == 0){ // considering only roots of the heap graph. + if (n instanceof PointerKey){ + if (n instanceof LocalPointerKey){ + LocalPointerKey lpk = (LocalPointerKey) n; + int nodeId = lpk.getNode().getGraphNodeId(); + mapUsingMutableMapping(cgNodeIdToLocalPointers, nodeId, lpk); + } else if (n instanceof ReturnValueKey){ + ReturnValueKey rvk = (ReturnValueKey) n; + int nodeId = rvk.getNode().getGraphNodeId(); + mapUsingMutableMapping(cgNodeIdToReturnValue, nodeId, rvk); + } else if (n instanceof InstanceFieldPointerKey){ + InstanceFieldPointerKey ifpk = (InstanceFieldPointerKey) n; + int instanceKeyId = instanceKeyMapping.getMappedIndex(ifpk.getInstanceKey()); + mapUsingMutableMapping(instanceKeyIdToInstanceFieldPointers, instanceKeyId, ifpk); + } + } else { + System.err.println("Non Pointer key root: " + n); + } + } + } + } + + + /** + * Override if you want different roots for your heap tree. + * @return + */ + protected List getRootNodes(){ + List ret = new ArrayList(); + for (CGNode n : cg){ + ret.add(n); + } + return ret; + } + + /** + * expands the given "treeNode" "rec" levels. + * @param treeNode + * @param rec + */ + private void expandNodeRec(DefaultMutableTreeNode treeNode, int rec) { + if (rec == 0){ + return; + } + + if (treeNode.getChildCount() == 0){ // may be expandable. + List children = getChildrenFor(treeNode.getUserObject()); + for (Object child : children){ + treeNode.add(new DefaultMutableTreeNode(child)); + } + } + + for (int i = 0 ; i < treeNode.getChildCount(); i++){ + TreeNode child = treeNode.getChildAt(i); + expandNodeRec((DefaultMutableTreeNode)child, rec-1); + } + } + + /** + * Used for filling the tree dynamically. Override and handle your own nodes / different links. + * @param node + * @return + */ + protected List getChildrenFor(Object node) { + List ret = new ArrayList(); + if (node instanceof InstanceKey){ + ret.addAll(getPointerKeysUnderInstanceKey((InstanceKey) node)); + } else if (node instanceof PointerKey){ + for (InstanceKey ik : pa.getPointsToSet((PointerKey) node)){ + ret.add(ik); + } + } else if (node instanceof CGNode){ + int nodeId = ((CGNode) node).getGraphNodeId(); + ret.addAll(nonNullList(cgNodeIdToLocalPointers.getMappedObject(nodeId))); + ret.addAll(nonNullList(cgNodeIdToReturnValue.getMappedObject(nodeId))); + } else { + assert false : "Unhandled Node : " + node; + } + return ret; + } + + /** + * Get the set of pointer keys that should be presented below an instance key in the heap tree. Override if you have special + * pointer keys (not just for fields) + * + * @param ik + * @return + */ + protected List getPointerKeysUnderInstanceKey(InstanceKey ik) { + int ikIndex = pa.getInstanceKeyMapping().getMappedIndex(ik); + List ret; + if (ikIndex <= instanceKeyIdToInstanceFieldPointers.getMaximumIndex()){ + ret = nonNullList(instanceKeyIdToInstanceFieldPointers.getMappedObject(ikIndex)); + } else { + ret = Collections.emptyList(); + } + return ret; + } + + + /** + * Utility method for mutable mapping. map[index] U= o + * @param + * @param map + * @param index + * @param o + */ + protected static void mapUsingMutableMapping(MutableMapping> map, int index, T o){ + List set; + if (index <= map.getMaximumIndex()){ + set = map.getMappedObject(index); + } else { + set = null; + } + if (null == set){ + set = new ArrayList(); + map.put(index, set); + } + set.add(o); + } + + protected List nonNullList(List l){ + if (null == l){ + return Collections.emptyList(); + } else { + return l; + } + } +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/SourceViewer.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/SourceViewer.java index 0d61cd604..319a6f82c 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/SourceViewer.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/SourceViewer.java @@ -1,89 +1,89 @@ -package com.ibm.wala.viz.viewer; - -import java.awt.BorderLayout; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.net.URL; - -import javax.swing.DefaultListModel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextField; - -public class SourceViewer extends JPanel{ - private URL sourceURL; - private JTextField sourceCodeLocation; - private DefaultListModel sourceCodeLinesList = new DefaultListModel(); - private JList sourceCodeLines; - - public SourceViewer() { - super(new BorderLayout()); - sourceURL = null; - sourceCodeLines = new JList(sourceCodeLinesList); - sourceCodeLocation = new JTextField("Source code"); - this.add(sourceCodeLocation, BorderLayout.PAGE_START); - this.add(new JScrollPane(sourceCodeLines), BorderLayout.CENTER); - } - - public void setSource(URL url) { - setSource(url, IrViewer.NA); - } - - public void setSource(URL url, int sourceLine) { - boolean succsess = loadSource(url); - if (succsess){ - sourceCodeLocation.setText("Source code: " + url); - if (sourceLine != IrViewer.NA){ - sourceCodeLines.ensureIndexIsVisible(sourceLine-1); - sourceCodeLines.setSelectedIndex(sourceLine-1); - sourceCodeLines.validate(); - } - } else { - sourceCodeLocation.setText("Error loading source code from: " + url); - } - } - - private boolean loadSource(URL url) { - if (url == null) { - if (sourceURL != null) { - // easing the current code. - sourceCodeLinesList.clear(); - } - return false; // nothing to load - } else { - if (url.equals(sourceURL)) { - return true; // already loaded - } else { - sourceCodeLinesList.clear(); - try { - BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream())); - String line; - while ((line = br.readLine()) != null) { - sourceCodeLinesList.addElement(line.replaceAll("\t", " ")); - } - br.close(); - return true; - } catch (IOException e) { - System.err.println("Could not load source at " + url); - return false; - } - } - } - } - - public void removeSelection() { - int curSelectedIndex = sourceCodeLines.getSelectedIndex(); - sourceCodeLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex); - } - - public void removeSource() { - sourceURL = null; - sourceCodeLocation.setText("Source code"); - sourceCodeLinesList.clear(); - sourceCodeLines.validate(); - } - - -} +package com.ibm.wala.viz.viewer; + +import java.awt.BorderLayout; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; + +import javax.swing.DefaultListModel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextField; + +public class SourceViewer extends JPanel{ + private URL sourceURL; + private JTextField sourceCodeLocation; + private DefaultListModel sourceCodeLinesList = new DefaultListModel(); + private JList sourceCodeLines; + + public SourceViewer() { + super(new BorderLayout()); + sourceURL = null; + sourceCodeLines = new JList(sourceCodeLinesList); + sourceCodeLocation = new JTextField("Source code"); + this.add(sourceCodeLocation, BorderLayout.PAGE_START); + this.add(new JScrollPane(sourceCodeLines), BorderLayout.CENTER); + } + + public void setSource(URL url) { + setSource(url, IrViewer.NA); + } + + public void setSource(URL url, int sourceLine) { + boolean succsess = loadSource(url); + if (succsess){ + sourceCodeLocation.setText("Source code: " + url); + if (sourceLine != IrViewer.NA){ + sourceCodeLines.ensureIndexIsVisible(sourceLine-1); + sourceCodeLines.setSelectedIndex(sourceLine-1); + sourceCodeLines.validate(); + } + } else { + sourceCodeLocation.setText("Error loading source code from: " + url); + } + } + + private boolean loadSource(URL url) { + if (url == null) { + if (sourceURL != null) { + // easing the current code. + sourceCodeLinesList.clear(); + } + return false; // nothing to load + } else { + if (url.equals(sourceURL)) { + return true; // already loaded + } else { + sourceCodeLinesList.clear(); + try { + BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream())); + String line; + while ((line = br.readLine()) != null) { + sourceCodeLinesList.addElement(line.replaceAll("\t", " ")); + } + br.close(); + return true; + } catch (IOException e) { + System.err.println("Could not load source at " + url); + return false; + } + } + } + } + + public void removeSelection() { + int curSelectedIndex = sourceCodeLines.getSelectedIndex(); + sourceCodeLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex); + } + + public void removeSource() { + sourceURL = null; + sourceCodeLocation.setText("Source code"); + sourceCodeLinesList.clear(); + sourceCodeLines.validate(); + } + + +} diff --git a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/WalaViewer.java b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/WalaViewer.java index 6d26c4d12..7221d64af 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/WalaViewer.java +++ b/com.ibm.wala.core/src/com/ibm/wala/viz/viewer/WalaViewer.java @@ -1,62 +1,62 @@ -package com.ibm.wala.viz.viewer; - -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; - -import javax.swing.JFrame; -import javax.swing.JTabbedPane; -import javax.swing.UIManager; - -import com.ibm.wala.ipa.callgraph.CallGraph; -import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; - -/** - * Viewer for ClassHeirarcy, CallGraph and Pointer Analysis results. - * A driver for example can be found in com.ibm.wala.js.rhino.vis.JsViewer. - * @author yinnonh - * - */ -public class WalaViewer extends JFrame { - - protected static final String DefaultMutableTreeNode = null; - - - public WalaViewer(CallGraph cg, PointerAnalysis pa) { - setNativeLookAndFeel(); - - JTabbedPane tabbedPane = new JTabbedPane(); - tabbedPane.add("Call Graph", new CgPanel(cg)); - tabbedPane.add("Class Hierarchy", new ChaPanel(cg.getClassHierarchy())); - PaPanel paPanel = createPaPanel(cg, pa); - paPanel.init(); - tabbedPane.add("Pointer Analysis", paPanel); - - setSize(600, 800); - setExtendedState(MAXIMIZED_BOTH); - addWindowListener(new ExitListener()); - - this.setTitle("Wala viewer"); - - add(tabbedPane); - setVisible(true); - } - - protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) { - return new PaPanel(cg, pa); - } - - public static void setNativeLookAndFeel() { - try { - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } catch(Exception e) { - e.printStackTrace(); - } - } - - private static class ExitListener extends WindowAdapter { - @Override - public void windowClosing(WindowEvent event) { - System.exit(0); - } - } +package com.ibm.wala.viz.viewer; + +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.JTabbedPane; +import javax.swing.UIManager; + +import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; + +/** + * Viewer for ClassHeirarcy, CallGraph and Pointer Analysis results. + * A driver for example can be found in com.ibm.wala.js.rhino.vis.JsViewer. + * @author yinnonh + * + */ +public class WalaViewer extends JFrame { + + protected static final String DefaultMutableTreeNode = null; + + + public WalaViewer(CallGraph cg, PointerAnalysis pa) { + setNativeLookAndFeel(); + + JTabbedPane tabbedPane = new JTabbedPane(); + tabbedPane.add("Call Graph", new CgPanel(cg)); + tabbedPane.add("Class Hierarchy", new ChaPanel(cg.getClassHierarchy())); + PaPanel paPanel = createPaPanel(cg, pa); + paPanel.init(); + tabbedPane.add("Pointer Analysis", paPanel); + + setSize(600, 800); + setExtendedState(MAXIMIZED_BOTH); + addWindowListener(new ExitListener()); + + this.setTitle("Wala viewer"); + + add(tabbedPane); + setVisible(true); + } + + protected PaPanel createPaPanel(CallGraph cg, PointerAnalysis pa) { + return new PaPanel(cg, pa); + } + + public static void setNativeLookAndFeel() { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch(Exception e) { + e.printStackTrace(); + } + } + + private static class ExitListener extends WindowAdapter { + @Override + public void windowClosing(WindowEvent event) { + System.exit(0); + } + } } \ No newline at end of file diff --git a/com.ibm.wala.util/src/com/ibm/wala/util/PlatformUtil.java b/com.ibm.wala.util/src/com/ibm/wala/util/PlatformUtil.java index cfd158f4b..f72157ae4 100644 --- a/com.ibm.wala.util/src/com/ibm/wala/util/PlatformUtil.java +++ b/com.ibm.wala.util/src/com/ibm/wala/util/PlatformUtil.java @@ -40,4 +40,11 @@ public class PlatformUtil { return osname.toLowerCase().contains("windows"); } + /** + * are we running on IKVM? see http://www.ikvm.net + */ + public static boolean onIKVM() { + return "IKVM.NET".equals(System.getProperty("java.runtime.name")); + } + } From cbd8b63142a8e5729eb22bdf9bfaa26f389f2009 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Wed, 28 Dec 2011 17:03:42 +0000 Subject: [PATCH 004/238] undo change to SlicerTest git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4291 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../src/com/ibm/wala/core/tests/slicer/SlicerTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java index 9d9b47160..e8804377e 100644 --- a/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java +++ b/com.ibm.wala.core.tests/src/com/ibm/wala/core/tests/slicer/SlicerTest.java @@ -21,7 +21,6 @@ import java.util.Iterator; import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Ignore; import org.junit.Test; import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil; @@ -221,7 +220,6 @@ public class SlicerTest { * @throws IllegalArgumentException * @throws IOException */ - @Ignore @Test public void testSlice7() throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException { AnalysisScope scope = findOrCreateAnalysisScope(); From d326e5e9f284aa77005060d72b8ae648337f7bb3 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Wed, 28 Dec 2011 17:03:55 +0000 Subject: [PATCH 005/238] bug fixes git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4292 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java index dd72e2940..367a57997 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ssa/SSABuilder.java @@ -1019,7 +1019,9 @@ public class SSABuilder extends AbstractIntStackMachine { * array of the local numbers. else return null. */ private int[] findLocalsForValueNumber(int pc, int vn) { - + if (vn < 0) { + return null; + } IBasicBlock bb = shrikeCFG.getBlockForInstruction(pc); int firstInstruction = bb.getFirstInstructionIndex(); // walk forward from the first instruction to reconstruct the @@ -1028,16 +1030,17 @@ public class SSABuilder extends AbstractIntStackMachine { for (int i = firstInstruction; i <= pc; i++) { if (localStoreMap[i] != null) { IntPair p = localStoreMap[i]; - setLocal(locals, p.getY(), p.getX()); + locals = setLocal(locals, p.getY(), p.getX()); } } - return extractIndices(locals, vn); + return locals == null ? null : extractIndices(locals, vn); } /** * @return the indices i s.t. x[i] == y, or null if none found. */ private int[] extractIndices(int[] x, int y) { + assert x != null; int count = 0; for (int i = 0; i < x.length; i++) { if (x[i] == y) { From e0e833e5116661efe77fe9323efd33b57a710972 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Thu, 5 Jan 2012 19:55:16 +0000 Subject: [PATCH 007/238] initial commit git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4294 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../.classpath | 9 + .../.project | 28 +++ .../.settings/org.eclipse.jdt.core.prefs | 12 ++ .../META-INF/MANIFEST.MF | 12 ++ .../build.properties | 3 + .../build.xml | 67 +++++++ .../nu_validator/NuValidatorHtmlParser.java | 164 ++++++++++++++++++ .../TestSimplePageCallGraphShapeRhinoNu.java | 16 ++ 8 files changed, 311 insertions(+) create mode 100644 com.ibm.wala.cast.js.html.nu_validator/.classpath create mode 100644 com.ibm.wala.cast.js.html.nu_validator/.project create mode 100644 com.ibm.wala.cast.js.html.nu_validator/.settings/org.eclipse.jdt.core.prefs create mode 100644 com.ibm.wala.cast.js.html.nu_validator/META-INF/MANIFEST.MF create mode 100644 com.ibm.wala.cast.js.html.nu_validator/build.properties create mode 100755 com.ibm.wala.cast.js.html.nu_validator/build.xml create mode 100644 com.ibm.wala.cast.js.html.nu_validator/src/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java create mode 100644 com.ibm.wala.cast.js.html.nu_validator/tests/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java diff --git a/com.ibm.wala.cast.js.html.nu_validator/.classpath b/com.ibm.wala.cast.js.html.nu_validator/.classpath new file mode 100644 index 000000000..abd692151 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/.classpath @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/com.ibm.wala.cast.js.html.nu_validator/.project b/com.ibm.wala.cast.js.html.nu_validator/.project new file mode 100644 index 000000000..d963a4a29 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/.project @@ -0,0 +1,28 @@ + + + com.ibm.wala.cast.js.html.nu_validator + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/com.ibm.wala.cast.js.html.nu_validator/.settings/org.eclipse.jdt.core.prefs b/com.ibm.wala.cast.js.html.nu_validator/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..d7bba4ec9 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Thu Jan 05 09:28:01 MST 2012 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/com.ibm.wala.cast.js.html.nu_validator/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js.html.nu_validator/META-INF/MANIFEST.MF new file mode 100644 index 000000000..5503cf8b1 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/META-INF/MANIFEST.MF @@ -0,0 +1,12 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Nu_validator +Bundle-SymbolicName: com.ibm.wala.cast.js.html.nu_validator +Bundle-Version: 1.0.0.qualifier +Export-Package: com.ibm.wala.cast.js.html.nu_validator +Require-Bundle: com.ibm.wala.cast.js;bundle-version="1.0.0", + com.ibm.wala.cast.js.rhino.test;bundle-version="1.0.0", + com.ibm.wala.cast.js.test;bundle-version="1.0.0", + com.ibm.wala.cast.test;bundle-version="1.0.0", + com.ibm.wala.core.tests;bundle-version="1.1.3", + com.ibm.wala.core;bundle-version="1.1.3" diff --git a/com.ibm.wala.cast.js.html.nu_validator/build.properties b/com.ibm.wala.cast.js.html.nu_validator/build.properties new file mode 100644 index 000000000..b107977f4 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/build.properties @@ -0,0 +1,3 @@ +source.. = src/ +bin.includes = META-INF/,\ + . diff --git a/com.ibm.wala.cast.js.html.nu_validator/build.xml b/com.ibm.wala.cast.js.html.nu_validator/build.xml new file mode 100755 index 000000000..df4a17321 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/build.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/com.ibm.wala.cast.js.html.nu_validator/src/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java b/com.ibm.wala.cast.js.html.nu_validator/src/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java new file mode 100644 index 000000000..0a7749a96 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/src/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java @@ -0,0 +1,164 @@ +/****************************************************************************** + * Copyright (c) 2002 - 2011 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.cast.js.html.nu_validator; + +import java.io.IOException; +import java.io.InputStream; +import java.io.LineNumberReader; +import java.io.StringReader; +import java.util.AbstractMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import nu.validator.htmlparser.common.XmlViolationPolicy; +import nu.validator.htmlparser.sax.HtmlParser; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; + +import com.ibm.wala.cast.js.html.IHtmlCallback; +import com.ibm.wala.cast.js.html.IHtmlParser; +import com.ibm.wala.cast.js.html.ITag; + +public class NuValidatorHtmlParser implements IHtmlParser { + + public void parse(final InputStream reader, final IHtmlCallback handler, String fileName) { + HtmlParser parser = new HtmlParser(); + parser.setXmlPolicy(XmlViolationPolicy.ALLOW); + parser.setContentHandler(new ContentHandler() { + private Locator locator; + private Stack tags = new Stack();; + + private int countLines(char[] ch, int start, int length) { + LineNumberReader r = new LineNumberReader(new StringReader (new String(ch, start, length))); + try { + while (r.read() > -1); + } catch (IOException e) { + throw new RuntimeException("cannot read from string", e); + } + return r.getLineNumber(); + } + + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + public void startElement(String uri, final String localName, String qName, final Attributes atts) throws SAXException { + final int line = locator.getLineNumber(); + tags.push(new ITag() { + + public String getName() { + return localName; + } + + public String getAttributeByName(String name) { + return atts.getValue(name); + } + + public Map getAllAttributes() { + return new AbstractMap() { + private Set> es = null; + + @Override + public Set> entrySet() { + if (es == null) { + es = new HashSet>(); + for(int i = 0; i < atts.getLength(); i++) { + final int index = i; + es.add(new Map.Entry() { + + public String getKey() { + return atts.getLocalName(index); + } + + public String getValue() { + return atts.getValue(index); + } + + public String setValue(String value) { + throw new UnsupportedOperationException(); + } + }); + } + } + return es; + } + }; + } + + public int getStartingLineNum() { + return line; + } + }); + handler.handleStartTag(tags.peek()); + } + + public void endElement(String uri, String localName, String qName) throws SAXException { + handler.handleEndTag(tags.pop()); + } + + public void characters(char[] ch, int start, int length) throws SAXException { + handler.handleText(locator.getLineNumber() - countLines(ch, start, length), new String(ch, start, length)); + } + + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + handler.handleText(locator.getLineNumber(), new String(ch, start, length)); + } + + public void startDocument() throws SAXException { + // do nothing + } + + public void endDocument() throws SAXException { + // do nothing + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + // do nothing + } + + public void endPrefixMapping(String prefix) throws SAXException { + // do nothing + } + + public void processingInstruction(String target, String data) throws SAXException { + // do nothing + } + + public void skippedEntity(String name) throws SAXException { + // do nothing + } + + }); + + try { + parser.parse(new InputSource(new InputStream() { + @Override + public int read() throws IOException { + int v; + do { + v = reader.read(); + } while (v == '\r'); + return v; + } + })); + } catch (IOException e) { + assert false : e.toString(); + } catch (SAXException e) { + assert false : e.toString(); + } + } +} diff --git a/com.ibm.wala.cast.js.html.nu_validator/tests/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java b/com.ibm.wala.cast.js.html.nu_validator/tests/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java new file mode 100644 index 000000000..9e2a9def6 --- /dev/null +++ b/com.ibm.wala.cast.js.html.nu_validator/tests/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java @@ -0,0 +1,16 @@ +package com.ibm.wala.cast.js.test; + +import com.ibm.wala.cast.js.html.IHtmlParser; +import com.ibm.wala.cast.js.html.nu_validator.NuValidatorHtmlParser; + +public class TestSimplePageCallGraphShapeRhinoNu extends TestSimplePageCallGraphShapeRhino { + + public static void main(String[] args) { + justThisTest(TestSimplePageCallGraphShapeRhinoNu.class); + } + + @Override + protected IHtmlParser getParser() { + return new NuValidatorHtmlParser(); + } +} From 05f0d27d45a64336ed3e22ed35b8666668c066c1 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Thu, 5 Jan 2012 19:58:35 +0000 Subject: [PATCH 009/238] move code related to validator.nu HTML parser to a separate project git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4296 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../META-INF/MANIFEST.MF | 1 + .../TestSimplePageCallGraphShapeRhinoNu.java | 16 -- com.ibm.wala.cast.js/.classpath | 1 - com.ibm.wala.cast.js/META-INF/MANIFEST.MF | 1 - com.ibm.wala.cast.js/build.xml | 14 +- .../nu_validator/NuValidatorHtmlParser.java | 164 ------------------ 6 files changed, 2 insertions(+), 195 deletions(-) delete mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java delete mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java diff --git a/com.ibm.wala.cast.js.rhino.test/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js.rhino.test/META-INF/MANIFEST.MF index ba0fd6df3..a29cbbf82 100644 --- a/com.ibm.wala.cast.js.rhino.test/META-INF/MANIFEST.MF +++ b/com.ibm.wala.cast.js.rhino.test/META-INF/MANIFEST.MF @@ -16,3 +16,4 @@ Require-Bundle: org.eclipse.core.runtime, org.junit4;bundle-version="4.3.1" Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-ActivationPolicy: lazy +Export-Package: com.ibm.wala.cast.js.test diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java deleted file mode 100644 index 9e2a9def6..000000000 --- a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShapeRhinoNu.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.ibm.wala.cast.js.test; - -import com.ibm.wala.cast.js.html.IHtmlParser; -import com.ibm.wala.cast.js.html.nu_validator.NuValidatorHtmlParser; - -public class TestSimplePageCallGraphShapeRhinoNu extends TestSimplePageCallGraphShapeRhino { - - public static void main(String[] args) { - justThisTest(TestSimplePageCallGraphShapeRhinoNu.class); - } - - @Override - protected IHtmlParser getParser() { - return new NuValidatorHtmlParser(); - } -} diff --git a/com.ibm.wala.cast.js/.classpath b/com.ibm.wala.cast.js/.classpath index 70b978254..f0389962a 100644 --- a/com.ibm.wala.cast.js/.classpath +++ b/com.ibm.wala.cast.js/.classpath @@ -2,7 +2,6 @@ - diff --git a/com.ibm.wala.cast.js/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js/META-INF/MANIFEST.MF index bb3ccdaa9..e5b9d9e7e 100644 --- a/com.ibm.wala.cast.js/META-INF/MANIFEST.MF +++ b/com.ibm.wala.cast.js/META-INF/MANIFEST.MF @@ -16,7 +16,6 @@ Export-Package: com.ibm.wala.cast.js, com.ibm.wala.cast.js.client.impl, com.ibm.wala.cast.js.html, com.ibm.wala.cast.js.html.jericho, - com.ibm.wala.cast.js.html.nu_validator, com.ibm.wala.cast.js.ipa.callgraph, com.ibm.wala.cast.js.ipa.summaries, com.ibm.wala.cast.js.loader, diff --git a/com.ibm.wala.cast.js/build.xml b/com.ibm.wala.cast.js/build.xml index 4ffa2b05b..17c47919f 100755 --- a/com.ibm.wala.cast.js/build.xml +++ b/com.ibm.wala.cast.js/build.xml @@ -45,20 +45,8 @@ - - - - - - - - - - - - - + diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java deleted file mode 100644 index 0a7749a96..000000000 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/nu_validator/NuValidatorHtmlParser.java +++ /dev/null @@ -1,164 +0,0 @@ -/****************************************************************************** - * Copyright (c) 2002 - 2011 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.cast.js.html.nu_validator; - -import java.io.IOException; -import java.io.InputStream; -import java.io.LineNumberReader; -import java.io.StringReader; -import java.util.AbstractMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.Stack; - -import nu.validator.htmlparser.common.XmlViolationPolicy; -import nu.validator.htmlparser.sax.HtmlParser; - -import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.InputSource; -import org.xml.sax.Locator; -import org.xml.sax.SAXException; - -import com.ibm.wala.cast.js.html.IHtmlCallback; -import com.ibm.wala.cast.js.html.IHtmlParser; -import com.ibm.wala.cast.js.html.ITag; - -public class NuValidatorHtmlParser implements IHtmlParser { - - public void parse(final InputStream reader, final IHtmlCallback handler, String fileName) { - HtmlParser parser = new HtmlParser(); - parser.setXmlPolicy(XmlViolationPolicy.ALLOW); - parser.setContentHandler(new ContentHandler() { - private Locator locator; - private Stack tags = new Stack();; - - private int countLines(char[] ch, int start, int length) { - LineNumberReader r = new LineNumberReader(new StringReader (new String(ch, start, length))); - try { - while (r.read() > -1); - } catch (IOException e) { - throw new RuntimeException("cannot read from string", e); - } - return r.getLineNumber(); - } - - public void setDocumentLocator(Locator locator) { - this.locator = locator; - } - - public void startElement(String uri, final String localName, String qName, final Attributes atts) throws SAXException { - final int line = locator.getLineNumber(); - tags.push(new ITag() { - - public String getName() { - return localName; - } - - public String getAttributeByName(String name) { - return atts.getValue(name); - } - - public Map getAllAttributes() { - return new AbstractMap() { - private Set> es = null; - - @Override - public Set> entrySet() { - if (es == null) { - es = new HashSet>(); - for(int i = 0; i < atts.getLength(); i++) { - final int index = i; - es.add(new Map.Entry() { - - public String getKey() { - return atts.getLocalName(index); - } - - public String getValue() { - return atts.getValue(index); - } - - public String setValue(String value) { - throw new UnsupportedOperationException(); - } - }); - } - } - return es; - } - }; - } - - public int getStartingLineNum() { - return line; - } - }); - handler.handleStartTag(tags.peek()); - } - - public void endElement(String uri, String localName, String qName) throws SAXException { - handler.handleEndTag(tags.pop()); - } - - public void characters(char[] ch, int start, int length) throws SAXException { - handler.handleText(locator.getLineNumber() - countLines(ch, start, length), new String(ch, start, length)); - } - - public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { - handler.handleText(locator.getLineNumber(), new String(ch, start, length)); - } - - public void startDocument() throws SAXException { - // do nothing - } - - public void endDocument() throws SAXException { - // do nothing - } - - public void startPrefixMapping(String prefix, String uri) throws SAXException { - // do nothing - } - - public void endPrefixMapping(String prefix) throws SAXException { - // do nothing - } - - public void processingInstruction(String target, String data) throws SAXException { - // do nothing - } - - public void skippedEntity(String name) throws SAXException { - // do nothing - } - - }); - - try { - parser.parse(new InputSource(new InputStream() { - @Override - public int read() throws IOException { - int v; - do { - v = reader.read(); - } while (v == '\r'); - return v; - } - })); - } catch (IOException e) { - assert false : e.toString(); - } catch (SAXException e) { - assert false : e.toString(); - } - } -} From 4edec7f18ebc8125626b3af5c031c4bfc82e5a44 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Thu, 5 Jan 2012 20:10:34 +0000 Subject: [PATCH 010/238] remove unused imports git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4297 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/js/translator/PropertyReadExpander.java | 1 - .../source/java/com/ibm/wala/cast/ipa/callgraph/Util.java | 1 - .../src/com/ibm/wala/analysis/reflection/JavaTypeContext.java | 1 - .../src/com/ibm/wala/classLoader/CompoundModule.java | 1 - .../wala/ipa/callgraph/propagation/ReceiverInstanceContext.java | 1 - 5 files changed, 5 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java index 019d328ba..aa8e2b1de 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java @@ -5,7 +5,6 @@ import java.util.Map; import com.ibm.wala.cast.ir.translator.AstTranslator.InternalCAstSymbol; import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAstNode; -import com.ibm.wala.cast.tree.impl.CAstBasicRewriter; import com.ibm.wala.cast.tree.impl.CAstOperator; import com.ibm.wala.cast.tree.impl.CAstRewriter; import com.ibm.wala.cast.tree.impl.CAstRewriter.CopyKey; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index 8b99338c3..41949a7b2 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -28,7 +28,6 @@ import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ipa.callgraph.propagation.PointerKey; -import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; import com.ibm.wala.ssa.IR; import com.ibm.wala.util.debug.Assertions; diff --git a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaTypeContext.java b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaTypeContext.java index d3b95b55b..4d4836c3a 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaTypeContext.java +++ b/com.ibm.wala.core/src/com/ibm/wala/analysis/reflection/JavaTypeContext.java @@ -17,7 +17,6 @@ import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; -import com.ibm.wala.util.debug.Assertions; /** * Implement a Context which corresponds to a given type abstraction. Thus, this maps the name "TYPE" to a JavaTypeAbstraction. diff --git a/com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java b/com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java index 42318f1ed..1a238737f 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java +++ b/com.ibm.wala.core/src/com/ibm/wala/classLoader/CompoundModule.java @@ -16,7 +16,6 @@ import java.io.InputStreamReader; import java.io.LineNumberReader; import java.net.URL; import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; import java.util.List; diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/ReceiverInstanceContext.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/ReceiverInstanceContext.java index cc5f508b1..7545222f2 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/ReceiverInstanceContext.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/ReceiverInstanceContext.java @@ -13,7 +13,6 @@ package com.ibm.wala.ipa.callgraph.propagation; import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.ContextKey; -import com.ibm.wala.util.debug.Assertions; /** * This is a context which is customized for the {@link InstanceKey} of the receiver. From a033b2364a3bfff49c7ddf7ef3e589f7a53add83 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:16:55 +0000 Subject: [PATCH 011/238] Extracted out some more general functionality from ForInLoopRewriter into new super class CAstRewriterExt. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4298 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f3b736a53..ffabbbb18 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ */bin/ com.ibm.wala.cast.js.rhino/lib/ com.ibm.wala.cast.js/lib/ +<<<<<<< HEAD com.ibm.wala.cast.java.polyglot/lib/ com.ibm.wala.cast.java.test.data/src/JLex/ .metadata/ @@ -9,3 +10,5 @@ com.ibm.wala.cast.js.test/examples-src/ajaxslt/ com.ibm.wala.core.testdata/@dot/ com.ibm.wala.core.testdata/lib/ com.ibm.wala.core/dat/wala.properties +======= +>>>>>>> Extracted out some more general functionality from ForInLoopRewriter into new super class CAstRewriterExt. From b517c6ca859ae2a1f07fbb2abc0b16e3cd3e1e83 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:17:15 +0000 Subject: [PATCH 012/238] Started testing on MooTools. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4299 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../javascript/RhinoToAstTranslator.java | 44 ++++++++++--------- .../tree/impl/CAstControlFlowRecorder.java | 1 + .../ibm/wala/cast/tree/impl/CAstRewriter.java | 8 ++-- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index 234f6f09a..b958a3226 100644 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -118,7 +118,7 @@ public class RhinoToAstTranslator { /** * @see BaseCollectingContext */ - CAstNode getBaseVarIfRelevant(Node node); + String getBaseVarNameIfRelevant(Node node); /** * @see BaseCollectingContext @@ -196,7 +196,7 @@ public class RhinoToAstTranslator { return null; } - public CAstNode getBaseVarIfRelevant(Node node) { + public String getBaseVarNameIfRelevant(Node node) { return null; } @@ -268,8 +268,8 @@ public class RhinoToAstTranslator { return parent.getCatchTarget(); } - public CAstNode getBaseVarIfRelevant(Node node) { - return parent.getBaseVarIfRelevant(node); + public String getBaseVarNameIfRelevant(Node node) { + return parent.getBaseVarNameIfRelevant(node); } public boolean foundBase(Node node) { @@ -447,30 +447,30 @@ public class RhinoToAstTranslator { private Node baseFor; /** - * the variable to be used to store the value of the expression passed as - * the 'this' parameter + * the name of the variable to be used to store the value of the expression + * passed as the 'this' parameter */ - private final CAstNode baseVar; + private final String baseVarName; /** * have we discovered a value to be passed as the 'this' parameter? */ private boolean foundBase = false; - BaseCollectingContext(WalkContext parent, Node initialBaseFor, CAstNode baseVar) { + BaseCollectingContext(WalkContext parent, Node initialBaseFor, String baseVarName) { super(parent); baseFor = initialBaseFor; - this.baseVar = baseVar; + this.baseVarName = baseVarName; } /** * if node is one that we care about, return baseVar, and as a side effect * set foundBase to true. Otherwise, return null. */ - public CAstNode getBaseVarIfRelevant(Node node) { + public String getBaseVarNameIfRelevant(Node node) { if (baseFor.equals(node)) { foundBase = true; - return baseVar; + return baseVarName; } else { return null; } @@ -1109,7 +1109,7 @@ public class RhinoToAstTranslator { if (!isPrimitiveCall(context, n)) { CAstNode base = Ast.makeNode(CAstNode.VAR, Ast.makeConstant("base")); Node callee = n.getFirstChild(); - WalkContext child = new BaseCollectingContext(context, callee, base); + WalkContext child = new BaseCollectingContext(context, callee, "base"); CAstNode fun = walkNodes(callee, child); // the first actual parameter appearing within the parentheses of the @@ -1401,14 +1401,14 @@ public class RhinoToAstTranslator { Node element = receiver.getNext(); CAstNode rcvr = walkNodes(receiver, context); - CAstNode baseVar = context.getBaseVarIfRelevant(n); + String baseVarName = context.getBaseVarNameIfRelevant(n); CAstNode elt = walkNodes(element, context); CAstNode get, result; - if (baseVar != null) { - result = Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, baseVar, rcvr), - get = Ast.makeNode(CAstNode.OBJECT_REF, baseVar, elt)); + if (baseVarName != null) { + result = Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), rcvr), + get = Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), elt)); } else { result = get = Ast.makeNode(CAstNode.OBJECT_REF, rcvr, elt); } @@ -1475,13 +1475,13 @@ public class RhinoToAstTranslator { Node element = receiver.getNext(); CAstNode rcvr = walkNodes(receiver, context); - CAstNode baseVar = context.getBaseVarIfRelevant(n); + String baseVarName = context.getBaseVarNameIfRelevant(n); CAstNode elt = walkNodes(element, context); - if (baseVar != null) { - return Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, baseVar, rcvr), - Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, baseVar, elt), Ast.makeConstant(null))); + if (baseVarName != null) { + return Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), rcvr), + Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), elt), Ast.makeConstant(null))); } else { return Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, rcvr, elt), Ast.makeConstant(null)); } @@ -1583,4 +1583,8 @@ public class RhinoToAstTranslator { this.scriptName = scriptName; this.sourceModule = M; } + + public static void resetGensymCounters() { + LoopContext.counter = 0; + } } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstControlFlowRecorder.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstControlFlowRecorder.java index 8aac9e2bf..1d3852087 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstControlFlowRecorder.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstControlFlowRecorder.java @@ -12,6 +12,7 @@ package com.ibm.wala.cast.tree.impl; import java.util.Collection; import java.util.Collections; +import java.util.IdentityHashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java index 8e2550ad5..cc328f724 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java @@ -137,7 +137,7 @@ public abstract class CAstRewriter, K e * (original node, copy key) pairs ot new nodes and the original control-flow * map. */ - private CAstControlFlowMap copyFlow(Map, CAstNode> nodeMap, CAstControlFlowMap orig, + protected CAstControlFlowMap copyFlow(Map, CAstNode> nodeMap, CAstControlFlowMap orig, CAstSourcePositionMap newSrc) { // the new control-flow map @@ -243,7 +243,7 @@ public abstract class CAstRewriter, K e return newMap; } - private CAstSourcePositionMap copySource(Map, CAstNode> nodeMap, CAstSourcePositionMap orig) { + protected CAstSourcePositionMap copySource(Map, CAstNode> nodeMap, CAstSourcePositionMap orig) { CAstSourcePositionRecorder newMap = new CAstSourcePositionRecorder(); for (Iterator, CAstNode>> NS = nodeMap.entrySet().iterator(); NS.hasNext();) { Map.Entry, CAstNode> entry = NS.next(); @@ -260,7 +260,7 @@ public abstract class CAstRewriter, K e return newMap; } - private CAstNodeTypeMap copyTypes(Map, CAstNode> nodeMap, CAstNodeTypeMap orig) { + protected CAstNodeTypeMap copyTypes(Map, CAstNode> nodeMap, CAstNodeTypeMap orig) { if (orig != null) { CAstNodeTypeMapRecorder newMap = new CAstNodeTypeMapRecorder(); for (Iterator, CAstNode>> NS = nodeMap.entrySet().iterator(); NS.hasNext();) { @@ -281,7 +281,7 @@ public abstract class CAstRewriter, K e } } - private Map> copyChildren(Map, CAstNode> nodeMap, + protected Map> copyChildren(Map, CAstNode> nodeMap, Map> children) { final Map> newChildren = new LinkedHashMap>(); From c0a99989a4e86a7cd861345da3af78d6b8d800a3 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:17:39 +0000 Subject: [PATCH 013/238] Support for applying a preprocessor to the generated CAst tree before translating it to IR. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4300 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/js/test/Util.java | 2 +- .../cast/js/html/WebPageLoaderFactory.java | 7 ++++- .../ibm/wala/cast/js/ipa/callgraph/Util.java | 14 +++++++++- .../wala/cast/js/loader/JavaScriptLoader.java | 28 +++++++++++++++++-- .../js/loader/JavaScriptLoaderFactory.java | 11 ++++++-- 5 files changed, 54 insertions(+), 8 deletions(-) diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java index cb7003674..fc7df36c5 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java @@ -87,7 +87,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { public static JSCFABuilder makeHTMLCGBuilder(URL url) throws IOException { JavaScriptLoader.addBootstrapFile(WebUtil.preamble); Set script = WebUtil.extractScriptFromHTML(url); - JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), script.toArray(new SourceModule[script.size()]), false); + JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory, preprocessor), script.toArray(new SourceModule[script.size()]), false); builder.setBaseURL(url); return builder; } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/WebPageLoaderFactory.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/WebPageLoaderFactory.java index c42ba63fb..fd05e2019 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/WebPageLoaderFactory.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/html/WebPageLoaderFactory.java @@ -10,6 +10,7 @@ import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAstNode; import com.ibm.wala.cast.tree.impl.CAstImpl; import com.ibm.wala.cast.tree.impl.CAstOperator; +import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.classLoader.IClassLoader; import com.ibm.wala.ipa.cha.IClassHierarchy; @@ -18,10 +19,14 @@ public class WebPageLoaderFactory extends JavaScriptLoaderFactory { public WebPageLoaderFactory(JavaScriptTranslatorFactory factory) { super(factory); } + + public WebPageLoaderFactory(JavaScriptTranslatorFactory factory, CAstRewriterFactory preprocessor) { + super(factory, preprocessor); + } @Override protected IClassLoader makeTheLoader(IClassHierarchy cha) { - return new JavaScriptLoader( cha, translatorFactory ) { + return new JavaScriptLoader( cha, translatorFactory, preprocessor ) { @Override protected TranslatorToIR initTranslator() { return new JSAstTranslator(this) { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java index 986722fe8..fe2ecf408 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java @@ -16,6 +16,8 @@ import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Set; import com.ibm.wala.cast.ipa.callgraph.StandardFunctionTargetSelector; @@ -30,6 +32,7 @@ import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation; import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstNode; import com.ibm.wala.cast.tree.impl.CAstImpl; +import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.cast.tree.visit.CAstVisitor; import com.ibm.wala.cast.types.AstMethodReference; import com.ibm.wala.cast.util.CAstPrinter; @@ -59,6 +62,11 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util { * needed instead of using a global? */ protected static JavaScriptTranslatorFactory translatorFactory; + + /** + * preprocessors to run generated CAst trees through, null if none + */ + protected static CAstRewriterFactory preprocessor; /** * Set up the translator factory. This method should be called before invoking @@ -71,6 +79,10 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util { public static JavaScriptTranslatorFactory getTranslatorFactory() { return translatorFactory; } + + public static void setPreprocessor(CAstRewriterFactory preprocessor) { + Util.preprocessor = preprocessor; + } public static AnalysisOptions makeOptions(AnalysisScope scope, IClassHierarchy cha, Iterable roots) { final AnalysisOptions options = new AnalysisOptions(scope, /* @@ -93,7 +105,7 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util { if (translatorFactory == null) { throw new IllegalStateException("com.ibm.wala.cast.js.ipa.callgraph.Util.setTranslatorFactory() must be invoked before makeLoaders()"); } - return new JavaScriptLoaderFactory(translatorFactory); + return new JavaScriptLoaderFactory(translatorFactory, preprocessor); } public static IClassHierarchy makeHierarchy(AnalysisScope scope, ClassLoaderFactory loaders) throws ClassHierarchyException { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java index ceaaae0d0..98eed7c68 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java @@ -10,6 +10,7 @@ *****************************************************************************/ package com.ibm.wala.cast.js.loader; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.Collections; @@ -57,6 +58,8 @@ import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstQualifier; import com.ibm.wala.cast.tree.CAstSourcePositionMap; +import com.ibm.wala.cast.tree.impl.CAstRewriter; +import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.cast.types.AstMethodReference; import com.ibm.wala.cfg.AbstractCFG; import com.ibm.wala.classLoader.CallSiteReference; @@ -572,10 +575,17 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader { private static final Map emptyMap2 = Collections.emptyMap(); private final JavaScriptTranslatorFactory translatorFactory; - + + private final CAstRewriterFactory preprocessor; + public JavaScriptLoader(IClassHierarchy cha, JavaScriptTranslatorFactory translatorFactory) { + this(cha, translatorFactory, null); + } + + public JavaScriptLoader(IClassHierarchy cha, JavaScriptTranslatorFactory translatorFactory, CAstRewriterFactory preprocessor) { super(cha); this.translatorFactory = translatorFactory; + this.preprocessor = preprocessor; } class JavaScriptClass extends AstClass { @@ -859,8 +869,20 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader { } @Override - protected TranslatorToCAst getTranslatorToCAst(CAst ast, SourceModule module) { - return translatorFactory.make(ast, module); + protected TranslatorToCAst getTranslatorToCAst(final CAst ast, SourceModule module) { + final TranslatorToCAst baseTranslator = translatorFactory.make(ast, module); + return new TranslatorToCAst() { + + @Override + public CAstEntity translateToCAst() throws IOException { + CAstEntity e = baseTranslator.translateToCAst(); + if(preprocessor != null) { + CAstRewriter rewriter = preprocessor.createCAstRewriter(ast); + e = rewriter.rewrite(e); + } + return e; + } + }; } @Override diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoaderFactory.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoaderFactory.java index f147b19cc..0c924c1d3 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoaderFactory.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoaderFactory.java @@ -13,6 +13,7 @@ package com.ibm.wala.cast.js.loader; import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory; import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.cast.loader.SingleClassLoaderFactory; +import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.classLoader.IClassLoader; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.types.ClassLoaderReference; @@ -22,13 +23,19 @@ import com.ibm.wala.types.ClassLoaderReference; */ public class JavaScriptLoaderFactory extends SingleClassLoaderFactory { protected final JavaScriptTranslatorFactory translatorFactory; - + protected final CAstRewriterFactory preprocessor; + public JavaScriptLoaderFactory(JavaScriptTranslatorFactory factory) { + this(factory, null); + } + + public JavaScriptLoaderFactory(JavaScriptTranslatorFactory factory, CAstRewriterFactory preprocessor) { this.translatorFactory = factory; + this.preprocessor = preprocessor; } protected IClassLoader makeTheLoader(IClassHierarchy cha) { - return new JavaScriptLoader( cha, translatorFactory ); + return new JavaScriptLoader( cha, translatorFactory, preprocessor ); } public ClassLoaderReference getTheReference() { From f763f34fda80c9d052a07fd70de06ba5756a6b88 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:17:52 +0000 Subject: [PATCH 014/238] Added support for CAstNode.IS_DEFINED_EXPR to CAstPrinter. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4301 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/java/com/ibm/wala/cast/util/CAstPrinter.java | 1 + 1 file changed, 1 insertion(+) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java index 03e774c81..e06154335 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPrinter.java @@ -89,6 +89,7 @@ public class CAstPrinter { case CAstNode.EACH_ELEMENT_GET: return "EACH_ELEMENT_GET"; case CAstNode.LIST_EXPR: return "LIST_EXPR"; case CAstNode.EMPTY_LIST_EXPR: return "EMPTY_LIST_EXPR"; + case CAstNode.IS_DEFINED_EXPR: return "IS_DEFINED_EXPR"; // explicit lexical scopes case CAstNode.LOCAL_SCOPE: return "SCOPE"; From 4d9876d45254c014966126604e57eb4d7019fe77 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:18:06 +0000 Subject: [PATCH 015/238] Fixed a bug where the property read expander was generating a DAG, and another one which prevented CFG node targets from being properly copied. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4302 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/js/translator/PropertyReadExpander.java | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java index aa8e2b1de..991ee06c5 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/PropertyReadExpander.java @@ -18,14 +18,11 @@ import com.ibm.wala.util.debug.Assertions; */ public class PropertyReadExpander extends CAstRewriter { - static class ExpanderKey implements CopyKey { - - public ExpanderKey parent() { - return null; - } - - static final ExpanderKey EVERYWHERE = new ExpanderKey(); - static final ExpanderKey EXTRA = new ExpanderKey(); + static enum ExpanderKey implements CopyKey { + EVERYWHERE, EXTRA { + public ExpanderKey parent() { return EVERYWHERE; } + }; + public ExpanderKey parent() { return null; } } private int readTempCounter = 0; @@ -241,7 +238,7 @@ public class PropertyReadExpander extends CAstRewriter Date: Fri, 6 Jan 2012 21:18:20 +0000 Subject: [PATCH 016/238] More correct handling of scoped entities. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4303 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/tree/impl/CAstRewriter.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java index cc328f724..8626940c6 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/impl/CAstRewriter.java @@ -11,6 +11,7 @@ package com.ibm.wala.cast.tree.impl; import java.util.Collection; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -239,10 +240,28 @@ public abstract class CAstRewriter, K e for (CAstNode newTarget : allNewTargetNodes) { newMap.map(newTarget, newTarget); } + + + assert !oldNodesInNewMap(nodeMap, newMap); return newMap; } + // check whether newMap contains any CFG edges involving nodes in the domain of nodeMap + private boolean oldNodesInNewMap(Map, CAstNode> nodeMap, final CAstControlFlowRecorder newMap) { + HashSet oldNodes = HashSetFactory.make(); + for(Entry, CAstNode> e : nodeMap.entrySet()) + oldNodes.add(e.getKey().fst); + for(CAstNode mappedNode : newMap.getMappedNodes()) { + if(oldNodes.contains(mappedNode)) + return true; + for(Object lbl : newMap.getTargetLabels(mappedNode)) + if(oldNodes.contains(newMap.getTarget(mappedNode, lbl))) + return true; + } + return false; + } + protected CAstSourcePositionMap copySource(Map, CAstNode> nodeMap, CAstSourcePositionMap orig) { CAstSourcePositionRecorder newMap = new CAstSourcePositionRecorder(); for (Iterator, CAstNode>> NS = nodeMap.entrySet().iterator(); NS.hasNext();) { @@ -281,7 +300,7 @@ public abstract class CAstRewriter, K e } } - protected Map> copyChildren(Map, CAstNode> nodeMap, + protected Map> copyChildren(CAstNode root, Map, CAstNode> nodeMap, Map> children) { final Map> newChildren = new LinkedHashMap>(); @@ -319,7 +338,7 @@ public abstract class CAstRewriter, K e /** * rewrite the CAst sub-tree rooted at root */ - public Rewrite rewrite(CAstNode root, final CAstControlFlowMap cfg, final CAstSourcePositionMap pos, final CAstNodeTypeMap types, + public Rewrite rewrite(final CAstNode root, final CAstControlFlowMap cfg, final CAstSourcePositionMap pos, final CAstNodeTypeMap types, final Map> children) { final Map, CAstNode> nodes = HashMapFactory.make(); final CAstNode newRoot = copyNodes(root, rootContext, nodes); @@ -356,7 +375,7 @@ public abstract class CAstRewriter, K e public Map> newChildren() { if (theChildren == null) - theChildren = copyChildren(nodes, children); + theChildren = copyChildren(root, nodes, children); return theChildren; } }; From 2ca41027c5430af264360f55d54bbc4ff38f8e00 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:18:30 +0000 Subject: [PATCH 017/238] Fixed CAst representation of || and &&. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4304 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../javascript/RhinoToAstTranslator.java | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index b958a3226..a7f90cae5 100644 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -656,7 +656,7 @@ public class RhinoToAstTranslator { return call; } - + /** * count the number of successor siblings of n, including n */ @@ -864,7 +864,7 @@ public class RhinoToAstTranslator { } private CAstNode readName(WalkContext context, String name) { - CAstNode cn = Ast.makeNode(CAstNode.VAR, Ast.makeConstant(name)); + CAstNode cn = makeVarRef(name); context.cfg().map(cn, cn); CAstNode target = context.getCatchTarget(); if (target != null) { @@ -1309,15 +1309,29 @@ public class RhinoToAstTranslator { } case Token.OR: { - Node l = n.getFirstChild(); - Node r = l.getNext(); - return Ast.makeNode(CAstNode.IF_EXPR, walkNodes(l, context), Ast.makeConstant(true), walkNodes(r, context)); + Node l = n.getFirstChild(); + Node r = l.getNext(); + CAstNode lhs = walkNodes(l, context); + String lhsTempName = "or___lhs"; + // { lhsTemp := ; if(lhsTemp) { lhsTemp } else { } + return Ast.makeNode( + CAstNode.LOCAL_SCOPE, + Ast.makeNode(CAstNode.BLOCK_EXPR, + Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(lhsTempName)), lhs), + Ast.makeNode(CAstNode.IF_EXPR, makeVarRef(lhsTempName), makeVarRef(lhsTempName), walkNodes(r, context)))); } case Token.AND: { Node l = n.getFirstChild(); Node r = l.getNext(); - return Ast.makeNode(CAstNode.IF_EXPR, walkNodes(l, context), walkNodes(r, context), Ast.makeConstant(false)); + CAstNode lhs = walkNodes(l, context); + String lhsTempName = "and___lhs"; + // { lhsTemp := ; if(lhsTemp) { } else { lhsTemp } + return Ast.makeNode( + CAstNode.LOCAL_SCOPE, + Ast.makeNode(CAstNode.BLOCK_EXPR, + Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl(lhsTempName)), lhs), + Ast.makeNode(CAstNode.IF_EXPR, makeVarRef(lhsTempName), walkNodes(r, context), makeVarRef(lhsTempName)))); } case Token.HOOK: { @@ -1407,8 +1421,8 @@ public class RhinoToAstTranslator { CAstNode get, result; if (baseVarName != null) { - result = Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), rcvr), - get = Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), elt)); + result = Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, makeVarRef(baseVarName), rcvr), + get = Ast.makeNode(CAstNode.OBJECT_REF, makeVarRef(baseVarName), elt)); } else { result = get = Ast.makeNode(CAstNode.OBJECT_REF, rcvr, elt); } @@ -1480,8 +1494,8 @@ public class RhinoToAstTranslator { CAstNode elt = walkNodes(element, context); if (baseVarName != null) { - return Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), rcvr), - Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(baseVarName)), elt), Ast.makeConstant(null))); + return Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.ASSIGN, makeVarRef(baseVarName), rcvr), + Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, makeVarRef(baseVarName), elt), Ast.makeConstant(null))); } else { return Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.OBJECT_REF, rcvr, elt), Ast.makeConstant(null)); } @@ -1546,6 +1560,10 @@ public class RhinoToAstTranslator { } } + private CAstNode makeVarRef(String lhsTempName) { + return Ast.makeNode(CAstNode.VAR, Ast.makeConstant(lhsTempName)); + } + /** * parse the JavaScript code using Rhino, and then translate the resulting AST * to CAst From 3d07fcb3a816a96b171cf010603e07731efeb1b8 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:18:41 +0000 Subject: [PATCH 018/238] Cosmetic changes. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4305 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../javascript/RhinoToAstTranslator.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index a7f90cae5..a4b0583eb 100644 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -1107,7 +1107,7 @@ public class RhinoToAstTranslator { case Token.CALL: { if (!isPrimitiveCall(context, n)) { - CAstNode base = Ast.makeNode(CAstNode.VAR, Ast.makeConstant("base")); + CAstNode base = makeVarRef("base"); Node callee = n.getFirstChild(); WalkContext child = new BaseCollectingContext(context, callee, "base"); CAstNode fun = walkNodes(callee, child); @@ -1134,11 +1134,11 @@ public class RhinoToAstTranslator { } case Token.THIS: { - return Ast.makeNode(CAstNode.VAR, Ast.makeConstant("this")); + return makeVarRef("this"); } case Token.THISFN: { - return Ast.makeNode(CAstNode.VAR, Ast.makeConstant(((FunctionNode) context.top()).getFunctionName())); + return makeVarRef(((FunctionNode) context.top()).getFunctionName()); } case Token.STRING: { @@ -1206,7 +1206,7 @@ public class RhinoToAstTranslator { if (nm.getFirstChild() != null) { WalkContext child = new ExpressionContext(context); - result.add(Ast.makeNode(CAstNode.ASSIGN, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(nm.getString())), + result.add(Ast.makeNode(CAstNode.ASSIGN, makeVarRef(nm.getString()), walkNodes(nm.getFirstChild(), child))); } @@ -1244,11 +1244,11 @@ public class RhinoToAstTranslator { } case Token.ENUM_ID: { - return Ast.makeNode(CAstNode.EACH_ELEMENT_GET, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(context.getForInInitVar()))); + return Ast.makeNode(CAstNode.EACH_ELEMENT_GET, makeVarRef(context.getForInInitVar())); } case Token.ENUM_NEXT: { - return Ast.makeNode(CAstNode.EACH_ELEMENT_HAS_NEXT, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(context.getForInInitVar()))); + return Ast.makeNode(CAstNode.EACH_ELEMENT_HAS_NEXT, makeVarRef(context.getForInInitVar())); } case Token.RETURN: { @@ -1502,7 +1502,7 @@ public class RhinoToAstTranslator { } case Token.TYPEOFNAME: { - return Ast.makeNode(CAstNode.TYPE_OF, Ast.makeNode(CAstNode.VAR, Ast.makeConstant(n.getString()))); + return Ast.makeNode(CAstNode.TYPE_OF, makeVarRef(n.getString())); } case Token.TYPEOF: { @@ -1560,8 +1560,8 @@ public class RhinoToAstTranslator { } } - private CAstNode makeVarRef(String lhsTempName) { - return Ast.makeNode(CAstNode.VAR, Ast.makeConstant(lhsTempName)); + private CAstNode makeVarRef(String varName) { + return Ast.makeNode(CAstNode.VAR, Ast.makeConstant(varName)); } /** From 939f6b3f34adc70465626ff2148b4f9bd8844756 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:19:01 +0000 Subject: [PATCH 019/238] Organise imports. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4306 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/com/ibm/wala/cast/js/ipa/callgraph/Util.java | 4 +--- .../cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java index fe2ecf408..3a2b3e8d1 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java @@ -16,8 +16,6 @@ import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; import java.util.Set; import com.ibm.wala.cast.ipa.callgraph.StandardFunctionTargetSelector; @@ -64,7 +62,7 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util { protected static JavaScriptTranslatorFactory translatorFactory; /** - * preprocessors to run generated CAst trees through, null if none + * preprocessor to run generated CAst trees through, null if none */ protected static CAstRewriterFactory preprocessor; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java index 1fa1508f2..8c60222aa 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java @@ -906,7 +906,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa while (insts.hasNext()) { SSAInstruction inst = insts.next(); if (inst instanceof SSAAbstractInvokeInstruction) { - System.err.println("clearing for " + inst); + //System.err.println("clearing for " + inst); CallSiteReference cs = ((SSAAbstractInvokeInstruction) inst).getCallSite(); ((AstCallGraph.AstCGNode) n).clearMutatedCache(cs); } From 45d15c2bd665d3b55671b45c237dbbb384b6d3f4 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:19:14 +0000 Subject: [PATCH 020/238] Filtering instance keys passed to extracted loop bodies to emulate ToString conversion. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4307 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/ForInContextSelector.java | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 1c9f9e0bb..e124bf744 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -15,13 +15,17 @@ import java.util.HashMap; import java.util.Map; import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; +import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey; +import com.ibm.wala.ipa.callgraph.propagation.ConstantKey; import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector; @@ -52,7 +56,7 @@ public class ForInContextSelector implements ContextSelector { public static boolean DEPENDENT_THRU_READS = true; public static class SelectiveCPAContext implements Context { - private final Context base; + protected final Context base; private final Map parameterObjs; @@ -117,7 +121,7 @@ public class ForInContextSelector implements ContextSelector { @Override public String toString() { - return "for in hack filter for " + get(ContextKey.PARAMETERS[2]); + return "for in hack filter for " + get(ContextKey.PARAMETERS[2]) + " over " + this.base; } } @@ -163,20 +167,39 @@ public class ForInContextSelector implements ContextSelector { this.base = base; this.oneLevel = new OneLevelSiteContextSelector(base); } - + public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { + Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); if (callee.getDeclaringClass().getName().toString().contains(HACK_METHOD_STR)) { - return new ForInContext(base.getCalleeTarget(caller, site, callee, receiver), receiver[2]); + InstanceKey loopVar = receiver[2]; + IClass stringClass = caller.getClassHierarchy().lookupClass(JavaScriptTypes.String); + if(loopVar instanceof ConstantKey) { + // do a manual ToString conversion if necessary + Object value = ((ConstantKey)loopVar).getValue(); + if(value instanceof String) { + return new ForInContext(baseContext, loopVar); + } else if(value instanceof Number) { + Integer ival = ((Number)value).intValue(); + return new ForInContext(baseContext, new ConstantKey(ival.toString(), stringClass)); + } else if(value instanceof Boolean) { + Boolean bval = (Boolean)value; + return new ForInContext(baseContext, new ConstantKey(bval.toString(), stringClass)); + } else if(value == null) { + return new ForInContext(baseContext, new ConstantKey("null", stringClass)); + } + } + ConcreteTypeKey stringKey = new ConcreteTypeKey(stringClass); + return new ForInContext(baseContext, stringKey); } else if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { - return new SelectiveCPAContext(base.getCalleeTarget(caller, site, callee, receiver), receiver); + return new SelectiveCPAContext(baseContext, receiver); } else if (USE_1LEVEL_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { if (! identifyDependentParameters(caller, site).isEmpty()) { return oneLevel.getCalleeTarget(caller, site, callee, receiver); } else { - return base.getCalleeTarget(caller, site, callee, receiver); + return baseContext; } } else { - return base.getCalleeTarget(caller, site, callee, receiver); + return baseContext; } } From ef41232ece2fa5aadc5093dfd04c172e7bc37f00 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:19:21 +0000 Subject: [PATCH 021/238] updated .gitignore to ignore Eclipse workspace metadata git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4308 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .gitignore | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index ffabbbb18..44e5bdb75 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,6 @@ */bin/ com.ibm.wala.cast.js.rhino/lib/ com.ibm.wala.cast.js/lib/ -<<<<<<< HEAD com.ibm.wala.cast.java.polyglot/lib/ com.ibm.wala.cast.java.test.data/src/JLex/ .metadata/ @@ -10,5 +9,5 @@ com.ibm.wala.cast.js.test/examples-src/ajaxslt/ com.ibm.wala.core.testdata/@dot/ com.ibm.wala.core.testdata/lib/ com.ibm.wala.core/dat/wala.properties -======= ->>>>>>> Extracted out some more general functionality from ForInLoopRewriter into new super class CAstRewriterExt. +com.ibm.wala.cast.java.polyglot/lib/ +.metadata/ From 74911f269e35ef56d2d94715e65b941683c5d147 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:19:36 +0000 Subject: [PATCH 022/238] fix test case for Function.call(), add test case for Function.apply() git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4309 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/function_apply.js | 5 +++++ .../examples-src/tests/function_call.js | 6 +++++- .../com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java | 6 ++++++ 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js new file mode 100644 index 000000000..bc45ab52e --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js @@ -0,0 +1,5 @@ +function bar(y) { return y + 3; } + +var p = bar; +p.apply(null, [7]); + diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js index 8f7ed0738..804090b22 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js @@ -1 +1,5 @@ -(function foo(x) { return x; }).call(null, 3); \ No newline at end of file +function foo(x) { return x; } + +var z = foo; +z.call(null, 3); + 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 3f81c5fc6..95c9bb686 100644 --- 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 @@ -292,6 +292,12 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { // TODO assert that foo() is reachable } + @Test public void testFunctionDotApply() throws IOException, IllegalArgumentException, CancelException { + Util.makeScriptCG("tests", "function_apply.js"); + // TODO assert that bar() is reachable + } + + protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. From 22e79d7ef7ddb2529a357d41bd7fe13a2bfd8821 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:19:49 +0000 Subject: [PATCH 023/238] make JSCFABuilder abstract git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4310 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/com/ibm/wala/cast/js/ipa/callgraph/JSCFABuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSCFABuilder.java index 8d8a5fdec..1bb36c229 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSCFABuilder.java @@ -28,7 +28,7 @@ import com.ibm.wala.util.collections.EmptyIterator; /** * Common utilities for CFA-style call graph builders. */ -public class JSCFABuilder extends JSSSAPropagationCallGraphBuilder { +public abstract class JSCFABuilder extends JSSSAPropagationCallGraphBuilder { public JSCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) { super(cha, options, cache, new AstCFAPointerKeys() { From b127720692bba61b456cea21be07a583ef093a63 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:20:00 +0000 Subject: [PATCH 024/238] move launcher git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4311 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com.ibm.wala.cast.js.rhino.test-JUnit.launch | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename com.ibm.wala.cast.js.rhino.test/{.launchConfigurations => launchers}/com.ibm.wala.cast.js.rhino.test-JUnit.launch (100%) diff --git a/com.ibm.wala.cast.js.rhino.test/.launchConfigurations/com.ibm.wala.cast.js.rhino.test-JUnit.launch b/com.ibm.wala.cast.js.rhino.test/launchers/com.ibm.wala.cast.js.rhino.test-JUnit.launch similarity index 100% rename from com.ibm.wala.cast.js.rhino.test/.launchConfigurations/com.ibm.wala.cast.js.rhino.test-JUnit.launch rename to com.ibm.wala.cast.js.rhino.test/launchers/com.ibm.wala.cast.js.rhino.test-JUnit.launch From 1673a200e57d1a545447768f579cedddf924b531 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:20:13 +0000 Subject: [PATCH 025/238] default to dumping files in temp directory git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4312 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/js/test/TestForInLoopHack.java | 2 +- .../com/ibm/wala/cast/js/test/TestMozillaBugPages.java | 2 +- .../com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java index 34ef64fb2..4b74a8ebb 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java @@ -17,7 +17,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape { @Before public void config() { - JSSourceExtractor.USE_TEMP_NAME = false; + JSSourceExtractor.USE_TEMP_NAME = true; JSSourceExtractor.DELETE_UPON_EXIT = false; } diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java index e8599172f..459e65283 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java @@ -19,7 +19,7 @@ public abstract class TestMozillaBugPages extends TestJSCallGraphShape { @Before public void config() { - JSSourceExtractor.USE_TEMP_NAME = false; + JSSourceExtractor.USE_TEMP_NAME = true; JSSourceExtractor.DELETE_UPON_EXIT = false; } diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java index 48e2e5eb4..5c48a9bab 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java @@ -43,7 +43,7 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape @Before public void config() { - JSSourceExtractor.USE_TEMP_NAME = false; + JSSourceExtractor.USE_TEMP_NAME = true; JSSourceExtractor.DELETE_UPON_EXIT = false; } From bf66d294919c2af0b90e1aa2b31e1c5358982b4b Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:20:28 +0000 Subject: [PATCH 026/238] fix bug in setting of __proto__ in function constructor git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4313 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../js/ipa/callgraph/JavaScriptConstructTargetSelector.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java index aa94c02bb..07be6d4cf 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructTargetSelector.java @@ -362,8 +362,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { S.addStatement(insts.NewInstruction(7, NewSiteReference.make(S.getNextProgramCounter(), JavaScriptTypes.Object))); - // TODO fix these writes to operate on __proto__, once we're sure we're doing the right thing here - S.addStatement(insts.PutInstruction(7, 4, "prototype")); + S.addStatement(insts.PutInstruction(5, 4, "__proto__")); S.getNextProgramCounter(); S.addStatement(insts.PutInstruction(5, 7, "prototype")); @@ -372,6 +371,7 @@ public class JavaScriptConstructTargetSelector implements MethodTargetSelector { S.addStatement(insts.PutInstruction(7, 5, "constructor")); S.getNextProgramCounter(); + // TODO we need to set v7.__proto__ to Object.prototype S.addStatement(insts.ReturnInstruction(5, false)); S.getNextProgramCounter(); From 31108fa7e256b270e655ecc3a1528805bb24225d Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:20:41 +0000 Subject: [PATCH 027/238] Avoid re-analysing the same file twice. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4314 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../js/ipa/callgraph/LoadFileTargetSelector.java | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/LoadFileTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/LoadFileTargetSelector.java index 1fd402d5d..641276f42 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/LoadFileTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/LoadFileTargetSelector.java @@ -22,6 +22,7 @@ import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.types.MethodReference; import com.ibm.wala.types.TypeName; import com.ibm.wala.types.TypeReference; +import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.intset.OrdinalSet; public class LoadFileTargetSelector implements MethodTargetSelector { @@ -33,6 +34,8 @@ public class LoadFileTargetSelector implements MethodTargetSelector { private final TypeReference loadFileRef = TypeReference.findOrCreate(JavaScriptTypes.jsLoader, TypeName.string2TypeName("Lprologue.js/loadFile")); private final MethodReference loadFileFunRef = AstMethodReference.fnReference(loadFileRef); + + private final HashSet loadedFiles = HashSetFactory.make(); public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { IMethod target = base.getCalleeTarget(caller, site, receiver); @@ -56,9 +59,12 @@ public class LoadFileTargetSelector implements MethodTargetSelector { try { JavaScriptLoader cl = (JavaScriptLoader) builder.getClassHierarchy().getLoader(JavaScriptTypes.jsLoader); URL url = new URL(builder.getBaseURL(), str); - Util.loadAdditionalFile(builder.getClassHierarchy() , cl, str, url, url.getFile()); - IClass script = builder.getClassHierarchy().lookupClass(TypeReference.findOrCreate(cl.getReference(), "L" + url.getFile())); - return script.getMethod(JavaScriptMethods.fnSelector); + if(!loadedFiles.contains(url)) { + Util.loadAdditionalFile(builder.getClassHierarchy() , cl, str, url, url.getFile()); + loadedFiles.add(url); + IClass script = builder.getClassHierarchy().lookupClass(TypeReference.findOrCreate(cl.getReference(), "L" + url.getFile())); + return script.getMethod(JavaScriptMethods.fnSelector); + } } catch (MalformedURLException e1) { // do nothing, fall through and return 'target' } catch (IOException e) { From c815519025ae56e920ef8e04bb07d7e2377839b5 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:20:55 +0000 Subject: [PATCH 028/238] ignore jquery test; no longer works due to proper handling of || construct git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4315 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/js/test/TestForInLoopHack.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java index 4b74a8ebb..4c1d7aedc 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java @@ -4,6 +4,7 @@ import java.io.IOException; import java.net.URL; import org.junit.Before; +import org.junit.Ignore; import org.junit.Test; import com.ibm.wala.cast.js.html.JSSourceExtractor; @@ -36,6 +37,7 @@ public abstract class TestForInLoopHack extends TestJSCallGraphShape { Util.dumpCG(builder.getPointerAnalysis(), CG); } + @Ignore("This test now blows up due to proper handling of the || construct, used in extend(). Should handle this eventually.") @Test public void testJQueryWithHack() throws IOException, IllegalArgumentException, CancelException { URL url = getClass().getClassLoader().getResource("pages/jquery_hacked.html"); JSCFABuilder builder = Util.makeHTMLCGBuilder(url); From b042d61a676b6089a006b0e56cc6db34df7791b7 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:21:26 +0000 Subject: [PATCH 029/238] initial implementation of handling Function.call(). also, fix previous change that caused some tests to fail git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4316 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/function_call.js | 9 +- .../js/test/TestSimpleCallGraphShape.java | 170 ++++++++++-------- .../js/test/TestSimplePageCallGraphShape.java | 4 +- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 2 +- ...ScriptFunctionCallApplyTargetSelector.java | 115 ++++++++++++ .../com/ibm/wala/cast/ipa/callgraph/Util.java | 2 +- 6 files changed, 225 insertions(+), 77 deletions(-) create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js index 804090b22..23097a876 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js @@ -1,5 +1,12 @@ function foo(x) { return x; } -var z = foo; +function bar(x) { return x + 1; } + +if (p > 3) { + z = foo; +} else { + z = bar; +} + z.call(null, 3); 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 95c9bb686..4cef15ce1 100644 --- 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 @@ -12,8 +12,11 @@ package com.ibm.wala.cast.js.test; import java.io.IOException; import java.util.Iterator; +import java.util.List; import java.util.Set; +import junit.framework.Assert; + import org.junit.Test; import com.ibm.wala.ipa.callgraph.CGNode; @@ -27,6 +30,7 @@ import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.util.CancelException; import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.IVector; +import com.ibm.wala.util.collections.Iterator2Collection; import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.collections.SparseVector; import com.ibm.wala.util.intset.IntSetAction; @@ -50,7 +54,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new Object[] { "tests/simple.js/fib", new String[] { "tests/simple.js/fib" } }, new Object[] { "tests/simple.js/weirder", new String[] { "prologue.js/abs" } } }; - @Test public void testSimple() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testSimple() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "simple.js"); verifyGraphAssertions(CG, assertionsForSimple); } @@ -63,7 +68,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new String[] { "tests/objects.js/something", "tests/objects.js/objects_are_fun/nothing" } }, new Object[] { "tests/objects.js/objects_are_fun", new String[] { "tests/objects.js/other", "tests/objects.js/whatever" } } }; - @Test public void testObjects() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testObjects() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "objects.js"); verifyGraphAssertions(CG, assertionsForObjects); } @@ -77,20 +83,25 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { "tests/inherit.js/sharedClassObject/Rectangle/area" } }, /* * new Object[]{"tests/inherit.js/objectMasquerading", new - * String[]{"ctor:tests/inherit.js/objectMasquerading/Rectangle"}}, new Object[]{"tests/inherit.js/sharedClassObject", - * new String[]{"ctor:tests/inherit.js/sharedClassObject/Rectangle"}}, + * String[]{"ctor:tests/inherit.js/objectMasquerading/Rectangle"}}, new + * Object[]{"tests/inherit.js/sharedClassObject", new + * String[]{"ctor:tests/inherit.js/sharedClassObject/Rectangle"}}, */ }; - @Test public void testInherit() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testInherit() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "inherit.js"); verifyGraphAssertions(CG, assertionsForInherit); } - private static final Object[][] assertionsForNewfn = new Object[][] { new Object[] { ROOT, new String[] { "tests/newfn.js" } }, - new Object[] { "tests/newfn.js", new String[] { "suffix:ctor$1/_fromctor", "suffix:ctor$2/_fromctor", "suffix:ctor$3/_fromctor" } } }; + private static final Object[][] assertionsForNewfn = new Object[][] { + new Object[] { ROOT, new String[] { "tests/newfn.js" } }, + new Object[] { "tests/newfn.js", + new String[] { "suffix:ctor$1/_fromctor", "suffix:ctor$2/_fromctor", "suffix:ctor$3/_fromctor" } } }; - @Test public void testNewfn() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testNewfn() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "newfn.js"); verifyGraphAssertions(CG, assertionsForNewfn); } @@ -102,7 +113,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new String[] { "tests/control-flow.js/testSwitch", "tests/control-flow.js/testDoWhile", "tests/control-flow.js/testWhile", "tests/control-flow.js/testFor", "tests/control-flow.js/testReturn" } } }; - @Test public void testControlflow() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testControlflow() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "control-flow.js"); verifyGraphAssertions(CG, assertionsForControlflow); } @@ -115,7 +127,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { "tests/more-control-flow.js/testDoWhile", "tests/more-control-flow.js/testWhile", "tests/more-control-flow.js/testFor", "tests/more-control-flow.js/testReturn" } } }; - @Test public void testMoreControlflow() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testMoreControlflow() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "more-control-flow.js"); verifyGraphAssertions(CG, assertionsForMoreControlflow); } @@ -124,7 +137,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new Object[] { "tests/forin.js", new String[] { "tests/forin.js/testForIn" } }, new Object[] { "tests/forin.js/testForIn", new String[] { "tests/forin.js/testForIn1", "tests/forin.js/testForIn2" } } }; - @Test public void testForin() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testForin() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "forin.js"); verifyGraphAssertions(CG, assertionsForForin); } @@ -141,7 +155,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new Object[] { "tests/simple-lexical.js/outer/indirect", new String[] { "tests/simple-lexical.js/outer/inner", "tests/simple-lexical.js/outer/inner3" } } }; - @Test public void testSimpleLexical() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testSimpleLexical() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "simple-lexical.js"); verifyGraphAssertions(CG, assertionsForSimpleLexical); } @@ -157,7 +172,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new Object[] { "tests/try.js/tryCatchFinally", new String[] { "tests/try.js/targetOne", "tests/try.js/targetTwo", "tests/try.js/three", "tests/try.js/two" } } }; - @Test public void testTry() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testTry() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "try.js", true); verifyGraphAssertions(CG, assertionsForTry); } @@ -166,7 +182,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new Object[] { ROOT, new String[] { "tests/string-op.js" } }, new Object[] { "tests/string-op.js", new String[] { "tests/string-op.js/getOp", "tests/string-op.js/plusNum" } } }; - @Test public void testStringOp() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testStringOp() throws IOException, IllegalArgumentException, CancelException { PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "string-op.js"); B.getOptions().setTraceStringConstants(true); CallGraph CG = B.makeCallGraph(B.getOptions()); @@ -177,9 +194,11 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new Object[] { ROOT, new String[] { "tests/upward.js" } }, new Object[] { "tests/upward.js", - new String[] { "tests/upward.js/Obj/setit", "tests/upward.js/Obj/getit", "tests/upward.js/tester1", "tests/upward.js/tester2" } } }; + new String[] { "tests/upward.js/Obj/setit", "tests/upward.js/Obj/getit", "tests/upward.js/tester1", + "tests/upward.js/tester2" } } }; - @Test public void testUpward() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testUpward() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "upward.js"); verifyGraphAssertions(CG, assertionsForUpward); } @@ -188,116 +207,123 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { new Object[] { ROOT, new String[] { "tests/string-prims.js" } }, new Object[] { "tests/string-prims.js", new String[] { "prologue.js/stringSplit", "prologue.js/toUpperCase" } } }; - @Test public void testStringPrims() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testStringPrims() throws IOException, IllegalArgumentException, CancelException { PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "string-prims.js"); B.getOptions().setTraceStringConstants(true); CallGraph CG = B.makeCallGraph(B.getOptions()); verifyGraphAssertions(CG, assertionsForStringPrims); } - - private static final Object[][] assertionsForNested = new Object[][] { - new Object[] { ROOT, new String[] { "tests/nested.js" } }, - new Object[] { "tests/nested.js", - new String[] { "tests/nested.js/f", - "tests/nested.js/f/ff", - "tests/nested.js/f/ff/fff" } - } - }; - - @Test public void testNested() throws IOException, IllegalArgumentException, CancelException { + + private static final Object[][] assertionsForNested = new Object[][] { new Object[] { ROOT, new String[] { "tests/nested.js" } }, + new Object[] { "tests/nested.js", new String[] { "tests/nested.js/f", "tests/nested.js/f/ff", "tests/nested.js/f/ff/fff" } } }; + + @Test + public void testNested() throws IOException, IllegalArgumentException, CancelException { PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "nested.js"); CallGraph CG = B.makeCallGraph(B.getOptions()); verifyGraphAssertions(CG, assertionsForNested); } - private static final Object[][] assertionsForInstanceof = new Object[][] { - new Object[] { ROOT, new String[] { "tests/instanceof.js" } } - }; - - @Test public void testInstanceof() throws IOException, IllegalArgumentException, CancelException { + private static final Object[][] assertionsForInstanceof = new Object[][] { new Object[] { ROOT, + new String[] { "tests/instanceof.js" } } }; + + @Test + public void testInstanceof() throws IOException, IllegalArgumentException, CancelException { PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "instanceof.js"); CallGraph CG = B.makeCallGraph(B.getOptions()); verifyGraphAssertions(CG, assertionsForInstanceof); } /* - private static final Object[][] assertionsForWith = new Object[][] { - new Object[] { ROOT, new String[] { "tests/with.js" } } - }; - - @Test public void testWith() throws IOException, IllegalArgumentException, CancelException { - PropagationCallGraphBuilder B = Util.makeScriptCGBuilder("tests", "with.js"); - CallGraph CG = B.makeCallGraph(B.getOptions()); - verifyGraphAssertions(CG, assertionsForWith); - } - */ - - @Test public void testCrash1() throws IOException, IllegalArgumentException, CancelException { + * private static final Object[][] assertionsForWith = new Object[][] { new + * Object[] { ROOT, new String[] { "tests/with.js" } } }; + * + * @Test public void testWith() throws IOException, IllegalArgumentException, + * CancelException { PropagationCallGraphBuilder B = + * Util.makeScriptCGBuilder("tests", "with.js"); CallGraph CG = + * B.makeCallGraph(B.getOptions()); verifyGraphAssertions(CG, + * assertionsForWith); } + */ + + @Test + public void testCrash1() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "crash1.js"); verifyGraphAssertions(CG, null); } - @Test public void testCrash2() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testCrash2() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "crash2.js"); verifyGraphAssertions(CG, null); } - - @Test public void testLexicalCtor() throws IOException, IllegalArgumentException, CancelException { + + @Test + public void testLexicalCtor() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "lexical-ctor.js"); verifyGraphAssertions(CG, null); } private static final Object[][] assertionsForMultivar = new Object[][] { - new Object[] { ROOT, new String[] { "tests/multivar.js" } }, - new Object[] { "tests/multivar.js", - new String[] { "tests/multivar.js/a", - "tests/multivar.js/bf", - "tests/multivar.js/c" - } - } - }; + new Object[] { ROOT, new String[] { "tests/multivar.js" } }, + new Object[] { "tests/multivar.js", new String[] { "tests/multivar.js/a", "tests/multivar.js/bf", "tests/multivar.js/c" } } }; - @Test public void testMultivar() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testMultivar() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "multivar.js"); verifyGraphAssertions(CG, assertionsForMultivar); } private static final Object[][] assertionsForPrototypeContamination = new Object[][] { - new Object[] { ROOT, new String[] { "tests/prototype_contamination_bug.js" } }, - new Object[] { "suffix:test1", - new String[] { "suffix:foo_of_A"} }, - new Object[] { "suffix:test2", - new String[] { "suffix:foo_of_B"} } - }; + new Object[] { ROOT, new String[] { "tests/prototype_contamination_bug.js" } }, + new Object[] { "suffix:test1", new String[] { "suffix:foo_of_A" } }, + new Object[] { "suffix:test2", new String[] { "suffix:foo_of_B" } } }; - @Test public void testProtoypeContamination() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testProtoypeContamination() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "prototype_contamination_bug.js"); verifyGraphAssertions(CG, assertionsForPrototypeContamination); verifyNoEdges(CG, "suffix:test1", "suffix:foo_of_B"); verifyNoEdges(CG, "suffix:test2", "suffix:foo_of_A"); } - - @Test public void testStackOverflowOnSsaConversionBug() throws IOException, IllegalArgumentException, CancelException { + + @Test + public void testStackOverflowOnSsaConversionBug() throws IOException, IllegalArgumentException, CancelException { Util.makeScriptCG("tests", "stack_overflow_on_ssa_conversion.js"); // all we need is for it to finish building CG successfully. } - @Test public void testExtJSSwitch() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testExtJSSwitch() throws IOException, IllegalArgumentException, CancelException { Util.makeScriptCG("tests", "extjs_switch.js"); // all we need is for it to finish building CG successfully. } - @Test public void testFunctionDotCall() throws IOException, IllegalArgumentException, CancelException { - Util.makeScriptCG("tests", "function_call.js"); - // TODO assert that foo() is reachable + private static final Object[][] assertionsForFunctionDotCall = new Object[][] { new Object[] { "suffix:call4", + new String[] { "suffix:foo", "suffix:bar" } } }; + + @Test + public void testFunctionDotCall() throws IOException, IllegalArgumentException, CancelException { + CallGraph cg = Util.makeScriptCG("tests", "function_call.js"); + for (CGNode n : cg) { + if (n.getMethod().getName().toString().equals("call4")) { + Assert.assertEquals(2, cg.getSuccNodeCount(n)); + // ugh + List succs = Iterator2Collection.toList(cg.getSuccNodes(n)); + Assert + .assertEquals( + "[Node: Context: Everywhere, Node: Context: Everywhere]", + succs.toString()); + } + } } - @Test public void testFunctionDotApply() throws IOException, IllegalArgumentException, CancelException { + @Test + public void testFunctionDotApply() throws IOException, IllegalArgumentException, CancelException { Util.makeScriptCG("tests", "function_apply.js"); // TODO assert that bar() is reachable } - protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java index 5c48a9bab..704ccca64 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java @@ -43,8 +43,8 @@ public abstract class TestSimplePageCallGraphShape extends TestJSCallGraphShape @Before public void config() { - JSSourceExtractor.USE_TEMP_NAME = true; - JSSourceExtractor.DELETE_UPON_EXIT = false; + JSSourceExtractor.USE_TEMP_NAME = false; + JSSourceExtractor.DELETE_UPON_EXIT = true; } private static final Object[][] assertionsForPage1 = new Object[][] { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 8d7a407d2..b9d9b9a4c 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -36,7 +36,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha); setContextInterpreter(contextInterpreter); - options.setSelector(new JavaScriptConstructTargetSelector(cha, options.getMethodTargetSelector())); + options.setSelector(new JavaScriptFunctionCallApplyTargetSelector(cha, new JavaScriptConstructTargetSelector(cha, options.getMethodTargetSelector()))); options.setSelector(new LoadFileTargetSelector(options.getMethodTargetSelector(), this)); ContextSelector def = new DefaultContextSelector(options, cha); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java new file mode 100644 index 000000000..ec38cebe5 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java @@ -0,0 +1,115 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import java.util.Arrays; + +import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummarizedFunction; +import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummary; +import com.ibm.wala.cast.js.loader.JSCallSiteReference; +import com.ibm.wala.cast.js.loader.JavaScriptLoader; +import com.ibm.wala.cast.js.ssa.JSInstructionFactory; +import com.ibm.wala.cast.js.types.JavaScriptMethods; +import com.ibm.wala.cast.js.types.JavaScriptTypes; +import com.ibm.wala.cast.loader.AstFunctionClass; +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.classLoader.NewSiteReference; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.MethodTargetSelector; +import com.ibm.wala.ipa.cha.IClassHierarchy; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; +import com.ibm.wala.types.Descriptor; +import com.ibm.wala.types.MethodReference; +import com.ibm.wala.util.strings.Atom; + +/** + * Generate IR to model Function.call() and Function.apply() + * + * @see MDN + * Function.apply() docs + * @see MDN + * Function.call() docs + * + * @author manu + * + */ +public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSelector { + + private final IClassHierarchy cha; + private final MethodTargetSelector base; + + public JavaScriptFunctionCallApplyTargetSelector(IClassHierarchy cha, MethodTargetSelector base) { + this.cha = cha; + this.base = base; + + } + + /* + * (non-Javadoc) + * + * @see + * com.ibm.wala.ipa.callgraph.MethodTargetSelector#getCalleeTarget(com.ibm + * .wala.ipa.callgraph.CGNode, com.ibm.wala.classLoader.CallSiteReference, + * com.ibm.wala.classLoader.IClass) + */ + @Override + public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { + if (cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.CodeBody))) { + // TODO better way to do these tests + String s = receiver.toString(); + if (s.equals("function Lprologue.js/functionCall")) { + return getFunctionCallTarget(caller, site, receiver); + } else if (s.equals("function Lprologue.js/functionApply")) { + return getFunctionApplyTarget(caller, site, receiver); + } + } + return base.getCalleeTarget(caller, site, receiver); + } + + private IMethod getFunctionApplyTarget(CGNode caller, CallSiteReference site, IClass receiver) { + System.err.println("TODO: handle Function.apply()"); + return base.getCalleeTarget(caller, site, receiver); + } + + /** + * generate a synthetic method modeling the invocation of Function.call() at the site + * @param caller + * @param site + * @param receiver + * @return + */ + private IMethod getFunctionCallTarget(CGNode caller, CallSiteReference site, IClass receiver) { + JSInstructionFactory insts = (JSInstructionFactory)receiver.getClassLoader().getInstructionFactory(); + IR callerIR = caller.getIR(); + SSAAbstractInvokeInstruction callStmts[] = callerIR.getCalls(site); + assert callStmts.length == 1; + int nargs = callStmts[0].getNumberOfParameters(); + Atom atom = Atom.findOrCreateUnicodeAtom("call" + nargs); + Descriptor desc = Descriptor.findOrCreateUTF8(JavaScriptLoader.JS, "()LRoot;"); + MethodReference ref = MethodReference.findOrCreate(receiver.getReference(), atom , desc ); + JavaScriptSummary S = new JavaScriptSummary(ref, nargs); + + // generate invocation instruction for the real method being invoked + int resultVal = nargs + 2; + CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter()); + int[] params = new int[nargs-2]; + for (int i = 0; i < params.length; i++) { + // add 3 to skip v1 (which points to Function.call() itself) and v2 (the real function being invoked) + params[i] = i+3; + } + // function being invoked is in v2 + S.addStatement(insts.Invoke(2, resultVal, params , resultVal+1, site)); + S.getNextProgramCounter(); + + + S.addStatement(insts.ReturnInstruction(resultVal, false)); + S.getNextProgramCounter(); + + JavaScriptSummarizedFunction t = new JavaScriptSummarizedFunction(ref, S, receiver); + return t; + } + +} diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index 41949a7b2..a3237183a 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -72,7 +72,7 @@ public class Util { } public static void dumpCG(PointerAnalysis PA, CallGraph CG) { - + if (true) return; for (Iterator x = CG.iterator(); x.hasNext();) { CGNode N = (CGNode) x.next(); System.err.println("\ncallees of node " + N.getMethod() + " " + N.getGraphNodeId()); From 1ea96713c377ad2f500a941de57a20a1c98cafb7 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:21:40 +0000 Subject: [PATCH 030/238] cache Function.call() synthetic methods and reuse git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4317 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- ...ScriptFunctionCallApplyTargetSelector.java | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java index ec38cebe5..da610f986 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java @@ -1,6 +1,7 @@ package com.ibm.wala.cast.js.ipa.callgraph; import java.util.Arrays; +import java.util.Map; import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummarizedFunction; import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummary; @@ -21,6 +22,7 @@ import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.types.Descriptor; import com.ibm.wala.types.MethodReference; +import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.strings.Atom; /** @@ -75,41 +77,57 @@ public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSe } /** - * generate a synthetic method modeling the invocation of Function.call() at the site + * cache synthetic method for each arity of Function.call() invocation + */ + private final Map callModels = HashMapFactory.make(); + + /** + * generate a synthetic method modeling the invocation of Function.call() at + * the site + * * @param caller * @param site * @param receiver * @return */ private IMethod getFunctionCallTarget(CGNode caller, CallSiteReference site, IClass receiver) { - JSInstructionFactory insts = (JSInstructionFactory)receiver.getClassLoader().getInstructionFactory(); - IR callerIR = caller.getIR(); - SSAAbstractInvokeInstruction callStmts[] = callerIR.getCalls(site); - assert callStmts.length == 1; - int nargs = callStmts[0].getNumberOfParameters(); + int nargs = getNumberOfArgsPassed(caller, site); + if (callModels.containsKey(nargs)) { + return callModels.get(nargs); + } + JSInstructionFactory insts = (JSInstructionFactory) receiver.getClassLoader().getInstructionFactory(); Atom atom = Atom.findOrCreateUnicodeAtom("call" + nargs); Descriptor desc = Descriptor.findOrCreateUTF8(JavaScriptLoader.JS, "()LRoot;"); - MethodReference ref = MethodReference.findOrCreate(receiver.getReference(), atom , desc ); + MethodReference ref = MethodReference.findOrCreate(receiver.getReference(), atom, desc); JavaScriptSummary S = new JavaScriptSummary(ref, nargs); // generate invocation instruction for the real method being invoked int resultVal = nargs + 2; CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter()); - int[] params = new int[nargs-2]; + int[] params = new int[nargs - 2]; for (int i = 0; i < params.length; i++) { - // add 3 to skip v1 (which points to Function.call() itself) and v2 (the real function being invoked) - params[i] = i+3; + // add 3 to skip v1 (which points to Function.call() itself) and v2 (the + // real function being invoked) + params[i] = i + 3; } // function being invoked is in v2 - S.addStatement(insts.Invoke(2, resultVal, params , resultVal+1, site)); + S.addStatement(insts.Invoke(2, resultVal, params, resultVal + 1, site)); S.getNextProgramCounter(); - - + S.addStatement(insts.ReturnInstruction(resultVal, false)); S.getNextProgramCounter(); JavaScriptSummarizedFunction t = new JavaScriptSummarizedFunction(ref, S, receiver); + callModels.put(nargs, t); return t; } + private int getNumberOfArgsPassed(CGNode caller, CallSiteReference site) { + IR callerIR = caller.getIR(); + SSAAbstractInvokeInstruction callStmts[] = callerIR.getCalls(site); + assert callStmts.length == 1; + int nargs = callStmts[0].getNumberOfParameters(); + return nargs; + } + } From 37f3af5b86b5996ebc1e2c8d818e2e9b94307a76 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:21:54 +0000 Subject: [PATCH 031/238] undo CG dumping change git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4318 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/java/com/ibm/wala/cast/ipa/callgraph/Util.java | 1 - 1 file changed, 1 deletion(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index a3237183a..cbbd08cfa 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -72,7 +72,6 @@ public class Util { } public static void dumpCG(PointerAnalysis PA, CallGraph CG) { - if (true) return; for (Iterator x = CG.iterator(); x.hasNext();) { CGNode N = (CGNode) x.next(); System.err.println("\ncallees of node " + N.getMethod() + " " + N.getGraphNodeId()); From e468d042fa6a7b28990f77802b8c3a46cce1809a Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:22:09 +0000 Subject: [PATCH 032/238] add option to generate separate synthetic method per call site of Function.call() git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4319 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- ...ScriptFunctionCallApplyTargetSelector.java | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java index da610f986..e3f83ac85 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java @@ -1,6 +1,5 @@ package com.ibm.wala.cast.js.ipa.callgraph; -import java.util.Arrays; import java.util.Map; import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummarizedFunction; @@ -8,13 +7,10 @@ import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummary; import com.ibm.wala.cast.js.loader.JSCallSiteReference; import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.ssa.JSInstructionFactory; -import com.ibm.wala.cast.js.types.JavaScriptMethods; import com.ibm.wala.cast.js.types.JavaScriptTypes; -import com.ibm.wala.cast.loader.AstFunctionClass; import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IMethod; -import com.ibm.wala.classLoader.NewSiteReference; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.MethodTargetSelector; import com.ibm.wala.ipa.cha.IClassHierarchy; @@ -23,6 +19,7 @@ import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.types.Descriptor; import com.ibm.wala.types.MethodReference; import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.strings.Atom; /** @@ -76,10 +73,12 @@ public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSe return base.getCalleeTarget(caller, site, receiver); } + private static final boolean SEPARATE_SYNTHETIC_METHOD_PER_SITE = true; + /** * cache synthetic method for each arity of Function.call() invocation */ - private final Map callModels = HashMapFactory.make(); + private final Map callModels = HashMapFactory.make(); /** * generate a synthetic method modeling the invocation of Function.call() at @@ -92,13 +91,12 @@ public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSe */ private IMethod getFunctionCallTarget(CGNode caller, CallSiteReference site, IClass receiver) { int nargs = getNumberOfArgsPassed(caller, site); - if (callModels.containsKey(nargs)) { - return callModels.get(nargs); + Object key = getKey(nargs, caller, site); + if (callModels.containsKey(key)) { + return callModels.get(key); } JSInstructionFactory insts = (JSInstructionFactory) receiver.getClassLoader().getInstructionFactory(); - Atom atom = Atom.findOrCreateUnicodeAtom("call" + nargs); - Descriptor desc = Descriptor.findOrCreateUTF8(JavaScriptLoader.JS, "()LRoot;"); - MethodReference ref = MethodReference.findOrCreate(receiver.getReference(), atom, desc); + MethodReference ref = genSyntheticMethodRef(receiver, nargs, key); JavaScriptSummary S = new JavaScriptSummary(ref, nargs); // generate invocation instruction for the real method being invoked @@ -111,17 +109,38 @@ public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSe params[i] = i + 3; } // function being invoked is in v2 - S.addStatement(insts.Invoke(2, resultVal, params, resultVal + 1, site)); + S.addStatement(insts.Invoke(2, resultVal, params, resultVal + 1, cs)); S.getNextProgramCounter(); S.addStatement(insts.ReturnInstruction(resultVal, false)); S.getNextProgramCounter(); JavaScriptSummarizedFunction t = new JavaScriptSummarizedFunction(ref, S, receiver); - callModels.put(nargs, t); + callModels.put(key, t); return t; } + private MethodReference genSyntheticMethodRef(IClass receiver, int nargs, Object key) { + Atom atom = null; + if (key instanceof Pair) { + Pair p = (Pair) key; + atom = Atom.findOrCreateUnicodeAtom("call_" + p.fst + "_" + p.snd); + } else { + atom = Atom.findOrCreateUnicodeAtom("call" + nargs); + } + Descriptor desc = Descriptor.findOrCreateUTF8(JavaScriptLoader.JS, "()LRoot;"); + MethodReference ref = MethodReference.findOrCreate(receiver.getReference(), atom, desc); + return ref; + } + + private Object getKey(int nargs, CGNode caller, CallSiteReference site) { + if (SEPARATE_SYNTHETIC_METHOD_PER_SITE) { + return Pair.make(caller.getGraphNodeId(), site.getProgramCounter()); + } else { + return nargs; + } + } + private int getNumberOfArgsPassed(CGNode caller, CallSiteReference site) { IR callerIR = caller.getIR(); SSAAbstractInvokeInstruction callStmts[] = callerIR.getCalls(site); From be1ead52456b7e69bacb30a7d62e3468147d88fd Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:22:27 +0000 Subject: [PATCH 033/238] additional modeling of prototype chains for built-in objects git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4320 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/complex_call.js | 18 ++++++++++++++++++ .../cast/js/test/TestSimpleCallGraphShape.java | 13 +++++++++++-- com.ibm.wala.cast.js/dat/prologue.js | 8 ++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/complex_call.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/complex_call.js b/com.ibm.wala.cast.js.test/examples-src/tests/complex_call.js new file mode 100644 index 000000000..9dafcdf14 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/complex_call.js @@ -0,0 +1,18 @@ +Function.prototype.useCall = function f1(){ + var self = this; + return function f1_inner(a, b){ + self.call(this, a, b); + return this; + }; +}; + + +Function.prototype.extend = function f2(key, value){ + this[key] = value; +}.useCall(); + +Number.extend('foobaz', function f3(min, max){ + return min; +}); + +var r = Number.foobaz(3, 4); 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 4cef15ce1..5a9472323 100644 --- 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 @@ -299,8 +299,6 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { // all we need is for it to finish building CG successfully. } - private static final Object[][] assertionsForFunctionDotCall = new Object[][] { new Object[] { "suffix:call4", - new String[] { "suffix:foo", "suffix:bar" } } }; @Test public void testFunctionDotCall() throws IOException, IllegalArgumentException, CancelException { @@ -324,6 +322,17 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { // TODO assert that bar() is reachable } + private static final Object[][] assertionsForComplexCall = new Object[][] { + new Object[] { ROOT, new String[] { "tests/complex_call.js" } }, + new Object[] { "suffix:call.js", new String[] { "suffix:f3" } } }; + + @Test + public void testComplexCall() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "complex_call.js"); + verifyGraphAssertions(CG, assertionsForComplexCall); + } + + protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. diff --git a/com.ibm.wala.cast.js/dat/prologue.js b/com.ibm.wala.cast.js/dat/prologue.js index d57d4c0da..d36e93603 100644 --- a/com.ibm.wala.cast.js/dat/prologue.js +++ b/com.ibm.wala.cast.js/dat/prologue.js @@ -129,6 +129,8 @@ Function.prototype = { /* Array properties, see spec 15.4 */ /************************************************************************/ +Array.__proto__ = Function.prototype; + Array.prototype = { __proto__: Object.prototype, @@ -248,6 +250,8 @@ Array.prototype = { /* String properties, see spec 15.4 */ /************************************************************************/ +String.__proto__ = Function.prototype; + String.prototype = { __proto__: Object.prototype, @@ -324,6 +328,8 @@ String.prototype = { /* Number properties, see spec 15.7 */ /************************************************************************/ +Number.__proto__ = Function.prototype; + Number.prototype = { __proto__: Object.prototype, @@ -412,6 +418,8 @@ Math = { /* RegExp properties, see spec 15.10 */ /************************************************************************/ +RegExp.__proto__ = Function.prototype; + RegExp.prototype = { __proto__: Object.prototype, From 306bc98bf52b4d9cf10e45d51dedcc496aaf2f96 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:22:58 +0000 Subject: [PATCH 034/238] progress on modeling the global object git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4321 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../tests/builtin_within_function.js | 1 + .../js/ipa/callgraph/GlobalObjectKey.java | 22 ++++ .../JSSSAPropagationCallGraphBuilder.java | 113 +++++++++++++++++- .../com/ibm/wala/cast/ipa/callgraph/Util.java | 1 + .../propagation/PointerAnalysisImpl.java | 3 +- 5 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/builtin_within_function.js create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/builtin_within_function.js b/com.ibm.wala.cast.js.test/examples-src/tests/builtin_within_function.js new file mode 100644 index 000000000..fdc3bf81e --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/builtin_within_function.js @@ -0,0 +1 @@ +z = (function foo() { return this; })(); \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java new file mode 100644 index 000000000..8dc77a825 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java @@ -0,0 +1,22 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; + +/** + * represents the JavaScript global object + */ +public class GlobalObjectKey implements InstanceKey { + + private final IClass concreteType; + + public GlobalObjectKey(IClass concreteType) { + this.concreteType = concreteType; + } + + @Override + public IClass getConcreteType() { + return concreteType; + } + +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java index 7f1ac293d..afdc0a134 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java @@ -15,6 +15,8 @@ import java.util.Set; import com.ibm.wala.analysis.typeInference.TypeInference; import com.ibm.wala.cast.ipa.callgraph.AstSSAPropagationCallGraphBuilder; +import com.ibm.wala.cast.ir.ssa.AstGlobalRead; +import com.ibm.wala.cast.ir.ssa.AstGlobalWrite; import com.ibm.wala.cast.ir.ssa.AstIsDefinedInstruction; import com.ibm.wala.cast.ir.ssa.EachElementHasNextInstruction; import com.ibm.wala.cast.js.analysis.typeInference.JSTypeInference; @@ -30,6 +32,7 @@ import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.cast.loader.AstMethod; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IField; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.fixpoint.AbstractOperator; import com.ibm.wala.ipa.callgraph.AnalysisCache; @@ -60,10 +63,14 @@ import com.ibm.wala.ssa.SSABinaryOpInstruction; import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.ssa.SSAUnaryOpInstruction; import com.ibm.wala.ssa.SymbolTable; +import com.ibm.wala.types.FieldReference; import com.ibm.wala.types.TypeReference; import com.ibm.wala.util.collections.HashSetFactory; +import com.ibm.wala.util.intset.IntSet; import com.ibm.wala.util.intset.IntSetAction; import com.ibm.wala.util.intset.MutableMapping; +import com.ibm.wala.util.intset.MutableSparseIntSet; +import com.ibm.wala.util.intset.OrdinalSet; public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraphBuilder { @@ -117,6 +124,8 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph // // /////////////////////////////////////////////////////////////////////////// + private final GlobalObjectKey globalObject = new GlobalObjectKey(cha.lookupClass(JavaScriptTypes.Object)); + protected ExplicitCallGraph createEmptyCallGraph(IClassHierarchy cha, AnalysisOptions options) { return new JSCallGraph(cha, options, getAnalysisCache()); } @@ -201,6 +210,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph public static class JSImplicitPointsToSetVisitor extends AstImplicitPointsToSetVisitor implements com.ibm.wala.cast.js.ssa.InstructionVisitor { + public JSImplicitPointsToSetVisitor(AstPointerAnalysisImpl analysis, LocalPointerKey lpk) { super(analysis, lpk); } @@ -232,6 +242,31 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph public void visitWithRegion(JavaScriptWithRegion instruction) { } + + @Override + public void visitAstGlobalRead(AstGlobalRead instruction) { + JSPointerAnalysisImpl jsAnalysis = (JSPointerAnalysisImpl) analysis; + pointsToSet = analysis.computeImplicitPointsToSetAtGet(node, instruction.getDeclaredField(), -1, true); + FieldReference field = instruction.getDeclaredField(); + IField f = jsAnalysis.builder.getCallGraph().getClassHierarchy().resolveField(field); + assert f != null; + // if (f == null) { + // pointsToSet = OrdinalSet.empty(); + // } + MutableSparseIntSet S = MutableSparseIntSet.makeEmpty(); + InstanceKey ik = ((JSSSAPropagationCallGraphBuilder)jsAnalysis.builder).globalObject; + PointerKey fkey = analysis.getHeapModel().getPointerKeyForInstanceField(ik, f); + if (fkey != null) { + OrdinalSet pointees = analysis.getPointsToSet(fkey); + IntSet set = pointees.getBackingSet(); + if (set != null) { + S.addAll(set); + } + } + pointsToSet = new OrdinalSet(S, analysis.getInstanceKeyMapping()); + + } + }; protected ImplicitPointsToSetVisitor makeImplicitPointsToVisitor(LocalPointerKey lpk) { @@ -283,6 +318,10 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph super(builder, node); } + protected JSSSAPropagationCallGraphBuilder getBuilder() { + return (JSSSAPropagationCallGraphBuilder) builder; + } + public void visitUnaryOp(SSAUnaryOpInstruction inst) { if (inst.getOpcode() == IUnaryOpInstruction.Operator.NEG) { addLvalTypeKeyConstraint(inst, JavaScriptTypes.Boolean); @@ -320,6 +359,78 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph addLvalTypeKeyConstraint(instruction, JavaScriptTypes.String); } + @Override + public void visitAstGlobalRead(AstGlobalRead instruction) { + int lval = instruction.getDef(); + FieldReference field = instruction.getDeclaredField(); + // skip getfields of primitive type (optimisation) + // this can't happen in JavaScript...right? + // if (field.getFieldType().isPrimitiveType()) { + // return; + // } + PointerKey def = getPointerKeyForLocal(lval); + assert def != null; + + IField f = getClassHierarchy().resolveField(field); + // if (f == null && + // callGraph.getFakeRootNode().getMethod().getDeclaringClass().getReference().equals(field.getDeclaringClass())) + // { + // f = + // callGraph.getFakeRootNode().getMethod().getDeclaringClass().getField(field.getName()); + // } + // + // if (f == null) { + // return; + // } + assert f != null : "could not resolve referenced global " + field; + + if (hasNoInterestingUses(lval)) { + system.recordImplicitPointsToSet(def); + } else { + InstanceKey ik = getBuilder().globalObject; + system.findOrCreateIndexForInstanceKey(ik); + PointerKey p = getPointerKeyForInstanceField(ik, f); + system.newConstraint(def, assignOperator, p); + } + + } + + @Override + public void visitAstGlobalWrite(AstGlobalWrite instruction) { + int rval = instruction.getVal(); + FieldReference field = instruction.getDeclaredField(); + + // skip putfields of primitive type + // if (field.getFieldType().isPrimitiveType()) { + // return; + // } + IField f = getClassHierarchy().resolveField(field); + // if (f == null) { + // if (DEBUG) { + // System.err.println("Could not resolve field " + field); + // } + // Warnings.add(FieldResolutionFailure.create(field)); + // return; + // } + assert f != null : "could not resolve referenced global " + field; + assert !f.getFieldTypeReference().isPrimitiveType(); + InstanceKey globalObj = getBuilder().globalObject; + system.findOrCreateIndexForInstanceKey(globalObj); + PointerKey p = getPointerKeyForInstanceField(globalObj, f); + + PointerKey rvalKey = getPointerKeyForLocal(rval); + if (contentsAreInvariant(symbolTable, du, rval)) { + system.recordImplicitPointsToSet(rvalKey); + InstanceKey[] ik = getInvariantContents(rval); + for (int i = 0; i < ik.length; i++) { + system.newConstraint(p, ik[i]); + } + } else { + system.newConstraint(p, assignOperator, rvalKey); + } + + } + public void visitBinaryOp(final SSABinaryOpInstruction instruction) { handleBinaryOp(instruction, node, symbolTable, du); } @@ -340,7 +451,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph SSAInstruction[] instructions = ir.getInstructions(); for (int ind = basicBlock.getFirstInstructionIndex(); ind <= basicBlock.getLastInstructionIndex(); ind++) { if (instruction.equals(instructions[ind])) { - return ((AstMethod)method).getSourcePosition(ind); + return ((AstMethod) method).getSourcePosition(ind); } } } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index cbbd08cfa..a3237183a 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -72,6 +72,7 @@ public class Util { } public static void dumpCG(PointerAnalysis PA, CallGraph CG) { + if (true) return; for (Iterator x = CG.iterator(); x.hasNext();) { CGNode N = (CGNode) x.next(); System.err.println("\ncallees of node " + N.getMethod() + " " + N.getGraphNodeId()); diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java index 667a6b98b..fd4567a69 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java @@ -70,7 +70,7 @@ public class PointerAnalysisImpl extends AbstractPointerAnalysis { */ private final InstanceKeyFactory iKeyFactory; - private final PropagationCallGraphBuilder builder; + protected final PropagationCallGraphBuilder builder; public PointerAnalysisImpl(PropagationCallGraphBuilder builder, CallGraph cg, PointsToMap pointsToMap, MutableMapping instanceKeys, PointerKeyFactory pointerKeys, InstanceKeyFactory iKeyFactory) { @@ -217,6 +217,7 @@ public class PointerAnalysisImpl extends AbstractPointerAnalysis { LocalPointerKey lpk = (LocalPointerKey) key; CGNode node = lpk.getNode(); IR ir = node.getIR(); + System.err.println(ir); DefUse du = node.getDU(); if (((SSAPropagationCallGraphBuilder) builder).contentsAreInvariant(ir.getSymbolTable(), du, lpk.getValueNumber())) { // cons up the points-to set for invariant contents From 5f91087b44594684f3e5c3cf05a1d02c495cea3b Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:23:13 +0000 Subject: [PATCH 035/238] re-enable debug output git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4322 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/java/com/ibm/wala/cast/ipa/callgraph/Util.java | 1 - 1 file changed, 1 deletion(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index a3237183a..cbbd08cfa 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -72,7 +72,6 @@ public class Util { } public static void dumpCG(PointerAnalysis PA, CallGraph CG) { - if (true) return; for (Iterator x = CG.iterator(); x.hasNext();) { CGNode N = (CGNode) x.next(); System.err.println("\ncallees of node " + N.getMethod() + " " + N.getGraphNodeId()); From 549c3d2775e0102d116090d18fdffe3d197e8385 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:23:25 +0000 Subject: [PATCH 036/238] rename git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4323 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../tests/{builtin_within_function.js => global_object.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename com.ibm.wala.cast.js.test/examples-src/tests/{builtin_within_function.js => global_object.js} (100%) diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/builtin_within_function.js b/com.ibm.wala.cast.js.test/examples-src/tests/global_object.js similarity index 100% rename from com.ibm.wala.cast.js.test/examples-src/tests/builtin_within_function.js rename to com.ibm.wala.cast.js.test/examples-src/tests/global_object.js From 8ce7db97ea764ef19da04c3745f90530579d4fae Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:23:56 +0000 Subject: [PATCH 037/238] more global object handling; needs documentation git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4324 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../javascript/RhinoToAstTranslator.java | 3 +- .../examples-src/tests/global_object.js | 6 ++- .../js/test/TestSimpleCallGraphShape.java | 8 +++ .../js/ipa/callgraph/GlobalObjectKey.java | 3 ++ .../JSSSAPropagationCallGraphBuilder.java | 51 ++++++++++++++----- .../propagation/PointerAnalysisImpl.java | 1 - 6 files changed, 56 insertions(+), 16 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index a4b0583eb..492591d9b 100644 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -23,6 +23,7 @@ import java.util.Map; import org.mozilla.javascript.tools.ToolErrorReporter; import com.ibm.wala.cast.js.html.MappedSourceModule; +import com.ibm.wala.cast.js.ipa.callgraph.JSSSAPropagationCallGraphBuilder; import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.cast.tree.CAst; @@ -1122,7 +1123,7 @@ public class RhinoToAstTranslator { Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("base")), Ast.makeConstant(null)), makeCall(fun, base, firstParamInParens, context))); else - return makeCall(fun, Ast.makeConstant(null), firstParamInParens, context); + return makeCall(fun, makeVarRef(JSSSAPropagationCallGraphBuilder.GLOBAL_OBJ_VAR_NAME), firstParamInParens, context); } else { return Ast.makeNode(CAstNode.PRIMITIVE, gatherChildren(n, context, 1)); } diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/global_object.js b/com.ibm.wala.cast.js.test/examples-src/tests/global_object.js index fdc3bf81e..591517886 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/global_object.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/global_object.js @@ -1 +1,5 @@ -z = (function foo() { return this; })(); \ No newline at end of file +function biz(p) { return p; } + +var z = (function foo() { return this; })(); + +var x = z.biz(3); \ 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 5a9472323..f19b2229a 100644 --- 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 @@ -333,6 +333,14 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { } + private static final Object[][] assertionsForGlobalObj = new Object[][] { + new Object[] { ROOT, new String[] { "tests/global_object.js" } }, + new Object[] { "suffix:global_object.js", new String[] { "suffix:biz" } } }; + + @Test + public void testGlobalObjPassing() throws IOException, IllegalArgumentException, CancelException { + Util.makeScriptCG("tests", "global_object.js"); + } protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java index 8dc77a825..4d310faa7 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java @@ -19,4 +19,7 @@ public class GlobalObjectKey implements InstanceKey { return concreteType; } + public String toString() { + return "JS Global Object"; + } } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java index afdc0a134..b418a070f 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java @@ -71,6 +71,7 @@ import com.ibm.wala.util.intset.IntSetAction; import com.ibm.wala.util.intset.MutableMapping; import com.ibm.wala.util.intset.MutableSparseIntSet; import com.ibm.wala.util.intset.OrdinalSet; +import com.ibm.wala.util.strings.Atom; public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraphBuilder { @@ -78,6 +79,25 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph public static final boolean DEBUG_TYPE_INFERENCE = false; + /** + * name to be used internally to pass around the global object + */ + public static final String GLOBAL_OBJ_VAR_NAME = "__WALA__int3rnal__global"; + + /** + * is field a direct (WALA-internal) reference to the global object? + */ + private static boolean directGlobalObjectRef(FieldReference field) { + return field.getName().toString().endsWith(GLOBAL_OBJ_VAR_NAME); + } + + private static FieldReference makeNonGlobalFieldReference(FieldReference field) { + String nonGlobalFieldName = field.getName().toString().substring(7); + field = FieldReference.findOrCreate(JavaScriptTypes.Root, Atom.findOrCreateUnicodeAtom(nonGlobalFieldName), JavaScriptTypes.Root); + return field; + } + + private URL scriptBaseURL; public URL getBaseURL() { @@ -210,7 +230,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph public static class JSImplicitPointsToSetVisitor extends AstImplicitPointsToSetVisitor implements com.ibm.wala.cast.js.ssa.InstructionVisitor { - + public JSImplicitPointsToSetVisitor(AstPointerAnalysisImpl analysis, LocalPointerKey lpk) { super(analysis, lpk); } @@ -246,16 +266,15 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph @Override public void visitAstGlobalRead(AstGlobalRead instruction) { JSPointerAnalysisImpl jsAnalysis = (JSPointerAnalysisImpl) analysis; - pointsToSet = analysis.computeImplicitPointsToSetAtGet(node, instruction.getDeclaredField(), -1, true); - FieldReference field = instruction.getDeclaredField(); + FieldReference field = makeNonGlobalFieldReference(instruction.getDeclaredField()); IField f = jsAnalysis.builder.getCallGraph().getClassHierarchy().resolveField(field); assert f != null; // if (f == null) { // pointsToSet = OrdinalSet.empty(); // } MutableSparseIntSet S = MutableSparseIntSet.makeEmpty(); - InstanceKey ik = ((JSSSAPropagationCallGraphBuilder)jsAnalysis.builder).globalObject; - PointerKey fkey = analysis.getHeapModel().getPointerKeyForInstanceField(ik, f); + InstanceKey globalObj = ((JSSSAPropagationCallGraphBuilder) jsAnalysis.builder).globalObject; + PointerKey fkey = analysis.getHeapModel().getPointerKeyForInstanceField(globalObj, f); if (fkey != null) { OrdinalSet pointees = analysis.getPointsToSet(fkey); IntSet set = pointees.getBackingSet(); @@ -264,7 +283,6 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph } } pointsToSet = new OrdinalSet(S, analysis.getInstanceKeyMapping()); - } }; @@ -362,7 +380,9 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph @Override public void visitAstGlobalRead(AstGlobalRead instruction) { int lval = instruction.getDef(); - FieldReference field = instruction.getDeclaredField(); + FieldReference field = makeNonGlobalFieldReference(instruction.getDeclaredField()); + // TODO new field reference should be FieldReference.findOrCreate(JavaScriptTypes.Root, Atom.findOrCreateUnicodeAtom(field), JavaScriptTypes.Root) + // strip off "global " from field name // skip getfields of primitive type (optimisation) // this can't happen in JavaScript...right? // if (field.getFieldType().isPrimitiveType()) { @@ -370,7 +390,6 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph // } PointerKey def = getPointerKeyForLocal(lval); assert def != null; - IField f = getClassHierarchy().resolveField(field); // if (f == null && // callGraph.getFakeRootNode().getMethod().getDeclaringClass().getReference().equals(field.getDeclaringClass())) @@ -387,18 +406,24 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph if (hasNoInterestingUses(lval)) { system.recordImplicitPointsToSet(def); } else { - InstanceKey ik = getBuilder().globalObject; - system.findOrCreateIndexForInstanceKey(ik); - PointerKey p = getPointerKeyForInstanceField(ik, f); - system.newConstraint(def, assignOperator, p); + InstanceKey globalObj = getBuilder().globalObject; + if (directGlobalObjectRef(field)) { + // points-to set is just the global object + system.newConstraint(def, globalObj); + } else { + system.findOrCreateIndexForInstanceKey(globalObj); + PointerKey p = getPointerKeyForInstanceField(globalObj, f); + system.newConstraint(def, assignOperator, p); + } } } + @Override public void visitAstGlobalWrite(AstGlobalWrite instruction) { int rval = instruction.getVal(); - FieldReference field = instruction.getDeclaredField(); + FieldReference field = makeNonGlobalFieldReference(instruction.getDeclaredField()); // skip putfields of primitive type // if (field.getFieldType().isPrimitiveType()) { diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java index fd4567a69..238c99ea7 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointerAnalysisImpl.java @@ -217,7 +217,6 @@ public class PointerAnalysisImpl extends AbstractPointerAnalysis { LocalPointerKey lpk = (LocalPointerKey) key; CGNode node = lpk.getNode(); IR ir = node.getIR(); - System.err.println(ir); DefUse du = node.getDU(); if (((SSAPropagationCallGraphBuilder) builder).contentsAreInvariant(ir.getSymbolTable(), du, lpk.getValueNumber())) { // cons up the points-to set for invariant contents From 02c1b8060554f050cc9bc518a00cda8d4a7c4cb8 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:24:07 +0000 Subject: [PATCH 038/238] update Eclipse prefs git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4325 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../.settings/org.eclipse.jdt.core.prefs | 339 +++++++++++++++++- .../.settings/org.eclipse.jdt.ui.prefs | 58 +++ 2 files changed, 396 insertions(+), 1 deletion(-) create mode 100644 com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.ui.prefs diff --git a/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.core.prefs b/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.core.prefs index 3336ef1b6..9a013352f 100644 --- a/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.core.prefs +++ b/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.core.prefs @@ -1,7 +1,344 @@ -#Tue Jun 23 17:02:07 EDT 2009 +#Thu Feb 03 10:12:26 EST 2011 eclipse.preferences.version=1 +instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=ignore +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=disabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=warning +org.eclipse.jdt.core.compiler.problem.unusedLabel=warning +org.eclipse.jdt.core.compiler.problem.unusedLocal=warning +org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=2 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=132 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=2 +org.eclipse.jdt.core.formatter.use_on_off_tags=false +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true diff --git a/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.ui.prefs b/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 000000000..77812d524 --- /dev/null +++ b/com.ibm.wala.cast.js.rhino/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,58 @@ +#Tue Dec 02 13:34:58 EST 2008 +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=false +cleanup.always_use_this_for_non_static_method_access=false +cleanup.convert_to_enhanced_for_loop=false +cleanup.correct_indentation=false +cleanup.format_source_code=false +cleanup.format_source_code_changes_only=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=false +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.organize_imports=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.remove_private_constructors=true +cleanup.remove_trailing_whitespaces=false +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.use_blocks=false +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_parentheses_in_expressions=false +cleanup.use_this_for_non_static_field_access=false +cleanup.use_this_for_non_static_field_access_only_if_necessary=true +cleanup.use_this_for_non_static_method_access=false +cleanup.use_this_for_non_static_method_access_only_if_necessary=true +cleanup_profile=org.eclipse.jdt.ui.default.eclipse_clean_up_profile +cleanup_settings_version=2 +eclipse.preferences.version=1 +formatter_profile=_WALA +formatter_settings_version=11 +instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true +org.eclipse.jdt.ui.text.custom_code_templates= From eb73fac9e47305cdfc09dbff50384006b92b2c2c Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:24:25 +0000 Subject: [PATCH 039/238] documentation of global object handling git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4326 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../javascript/RhinoToAstTranslator.java | 4 +- .../js/ipa/callgraph/GlobalObjectKey.java | 4 +- .../JSSSAPropagationCallGraphBuilder.java | 59 +++++++------------ 3 files changed, 28 insertions(+), 39 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index 492591d9b..beb40f357 100644 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -1122,8 +1122,10 @@ public class RhinoToAstTranslator { Ast.makeNode(CAstNode.BLOCK_EXPR, Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("base")), Ast.makeConstant(null)), makeCall(fun, base, firstParamInParens, context))); - else + else { + // pass the global object as the receiver argument return makeCall(fun, makeVarRef(JSSSAPropagationCallGraphBuilder.GLOBAL_OBJ_VAR_NAME), firstParamInParens, context); + } } else { return Ast.makeNode(CAstNode.PRIMITIVE, gatherChildren(n, context, 1)); } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java index 4d310faa7..ec3402833 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/GlobalObjectKey.java @@ -4,7 +4,9 @@ import com.ibm.wala.classLoader.IClass; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; /** - * represents the JavaScript global object + * Represents the JavaScript global object. + * + * @see JSSSAPropagationCallGraphBuilder */ public class GlobalObjectKey implements InstanceKey { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java index b418a070f..d6b297002 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java @@ -20,6 +20,7 @@ import com.ibm.wala.cast.ir.ssa.AstGlobalWrite; import com.ibm.wala.cast.ir.ssa.AstIsDefinedInstruction; import com.ibm.wala.cast.ir.ssa.EachElementHasNextInstruction; import com.ibm.wala.cast.js.analysis.typeInference.JSTypeInference; +import com.ibm.wala.cast.js.ipa.callgraph.JSSSAPropagationCallGraphBuilder.JSPointerAnalysisImpl.JSImplicitPointsToSetVisitor; import com.ibm.wala.cast.js.ssa.InstructionVisitor; import com.ibm.wala.cast.js.ssa.JavaScriptCheckReference; import com.ibm.wala.cast.js.ssa.JavaScriptInstanceOf; @@ -73,6 +74,23 @@ import com.ibm.wala.util.intset.MutableSparseIntSet; import com.ibm.wala.util.intset.OrdinalSet; import com.ibm.wala.util.strings.Atom; +/** + * Specialized pointer analysis constraint generation for JavaScript. + * + *

Global object handling

+ * + * The global object is represented by a {@link GlobalObjectKey} stored in + * {@link #globalObject}. {@link AstGlobalRead} and {@link AstGlobalWrite} + * instructions are treated as accessing properties of the global object; see + * {@link JSConstraintVisitor#visitAstGlobalRead(AstGlobalRead)}, + * {@link JSConstraintVisitor#visitAstGlobalWrite(AstGlobalWrite)}, and + * {@link JSImplicitPointsToSetVisitor#visitAstGlobalRead(AstGlobalRead)}. + * Finally, we need to represent direct flow of the global object to handle + * receiver argument semantics (see + * {@link org.mozilla.javascript.RhinoToAstTranslator}). To do so, we create a + * reference to a global named {@link #GLOBAL_OBJ_VAR_NAME}, which is handled + * specially in {@link JSConstraintVisitor#visitAstGlobalRead(AstGlobalRead)}. + */ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraphBuilder { public static final boolean DEBUG_LEXICAL = false; @@ -90,14 +108,14 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph private static boolean directGlobalObjectRef(FieldReference field) { return field.getName().toString().endsWith(GLOBAL_OBJ_VAR_NAME); } - + private static FieldReference makeNonGlobalFieldReference(FieldReference field) { String nonGlobalFieldName = field.getName().toString().substring(7); - field = FieldReference.findOrCreate(JavaScriptTypes.Root, Atom.findOrCreateUnicodeAtom(nonGlobalFieldName), JavaScriptTypes.Root); + field = FieldReference.findOrCreate(JavaScriptTypes.Root, Atom.findOrCreateUnicodeAtom(nonGlobalFieldName), + JavaScriptTypes.Root); return field; } - private URL scriptBaseURL; public URL getBaseURL() { @@ -267,11 +285,9 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph public void visitAstGlobalRead(AstGlobalRead instruction) { JSPointerAnalysisImpl jsAnalysis = (JSPointerAnalysisImpl) analysis; FieldReference field = makeNonGlobalFieldReference(instruction.getDeclaredField()); + assert !directGlobalObjectRef(field); IField f = jsAnalysis.builder.getCallGraph().getClassHierarchy().resolveField(field); assert f != null; - // if (f == null) { - // pointsToSet = OrdinalSet.empty(); - // } MutableSparseIntSet S = MutableSparseIntSet.makeEmpty(); InstanceKey globalObj = ((JSSSAPropagationCallGraphBuilder) jsAnalysis.builder).globalObject; PointerKey fkey = analysis.getHeapModel().getPointerKeyForInstanceField(globalObj, f); @@ -381,28 +397,10 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph public void visitAstGlobalRead(AstGlobalRead instruction) { int lval = instruction.getDef(); FieldReference field = makeNonGlobalFieldReference(instruction.getDeclaredField()); - // TODO new field reference should be FieldReference.findOrCreate(JavaScriptTypes.Root, Atom.findOrCreateUnicodeAtom(field), JavaScriptTypes.Root) - // strip off "global " from field name - // skip getfields of primitive type (optimisation) - // this can't happen in JavaScript...right? - // if (field.getFieldType().isPrimitiveType()) { - // return; - // } PointerKey def = getPointerKeyForLocal(lval); assert def != null; IField f = getClassHierarchy().resolveField(field); - // if (f == null && - // callGraph.getFakeRootNode().getMethod().getDeclaringClass().getReference().equals(field.getDeclaringClass())) - // { - // f = - // callGraph.getFakeRootNode().getMethod().getDeclaringClass().getField(field.getName()); - // } - // - // if (f == null) { - // return; - // } assert f != null : "could not resolve referenced global " + field; - if (hasNoInterestingUses(lval)) { system.recordImplicitPointsToSet(def); } else { @@ -419,24 +417,11 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph } - @Override public void visitAstGlobalWrite(AstGlobalWrite instruction) { int rval = instruction.getVal(); FieldReference field = makeNonGlobalFieldReference(instruction.getDeclaredField()); - - // skip putfields of primitive type - // if (field.getFieldType().isPrimitiveType()) { - // return; - // } IField f = getClassHierarchy().resolveField(field); - // if (f == null) { - // if (DEBUG) { - // System.err.println("Could not resolve field " + field); - // } - // Warnings.add(FieldResolutionFailure.create(field)); - // return; - // } assert f != null : "could not resolve referenced global " + field; assert !f.getFieldTypeReference().isPrimitiveType(); InstanceKey globalObj = getBuilder().globalObject; From 515c9b8f183aaf0de8e2425638eb8cd4f26f0358 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:24:38 +0000 Subject: [PATCH 040/238] Fixed code for determining whether a callee should be analysed in a for-in context: checking whether its name _contains_ HACK_METHOD_STR is not a good idea, since this is true also for inner functions of the forin_body functions. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4327 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index e124bf744..3e7271df8 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -170,7 +170,9 @@ public class ForInContextSelector implements ContextSelector { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); - if (callee.getDeclaringClass().getName().toString().contains(HACK_METHOD_STR)) { + String calleeFullName = callee.getDeclaringClass().getName().toString(); + String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); + if (calleeShortName.startsWith(HACK_METHOD_STR)) { InstanceKey loopVar = receiver[2]; IClass stringClass = caller.getClassHierarchy().lookupClass(JavaScriptTypes.String); if(loopVar instanceof ConstantKey) { From 3172ba6b0fd2601ae85714849f6a7a19b55886b9 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:24:53 +0000 Subject: [PATCH 041/238] Fixed data flow propagation code for the arguments array: arguments[0] is not the receiver, it is the first real argument. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4328 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../JSSSAPropagationCallGraphBuilder.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java index d6b297002..0b70ca4d6 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java @@ -670,10 +670,14 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph int paramCount = targetST.getParameterValueNumbers().length; int argCount = instruction.getNumberOfParameters(); + + // the first argument is not actually an argument, it is the receiver object; + // we should skip it when setting up the arguments array + int num_pseudoargs = 1; // pass actual arguments to formals in the normal way for (int i = 0; i < Math.min(paramCount, argCount); i++) { - InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, i) }; + InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, i-num_pseudoargs) }; PointerKey F = getTargetPointerKey(target, i); if (constParams != null && constParams[i] != null) { @@ -681,14 +685,14 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph system.newConstraint(F, constParams[i][j]); } - if (av != -1) + if (av != -1 && i > num_pseudoargs) targetVisitor.newFieldWrite(target, av, fn, constParams[i]); } else { PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i)); system.newConstraint(F, (F instanceof FilteredPointerKey) ? filterOperator : assignOperator, A); - if (av != -1) + if (av != -1 && i > num_pseudoargs) targetVisitor.newFieldWrite(target, av, fn, F); } } @@ -697,10 +701,10 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph if (paramCount < argCount) { if (av != -1) { for (int i = paramCount; i < argCount; i++) { - InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, i) }; - if (constParams != null && constParams[i] != null) { - targetVisitor.newFieldWrite(target, av, fn, constParams[i]); - } else { + InstanceKey[] fn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, i-num_pseudoargs) }; + if (constParams != null && constParams[i] != null && i > num_pseudoargs) { + targetVisitor.newFieldWrite(target, av, fn, constParams[i]); + } else if(i > num_pseudoargs) { PointerKey A = getPointerKeyForLocal(caller, instruction.getUse(i)); targetVisitor.newFieldWrite(target, av, fn, A); } @@ -723,7 +727,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph // write `length' in argument objects if (av != -1) { - InstanceKey[] svn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, argCount) }; + InstanceKey[] svn = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.Number, argCount-1) }; InstanceKey[] lnv = new InstanceKey[] { getInstanceKeyForConstant(JavaScriptTypes.String, "length") }; targetVisitor.newFieldWrite(target, av, lnv, svn); } From f9d6e38eeadd06a8931b51aea5d37a8f960de015 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:25:06 +0000 Subject: [PATCH 042/238] Removed spurious "arguments" property on function objects. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4329 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/com/ibm/wala/cast/js/translator/JSAstTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JSAstTranslator.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JSAstTranslator.java index a6d109a31..ca851601c 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JSAstTranslator.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/translator/JSAstTranslator.java @@ -359,7 +359,7 @@ public class JSAstTranslator extends AstTranslator { doNewObject(context, null, tempVal, "Array", null); CAstSymbol args = new CAstSymbolImpl("arguments"); context.currentScope().declare(args, tempVal); - context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(1, tempVal, "arguments")); + //context.cfg().addInstruction(((JSInstructionFactory) insts).PutInstruction(1, tempVal, "arguments")); } protected boolean doVisit(CAstNode n, Context cntxt, CAstVisitor visitor) { From 33378fd07114b8d568f11b70ead1e0e5415a2262 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:25:20 +0000 Subject: [PATCH 043/238] Added option to warn about big points-to sets. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4330 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../propagation/PointsToSetVariable.java | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointsToSetVariable.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointsToSetVariable.java index ab2baca1b..af29270cd 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointsToSetVariable.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/PointsToSetVariable.java @@ -27,7 +27,12 @@ import com.ibm.wala.util.intset.MutableSparseIntSet; * Representation of a points-to set during an andersen-style analysis. */ public class PointsToSetVariable extends IntSetVariable { - + /** + * if set, emits a warning whenever a points-to set grows bigger than {@link #SIZE_THRESHOLD} + */ + public static final boolean CRY_ABOUT_BIG_POINTSTO_SETS = false; + public static final int SIZE_THRESHOLD = 100; + /** * if set, check that all instance keys in a points-to set are consistent with the type of the corresponding pointer key */ @@ -61,6 +66,15 @@ public class PointsToSetVariable extends IntSetVariable { } } + private boolean cried = false; + @SuppressWarnings("unused") + private void cryIfTooBig() { + if (CRY_ABOUT_BIG_POINTSTO_SETS && !cried && super.size() > SIZE_THRESHOLD) { + cried = true; + System.err.println("too big: " + pointerKey + ": " + size()); + } + } + @Override public void add(int b) { if (PARANOID) { @@ -69,6 +83,7 @@ public class PointsToSetVariable extends IntSetVariable { checkTypes(m); } super.add(b); + cryIfTooBig(); } @Override @@ -76,7 +91,9 @@ public class PointsToSetVariable extends IntSetVariable { if (PARANOID) { checkTypes(B); } - return super.addAll(B); + boolean v = super.addAll(B); + cryIfTooBig(); + return v; } /** @@ -126,7 +143,9 @@ public class PointsToSetVariable extends IntSetVariable { checkTypes(other.getValue()); } // TODO Auto-generated method stub - return super.addAll(other); + boolean v = super.addAll(other); + cryIfTooBig(); + return v; } /** From 875347167beeed8b8b9dc888f9216f396135833e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:25:38 +0000 Subject: [PATCH 044/238] started some work git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4331 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/function_apply.js | 6 ++ .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 1 + ...avaScriptFunctionApplyContextSelector.java | 85 +++++++++++++++++++ ...ScriptFunctionCallApplyTargetSelector.java | 2 +- 4 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js index bc45ab52e..cc670aac0 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js @@ -3,3 +3,9 @@ function bar(y) { return y + 3; } var p = bar; p.apply(null, [7]); +function biz() { return this; } + +var q = biz; +var o = { m: function n() {} } +var r = q.apply(o); +o.m() \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index b9d9b9a4c..57f9f596a 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -43,6 +43,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); + contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector, this); contextSelector = new LexicalScopingResolverContexts(this, contextSelector); if (doOneCFA) { contextSelector = new nCFAContextSelector(1, contextSelector); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java new file mode 100644 index 000000000..c85223acf --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -0,0 +1,85 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.ContextItem; +import com.ibm.wala.ipa.callgraph.ContextKey; +import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.util.intset.IntSet; +import com.ibm.wala.util.intset.IntSetUtil; + +public class JavaScriptFunctionApplyContextSelector implements ContextSelector { + + private final ContextSelector base; + + private final JSSSAPropagationCallGraphBuilder builder; + + public JavaScriptFunctionApplyContextSelector(ContextSelector base, JSSSAPropagationCallGraphBuilder builder) { + this.base = base; + this.builder = builder; + } + + public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { + // 0 for function (synthetic apply), 1 for this (function being invoked), 2 + // for this arg of function being invoked, + // 3 for arguments array + if (caller.getIR().getCalls(site)[0].getNumberOfUses() >= 4) { + return IntSetUtil.make(new int[] { 3 }).union(base.getRelevantParameters(caller, site)); + } else { + return base.getRelevantParameters(caller, site); + } + } + + public static class ApplyContext implements Context { + private final Context delegate; + + /** + * null in the case where no args array is passed + * + * TODO strictly speaking, we don't care about the exact InstanceKey per se; we only care about + * some of its properties...capture more directly? + */ + private final InstanceKey argsList; + + ApplyContext(Context delegate, InstanceKey argsList) { + this.delegate = delegate; + this.argsList = argsList; + } + + @Override + public ContextItem get(ContextKey name) { + return delegate.get(name); + } + + } + + public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { + if (callee.toString().equals("")) { + System.err.println("CALLEE: " + callee); + InstanceKey argsList = null; + if (receiver.length >= 4) { + argsList = receiver[3]; + // System.err.println(argsList); + // if + // (argsList.getConcreteType().equals(caller.getClassHierarchy().lookupClass(JavaScriptTypes.Array))) + // { + // System.err.println("it's an array"); + // PointerKey catalog = ((AstPointerKeyFactory) + // builder.getPointerKeyFactory()).getPointerKeyForObjectCatalog(argsList); + // System.err.println(catalog); + // OrdinalSet catalogp2set = + // builder.getPointerAnalysis().getPointsToSet(catalog); + // System.err.println(catalogp2set); + // } + } else { + System.err.println("no arguments array"); + } + return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), argsList); + } + return base.getCalleeTarget(caller, site, callee, receiver); + } + +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java index e3f83ac85..9f82f6108 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java @@ -69,7 +69,7 @@ public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSe } private IMethod getFunctionApplyTarget(CGNode caller, CallSiteReference site, IClass receiver) { - System.err.println("TODO: handle Function.apply()"); +// System.err.println("TODO: handle Function.apply()"); return base.getCalleeTarget(caller, site, receiver); } From a30ea94aac6d79087f173f360e8868bb2b377d82 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:26:01 +0000 Subject: [PATCH 045/238] support Function.apply() with no argsList array git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4332 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/function_apply.js | 8 +- .../js/test/TestSimpleCallGraphShape.java | 8 +- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 4 +- ...ScriptFunctionApplyContextInterpreter.java | 79 +++++++++++++++++++ ...avaScriptFunctionApplyContextSelector.java | 46 ++++++++++- 5 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js index cc670aac0..769bb7095 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js @@ -1,11 +1,11 @@ -function bar(y) { return y + 3; } +//function bar(y) { return y + 3; } -var p = bar; -p.apply(null, [7]); +//var p = bar; +//p.apply(null, [7]); function biz() { return this; } var q = biz; -var o = { m: function n() {} } +var o = { m: function theOne() {} } var r = q.apply(o); o.m() \ 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 f19b2229a..b06538c4b 100644 --- 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 @@ -316,10 +316,14 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { } } + private static final Object[][] assertionsForFunctionApply = new Object[][] { + new Object[] { ROOT, new String[] { "tests/function_apply.js" } }, + new Object[] { "suffix:function_apply.js", new String[] { "suffix:theOne" } } }; + @Test public void testFunctionDotApply() throws IOException, IllegalArgumentException, CancelException { - Util.makeScriptCG("tests", "function_apply.js"); - // TODO assert that bar() is reachable + CallGraph CG = Util.makeScriptCG("tests", "function_apply.js"); + verifyGraphAssertions(CG, assertionsForFunctionApply); } private static final Object[][] assertionsForComplexCall = new Object[][] { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 57f9f596a..1834e0f79 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -19,6 +19,7 @@ import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.impl.DefaultContextSelector; import com.ibm.wala.ipa.callgraph.impl.DelegatingContextSelector; import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; +import com.ibm.wala.ipa.callgraph.propagation.cfa.DelegatingSSAContextInterpreter; import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys; import com.ibm.wala.ipa.callgraph.propagation.cfa.nCFAContextSelector; import com.ibm.wala.ipa.cha.IClassHierarchy; @@ -34,6 +35,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { super(cha, options, cache); SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha); + contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache), contextInterpreter); setContextInterpreter(contextInterpreter); options.setSelector(new JavaScriptFunctionCallApplyTargetSelector(cha, new JavaScriptConstructTargetSelector(cha, options.getMethodTargetSelector()))); @@ -43,7 +45,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); - contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector, this); + contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); contextSelector = new LexicalScopingResolverContexts(this, contextSelector); if (doOneCFA) { contextSelector = new nCFAContextSelector(1, contextSelector); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java new file mode 100644 index 000000000..057d8626a --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java @@ -0,0 +1,79 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import com.ibm.wala.cast.ipa.callgraph.AstContextInsensitiveSSAContextInterpreter; +import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptFunctionApplyContextSelector.ApplyContext; +import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummarizedFunction; +import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummary; +import com.ibm.wala.cast.js.loader.JSCallSiteReference; +import com.ibm.wala.cast.js.ssa.JSInstructionFactory; +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ipa.callgraph.AnalysisCache; +import com.ibm.wala.ipa.callgraph.AnalysisOptions; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ssa.DefUse; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.types.MethodReference; + +public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensitiveSSAContextInterpreter { + + public JavaScriptFunctionApplyContextInterpreter(AnalysisOptions options, AnalysisCache cache) { + super(options, cache); + } + + @Override + public boolean understands(IMethod method, Context context) { + return context instanceof ApplyContext; + } + + @Override + public IR getIR(CGNode node) { + if (understands(node.getMethod(), node.getContext())) { + ApplyContext applyContext = (ApplyContext) node.getContext(); + InstanceKey argsList = applyContext.getArgsListKey(); + if (argsList == null) { + return makeIRForNoArgList(node); + } + assert false : "asking for IR for " + node; + } + return super.getIR(node); + } + + private IR makeIRForNoArgList(CGNode node) { + // kind of a hack; re-use the summarized function infrastructure + MethodReference ref = node.getMethod().getReference(); + IClass declaringClass = node.getMethod().getDeclaringClass(); + JSInstructionFactory insts = (JSInstructionFactory) declaringClass.getClassLoader().getInstructionFactory(); + // nargs needs to match that of Function.apply(), even though no argsList + // argument was passed in this case + int nargs = 4; + JavaScriptSummary S = new JavaScriptSummary(ref, nargs); + + // generate invocation instruction for the real method being invoked + int resultVal = nargs + 2; + CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter()); + int[] params = new int[1]; + params[0] = 3; + // function being invoked is in v2 + S.addStatement(insts.Invoke(2, resultVal, params, resultVal + 1, cs)); + S.getNextProgramCounter(); + + S.addStatement(insts.ReturnInstruction(resultVal, false)); + S.getNextProgramCounter(); + + JavaScriptSummarizedFunction t = new JavaScriptSummarizedFunction(ref, S, declaringClass); + return t.makeIR(node.getContext(), null); + } + + @Override + public DefUse getDU(CGNode node) { + if (understands(node.getMethod(), node.getContext())) { + return new DefUse(getIR(node)); + } + return super.getDU(node); + } + +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index c85223acf..872ddf1e3 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -15,11 +15,8 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { private final ContextSelector base; - private final JSSSAPropagationCallGraphBuilder builder; - - public JavaScriptFunctionApplyContextSelector(ContextSelector base, JSSSAPropagationCallGraphBuilder builder) { + public JavaScriptFunctionApplyContextSelector(ContextSelector base) { this.base = base; - this.builder = builder; } public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { @@ -54,6 +51,47 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { return delegate.get(name); } + public InstanceKey getArgsListKey() { + return argsList; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((argsList == null) ? 0 : argsList.hashCode()); + result = prime * result + ((delegate == null) ? 0 : delegate.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ApplyContext other = (ApplyContext) obj; + if (argsList == null) { + if (other.argsList != null) + return false; + } else if (!argsList.equals(other.argsList)) + return false; + if (delegate == null) { + if (other.delegate != null) + return false; + } else if (!delegate.equals(other.delegate)) + return false; + return true; + } + + @Override + public String toString() { + return "ApplyContext [delegate=" + delegate + ", argsList=" + argsList + "]"; + } + + } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { From c250331e78b78f9fafcfa1ba513204db8f7dfade Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:26:23 +0000 Subject: [PATCH 046/238] more work on Function.apply(), but regression tests aren't passing yet git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4333 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/function_apply.js | 17 ++-- .../js/test/TestSimpleCallGraphShape.java | 4 +- ...ScriptFunctionApplyContextInterpreter.java | 81 ++++++++++++++++++- ...avaScriptFunctionApplyContextSelector.java | 55 ++++--------- 4 files changed, 107 insertions(+), 50 deletions(-) diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js index 769bb7095..2c654bc7a 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js @@ -1,11 +1,16 @@ -//function bar(y) { return y + 3; } - -//var p = bar; -//p.apply(null, [7]); - function biz() { return this; } var q = biz; var o = { m: function theOne() {} } var r = q.apply(o); -o.m() \ No newline at end of file +o.m() + +function id(y) { return y; } + +function theTwo() {} +var p = id; +var s = p.apply(null, [theTwo]); +s(); + +// test invoking with non-array argsList +p.apply(null, o); 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 b06538c4b..54b881c19 100644 --- 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 @@ -318,7 +318,9 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { private static final Object[][] assertionsForFunctionApply = new Object[][] { new Object[] { ROOT, new String[] { "tests/function_apply.js" } }, - new Object[] { "suffix:function_apply.js", new String[] { "suffix:theOne" } } }; + new Object[] { "suffix:function_apply.js", new String[] { "suffix:theOne" } }, + new Object[] { "suffix:function_apply.js", new String[] { "suffix:theTwo" } } }; + @Test public void testFunctionDotApply() throws IOException, IllegalArgumentException, CancelException { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java index 057d8626a..d8facf8b5 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java @@ -13,11 +13,16 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; -import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ssa.DefUse; import com.ibm.wala.ssa.IR; import com.ibm.wala.types.MethodReference; +/** + * TODO cache generated IRs + * + * @author manu + * + */ public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensitiveSSAContextInterpreter { public JavaScriptFunctionApplyContextInterpreter(AnalysisOptions options, AnalysisCache cache) { @@ -33,15 +38,83 @@ public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensi public IR getIR(CGNode node) { if (understands(node.getMethod(), node.getContext())) { ApplyContext applyContext = (ApplyContext) node.getContext(); - InstanceKey argsList = applyContext.getArgsListKey(); - if (argsList == null) { + boolean isNonNullArray = applyContext.isNonNullArray(); + if (isNonNullArray) { + return makeIRForArgList(node); + } else { return makeIRForNoArgList(node); } - assert false : "asking for IR for " + node; } return super.getIR(node); } + private IR makeIRForArgList(CGNode node) { + // we have: v1 is dummy apply method + // v2 is function to be invoked + // v3 is argument to be passed as 'this' + // v4 is array containing remaining arguments + // Ideally, we would take advantage of cases like constant arrays and + // precisely pass arguments in the appropriate slots. Unfortunately, in the + // pointer analysis fixed-point computation, it's possible that we will + // process the apply() call and then process some update to the arguments + // array, reflected only in its property values and object catalog. Perhaps + // eventually, we could create contexts based on the catalog of the object + // and then do a better job, but since the catalog is not passed directly as + // a parameter to apply(), this is not so easy. + // In the meantime, we do things imprecisely. We read an arbitrary + // enumerable property name of the argument list (via an + // EachElementGetInstruction), perform a dynamic read of that property, and + // then pass the resulting values in all argument positions (except 'this'). + // + // NOTE: we don't know how many arguments the callee will take, whether it + // uses + // the arguments array, etc. For now, we use an unsound hack and pass the + // argument 10 times. + // + // NOTE: strictly speaking, using EachElementGet could be imprecise, as it + // should + // return properties inherited via the prototype chain. However, since this + // behavior + // is not modeled in WALA as of now, using the instruction is ok. + MethodReference ref = node.getMethod().getReference(); + IClass declaringClass = node.getMethod().getDeclaringClass(); + JSInstructionFactory insts = (JSInstructionFactory) declaringClass.getClassLoader().getInstructionFactory(); + // nargs needs to match that of Function.apply(), even though no argsList + // argument was passed in this case + int nargs = 4; + JavaScriptSummary S = new JavaScriptSummary(ref, nargs); + + // read an arbitrary property name via EachElementGet + int curValNum = nargs + 2; + int eachElementGetResult = curValNum++; + S.addStatement(insts.EachElementGetInstruction(eachElementGetResult, 4)); + S.getNextProgramCounter(); + // read value from the arbitrary property name + int propertyReadResult = curValNum++; + S.addStatement(insts.PropertyRead(propertyReadResult, 4, eachElementGetResult)); + S.getNextProgramCounter(); + + int numParamsToPass = 10; + CallSiteReference cs = new JSCallSiteReference(S.getNextProgramCounter()); + int[] params = new int[numParamsToPass + 1]; + // pass the 'this' argument first + params[0] = 3; + for (int i = 1; i < params.length; i++) { + params[i] = propertyReadResult; + } + // function being invoked is in v2 + int resultVal = curValNum++; + int excVal = curValNum++; + S.addStatement(insts.Invoke(2, resultVal, params, excVal, cs)); + S.getNextProgramCounter(); + + S.addStatement(insts.ReturnInstruction(resultVal, false)); + S.getNextProgramCounter(); + + JavaScriptSummarizedFunction t = new JavaScriptSummarizedFunction(ref, S, declaringClass); + return t.makeIR(node.getContext(), null); + } + private IR makeIRForNoArgList(CGNode node) { // kind of a hack; re-use the summarized function infrastructure MethodReference ref = node.getMethod().getReference(); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index 872ddf1e3..1157d0ca2 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -1,5 +1,6 @@ package com.ibm.wala.cast.js.ipa.callgraph; +import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; @@ -34,16 +35,13 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { private final Context delegate; /** - * null in the case where no args array is passed - * - * TODO strictly speaking, we don't care about the exact InstanceKey per se; we only care about - * some of its properties...capture more directly? + * was the argsList argument a non-null Array? */ - private final InstanceKey argsList; + private final boolean isNonNullArray; - ApplyContext(Context delegate, InstanceKey argsList) { + ApplyContext(Context delegate, boolean isNonNullArray) { this.delegate = delegate; - this.argsList = argsList; + this.isNonNullArray = isNonNullArray; } @Override @@ -51,16 +49,16 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { return delegate.get(name); } - public InstanceKey getArgsListKey() { - return argsList; + public boolean isNonNullArray() { + return isNonNullArray; } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((argsList == null) ? 0 : argsList.hashCode()); result = prime * result + ((delegate == null) ? 0 : delegate.hashCode()); + result = prime * result + (isNonNullArray ? 1231 : 1237); return result; } @@ -73,49 +71,28 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { if (getClass() != obj.getClass()) return false; ApplyContext other = (ApplyContext) obj; - if (argsList == null) { - if (other.argsList != null) - return false; - } else if (!argsList.equals(other.argsList)) - return false; if (delegate == null) { if (other.delegate != null) return false; } else if (!delegate.equals(other.delegate)) return false; + if (isNonNullArray != other.isNonNullArray) + return false; return true; } - @Override - public String toString() { - return "ApplyContext [delegate=" + delegate + ", argsList=" + argsList + "]"; - } - - } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { if (callee.toString().equals("")) { - System.err.println("CALLEE: " + callee); - InstanceKey argsList = null; + boolean isNonNullArray = false; if (receiver.length >= 4) { - argsList = receiver[3]; - // System.err.println(argsList); - // if - // (argsList.getConcreteType().equals(caller.getClassHierarchy().lookupClass(JavaScriptTypes.Array))) - // { - // System.err.println("it's an array"); - // PointerKey catalog = ((AstPointerKeyFactory) - // builder.getPointerKeyFactory()).getPointerKeyForObjectCatalog(argsList); - // System.err.println(catalog); - // OrdinalSet catalogp2set = - // builder.getPointerAnalysis().getPointsToSet(catalog); - // System.err.println(catalogp2set); - // } - } else { - System.err.println("no arguments array"); + InstanceKey argsList = receiver[3]; + if (argsList.getConcreteType().equals(caller.getClassHierarchy().lookupClass(JavaScriptTypes.Array))) { + isNonNullArray = true; + } } - return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), argsList); + return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), isNonNullArray); } return base.getCalleeTarget(caller, site, callee, receiver); } From efa0efa796be0f19900f85726e1227b108388b3b Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:26:41 +0000 Subject: [PATCH 047/238] fix bad method overriding git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4334 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- ...ScriptFunctionApplyContextInterpreter.java | 30 ++++++++----------- 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java index d8facf8b5..6da84f2fb 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java @@ -8,11 +8,9 @@ import com.ibm.wala.cast.js.loader.JSCallSiteReference; import com.ibm.wala.cast.js.ssa.JSInstructionFactory; import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IClass; -import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.CGNode; -import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ssa.DefUse; import com.ibm.wala.ssa.IR; import com.ibm.wala.types.MethodReference; @@ -21,7 +19,7 @@ import com.ibm.wala.types.MethodReference; * TODO cache generated IRs * * @author manu - * + * */ public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensitiveSSAContextInterpreter { @@ -30,22 +28,20 @@ public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensi } @Override - public boolean understands(IMethod method, Context context) { - return context instanceof ApplyContext; + public boolean understands(CGNode node) { + return node.getContext() instanceof ApplyContext; } @Override public IR getIR(CGNode node) { - if (understands(node.getMethod(), node.getContext())) { - ApplyContext applyContext = (ApplyContext) node.getContext(); - boolean isNonNullArray = applyContext.isNonNullArray(); - if (isNonNullArray) { - return makeIRForArgList(node); - } else { - return makeIRForNoArgList(node); - } + assert understands(node); + ApplyContext applyContext = (ApplyContext) node.getContext(); + boolean isNonNullArray = applyContext.isNonNullArray(); + if (isNonNullArray) { + return makeIRForArgList(node); + } else { + return makeIRForNoArgList(node); } - return super.getIR(node); } private IR makeIRForArgList(CGNode node) { @@ -143,10 +139,8 @@ public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensi @Override public DefUse getDU(CGNode node) { - if (understands(node.getMethod(), node.getContext())) { - return new DefUse(getIR(node)); - } - return super.getDU(node); + assert understands(node); + return new DefUse(getIR(node)); } } From 14c4cdb25122d715cf191254d1912c31c2154ad8 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:27:03 +0000 Subject: [PATCH 048/238] bug fix in SSAPropagationCallGraphBuilder: allow empty points-to sets for interesting non-receiver arguments git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4335 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/js/test/Util.java | 2 +- .../SSAPropagationCallGraphBuilder.java | 45 +++++++++++-------- 2 files changed, 28 insertions(+), 19 deletions(-) diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java index fc7df36c5..583f35e05 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java @@ -95,7 +95,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { public static CallGraph makeHTMLCG(URL url) throws IOException, IllegalArgumentException, CancelException { PropagationCallGraphBuilder b = makeHTMLCGBuilder(url); CallGraph CG = b.makeCallGraph(b.getOptions()); - // dumpCG(b, CG); + //dumpCG(b.getPointerAnalysis(), CG); return CG; } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java index 9095c4328..46bf5a18b 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java @@ -1575,20 +1575,21 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap public byte evaluate(PointsToSetVariable lhs, final PointsToSetVariable[] rhs) { assert dispatchIndices.length >= rhs.length : "bad operator at " + call; final MutableBoolean sideEffect = new MutableBoolean(); - for(PointsToSetVariable v : rhs) { - if (v.getValue() == null) { - // this constraint was put on the work list, probably by - // initialization, - // even though the right-hand-side is empty. - // TODO: be more careful about what goes on the worklist to - // avoid this. - if (DEBUG) { - System.err.println("EVAL dispatch with value null"); - } - return NOT_CHANGED; + // NOTE: we allow the value of points-to set variables other than rhs[0] + // to be null. rhs[0] is the receiver, so to avoid an exception it must be + // non-empty, but empty points-to sets in other slots are allowed. + if (rhs[0].getValue() == null) { + // this constraint was put on the work list, probably by + // initialization, + // even though the right-hand-side is empty. + // TODO: be more careful about what goes on the worklist to + // avoid this. + if (DEBUG) { + System.err.println("EVAL dispatch with value null"); } + return NOT_CHANGED; + } - new Object() { InstanceKey keys[] = new InstanceKey[constParams == null? dispatchIndices[dispatchIndices.length-1]+1: constParams.length]; void rec(int index, int rhsIndex, boolean redundant) { @@ -1602,11 +1603,16 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap } } else { PointsToSetVariable v = rhs[rhsIndex]; - IntIterator ptrs = v.getValue().intIterator(); - while (ptrs.hasNext()) { - int ptr = ptrs.next(); - keys[dispatchIndices[index]] = system.getInstanceKey(ptr); - rec(index+1, rhsIndex+1, redundant & previousPtrs[index].contains(ptr)); + if (v.getValue() != null) { + IntIterator ptrs = v.getValue().intIterator(); + while (ptrs.hasNext()) { + int ptr = ptrs.next(); + keys[dispatchIndices[index]] = system.getInstanceKey(ptr); + rec(index+1, rhsIndex+1, redundant & previousPtrs[index].contains(ptr)); + } + } else { + keys[dispatchIndices[index]] = null; + rec(index+1, rhsIndex+1, redundant); } } } else if (!redundant) { @@ -1659,7 +1665,10 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap previousPtrs[i].add(system.instanceKeys.getMappedIndex(constParams[i][ci])); } } else { - previousPtrs[i].addAll(rhs[ri++].getValue()); + if (rhs[ri].getValue() != null) { + previousPtrs[i].addAll(rhs[ri].getValue()); + } + ri++; } } From 610c7e252e0a9fca4beebc9101cc118a240b7bb8 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:27:21 +0000 Subject: [PATCH 049/238] add a test for Function.apply() with the arguments array git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4336 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/function_apply.js | 4 +++- .../examples-src/tests/function_apply2.js | 9 +++++++++ .../wala/cast/js/test/TestSimpleCallGraphShape.java | 10 ++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/function_apply2.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js index 2c654bc7a..c72ab32e3 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js @@ -3,7 +3,7 @@ function biz() { return this; } var q = biz; var o = { m: function theOne() {} } var r = q.apply(o); -o.m() +r.m() function id(y) { return y; } @@ -14,3 +14,5 @@ s(); // test invoking with non-array argsList p.apply(null, o); + + diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply2.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply2.js new file mode 100644 index 000000000..3247ae443 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply2.js @@ -0,0 +1,9 @@ +// test use of arguments array +function useArgs() { + return arguments[2]; +} +var o = {} +function theThree() {} +var a = useArgs; +var b = a.apply(o, [o,o,theThree]); +b(); \ 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 54b881c19..b4c9c9174 100644 --- 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 @@ -328,6 +328,16 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { verifyGraphAssertions(CG, assertionsForFunctionApply); } + private static final Object[][] assertionsForFunctionApply2 = new Object[][] { + new Object[] { ROOT, new String[] { "tests/function_apply2.js" } }, + new Object[] { "suffix:function_apply2.js", new String[] { "suffix:theThree" } } }; + + @Test + public void testFunctionDotApply2() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "function_apply2.js"); + verifyGraphAssertions(CG, assertionsForFunctionApply2); + } + private static final Object[][] assertionsForComplexCall = new Object[][] { new Object[] { ROOT, new String[] { "tests/complex_call.js" } }, new Object[] { "suffix:call.js", new String[] { "suffix:f3" } } }; From 3057d11607818fb7f9d5feff380de95753ec566f Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:27:42 +0000 Subject: [PATCH 050/238] stop dumping call graph in the MediaWiki test to speed things up; add a flag to Util to suppress call graph output in other cases git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4337 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java | 1 - .../source/java/com/ibm/wala/cast/ipa/callgraph/Util.java | 6 ++++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java index 85eea6497..4370272a0 100644 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java @@ -32,7 +32,6 @@ public abstract class TestMediawikiCallGraphShape extends TestJSCallGraphShape { URL url = new URL("http://en.wikipedia.org/wiki/2009_swine_flu_outbreak"); CallGraph CG = Util.makeHTMLCG(url); verifyGraphAssertions(CG, assertionsForSwineFlu); - System.err.println(CG); } } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index cbbd08cfa..905ebec0a 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -33,6 +33,11 @@ import com.ibm.wala.util.debug.Assertions; public class Util { + /** + * flag to prevent dumping of verbose call graph / pointer analysis output + */ + private static final boolean AVOID_DUMP = false; + public static SourceFileModule makeSourceModule(URL script, String dir, String name) { // DO NOT use File.separator here, since this name is matched against // URLs. It seems that, in DOS, URL.getFile() does not return a @@ -72,6 +77,7 @@ public class Util { } public static void dumpCG(PointerAnalysis PA, CallGraph CG) { + if (AVOID_DUMP) return; for (Iterator x = CG.iterator(); x.hasNext();) { CGNode N = (CGNode) x.next(); System.err.println("\ncallees of node " + N.getMethod() + " " + N.getGraphNodeId()); From 6a2dc42d4959ffef7bce154ff0e70f56ef48bb82 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:28:02 +0000 Subject: [PATCH 051/238] fix a couple of NPEs git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4338 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JavaScriptFunctionApplyContextSelector.java | 2 +- .../callgraph/propagation/SSAPropagationCallGraphBuilder.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index 1157d0ca2..ea45cc592 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -88,7 +88,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { boolean isNonNullArray = false; if (receiver.length >= 4) { InstanceKey argsList = receiver[3]; - if (argsList.getConcreteType().equals(caller.getClassHierarchy().lookupClass(JavaScriptTypes.Array))) { + if (argsList != null && argsList.getConcreteType().equals(caller.getClassHierarchy().lookupClass(JavaScriptTypes.Array))) { isNonNullArray = true; } } diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java index 46bf5a18b..12d6b19e7 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/propagation/SSAPropagationCallGraphBuilder.java @@ -1662,7 +1662,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap int pi = dispatchIndices[i]; if (constParams != null && constParams[pi] != null) { for(int ci = 0; ci < constParams[pi].length; ci++) { - previousPtrs[i].add(system.instanceKeys.getMappedIndex(constParams[i][ci])); + previousPtrs[i].add(system.instanceKeys.getMappedIndex(constParams[pi][ci])); } } else { if (rhs[ri].getValue() != null) { From e71b067b6e6d290974c4e0e7b87c2e241a5c1b4a Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:28:16 +0000 Subject: [PATCH 052/238] default call graph dumping to off git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4339 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/java/com/ibm/wala/cast/ipa/callgraph/Util.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index 905ebec0a..5a4fce41c 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -36,7 +36,7 @@ public class Util { /** * flag to prevent dumping of verbose call graph / pointer analysis output */ - private static final boolean AVOID_DUMP = false; + private static final boolean AVOID_DUMP = true; public static SourceFileModule makeSourceModule(URL script, String dir, String name) { // DO NOT use File.separator here, since this name is matched against @@ -76,6 +76,7 @@ public class Util { return new AnalysisCache(AstIRFactory.makeDefaultFactory()); } + @SuppressWarnings("unused") public static void dumpCG(PointerAnalysis PA, CallGraph CG) { if (AVOID_DUMP) return; for (Iterator x = CG.iterator(); x.hasNext();) { From 8c2fd9cb10aad936d8af8585958206a7774c6d81 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:28:34 +0000 Subject: [PATCH 053/238] kill some old code and rename a class git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4340 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 2 +- ...ScriptFunctionApplyContextInterpreter.java | 5 +++-- ...avaScriptFunctionApplyContextSelector.java | 6 ++++++ ...aScriptFunctionDotCallTargetSelector.java} | 20 +++++-------------- 4 files changed, 15 insertions(+), 18 deletions(-) rename com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/{JavaScriptFunctionCallApplyTargetSelector.java => JavaScriptFunctionDotCallTargetSelector.java} (85%) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 1834e0f79..f1ab9ff29 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -38,7 +38,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache), contextInterpreter); setContextInterpreter(contextInterpreter); - options.setSelector(new JavaScriptFunctionCallApplyTargetSelector(cha, new JavaScriptConstructTargetSelector(cha, options.getMethodTargetSelector()))); + options.setSelector(new JavaScriptFunctionDotCallTargetSelector(cha, new JavaScriptConstructTargetSelector(cha, options.getMethodTargetSelector()))); options.setSelector(new LoadFileTargetSelector(options.getMethodTargetSelector(), this)); ContextSelector def = new DefaultContextSelector(options, cha); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java index 6da84f2fb..83ac727ca 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java @@ -18,8 +18,9 @@ import com.ibm.wala.types.MethodReference; /** * TODO cache generated IRs * - * @author manu - * + * @see MDN + * Function.apply() docs * */ public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensitiveSSAContextInterpreter { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index ea45cc592..3ecbbd67a 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -12,6 +12,12 @@ import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.util.intset.IntSet; import com.ibm.wala.util.intset.IntSetUtil; +/** + * + * @see MDN + * Function.apply() docs + */ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { private final ContextSelector base; diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java similarity index 85% rename from com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java rename to com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java index 9f82f6108..76d18707b 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionCallApplyTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java @@ -23,24 +23,21 @@ import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.strings.Atom; /** - * Generate IR to model Function.call() and Function.apply() + * Generate IR to model Function.call() * * @see MDN - * Function.apply() docs - * @see MDN * Function.call() docs * * @author manu * */ -public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSelector { +public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSelector { private final IClassHierarchy cha; private final MethodTargetSelector base; - public JavaScriptFunctionCallApplyTargetSelector(IClassHierarchy cha, MethodTargetSelector base) { + public JavaScriptFunctionDotCallTargetSelector(IClassHierarchy cha, MethodTargetSelector base) { this.cha = cha; this.base = base; @@ -57,22 +54,15 @@ public class JavaScriptFunctionCallApplyTargetSelector implements MethodTargetSe @Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { if (cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.CodeBody))) { - // TODO better way to do these tests + // TODO better way to do this test? String s = receiver.toString(); if (s.equals("function Lprologue.js/functionCall")) { return getFunctionCallTarget(caller, site, receiver); - } else if (s.equals("function Lprologue.js/functionApply")) { - return getFunctionApplyTarget(caller, site, receiver); - } + } } return base.getCalleeTarget(caller, site, receiver); } - private IMethod getFunctionApplyTarget(CGNode caller, CallSiteReference site, IClass receiver) { -// System.err.println("TODO: handle Function.apply()"); - return base.getCalleeTarget(caller, site, receiver); - } - private static final boolean SEPARATE_SYNTHETIC_METHOD_PER_SITE = true; /** From 9a3b4f3d8a4420b0d0807882c92b2245a6f20c9a Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:28:46 +0000 Subject: [PATCH 054/238] add missing assertion check git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4341 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 b4c9c9174..71548222c 100644 --- 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 @@ -355,8 +355,10 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { @Test public void testGlobalObjPassing() throws IOException, IllegalArgumentException, CancelException { - Util.makeScriptCG("tests", "global_object.js"); + CallGraph CG = Util.makeScriptCG("tests", "global_object.js"); + verifyGraphAssertions(CG, assertionsForGlobalObj); } + protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. From fa1f572d60f5bc8929a5cde1bb9d5bf5bdc21b9e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:29:01 +0000 Subject: [PATCH 055/238] add one level of call-string sensitivity for Function.apply() git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4342 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- ...avaScriptFunctionApplyContextSelector.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index 3ecbbd67a..ccac33a1f 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -40,13 +40,16 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { public static class ApplyContext implements Context { private final Context delegate; + private final CallSiteReference site; + /** * was the argsList argument a non-null Array? */ private final boolean isNonNullArray; - ApplyContext(Context delegate, boolean isNonNullArray) { + ApplyContext(Context delegate, CallSiteReference site, boolean isNonNullArray) { this.delegate = delegate; + this.site = site; this.isNonNullArray = isNonNullArray; } @@ -65,6 +68,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { int result = 1; result = prime * result + ((delegate == null) ? 0 : delegate.hashCode()); result = prime * result + (isNonNullArray ? 1231 : 1237); + result = prime * result + ((site == null) ? 0 : site.hashCode()); return result; } @@ -84,9 +88,21 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { return false; if (isNonNullArray != other.isNonNullArray) return false; + if (site == null) { + if (other.site != null) + return false; + } else if (!site.equals(other.site)) + return false; return true; } + @Override + public String toString() { + return "ApplyContext [delegate=" + delegate + ", site=" + site + ", isNonNullArray=" + isNonNullArray + "]"; + } + + + } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { @@ -98,7 +114,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { isNonNullArray = true; } } - return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), isNonNullArray); + return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), site, isNonNullArray); } return base.getCalleeTarget(caller, site, callee, receiver); } From d01db4d276514267f3ef88036e50d9b1787f5c90 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:29:14 +0000 Subject: [PATCH 056/238] Now eliminating duplicates when copying names during SSA conversion. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4343 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../java/com/ibm/wala/cast/ir/ssa/SSAConversion.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) 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 d0aa5d5d5..3afecfea2 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 @@ -489,10 +489,12 @@ public class SSAConversion extends AbstractSSAConversion { if (namesData[to] == null) { namesData[to] = namesData[from]; } else { - String[] newNames = new String[namesData[from].length + namesData[to].length]; - System.arraycopy(namesData[from], 0, newNames, 0, namesData[from].length); - System.arraycopy(namesData[to], 0, newNames, namesData[from].length, namesData[to].length); - namesData[to] = newNames; + 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()]); } } } From 2989bc2e6af34b4680e9a03d9cd4534c08ff9774 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:29:27 +0000 Subject: [PATCH 057/238] add flag to disable handling of Function.apply() git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4344 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 45 ++++++++++++------- 1 file changed, 30 insertions(+), 15 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index f1ab9ff29..6a08146d8 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -25,44 +25,59 @@ import com.ibm.wala.ipa.callgraph.propagation.cfa.nCFAContextSelector; import com.ibm.wala.ipa.cha.IClassHierarchy; /** - * 0-x-CFA Call graph builder, optimized to not disambiguate instances of "uninteresting" types + * 0-x-CFA Call graph builder, optimized to not disambiguate instances of + * "uninteresting" types */ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { + private static final boolean HANDLE_FUNCTION_APPLY = true; + public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, - ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, - boolean doOneCFA) { + ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { super(cha, options, cache); SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha); - contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache), contextInterpreter); + if (HANDLE_FUNCTION_APPLY) { + contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache), + contextInterpreter); + } setContextInterpreter(contextInterpreter); - options.setSelector(new JavaScriptFunctionDotCallTargetSelector(cha, new JavaScriptConstructTargetSelector(cha, options.getMethodTargetSelector()))); + options.setSelector(new JavaScriptFunctionDotCallTargetSelector(cha, new JavaScriptConstructTargetSelector(cha, options + .getMethodTargetSelector()))); options.setSelector(new LoadFileTargetSelector(options.getMethodTargetSelector(), this)); - + ContextSelector def = new DefaultContextSelector(options, cha); ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); - contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); + if (HANDLE_FUNCTION_APPLY) { + contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); + } contextSelector = new LexicalScopingResolverContexts(this, contextSelector); if (doOneCFA) { contextSelector = new nCFAContextSelector(1, contextSelector); } setContextSelector(contextSelector); - setInstanceKeys(new JavaScriptScopeMappingInstanceKeys(cha, this, new JavaScriptConstructorInstanceKeys(new ZeroXInstanceKeys(options, cha, contextInterpreter, - instancePolicy)))); + setInstanceKeys(new JavaScriptScopeMappingInstanceKeys(cha, this, new JavaScriptConstructorInstanceKeys(new ZeroXInstanceKeys( + options, cha, contextInterpreter, instancePolicy)))); } /** - * @param options options that govern call graph construction - * @param cha governing class hierarchy - * @param cl classloader that can find DOMO resources - * @param scope representation of the analysis scope - * @param xmlFiles set of Strings that are names of XML files holding bypass logic specifications. - * @param dmd deployment descriptor abstraction + * @param options + * options that govern call graph construction + * @param cha + * governing class hierarchy + * @param cl + * classloader that can find DOMO resources + * @param scope + * representation of the analysis scope + * @param xmlFiles + * set of Strings that are names of XML files holding bypass logic + * specifications. + * @param dmd + * deployment descriptor abstraction * @return a 0-1-Opt-CFA Call Graph Builder. */ public static JSCFABuilder make(AnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, ClassLoader cl, From 48b42a18a08ab7e8a8a435466b4e9935c1e4e629 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:29:42 +0000 Subject: [PATCH 058/238] tinkering with jquery git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4345 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js/dat/preamble.js | 2 +- com.ibm.wala.cast.js/dat/prologue.js | 2 +- .../ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/com.ibm.wala.cast.js/dat/preamble.js b/com.ibm.wala.cast.js/dat/preamble.js index a3408ac6d..d1c5b4d1f 100644 --- a/com.ibm.wala.cast.js/dat/preamble.js +++ b/com.ibm.wala.cast.js/dat/preamble.js @@ -209,7 +209,7 @@ DOMElement = function DOMElement() { // An impostor for the Element class return this[name]; } this.setAttribute = function setAttribute(name, value) { - this[name] = value; +// this[name] = value; } this.removeAttribute = function removeAttribute(name) { diff --git a/com.ibm.wala.cast.js/dat/prologue.js b/com.ibm.wala.cast.js/dat/prologue.js index d36e93603..f69c68639 100644 --- a/com.ibm.wala.cast.js/dat/prologue.js +++ b/com.ibm.wala.cast.js/dat/prologue.js @@ -186,7 +186,7 @@ Array.prototype = { push: function push () { var n = this.length for(var i = 0; i < arguments.length; i++) { - this[ n++ ] = arguments[i]; +// this[ n++ ] = arguments[i]; } this.length = n; diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 6a08146d8..f54895b4c 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -30,7 +30,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; */ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { - private static final boolean HANDLE_FUNCTION_APPLY = true; + private static final boolean HANDLE_FUNCTION_APPLY = false; public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { From fc1a961c4cf26f88aac87a017b53be2aa34a3667 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:29:52 +0000 Subject: [PATCH 059/238] undo hacks git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4346 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js/dat/preamble.js | 2 +- com.ibm.wala.cast.js/dat/prologue.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/dat/preamble.js b/com.ibm.wala.cast.js/dat/preamble.js index d1c5b4d1f..a3408ac6d 100644 --- a/com.ibm.wala.cast.js/dat/preamble.js +++ b/com.ibm.wala.cast.js/dat/preamble.js @@ -209,7 +209,7 @@ DOMElement = function DOMElement() { // An impostor for the Element class return this[name]; } this.setAttribute = function setAttribute(name, value) { -// this[name] = value; + this[name] = value; } this.removeAttribute = function removeAttribute(name) { diff --git a/com.ibm.wala.cast.js/dat/prologue.js b/com.ibm.wala.cast.js/dat/prologue.js index f69c68639..d36e93603 100644 --- a/com.ibm.wala.cast.js/dat/prologue.js +++ b/com.ibm.wala.cast.js/dat/prologue.js @@ -186,7 +186,7 @@ Array.prototype = { push: function push () { var n = this.length for(var i = 0; i < arguments.length; i++) { -// this[ n++ ] = arguments[i]; + this[ n++ ] = arguments[i]; } this.length = n; From a55135831e63e50a1a75efc7453fcd589ccbdc9e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:30:02 +0000 Subject: [PATCH 060/238] fix missing semi-colon git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4347 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js/dat/prologue.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/dat/prologue.js b/com.ibm.wala.cast.js/dat/prologue.js index d36e93603..b1ae2bc87 100644 --- a/com.ibm.wala.cast.js/dat/prologue.js +++ b/com.ibm.wala.cast.js/dat/prologue.js @@ -184,7 +184,7 @@ Array.prototype = { }, push: function push () { - var n = this.length + var n = this.length; for(var i = 0; i < arguments.length; i++) { this[ n++ ] = arguments[i]; } From aa94e289085ded23f6bbb778debcf591f7a9db56 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:30:17 +0000 Subject: [PATCH 061/238] some javadoc git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4348 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/loader/AstMethod.java | 113 +++++++++++------- 1 file changed, 69 insertions(+), 44 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstMethod.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstMethod.java index 2af0880b0..b4d56b775 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstMethod.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/loader/AstMethod.java @@ -33,29 +33,65 @@ public abstract class AstMethod implements IMethod { public interface DebuggingInformation { Position getCodeBodyPosition(); - + Position getInstructionPosition(int instructionOffset); - + String[][] getSourceNamesForValues(); } + /** + * lexical access information for some entity scope. used during call graph + * construction to handle lexical accesses. + */ public interface LexicalInformation { - public int[] getExitExposedUses(); - - public int[] getExposedUses(int instructionOffset); - - public IntSet getAllExposedUses(); - + /** + * names possibly accessed in a nested lexical scope, represented as pairs + * (name,nameOfDefiningEntity) + */ public Pair[] getExposedNames(); + /** + * maps each exposed name (via its index in {@link #getExposedNames()}) to + * its value number at method exit. + */ + public int[] getExitExposedUses(); + + /** + * get a map from exposed name (via its index in {@link #getExposedNames()}) + * to its value number at the instruction at offset instructionOffset. + */ + public int[] getExposedUses(int instructionOffset); + + /** + * return all value numbers appearing as entries in either + * {@link #getExposedUses(int)} or {@link #getExitExposedUses()} + */ + public IntSet getAllExposedUses(); + + /** + * return the names of the enclosing methods declaring names that are + * lexically accessed by the entity + */ public String[] getScopingParents(); - + + /** + * returns true if name may be read in nested lexical scopes but cannot be + * written + */ public boolean isReadOnly(String name); - + + /** + * invoked to indicate that value numbering may have changed; implementation + * should discard any cached information and recompute + */ public void handleAlteration(); - + + /** + * get the name of this entity, as it appears in the definer portion of a + * lexical name + */ public String getScopingName(); } @@ -63,7 +99,7 @@ public abstract class AstMethod implements IMethod { protected final IClass cls; private final Collection qualifiers; private final AbstractCFG cfg; - private final SymbolTable symtab; + private final SymbolTable symtab; private final MethodReference ref; private final boolean hasCatchBlock; private final boolean hasMonitorOp; @@ -71,16 +107,9 @@ public abstract class AstMethod implements IMethod { private final AstLexicalInformation lexicalInfo; private final DebuggingInformation debugInfo; - protected AstMethod(IClass cls, - Collection qualifiers, - AbstractCFG cfg, - SymbolTable symtab, - MethodReference ref, - boolean hasCatchBlock, - TypeReference[][] catchTypes, - boolean hasMonitorOp, - AstLexicalInformation lexicalInfo, DebuggingInformation debugInfo) - { + protected AstMethod(IClass cls, Collection qualifiers, AbstractCFG cfg, SymbolTable symtab, MethodReference ref, + boolean hasCatchBlock, TypeReference[][] catchTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo, + DebuggingInformation debugInfo) { this.cls = cls; this.cfg = cfg; this.ref = ref; @@ -92,11 +121,8 @@ public abstract class AstMethod implements IMethod { this.lexicalInfo = lexicalInfo; this.debugInfo = debugInfo; } - - protected AstMethod(IClass cls, - Collection qualifiers, - MethodReference ref) - { + + protected AstMethod(IClass cls, Collection qualifiers, MethodReference ref) { this.cls = cls; this.qualifiers = qualifiers; this.ref = ref; @@ -108,60 +134,59 @@ public abstract class AstMethod implements IMethod { this.hasMonitorOp = false; this.lexicalInfo = null; this.debugInfo = null; - + assert isAbstract(); } public AbstractCFG cfg() { return cfg; } - + public boolean hasCatchBlock() { return hasCatchBlock(); } - + public SymbolTable symbolTable() { return symtab; } - + public TypeReference[][] catchTypes() { return catchTypes; } - + public LexicalInformation cloneLexicalInfo() { return new AstLexicalInformation(lexicalInfo); } - + public LexicalInformation lexicalInfo() { return lexicalInfo; } - + public DebuggingInformation debugInfo() { return debugInfo; } - + /** - * Parents of this method with respect to lexical scoping, that is, - * methods containing state possibly referenced lexically in this - * method + * Parents of this method with respect to lexical scoping, that is, methods + * containing state possibly referenced lexically in this method */ public static abstract class LexicalParent { public abstract String getName(); + public abstract AstMethod getMethod(); - public int hashCode() { - return getName().hashCode()*getMethod().hashCode(); + public int hashCode() { + return getName().hashCode() * getMethod().hashCode(); } public boolean equals(Object o) { - return (o instanceof LexicalParent) && - getName().equals(((LexicalParent)o).getName()) && - getMethod().equals(((LexicalParent)o).getMethod()); + return (o instanceof LexicalParent) && getName().equals(((LexicalParent) o).getName()) + && getMethod().equals(((LexicalParent) o).getMethod()); } }; public abstract LexicalParent[] getParents(); - + public IClass getDeclaringClass() { return cls; } From 1aa85b27eb3ca72a5af4c2af44bb256b595e2636 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:30:32 +0000 Subject: [PATCH 062/238] comments and formatting git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4349 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../LexicalScopingResolverContexts.java | 233 +++++++++++------- 1 file changed, 149 insertions(+), 84 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index 9f110b011..8c4d295db 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -32,71 +32,106 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } }; + /** + * used to resolve lexical accesses during call graph construction + */ interface LexicalScopingResolver extends ContextItem { - + + /** + * return resolver for parent lexical scope + */ LexicalScopingResolver getParent(); - - boolean isReadOnly(Pair name); - - LocalPointerKey getReadOnlyValue(Pair name); - - Iterator> getLexicalSites(Pair name); - - Map children(); - - CGNode getOriginalDefiner(Pair name); + + /** + * return true if name may only be read in nested lexical scopes, otherwise + * false + */ + boolean isReadOnly(Pair name); + + /** + * if {@link #isReadOnly(Pair)} returns true for name, get the + * {@link LocalPointerKey} corresponding to name from the {@link CGNode} + * that defines it + */ + LocalPointerKey getReadOnlyValue(Pair name); + + /** + * get the site-node pairs (s,n) in the scope-resolver chain such that n has + * a definition of the name and s is the call site in n possibly exposing + * the name to an invoked nested function + */ + Iterator> getLexicalSites(Pair name); + + /** + * resolvers for child lexical scopes. updates are performed via mutations + * of the returned map. + */ + Map children(); + + /** + * get the CGNode in the scope-resolver chain that defines name, or + * null if so such node exists (happens when accesses occurs + * after exit of defining function) + */ + CGNode getOriginalDefiner(Pair name); } - - private LexicalScopingResolver findChild(CGNode caller, CallSiteReference callSite) { + + /** + * find or create an appropriate {@link LexicalScopingResolver} for the caller + * and callSite. Note that {@link #hasExposedUses(CGNode, CallSiteReference)} + * must be true for caller and callSite. We try to re-use a previously-created + * context whenever possible. + */ + private LexicalScopingResolver findChild(CGNode caller, CallSiteReference callSite) { LexicalScopingResolver parent = (LexicalScopingResolver) caller.getContext().get(RESOLVER); if (parent == null) { parent = globalResolver; } - - Map readOnlyNames = new HashMap(); - Set> names = new HashSet>(); - - LexicalInformation LI = ((AstMethod)caller.getMethod()).lexicalInfo(); - int[] exposedUses = LI.getExposedUses(callSite.getProgramCounter()); + + Map readOnlyNames = new HashMap(); + Set> readWritesNames = new HashSet>(); + + LexicalInformation LI = ((AstMethod) caller.getMethod()).lexicalInfo(); + int[] exposedUses = LI.getExposedUses(callSite.getProgramCounter()); if (exposedUses.length > 0) { - Pair exposedNames[] = LI.getExposedNames(); - for(int i = 0; i < exposedUses.length; i++) { + Pair exposedNames[] = LI.getExposedNames(); + for (int i = 0; i < exposedUses.length; i++) { if (exposedUses[i] != -1) { - if (! parent.isReadOnly(exposedNames[i])) { + if (!parent.isReadOnly(exposedNames[i])) { if (LI.isReadOnly(exposedNames[i].snd)) { readOnlyNames.put(exposedNames[i].snd, new LocalPointerKey(caller, exposedUses[i])); } else { - names.add(exposedNames[i]); + readWritesNames.add(exposedNames[i]); } } } } Object key; - if (! names.isEmpty()) { + if (!readWritesNames.isEmpty()) { key = Pair.make(caller, callSite); } else { key = readOnlyNames.keySet(); } - + if (parent.children().containsKey(key)) { return parent.children().get(key); - } - - if (! names.isEmpty()) { - SiteResolver result = new SiteResolver(parent, caller, readOnlyNames, callSite, names); - parent.children().put(key,result); + } + + if (!readWritesNames.isEmpty()) { + SiteResolver result = new SiteResolver(parent, caller, readOnlyNames, callSite, readWritesNames); + parent.children().put(key, result); return result; } else { ReadOnlyResolver result = new ReadOnlyResolver(parent, caller, readOnlyNames); - parent.children().put(key,result); + parent.children().put(key, result); return result; } } - + return parent; } - + LexicalScopingResolver globalResolver = new LexicalScopingResolver() { public boolean isReadOnly(Pair name) { @@ -109,17 +144,18 @@ public final class LexicalScopingResolverContexts implements ContextSelector { public Iterator> getLexicalSites(Pair name) { if (name.snd == null) { - return new NonNullSingletonIterator>(Pair.make((CallSiteReference)null, builder.getCallGraph().getFakeRootNode())); + return new NonNullSingletonIterator>(Pair.make((CallSiteReference) null, builder + .getCallGraph().getFakeRootNode())); } else { return EmptyIterator.instance(); } } - - private Map children; - - public Map children() { - if (children == null) { - children = new HashMap(); + + private Map children; + + public Map children() { + if (children == null) { + children = new HashMap(); } return children; } @@ -136,21 +172,28 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } } }; - + + /** + * {@link LexicalScopingResolver} for case where all exposed names from the + * corresponding scope are read-only + */ class ReadOnlyResolver implements LexicalScopingResolver { final protected LexicalScopingResolver parent; - protected Map children; + protected Map children; + /** + * definer name for corresponding scope + */ final protected String myDefiner; - final private Map myReadOnlyDefs; + final private Map myReadOnlyDefs; final protected CGNode myNode; - - private ReadOnlyResolver(LexicalScopingResolver parent, CGNode caller, Map readOnlyDefs) { - this.myDefiner = ((AstMethod)caller.getMethod()).lexicalInfo().getScopingName(); + + private ReadOnlyResolver(LexicalScopingResolver parent, CGNode caller, Map readOnlyDefs) { + this.myDefiner = ((AstMethod) caller.getMethod()).lexicalInfo().getScopingName(); this.parent = parent; this.myReadOnlyDefs = readOnlyDefs; this.myNode = caller; } - + public boolean isReadOnly(Pair name) { if (myDefiner.equals(name.fst)) { return myReadOnlyDefs.containsKey(name.snd); @@ -167,9 +210,9 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } } - public Map children() { - if (children == null) { - children = new HashMap(); + public Map children() { + if (children == null) { + children = new HashMap(); } return children; } @@ -188,20 +231,36 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } else { return parent.getOriginalDefiner(name); } - } - + } + + // @Override + // public String toString() { + // return "ReadOnlyResolver [parent=" + parent + ", myDefiner=" + myDefiner + // + ", myReadOnlyDefs=" + // + myReadOnlyDefs + ", myNode=" + myNode + "]"; + // } + } - + + /** + * {@link LexicalScopingResolver} handling case where some exposed names may + * be written in enclosed scopes + */ class SiteResolver extends ReadOnlyResolver implements LexicalScopingResolver { - private final Set> myDefs; + /** + * names defined in the corresponding scope that may be written in a nested + * scope + */ + private final Set> myDefs; private final CallSiteReference mySite; - - private SiteResolver(LexicalScopingResolver parent, CGNode caller, Map readOnlyDefs, CallSiteReference site, Set> defs) { + + private SiteResolver(LexicalScopingResolver parent, CGNode caller, Map readOnlyDefs, + CallSiteReference site, Set> defs) { super(parent, caller, readOnlyDefs); this.mySite = site; this.myDefs = defs; } - + public Iterator> getLexicalSites(Pair name) { if (myDefs.contains(name)) { if (myDefiner.equals(name.snd)) { @@ -213,49 +272,58 @@ public final class LexicalScopingResolverContexts implements ContextSelector { return parent.getLexicalSites(name); } } + + @Override + public String toString() { + return "SiteResolver [myDefs=" + myDefs + ", mySite=" + mySite + ", toString()=" + super.toString() + "]"; + } + } - private class LexicalScopingResolverContext implements Context { private final LexicalScopingResolver governingCallSites; private final Context base; public int hashCode() { - return base.hashCode() * (governingCallSites==null? 1077651: governingCallSites.hashCode()); + return base.hashCode() * (governingCallSites == null ? 1077651 : governingCallSites.hashCode()); } public boolean equals(Object o) { if (this == o) { return true; } else if (getClass().equals(o.getClass())) { - LexicalScopingResolverContext c = (LexicalScopingResolverContext)o; - return (base==null? c.base==null: base.equals(c.base)) - && - (governingCallSites == c.governingCallSites); + LexicalScopingResolverContext c = (LexicalScopingResolverContext) o; + return (base == null ? c.base == null : base.equals(c.base)) && (governingCallSites == c.governingCallSites); } else { return false; } } public ContextItem get(ContextKey name) { - return name.equals(RESOLVER)? governingCallSites: base!=null? base.get(name): null; + return name.equals(RESOLVER) ? governingCallSites : base != null ? base.get(name) : null; } private LexicalScopingResolverContext(LexicalScopingResolver governingCallSites, Context base) { this.base = base; this.governingCallSites = governingCallSites; } - + private LexicalScopingResolverContext(CGNode source, CallSiteReference callSite, Context base) { this.base = base; - this.governingCallSites = findChild(source, callSite); - } + this.governingCallSites = findChild(source, callSite); + } + + @Override + public String toString() { + return "LexicalScopingResolverContext [governingCallSites=" + governingCallSites + ", base=" + base + "]"; + } + } - + private final ContextSelector base; - + private final PropagationCallGraphBuilder builder; - + public LexicalScopingResolverContexts(PropagationCallGraphBuilder builder, ContextSelector base) { this.base = base; this.builder = builder; @@ -263,7 +331,7 @@ public final class LexicalScopingResolverContexts implements ContextSelector { private Context checkForRecursion(IMethod target, LexicalScopingResolver srcResolver) { while (srcResolver != null) { - for(CGNode n : builder.getCallGraph().getNodes(target.getReference())) { + for (CGNode n : builder.getCallGraph().getNodes(target.getReference())) { if (n.getContext().get(RESOLVER) == srcResolver) { return n.getContext(); } @@ -272,40 +340,37 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } return null; } - + private boolean hasExposedUses(CGNode caller, CallSiteReference site) { - int uses[] = ((AstMethod)caller.getMethod()).lexicalInfo().getExposedUses(site.getProgramCounter()); + int uses[] = ((AstMethod) caller.getMethod()).lexicalInfo().getExposedUses(site.getProgramCounter()); if (uses != null && uses.length > 0) { - for(int use : uses) { + for (int use : uses) { if (use > 0) { return true; } } } - + return false; } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) { Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters); - LexicalScopingResolver resolver = (LexicalScopingResolver)caller.getContext().get(RESOLVER); - + LexicalScopingResolver resolver = (LexicalScopingResolver) caller.getContext().get(RESOLVER); + Context recursiveParent = checkForRecursion(callee, resolver); if (recursiveParent != null) { return recursiveParent; } - - if (caller.getMethod() instanceof AstMethod - && - hasExposedUses(caller, site)) - { + + if (caller.getMethod() instanceof AstMethod && hasExposedUses(caller, site)) { return new LexicalScopingResolverContext(caller, site, baseContext); } - + else if (resolver != null) { return new LexicalScopingResolverContext(resolver, baseContext); } - + else { return baseContext; } From cf37a6728d67c33e71d50473dcb1be9c1d1eb156 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:30:46 +0000 Subject: [PATCH 063/238] more work on toString() methods git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4350 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../LexicalScopingResolverContexts.java | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index 8c4d295db..e15185439 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -171,6 +171,10 @@ public final class LexicalScopingResolverContexts implements ContextSelector { return null; } } + + public String toString() { + return "GLOBAL_RESOLVER"; + } }; /** @@ -184,7 +188,7 @@ public final class LexicalScopingResolverContexts implements ContextSelector { * definer name for corresponding scope */ final protected String myDefiner; - final private Map myReadOnlyDefs; + final protected Map myReadOnlyDefs; final protected CGNode myNode; private ReadOnlyResolver(LexicalScopingResolver parent, CGNode caller, Map readOnlyDefs) { @@ -233,12 +237,20 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } } - // @Override - // public String toString() { - // return "ReadOnlyResolver [parent=" + parent + ", myDefiner=" + myDefiner - // + ", myReadOnlyDefs=" - // + myReadOnlyDefs + ", myNode=" + myNode + "]"; - // } + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("ReadOnlyResolver[myDefiner="); + result.append(myDefiner); +// result.append(", myNode="); +// result.append(myNode); + result.append(",\n myReadOnlyDefs="); + result.append(myReadOnlyDefs); + result.append(",\n parent="); + result.append(parent); + result.append("]"); + return result.toString(); + } } @@ -275,7 +287,21 @@ public final class LexicalScopingResolverContexts implements ContextSelector { @Override public String toString() { - return "SiteResolver [myDefs=" + myDefs + ", mySite=" + mySite + ", toString()=" + super.toString() + "]"; + StringBuilder result = new StringBuilder(); + result.append("SiteResolver[myDefiner="); + result.append(myDefiner); +// result.append(", myNode="); +// result.append(myNode); + result.append(",\n mySite="); + result.append(mySite); + result.append(",\n myReadOnlyDefs="); + result.append(myReadOnlyDefs); + result.append(",\n myDefs="); + result.append(myDefs); + result.append(",\n parent="); + result.append(parent); + result.append("]"); + return result.toString(); } } From 6e4db282b606de64c0dd4349b4a58b9f1bb85285 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:30:59 +0000 Subject: [PATCH 064/238] undo change git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4351 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index f54895b4c..6a08146d8 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -30,7 +30,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; */ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { - private static final boolean HANDLE_FUNCTION_APPLY = false; + private static final boolean HANDLE_FUNCTION_APPLY = true; public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { From 72c2c922948416a990b0275aa2fc088e4556c3a7 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:31:15 +0000 Subject: [PATCH 065/238] added coarser lexical-scoping resolver. reduces memory usage, but analysis seems to slower. disabled as regression tests don't pass git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4352 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../AstSSAPropagationCallGraphBuilder.java | 7 +- .../LexicalScopingResolverContexts.java | 185 ++++++++++++++---- 2 files changed, 156 insertions(+), 36 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java index 8c60222aa..f55650e88 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstSSAPropagationCallGraphBuilder.java @@ -314,7 +314,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa } else { for(Access a : instruction.getAccesses()) { Pair name = a.getName(); - if ((r.isReadOnly(name)? r.getReadOnlyValue(name): r.getLexicalSites(name)) == null) { + if ((r.isReadOnly(name)? r.getReadOnlyValues(name): r.getLexicalSites(name)) == null) { return false; } } @@ -608,7 +608,10 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa if (r.isReadOnly(accesses[i].getName())) { assert isLoad; foundOnStack = true; - action(r.getReadOnlyValue(accesses[i].getName()), vn); + Set vals = r.getReadOnlyValues(accesses[i].getName()); + for (LocalPointerKey val : vals) { + action(val, vn); + } } else { Iterator> sites = r.getLexicalSites(accesses[i].getName()); while(sites.hasNext()) { diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index e15185439..d1265f808 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -1,7 +1,6 @@ package com.ibm.wala.cast.ipa.callgraph; -import java.util.HashMap; -import java.util.HashSet; +import java.util.Collections; import java.util.Iterator; import java.util.Map; import java.util.Set; @@ -18,8 +17,12 @@ import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; +import com.ibm.wala.util.collections.CompoundIterator; import com.ibm.wala.util.collections.EmptyIterator; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.collections.HashSetFactory; import com.ibm.wala.util.collections.IteratorPlusOne; +import com.ibm.wala.util.collections.MapUtil; import com.ibm.wala.util.collections.NonNullSingletonIterator; import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.intset.IntSet; @@ -32,6 +35,8 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } }; + private static final boolean USE_CGNODE_RESOLVER = false; + /** * used to resolve lexical accesses during call graph construction */ @@ -53,7 +58,7 @@ public final class LexicalScopingResolverContexts implements ContextSelector { * {@link LocalPointerKey} corresponding to name from the {@link CGNode} * that defines it */ - LocalPointerKey getReadOnlyValue(Pair name); + Set getReadOnlyValues(Pair name); /** * get the site-node pairs (s,n) in the scope-resolver chain such that n has @@ -88,8 +93,8 @@ public final class LexicalScopingResolverContexts implements ContextSelector { parent = globalResolver; } - Map readOnlyNames = new HashMap(); - Set> readWritesNames = new HashSet>(); + Map readOnlyNames = HashMapFactory.make(); + Set> readWriteNames = HashSetFactory.make(); LexicalInformation LI = ((AstMethod) caller.getMethod()).lexicalInfo(); int[] exposedUses = LI.getExposedUses(callSite.getProgramCounter()); @@ -101,31 +106,46 @@ public final class LexicalScopingResolverContexts implements ContextSelector { if (LI.isReadOnly(exposedNames[i].snd)) { readOnlyNames.put(exposedNames[i].snd, new LocalPointerKey(caller, exposedUses[i])); } else { - readWritesNames.add(exposedNames[i]); + readWriteNames.add(exposedNames[i]); } } } } - Object key; - if (!readWritesNames.isEmpty()) { - key = Pair.make(caller, callSite); - } else { - key = readOnlyNames.keySet(); - } - - if (parent.children().containsKey(key)) { - return parent.children().get(key); - } - - if (!readWritesNames.isEmpty()) { - SiteResolver result = new SiteResolver(parent, caller, readOnlyNames, callSite, readWritesNames); - parent.children().put(key, result); + if (USE_CGNODE_RESOLVER) { + CGNodeResolver result = (CGNodeResolver) parent.children().get(caller); + if (result == null) { + result = new CGNodeResolver(parent, caller); + parent.children().put(caller, result); + } + for (String readOnlyName : readOnlyNames.keySet()) { + result.addReadOnlyName(readOnlyName, readOnlyNames.get(readOnlyName)); + } + for (Pair readWriteName : readWriteNames) { + result.addReadWriteName(readWriteName, callSite); + } return result; } else { - ReadOnlyResolver result = new ReadOnlyResolver(parent, caller, readOnlyNames); - parent.children().put(key, result); - return result; + Object key; + if (!readWriteNames.isEmpty()) { + key = Pair.make(caller, callSite); + } else { + key = readOnlyNames.keySet(); + } + + if (parent.children().containsKey(key)) { + return parent.children().get(key); + } + + if (!readWriteNames.isEmpty()) { + SiteResolver result = new SiteResolver(parent, caller, readOnlyNames, callSite, readWriteNames); + parent.children().put(key, result); + return result; + } else { + ReadOnlyResolver result = new ReadOnlyResolver(parent, caller, readOnlyNames); + parent.children().put(key, result); + return result; + } } } @@ -138,7 +158,7 @@ public final class LexicalScopingResolverContexts implements ContextSelector { return false; } - public LocalPointerKey getReadOnlyValue(Pair name) { + public Set getReadOnlyValues(Pair name) { throw new UnsupportedOperationException("not expecting read only global"); } @@ -155,7 +175,7 @@ public final class LexicalScopingResolverContexts implements ContextSelector { public Map children() { if (children == null) { - children = new HashMap(); + children = HashMapFactory.make(); } return children; } @@ -171,12 +191,109 @@ public final class LexicalScopingResolverContexts implements ContextSelector { return null; } } - + public String toString() { return "GLOBAL_RESOLVER"; } }; + /** + * single {@link LexicalScopingResolver} for a CGNode, handling read-only and + * read-write names + */ + class CGNodeResolver implements LexicalScopingResolver { + + private final LexicalScopingResolver parent; + private Map children; + /** + * definer name for corresponding scope + */ + private final String myDefiner; + private final CGNode myNode; + + /** + * maps a read-only name defined in this scope to the local pointer keys by + * which it is referenced at call sites encountered thus far + */ + private Map> myReadOnlyDefs = null; + + /** + * maps a name defined in this scope that may be defined in a nested scope + * to the set of call sites at which it is exposed for nested writes + */ + private Map, Set>> myDefs = null; + + public CGNodeResolver(LexicalScopingResolver parent, CGNode myNode) { + super(); + this.parent = parent; + this.myDefiner = ((AstMethod) myNode.getMethod()).lexicalInfo().getScopingName(); + this.myNode = myNode; + } + + public void addReadWriteName(Pair readWriteName, CallSiteReference callSite) { + if (myDefs == null) { + myDefs = HashMapFactory.make(); + } + MapUtil.findOrCreateSet(myDefs, readWriteName).add(Pair.make(callSite, myNode)); + } + + public void addReadOnlyName(String readOnlyName, LocalPointerKey localPointerKey) { + if (myReadOnlyDefs == null) { + myReadOnlyDefs = HashMapFactory.make(); + } + MapUtil.findOrCreateSet(myReadOnlyDefs, readOnlyName).add(localPointerKey); + } + + public LexicalScopingResolver getParent() { + return parent; + } + + public boolean isReadOnly(Pair name) { + if (myDefiner.equals(name.fst)) { + return myReadOnlyDefs != null && myReadOnlyDefs.containsKey(name.snd); + } else { + return parent.isReadOnly(name); + } + } + + public Set getReadOnlyValues(Pair name) { + if (myDefiner.equals(name.fst)) { + return myReadOnlyDefs.get(name.snd); + } else { + return parent.getReadOnlyValues(name); + } + } + + public Iterator> getLexicalSites(Pair name) { + if (myDefs == null || myDefs.containsKey(name)) { + if (myDefiner.equals(name.snd)) { + // no need to recurse to parent + return myDefs.get(name).iterator(); + } else { + return new CompoundIterator>(parent.getLexicalSites(name), myDefs.get(name).iterator()); + } + } else { + return parent.getLexicalSites(name); + } + } + + public Map children() { + if (children == null) { + children = HashMapFactory.make(); + } + return children; + } + + public CGNode getOriginalDefiner(Pair name) { + if (myDefiner.equals(name.snd)) { + return myNode; + } else { + return parent.getOriginalDefiner(name); + } + } + + } + /** * {@link LexicalScopingResolver} for case where all exposed names from the * corresponding scope are read-only @@ -206,17 +323,17 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } } - public LocalPointerKey getReadOnlyValue(Pair name) { + public Set getReadOnlyValues(Pair name) { if (myDefiner.equals(name.fst)) { - return myReadOnlyDefs.get(name.snd); + return Collections.singleton(myReadOnlyDefs.get(name.snd)); } else { - return parent.getReadOnlyValue(name); + return parent.getReadOnlyValues(name); } } public Map children() { if (children == null) { - children = new HashMap(); + children = HashMapFactory.make(); } return children; } @@ -242,8 +359,8 @@ public final class LexicalScopingResolverContexts implements ContextSelector { StringBuilder result = new StringBuilder(); result.append("ReadOnlyResolver[myDefiner="); result.append(myDefiner); -// result.append(", myNode="); -// result.append(myNode); + // result.append(", myNode="); + // result.append(myNode); result.append(",\n myReadOnlyDefs="); result.append(myReadOnlyDefs); result.append(",\n parent="); @@ -290,8 +407,8 @@ public final class LexicalScopingResolverContexts implements ContextSelector { StringBuilder result = new StringBuilder(); result.append("SiteResolver[myDefiner="); result.append(myDefiner); -// result.append(", myNode="); -// result.append(myNode); + // result.append(", myNode="); + // result.append(myNode); result.append(",\n mySite="); result.append(mySite); result.append(",\n myReadOnlyDefs="); From e4bab37a82b68ff40a4bee51f7bee0d6de74ee7e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:31:30 +0000 Subject: [PATCH 066/238] bug fix with cached DefUse in AstCGNode git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4353 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../wala/cast/ipa/callgraph/AstCallGraph.java | 5 ++++- .../LexicalScopingResolverContexts.java | 19 ++++++++++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstCallGraph.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstCallGraph.java index d2c9a5828..9158cbef8 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstCallGraph.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/AstCallGraph.java @@ -148,7 +148,7 @@ public class AstCallGraph extends ExplicitCallGraph { public void setLexicallyMutatedIR(IR ir) { lexicalScopingChanges = true; cachedIR = ir; - cachedDU = new DefUse(ir); + cachedDU = null; } public void clearMutatedCache(CallSiteReference cs) { @@ -165,6 +165,9 @@ public class AstCallGraph extends ExplicitCallGraph { public DefUse getLexicallyMutatedDU() { if (lexicalScopingChanges) { + if (cachedDU == null) { + cachedDU = new DefUse(cachedIR); + } return cachedDU; } else { return null; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index d1265f808..5da7ddd10 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -35,7 +35,7 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } }; - private static final boolean USE_CGNODE_RESOLVER = false; + private static final boolean USE_CGNODE_RESOLVER = true; /** * used to resolve lexical accesses during call graph construction @@ -292,6 +292,23 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } } + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append("CGNodeResolver[myDefiner="); + result.append(myDefiner); + // result.append(", myNode="); + // result.append(myNode); +// result.append(",\n myReadOnlyDefs="); +// result.append(myReadOnlyDefs); +// result.append(",\n myDefs="); +// result.append(myDefs); + result.append(",\n parent="); + result.append(parent); + result.append("]"); + return result.toString(); + } + } /** From 22f6ba3e0cbda840792a403e5d74ccfeb2f1c422 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:31:44 +0000 Subject: [PATCH 067/238] extra diagnostics git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4354 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java index 0b70ca4d6..a02bc84e8 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java @@ -335,7 +335,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph return new JSConstraintVisitor(this, node); } - private Position getSomePositionForMethod(IR ir, AstMethod method) { + public static Position getSomePositionForMethod(IR ir, AstMethod method) { SSAInstruction[] instructions = ir.getInstructions(); for (int i = 0; i < instructions.length; i++) { Position p = method.getSourcePosition(i); From 9aabf5c042abbee195c9e69cec61162e0eaec320 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:31:57 +0000 Subject: [PATCH 068/238] extra javadoc git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4355 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../callgraph/ScopeMappingInstanceKeys.java | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java index d79d945df..de6e31b01 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java @@ -31,13 +31,15 @@ import com.ibm.wala.util.intset.OrdinalSet; /** * An {@link InstanceKeyFactory} that returns {@link ScopeMappingInstanceKey}s - * as necessary to handle interprocedural lexical scoping + * as necessary to handle interprocedural lexical scoping (specifically, to + * handle closure creation when a function escapes its allocating scope) */ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory { /** * does base require a scope mapping key? Typically, true if base is allocated - * in a nested lexical scope + * in a nested lexical scope, to handle the case of base being a function that + * performs closure accesses */ protected abstract boolean needsScopeMappingKey(InstanceKey base); @@ -72,13 +74,12 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory { */ private final CGNode creator; - /** * compute the {@link CGNode} correspond to each specified * {@link LexicalParent} of {@link #base}, populating {@link #scopeMap} * */ - + private ScopeMappingInstanceKey(CGNode creator, InstanceKey base) { this.creator = creator; this.base = base; @@ -89,29 +90,31 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory { } /** - * get the CGNode representing the lexical parent of {@link #creator} with name definer + * get the CGNode representing the lexical parent of {@link #creator} with + * name definer + * * @param definer * @return */ - Iterator getFunargNodes(Pair name) { + Iterator getFunargNodes(Pair name) { Iterator result = EmptyIterator.instance(); - - LexicalScopingResolver r = (LexicalScopingResolver)creator.getContext().get(LexicalScopingResolverContexts.RESOLVER); + + LexicalScopingResolver r = (LexicalScopingResolver) creator.getContext().get(LexicalScopingResolverContexts.RESOLVER); if (r != null) { CGNode def = r.getOriginalDefiner(name); if (def != null) { result = new NonNullSingletonIterator(def); } } - + PointerKey funcKey = builder.getPointerKeyForLocal(creator, 1); OrdinalSet funcPtrs = builder.getPointerAnalysis().getPointsToSet(funcKey); - for(InstanceKey x : funcPtrs) { + for (InstanceKey x : funcPtrs) { if (x instanceof ScopeMappingInstanceKey) { - result = new CompoundIterator(result, ((ScopeMappingInstanceKey)x).getFunargNodes(name)); + result = new CompoundIterator(result, ((ScopeMappingInstanceKey) x).getFunargNodes(name)); } } - + return result; } From 899824081e81dd58ee62387ec94c043d0698f74e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:32:12 +0000 Subject: [PATCH 069/238] always add one level of call-string sensitivity for constructors git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4356 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../JavaScriptConstructorContextSelector.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java index fe416dfb7..cab4b2570 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java @@ -8,13 +8,17 @@ import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector; import com.ibm.wala.util.intset.IntSet; public class JavaScriptConstructorContextSelector implements ContextSelector { private final ContextSelector base; + private final ContextSelector oneLevel; + public JavaScriptConstructorContextSelector(ContextSelector base) { this.base = base; + this.oneLevel = new OneLevelSiteContextSelector(base); } @@ -24,8 +28,13 @@ public class JavaScriptConstructorContextSelector implements ContextSelector { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { - if (callee instanceof JavaScriptConstructor && caller.getContext() instanceof ScopeMappingContext) { - return caller.getContext(); + if (callee instanceof JavaScriptConstructor) { + if (caller.getContext() instanceof ScopeMappingContext) { + return caller.getContext(); + } else { + // use one-level of call-site sensitivity for constructors always + return oneLevel.getCalleeTarget(caller, site, callee, receiver); + } } else { return base.getCalleeTarget(caller, site, callee, receiver); } From 63c20d5f8d7e0fa50114bbf20183b26ce8cf34f7 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:32:25 +0000 Subject: [PATCH 070/238] reset default timeout in TestUtil; kill CGNodeResolver.toString() git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4357 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../LexicalScopingResolverContexts.java | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index 5da7ddd10..cf962aa0d 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -292,22 +292,16 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } } - @Override - public String toString() { - StringBuilder result = new StringBuilder(); - result.append("CGNodeResolver[myDefiner="); - result.append(myDefiner); - // result.append(", myNode="); - // result.append(myNode); -// result.append(",\n myReadOnlyDefs="); -// result.append(myReadOnlyDefs); -// result.append(",\n myDefs="); -// result.append(myDefs); - result.append(",\n parent="); - result.append(parent); - result.append("]"); - return result.toString(); - } +// @Override +// public String toString() { +// StringBuilder result = new StringBuilder(); +// result.append("CGNodeResolver[myDefiner="); +// result.append(myDefiner); +// result.append(",\n parent="); +// result.append(parent); +// result.append("]"); +// return result.toString(); +// } } From 063ddd32cdd8d116b1165c606750cbbafac69880 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:32:38 +0000 Subject: [PATCH 071/238] Renamed temporary variable "base" used when expanding property reads to "$$ base" to avoid name clashes with user-defined variables. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4358 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/org/mozilla/javascript/RhinoToAstTranslator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index beb40f357..543e5f8c3 100644 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -1108,9 +1108,9 @@ public class RhinoToAstTranslator { case Token.CALL: { if (!isPrimitiveCall(context, n)) { - CAstNode base = makeVarRef("base"); + CAstNode base = makeVarRef("$$ base"); Node callee = n.getFirstChild(); - WalkContext child = new BaseCollectingContext(context, callee, "base"); + WalkContext child = new BaseCollectingContext(context, callee, "$$ base"); CAstNode fun = walkNodes(callee, child); // the first actual parameter appearing within the parentheses of the @@ -1120,7 +1120,7 @@ public class RhinoToAstTranslator { return Ast.makeNode( CAstNode.LOCAL_SCOPE, Ast.makeNode(CAstNode.BLOCK_EXPR, - Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("base")), Ast.makeConstant(null)), + Ast.makeNode(CAstNode.DECL_STMT, Ast.makeConstant(new CAstSymbolImpl("$$ base")), Ast.makeConstant(null)), makeCall(fun, base, firstParamInParens, context))); else { // pass the global object as the receiver argument From 87ea0760cfd8920662864e79bb5f7b29b2107d6e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:32:51 +0000 Subject: [PATCH 072/238] Additional check to ensure that the expected number of arguments is provided. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4359 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 3e7271df8..3d0a51afc 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -172,7 +172,7 @@ public class ForInContextSelector implements ContextSelector { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); String calleeFullName = callee.getDeclaringClass().getName().toString(); String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); - if (calleeShortName.startsWith(HACK_METHOD_STR)) { + if (calleeShortName.startsWith(HACK_METHOD_STR) && receiver.length > 2) { InstanceKey loopVar = receiver[2]; IClass stringClass = caller.getClassHierarchy().lookupClass(JavaScriptTypes.String); if(loopVar instanceof ConstantKey) { From f0bee15f9fce37777549cc8f0a74328e4acdf463 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:33:06 +0000 Subject: [PATCH 073/238] Minor change. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4360 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JavaScriptFunctionApplyContextSelector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index ccac33a1f..ae0093c75 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -16,7 +16,7 @@ import com.ibm.wala.util.intset.IntSetUtil; * * @see MDN - * Function.apply() docs + * Function.prototype.apply() docs */ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { From 46dc76754968441d178af5a4913af9f7990a1e51 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:33:19 +0000 Subject: [PATCH 074/238] Minor change. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4361 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../callgraph/JavaScriptFunctionDotCallTargetSelector.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java index 76d18707b..d96cd9f70 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java @@ -110,13 +110,14 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele return t; } + public static final String SYNTHETIC_CALL_METHOD_PREFIX = "$$ call_"; private MethodReference genSyntheticMethodRef(IClass receiver, int nargs, Object key) { Atom atom = null; if (key instanceof Pair) { Pair p = (Pair) key; - atom = Atom.findOrCreateUnicodeAtom("call_" + p.fst + "_" + p.snd); + atom = Atom.findOrCreateUnicodeAtom(SYNTHETIC_CALL_METHOD_PREFIX + p.fst + "_" + p.snd); } else { - atom = Atom.findOrCreateUnicodeAtom("call" + nargs); + atom = Atom.findOrCreateUnicodeAtom(SYNTHETIC_CALL_METHOD_PREFIX + nargs); } Descriptor desc = Descriptor.findOrCreateUTF8(JavaScriptLoader.JS, "()LRoot;"); MethodReference ref = MethodReference.findOrCreate(receiver.getReference(), atom, desc); From e62fdc5b1fffb1ab1ada4256cb3210f7a9c94feb Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:33:34 +0000 Subject: [PATCH 075/238] Added custom context selector for uses of Function.prototype.call, which adds object sensitivity on such uses. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4362 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 1 + ...aScriptFunctionDotCallContextSelector.java | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 6a08146d8..2a4ba667a 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -51,6 +51,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); + contextSelector = new JavaScriptFunctionDotCallContextSelector(contextSelector); if (HANDLE_FUNCTION_APPLY) { contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java new file mode 100644 index 000000000..ee9a49b1c --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java @@ -0,0 +1,51 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.util.intset.IntSet; +import com.ibm.wala.util.intset.IntSetUtil; + +/** + * Special-purpose context selector which adds object sensitivity on uses of Function.prototype.call. + * + * @see MDN + * Function.prototype.call() docs + * + * @author mschaefer + */ +public class JavaScriptFunctionDotCallContextSelector implements ContextSelector { + + private final ContextSelector base; + + public JavaScriptFunctionDotCallContextSelector(ContextSelector base) { + this.base = base; + } + + // parameter 0 is the function being invoked, parameter 1 its receiver + private final static int PARAMETER_INDEX = 1; + + public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { + if (caller.getIR().getCalls(site)[0].getNumberOfUses() > PARAMETER_INDEX) { + return IntSetUtil.make(new int[] { PARAMETER_INDEX }).union(base.getRelevantParameters(caller, site)); + } else { + return base.getRelevantParameters(caller, site); + } + } + + public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { + String calleeName = callee.getName().toString(); + Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); + // TODO: use a better test here + if (calleeName.contains(JavaScriptFunctionDotCallTargetSelector.SYNTHETIC_CALL_METHOD_PREFIX)) { + if (receiver.length > PARAMETER_INDEX && receiver[PARAMETER_INDEX] != null) + // TODO: don't use ForInContext here, introduce new kind of context for specialising on parameter position + return new ForInContextSelector.ForInContext(base.getCalleeTarget(caller, site, callee, receiver), receiver[PARAMETER_INDEX]); + } + return baseContext; + } +} From 7026301ed4562ab8be3adbaf96e072df598f4bc2 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:33:48 +0000 Subject: [PATCH 076/238] Fixed unsoundness in the context selector; unsurprisingly, this makes the analysis explode on MooTools again... git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4363 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- ...aScriptFunctionDotCallContextSelector.java | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java index ee9a49b1c..dec728360 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java @@ -4,7 +4,10 @@ import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.ContextItem; +import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.util.intset.IntSet; import com.ibm.wala.util.intset.IntSetUtil; @@ -26,8 +29,8 @@ public class JavaScriptFunctionDotCallContextSelector implements ContextSelector this.base = base; } - // parameter 0 is the function being invoked, parameter 1 its receiver - private final static int PARAMETER_INDEX = 1; + // parameter 0 is the call function itself, parameter 1 is the function to call, parameter 2 its receiver + private final static int PARAMETER_INDEX = 2; public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { if (caller.getIR().getCalls(site)[0].getNumberOfUses() > PARAMETER_INDEX) { @@ -42,10 +45,33 @@ public class JavaScriptFunctionDotCallContextSelector implements ContextSelector Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); // TODO: use a better test here if (calleeName.contains(JavaScriptFunctionDotCallTargetSelector.SYNTHETIC_CALL_METHOD_PREFIX)) { - if (receiver.length > PARAMETER_INDEX && receiver[PARAMETER_INDEX] != null) - // TODO: don't use ForInContext here, introduce new kind of context for specialising on parameter position - return new ForInContextSelector.ForInContext(base.getCalleeTarget(caller, site, callee, receiver), receiver[PARAMETER_INDEX]); + if (receiver.length > PARAMETER_INDEX && receiver[PARAMETER_INDEX] != null) { + return new ParameterInstanceContext(baseContext, PARAMETER_INDEX, receiver[PARAMETER_INDEX]); + } } return baseContext; } + + public class ParameterInstanceContext implements Context { + private final Context baseContext; + private final int index; + private final InstanceKey key; + + public ParameterInstanceContext(Context baseContext, int index, InstanceKey key) { + if(key == null) + throw new IllegalArgumentException("Null key provided for parameter."); + if(index <= 0 || index > ContextKey.PARAMETERS.length) + throw new IllegalArgumentException("Parameter index out of range."); + this.baseContext = baseContext; + this.index = index; + this.key = key; + } + + public ContextItem get(ContextKey name) { + if(name == ContextKey.PARAMETERS[index]) + return new FilteredPointerKey.SingleInstanceFilter(key); + else + return baseContext.get(name); + } + } } From 98f89876b110126b6ea46e4837631ad1ebdfc032 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:34:04 +0000 Subject: [PATCH 077/238] Adding two simple regression tests. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4364 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/wrap1.js | 15 +++++++++++++ .../examples-src/tests/wrap2.js | 15 +++++++++++++ .../js/test/TestSimpleCallGraphShape.java | 22 +++++++++++++++++++ 3 files changed, 52 insertions(+) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js new file mode 100644 index 000000000..948e86df8 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js @@ -0,0 +1,15 @@ +Function.prototype.wrap = function f_wrap(){ + var self = this; + return function wrapper(x, y, z){ + return self(x, y, z); + }; +}; + + +Function.prototype.extend = function f_extend(thi$, key, value){ + thi$[key] = value; +}.wrap(); + +Number.extend(Number, 'g', function i_am_reachable(x){ return x+19; }); + +print(Number.g(23)); diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js new file mode 100644 index 000000000..91fa862df --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js @@ -0,0 +1,15 @@ +Function.prototype.wrap = function f_wrap(){ + var self = this; + return function wrapper(x, y, z){ + return (function wrapper_inner() { self(x, y, z); })(); + }; +}; + + +Function.prototype.extend = function f_extend(thi$, key, value){ + thi$[key] = value; +}.wrap(); + +Number.extend(Number, 'g', function i_am_reachable(x){ return x+19; }); + +print(Number.g(23)); 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 71548222c..1eb091b10 100644 --- 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 @@ -337,6 +337,26 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { CallGraph CG = Util.makeScriptCG("tests", "function_apply2.js"); verifyGraphAssertions(CG, assertionsForFunctionApply2); } + + private static final Object[][] assertionsForWrap1 = new Object[][] { + new Object[] { ROOT, new String[] { "tests/wrap1.js" } }, + new Object[] { "suffix:wrap1.js", new String[] { "suffix:i_am_reachable" } } }; + + @Test + public void testWrap1() throws IllegalArgumentException, IOException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "wrap1.js"); + verifyGraphAssertions(CG, assertionsForWrap1); + } + + private static final Object[][] assertionsForWrap2 = new Object[][] { + new Object[] { ROOT, new String[] { "tests/wrap2.js" } }, + new Object[] { "suffix:wrap2.js", new String[] { "suffix:i_am_reachable" } } }; + + @Test + public void testWrap2() throws IllegalArgumentException, IOException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "wrap2.js"); + verifyGraphAssertions(CG, assertionsForWrap2); + } private static final Object[][] assertionsForComplexCall = new Object[][] { new Object[] { ROOT, new String[] { "tests/complex_call.js" } }, @@ -345,6 +365,8 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { @Test public void testComplexCall() throws IOException, IllegalArgumentException, CancelException { CallGraph CG = Util.makeScriptCG("tests", "complex_call.js"); + for(CGNode nd : CG) + System.out.println(nd); verifyGraphAssertions(CG, assertionsForComplexCall); } From 2dc375340af5dad4713534471a98f99fed6e22fb Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:34:14 +0000 Subject: [PATCH 078/238] Simplified test cases. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4365 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js | 6 +++--- com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js index 948e86df8..80d505b42 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js @@ -6,10 +6,10 @@ Function.prototype.wrap = function f_wrap(){ }; -Function.prototype.extend = function f_extend(thi$, key, value){ +var extend = function f_extend(thi$, key, value){ thi$[key] = value; }.wrap(); -Number.extend(Number, 'g', function i_am_reachable(x){ return x+19; }); +extend(Number, 'g', function i_am_reachable(x){ return x+19; }); -print(Number.g(23)); +Number.g(23); diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js index 91fa862df..17f9699a7 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js @@ -6,10 +6,10 @@ Function.prototype.wrap = function f_wrap(){ }; -Function.prototype.extend = function f_extend(thi$, key, value){ +var extend = function f_extend(thi$, key, value){ thi$[key] = value; }.wrap(); -Number.extend(Number, 'g', function i_am_reachable(x){ return x+19; }); +extend(Number, 'g', function i_am_reachable(x){ return x+19; }); -print(Number.g(23)); +Number.g(23); From df0525d55c9e0cdf7be6eaaea26699a8b2430a54 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:34:27 +0000 Subject: [PATCH 079/238] Extending for-in context selector to also provide contexts for functions that perform for-in iteration on their first parameter. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4366 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/ForInContextSelector.java | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 3d0a51afc..5ef1298ee 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -12,9 +12,12 @@ package com.ibm.wala.cast.js.ipa.callgraph; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; +import com.ibm.wala.cast.ir.ssa.AstIRFactory; +import com.ibm.wala.cast.ir.ssa.EachElementGetInstruction; import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IClass; @@ -24,15 +27,21 @@ import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.impl.Everywhere; import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey; import com.ibm.wala.ipa.callgraph.propagation.ConstantKey; import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector; import com.ibm.wala.ssa.DefUse; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.ssa.IRFactory; import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.ssa.SSAGetInstruction; import com.ibm.wala.ssa.SSAInstruction; +import com.ibm.wala.ssa.SSAOptions; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.collections.Iterator2Iterable; import com.ibm.wala.util.intset.IntSet; import com.ibm.wala.util.intset.IntSetUtil; import com.ibm.wala.util.intset.MutableIntSet; @@ -168,11 +177,32 @@ public class ForInContextSelector implements ContextSelector { this.oneLevel = new OneLevelSiteContextSelector(base); } + private final HashMap forInOnFirstArg_cache = HashMapFactory.make(); + private final IRFactory factory = AstIRFactory.makeDefaultFactory(); + private boolean forInOnFirstArg(IMethod method) { + if(method.getNumberOfParameters() < 2) + return false; + Boolean b = forInOnFirstArg_cache.get(method); + if(b != null) + return b; + IR ir = factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions()); + DefUse du = new DefUse(ir); + Iterator uses = du.getUses(3); + for(SSAInstruction use : Iterator2Iterable.make(uses)) { + if(use instanceof EachElementGetInstruction) { + forInOnFirstArg_cache.put(method, true); + return true; + } + } + forInOnFirstArg_cache.put(method, false); + return false; + } + public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); String calleeFullName = callee.getDeclaringClass().getName().toString(); String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); - if (calleeShortName.startsWith(HACK_METHOD_STR) && receiver.length > 2) { + if (receiver.length > 2 && (calleeShortName.startsWith(HACK_METHOD_STR) || forInOnFirstArg(callee))) { InstanceKey loopVar = receiver[2]; IClass stringClass = caller.getClassHierarchy().lookupClass(JavaScriptTypes.String); if(loopVar instanceof ConstantKey) { From 3388b8dc7b6fb34df2cdd51b26f890f286dd312f Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:34:40 +0000 Subject: [PATCH 080/238] Removing custom context selector for Function.prototype.call; it doesn't seem worth having. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4367 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 1 - ...aScriptFunctionDotCallContextSelector.java | 77 ------------------- 2 files changed, 78 deletions(-) delete mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 2a4ba667a..6a08146d8 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -51,7 +51,6 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); - contextSelector = new JavaScriptFunctionDotCallContextSelector(contextSelector); if (HANDLE_FUNCTION_APPLY) { contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java deleted file mode 100644 index dec728360..000000000 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallContextSelector.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.ibm.wala.cast.js.ipa.callgraph; - -import com.ibm.wala.classLoader.CallSiteReference; -import com.ibm.wala.classLoader.IMethod; -import com.ibm.wala.ipa.callgraph.CGNode; -import com.ibm.wala.ipa.callgraph.Context; -import com.ibm.wala.ipa.callgraph.ContextItem; -import com.ibm.wala.ipa.callgraph.ContextKey; -import com.ibm.wala.ipa.callgraph.ContextSelector; -import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; -import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; -import com.ibm.wala.util.intset.IntSet; -import com.ibm.wala.util.intset.IntSetUtil; - -/** - * Special-purpose context selector which adds object sensitivity on uses of Function.prototype.call. - * - * @see MDN - * Function.prototype.call() docs - * - * @author mschaefer - */ -public class JavaScriptFunctionDotCallContextSelector implements ContextSelector { - - private final ContextSelector base; - - public JavaScriptFunctionDotCallContextSelector(ContextSelector base) { - this.base = base; - } - - // parameter 0 is the call function itself, parameter 1 is the function to call, parameter 2 its receiver - private final static int PARAMETER_INDEX = 2; - - public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { - if (caller.getIR().getCalls(site)[0].getNumberOfUses() > PARAMETER_INDEX) { - return IntSetUtil.make(new int[] { PARAMETER_INDEX }).union(base.getRelevantParameters(caller, site)); - } else { - return base.getRelevantParameters(caller, site); - } - } - - public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { - String calleeName = callee.getName().toString(); - Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); - // TODO: use a better test here - if (calleeName.contains(JavaScriptFunctionDotCallTargetSelector.SYNTHETIC_CALL_METHOD_PREFIX)) { - if (receiver.length > PARAMETER_INDEX && receiver[PARAMETER_INDEX] != null) { - return new ParameterInstanceContext(baseContext, PARAMETER_INDEX, receiver[PARAMETER_INDEX]); - } - } - return baseContext; - } - - public class ParameterInstanceContext implements Context { - private final Context baseContext; - private final int index; - private final InstanceKey key; - - public ParameterInstanceContext(Context baseContext, int index, InstanceKey key) { - if(key == null) - throw new IllegalArgumentException("Null key provided for parameter."); - if(index <= 0 || index > ContextKey.PARAMETERS.length) - throw new IllegalArgumentException("Parameter index out of range."); - this.baseContext = baseContext; - this.index = index; - this.key = key; - } - - public ContextItem get(ContextKey name) { - if(name == ContextKey.PARAMETERS[index]) - return new FilteredPointerKey.SingleInstanceFilter(key); - else - return baseContext.get(name); - } - } -} From 74502bafb8994bf5a011333f1e778e580d637818 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:34:54 +0000 Subject: [PATCH 081/238] Cleaner handling of for-in context selection: instead of matching on function name, we now use a for-in context for every function that uses its first argument as a property name. There is a flag to restore the old behaviour. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4368 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/ForInContextSelector.java | 61 ++++++++++++++++--- 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 5ef1298ee..da43e8aa9 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -12,7 +12,6 @@ package com.ibm.wala.cast.js.ipa.callgraph; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; @@ -36,6 +35,7 @@ import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector; import com.ibm.wala.ssa.DefUse; import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.IRFactory; +import com.ibm.wala.ssa.ReflectiveMemberAccess; import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.ssa.SSAGetInstruction; import com.ibm.wala.ssa.SSAInstruction; @@ -57,6 +57,10 @@ public class ForInContextSelector implements ContextSelector { }; public static final String HACK_METHOD_STR = "_forin_body"; + + // if this flag is set to true, functions are given ForInContexts based on their name + // if it is false, any function that uses its first argument as a property name will be given a ForInContext + public static final boolean USE_NAME_TO_SELECT_CONTEXT = false; public static boolean USE_CPA_IN_BODIES = false; @@ -178,6 +182,7 @@ public class ForInContextSelector implements ContextSelector { } private final HashMap forInOnFirstArg_cache = HashMapFactory.make(); + private final HashMap du_cache = HashMapFactory.make(); private final IRFactory factory = AstIRFactory.makeDefaultFactory(); private boolean forInOnFirstArg(IMethod method) { if(method.getNumberOfParameters() < 2) @@ -185,10 +190,8 @@ public class ForInContextSelector implements ContextSelector { Boolean b = forInOnFirstArg_cache.get(method); if(b != null) return b; - IR ir = factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions()); - DefUse du = new DefUse(ir); - Iterator uses = du.getUses(3); - for(SSAInstruction use : Iterator2Iterable.make(uses)) { + DefUse du = getDefUse(method); + for(SSAInstruction use : Iterator2Iterable.make(du.getUses(3))) { if(use instanceof EachElementGetInstruction) { forInOnFirstArg_cache.put(method, true); return true; @@ -197,12 +200,54 @@ public class ForInContextSelector implements ContextSelector { forInOnFirstArg_cache.put(method, false); return false; } + + protected DefUse getDefUse(IMethod method) { + DefUse du = du_cache.get(method); + if(du == null) { + IR ir = factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions()); + du_cache.put(method, du = new DefUse(ir)); + } + return du; + } + + private final HashMap usesFirstArgAsPropertyName_cache = HashMapFactory.make(); + private boolean usesFirstArgAsPropertyName(IMethod method) { + if(method.getNumberOfParameters() < 2) + return false; + Boolean b = usesFirstArgAsPropertyName_cache.get(method); + if(b != null) + return b; + DefUse du = getDefUse(method); + for(SSAInstruction use : Iterator2Iterable.make(du.getUses(3))) { + if(use instanceof ReflectiveMemberAccess) { + ReflectiveMemberAccess rma = (ReflectiveMemberAccess)use; + if(rma.getMemberRef() == 3) { + usesFirstArgAsPropertyName_cache.put(method, true); + return true; + } + } + } + usesFirstArgAsPropertyName_cache.put(method, false); + return false; + } + + private boolean useForInContext(IMethod callee, InstanceKey[] receiver) { + if(receiver.length <= 2) + return false; + if(USE_NAME_TO_SELECT_CONTEXT) { + String calleeFullName = callee.getDeclaringClass().getName().toString(); + String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); + if(calleeShortName.contains(HACK_METHOD_STR)) + return true; + } else if(usesFirstArgAsPropertyName(callee)) { + return true; + } + return forInOnFirstArg(callee); + } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); - String calleeFullName = callee.getDeclaringClass().getName().toString(); - String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); - if (receiver.length > 2 && (calleeShortName.startsWith(HACK_METHOD_STR) || forInOnFirstArg(callee))) { + if(useForInContext(callee, receiver)) { InstanceKey loopVar = receiver[2]; IClass stringClass = caller.getClassHierarchy().lookupClass(JavaScriptTypes.String); if(loopVar instanceof ConstantKey) { From f874332a9d8c03f43d32ffd4095febb0cea30517 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:35:08 +0000 Subject: [PATCH 082/238] Bug fix: only use ToString conversion if we are sure the variable is only ever used as a property name. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4369 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/ForInContextSelector.java | 104 ++++++++++-------- 1 file changed, 59 insertions(+), 45 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index da43e8aa9..7cd54977c 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -32,6 +32,7 @@ import com.ibm.wala.ipa.callgraph.propagation.ConstantKey; import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector; +import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ssa.DefUse; import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.IRFactory; @@ -60,7 +61,7 @@ public class ForInContextSelector implements ContextSelector { // if this flag is set to true, functions are given ForInContexts based on their name // if it is false, any function that uses its first argument as a property name will be given a ForInContext - public static final boolean USE_NAME_TO_SELECT_CONTEXT = false; + public static final boolean USE_NAME_TO_SELECT_CONTEXT = true; public static boolean USE_CPA_IN_BODIES = false; @@ -184,6 +185,8 @@ public class ForInContextSelector implements ContextSelector { private final HashMap forInOnFirstArg_cache = HashMapFactory.make(); private final HashMap du_cache = HashMapFactory.make(); private final IRFactory factory = AstIRFactory.makeDefaultFactory(); + + // determine whether the method performs a for-in loop over the properties of its first argument private boolean forInOnFirstArg(IMethod method) { if(method.getNumberOfParameters() < 2) return false; @@ -210,64 +213,76 @@ public class ForInContextSelector implements ContextSelector { return du; } - private final HashMap usesFirstArgAsPropertyName_cache = HashMapFactory.make(); - private boolean usesFirstArgAsPropertyName(IMethod method) { + private enum Frequency { NEVER, SOMETIMES, ALWAYS }; + private final HashMap usesFirstArgAsPropertyName_cache = HashMapFactory.make(); + + // determine whether the method never/sometimes/always uses its first argument as a property name + private Frequency usesFirstArgAsPropertyName(IMethod method) { if(method.getNumberOfParameters() < 2) - return false; - Boolean b = usesFirstArgAsPropertyName_cache.get(method); - if(b != null) - return b; + return Frequency.NEVER; + Frequency f = usesFirstArgAsPropertyName_cache.get(method); + if(f != null) + return f; + boolean usedAsPropertyName = false, usedAsSomethingElse = false; DefUse du = getDefUse(method); for(SSAInstruction use : Iterator2Iterable.make(du.getUses(3))) { if(use instanceof ReflectiveMemberAccess) { ReflectiveMemberAccess rma = (ReflectiveMemberAccess)use; if(rma.getMemberRef() == 3) { - usesFirstArgAsPropertyName_cache.put(method, true); - return true; + usedAsPropertyName = true; + continue; } } + usedAsSomethingElse = true; } - usesFirstArgAsPropertyName_cache.put(method, false); - return false; + if(!usedAsPropertyName) + f = Frequency.NEVER; + else if(usedAsSomethingElse) + f = Frequency.SOMETIMES; + else + f = Frequency.ALWAYS; + usesFirstArgAsPropertyName_cache.put(method, f); + return f; } - - private boolean useForInContext(IMethod callee, InstanceKey[] receiver) { - if(receiver.length <= 2) - return false; - if(USE_NAME_TO_SELECT_CONTEXT) { - String calleeFullName = callee.getDeclaringClass().getName().toString(); - String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); - if(calleeShortName.contains(HACK_METHOD_STR)) - return true; - } else if(usesFirstArgAsPropertyName(callee)) { - return true; + + // simulate effect of ToString conversion on key + private InstanceKey simulateToString(IClassHierarchy cha, InstanceKey key) { + IClass stringClass = cha.lookupClass(JavaScriptTypes.String); + if(key instanceof ConstantKey) { + Object value = ((ConstantKey)key).getValue(); + if(value instanceof String) { + return key; + } else if(value instanceof Number) { + Integer ival = ((Number)value).intValue(); + return new ConstantKey(ival.toString(), stringClass); + } else if(value instanceof Boolean) { + Boolean bval = (Boolean)value; + return new ConstantKey(bval.toString(), stringClass); + } else if(value == null) { + return new ConstantKey("null", stringClass); + } } - return forInOnFirstArg(callee); + return new ConcreteTypeKey(stringClass); } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); - if(useForInContext(callee, receiver)) { - InstanceKey loopVar = receiver[2]; - IClass stringClass = caller.getClassHierarchy().lookupClass(JavaScriptTypes.String); - if(loopVar instanceof ConstantKey) { - // do a manual ToString conversion if necessary - Object value = ((ConstantKey)loopVar).getValue(); - if(value instanceof String) { - return new ForInContext(baseContext, loopVar); - } else if(value instanceof Number) { - Integer ival = ((Number)value).intValue(); - return new ForInContext(baseContext, new ConstantKey(ival.toString(), stringClass)); - } else if(value instanceof Boolean) { - Boolean bval = (Boolean)value; - return new ForInContext(baseContext, new ConstantKey(bval.toString(), stringClass)); - } else if(value == null) { - return new ForInContext(baseContext, new ConstantKey("null", stringClass)); - } + String calleeFullName = callee.getDeclaringClass().getName().toString(); + String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); + if(USE_NAME_TO_SELECT_CONTEXT) { + if(calleeShortName.contains(HACK_METHOD_STR)) { + // we assume that the argument is only used as a property name, so we can do ToString + return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); } - ConcreteTypeKey stringKey = new ConcreteTypeKey(stringClass); - return new ForInContext(baseContext, stringKey); - } else if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { + } else if(receiver.length > 2 && receiver[2] != null) { + Frequency f = usesFirstArgAsPropertyName(callee); + if(f == Frequency.ALWAYS) { + return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); + } else if(f == Frequency.SOMETIMES || forInOnFirstArg(callee)) { + return new ForInContext(baseContext, receiver[2]); + } + } + if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { return new SelectiveCPAContext(baseContext, receiver); } else if (USE_1LEVEL_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { if (! identifyDependentParameters(caller, site).isEmpty()) { @@ -275,9 +290,8 @@ public class ForInContextSelector implements ContextSelector { } else { return baseContext; } - } else { - return baseContext; } + return baseContext; } public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { From fc57c3b8789f18d9afe1b310f9f1f2401a71662c Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:35:24 +0000 Subject: [PATCH 083/238] small optimizations; don't call toString() as much git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4370 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 2 +- ...avaScriptFunctionApplyContextSelector.java | 25 +++++++++++-------- ...vaScriptFunctionDotCallTargetSelector.java | 20 +++++++-------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 6a08146d8..0c296b2e7 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -43,7 +43,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { } setContextInterpreter(contextInterpreter); - options.setSelector(new JavaScriptFunctionDotCallTargetSelector(cha, new JavaScriptConstructTargetSelector(cha, options + options.setSelector(new JavaScriptFunctionDotCallTargetSelector(new JavaScriptConstructTargetSelector(cha, options .getMethodTargetSelector()))); options.setSelector(new LoadFileTargetSelector(options.getMethodTargetSelector(), this)); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index ae0093c75..795c9d331 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -1,7 +1,9 @@ package com.ibm.wala.cast.js.ipa.callgraph; import com.ibm.wala.cast.js.types.JavaScriptTypes; +import com.ibm.wala.cast.types.AstMethodReference; import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; @@ -41,7 +43,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { private final Context delegate; private final CallSiteReference site; - + /** * was the argsList argument a non-null Array? */ @@ -101,20 +103,23 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { return "ApplyContext [delegate=" + delegate + ", site=" + site + ", isNonNullArray=" + isNonNullArray + "]"; } - - } public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { - if (callee.toString().equals("")) { - boolean isNonNullArray = false; - if (receiver.length >= 4) { - InstanceKey argsList = receiver[3]; - if (argsList != null && argsList.getConcreteType().equals(caller.getClassHierarchy().lookupClass(JavaScriptTypes.Array))) { - isNonNullArray = true; + IClass declaringClass = callee.getDeclaringClass(); + IMethod method = declaringClass.getMethod(AstMethodReference.fnSelector); + if (method != null) { + String s = method.getReference().getDeclaringClass().getName().toString(); + if (s.equals("Lprologue.js/functionApply")) { + boolean isNonNullArray = false; + if (receiver.length >= 4) { + InstanceKey argsList = receiver[3]; + if (argsList != null && argsList.getConcreteType().equals(caller.getClassHierarchy().lookupClass(JavaScriptTypes.Array))) { + isNonNullArray = true; + } } + return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), site, isNonNullArray); } - return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), site, isNonNullArray); } return base.getCalleeTarget(caller, site, callee, receiver); } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java index d96cd9f70..300959793 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java @@ -7,13 +7,12 @@ import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummary; import com.ibm.wala.cast.js.loader.JSCallSiteReference; import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.ssa.JSInstructionFactory; -import com.ibm.wala.cast.js.types.JavaScriptTypes; +import com.ibm.wala.cast.types.AstMethodReference; import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.MethodTargetSelector; -import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ssa.IR; import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.types.Descriptor; @@ -23,7 +22,7 @@ import com.ibm.wala.util.collections.Pair; import com.ibm.wala.util.strings.Atom; /** - * Generate IR to model Function.call() + * Generate IR to model Function.call() * * @see MDN @@ -34,11 +33,9 @@ import com.ibm.wala.util.strings.Atom; */ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSelector { - private final IClassHierarchy cha; private final MethodTargetSelector base; - public JavaScriptFunctionDotCallTargetSelector(IClassHierarchy cha, MethodTargetSelector base) { - this.cha = cha; + public JavaScriptFunctionDotCallTargetSelector(MethodTargetSelector base) { this.base = base; } @@ -53,12 +50,12 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele */ @Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { - if (cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.CodeBody))) { - // TODO better way to do this test? - String s = receiver.toString(); - if (s.equals("function Lprologue.js/functionCall")) { + IMethod method = receiver.getMethod(AstMethodReference.fnSelector); + if (method != null) { + String s = method.getReference().getDeclaringClass().getName().toString(); + if (s.equals("Lprologue.js/functionCall")) { return getFunctionCallTarget(caller, site, receiver); - } + } } return base.getCalleeTarget(caller, site, receiver); } @@ -111,6 +108,7 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele } public static final String SYNTHETIC_CALL_METHOD_PREFIX = "$$ call_"; + private MethodReference genSyntheticMethodRef(IClass receiver, int nargs, Object key) { Atom atom = null; if (key instanceof Pair) { From 6e922aac6a56be949664bfeb74c26aa25e838855 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:35:38 +0000 Subject: [PATCH 084/238] Shouldn't use IMethods as keys in maps. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4371 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/ForInContextSelector.java | 39 ++++++++++++------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 7cd54977c..0205254a7 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -16,6 +16,7 @@ import java.util.Map; import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; import com.ibm.wala.cast.ir.ssa.AstIRFactory; +import com.ibm.wala.cast.ir.ssa.AstIsDefinedInstruction; import com.ibm.wala.cast.ir.ssa.EachElementGetInstruction; import com.ibm.wala.cast.js.types.JavaScriptTypes; import com.ibm.wala.classLoader.CallSiteReference; @@ -41,6 +42,7 @@ import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; import com.ibm.wala.ssa.SSAGetInstruction; import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.ssa.SSAOptions; +import com.ibm.wala.types.MethodReference; import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.Iterator2Iterable; import com.ibm.wala.util.intset.IntSet; @@ -182,45 +184,48 @@ public class ForInContextSelector implements ContextSelector { this.oneLevel = new OneLevelSiteContextSelector(base); } - private final HashMap forInOnFirstArg_cache = HashMapFactory.make(); - private final HashMap du_cache = HashMapFactory.make(); + private final HashMap forInOnFirstArg_cache = HashMapFactory.make(); + private final HashMap du_cache = HashMapFactory.make(); private final IRFactory factory = AstIRFactory.makeDefaultFactory(); // determine whether the method performs a for-in loop over the properties of its first argument private boolean forInOnFirstArg(IMethod method) { + MethodReference mref = method.getReference(); if(method.getNumberOfParameters() < 2) return false; - Boolean b = forInOnFirstArg_cache.get(method); + Boolean b = forInOnFirstArg_cache.get(mref); if(b != null) return b; DefUse du = getDefUse(method); for(SSAInstruction use : Iterator2Iterable.make(du.getUses(3))) { if(use instanceof EachElementGetInstruction) { - forInOnFirstArg_cache.put(method, true); + forInOnFirstArg_cache.put(mref, true); return true; } } - forInOnFirstArg_cache.put(method, false); + forInOnFirstArg_cache.put(mref, false); return false; } protected DefUse getDefUse(IMethod method) { - DefUse du = du_cache.get(method); + MethodReference mref = method.getReference(); + DefUse du = du_cache.get(mref); if(du == null) { IR ir = factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions()); - du_cache.put(method, du = new DefUse(ir)); + du_cache.put(mref, du = new DefUse(ir)); } return du; } private enum Frequency { NEVER, SOMETIMES, ALWAYS }; - private final HashMap usesFirstArgAsPropertyName_cache = HashMapFactory.make(); + private final HashMap usesFirstArgAsPropertyName_cache = HashMapFactory.make(); // determine whether the method never/sometimes/always uses its first argument as a property name private Frequency usesFirstArgAsPropertyName(IMethod method) { + MethodReference mref = method.getReference(); if(method.getNumberOfParameters() < 2) return Frequency.NEVER; - Frequency f = usesFirstArgAsPropertyName_cache.get(method); + Frequency f = usesFirstArgAsPropertyName_cache.get(mref); if(f != null) return f; boolean usedAsPropertyName = false, usedAsSomethingElse = false; @@ -232,6 +237,12 @@ public class ForInContextSelector implements ContextSelector { usedAsPropertyName = true; continue; } + } else if(use instanceof AstIsDefinedInstruction) { + AstIsDefinedInstruction aidi = (AstIsDefinedInstruction)use; + if(aidi.getNumberOfUses() > 1 && aidi.getUse(1) == 3) { + usedAsPropertyName = true; + continue; + } } usedAsSomethingElse = true; } @@ -241,7 +252,7 @@ public class ForInContextSelector implements ContextSelector { f = Frequency.SOMETIMES; else f = Frequency.ALWAYS; - usesFirstArgAsPropertyName_cache.put(method, f); + usesFirstArgAsPropertyName_cache.put(mref, f); return f; } @@ -267,18 +278,18 @@ public class ForInContextSelector implements ContextSelector { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); - String calleeFullName = callee.getDeclaringClass().getName().toString(); - String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); if(USE_NAME_TO_SELECT_CONTEXT) { + String calleeFullName = callee.getDeclaringClass().getName().toString(); + String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); if(calleeShortName.contains(HACK_METHOD_STR)) { // we assume that the argument is only used as a property name, so we can do ToString return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); } - } else if(receiver.length > 2 && receiver[2] != null) { + } else if(receiver.length > 2) { Frequency f = usesFirstArgAsPropertyName(callee); if(f == Frequency.ALWAYS) { return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); - } else if(f == Frequency.SOMETIMES || forInOnFirstArg(callee)) { + } else if(receiver[2] != null && (f == Frequency.SOMETIMES || forInOnFirstArg(callee))) { return new ForInContext(baseContext, receiver[2]); } } From c48935c0b9494d975ef01ad1ff7a463b9e8a2f4c Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:35:52 +0000 Subject: [PATCH 085/238] Improved target selector for Function.prototype.call to handle cases where it is invoked as a constructor. As this is almost certainly due to call graph imprecision, we optionally emit a warning when this happens. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4372 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- ...vaScriptFunctionDotCallTargetSelector.java | 40 ++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java index 300959793..9953b6525 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java @@ -8,6 +8,9 @@ import com.ibm.wala.cast.js.loader.JSCallSiteReference; import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.ssa.JSInstructionFactory; import com.ibm.wala.cast.types.AstMethodReference; +import com.ibm.wala.cast.js.types.JavaScriptMethods; +import com.ibm.wala.cast.js.types.JavaScriptTypes; +import com.ibm.wala.cast.loader.AstMethod; import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IMethod; @@ -19,7 +22,10 @@ import com.ibm.wala.types.Descriptor; import com.ibm.wala.types.MethodReference; import com.ibm.wala.util.collections.HashMapFactory; import com.ibm.wala.util.collections.Pair; +import com.ibm.wala.util.debug.Assertions; +import com.ibm.wala.util.intset.IntIterator; import com.ibm.wala.util.strings.Atom; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; /** * Generate IR to model Function.call() @@ -32,6 +38,9 @@ import com.ibm.wala.util.strings.Atom; * */ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSelector { + // whether to warn about what looks like constructor invocations of Function.prototype.call + // while not impossible, such invocations always result in a TypeError and thus are likely due to imprecise call graph information + public static final boolean WARN_ABOUT_NEW_CALL = true; private final MethodTargetSelector base; @@ -50,16 +59,43 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele */ @Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { +<<<<<<< HEAD IMethod method = receiver.getMethod(AstMethodReference.fnSelector); if (method != null) { String s = method.getReference().getDeclaringClass().getName().toString(); if (s.equals("Lprologue.js/functionCall")) { return getFunctionCallTarget(caller, site, receiver); +======= + if (cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.CodeBody))) { + // TODO better way to do this test? + String s = receiver.toString(); + if (s.equals("function Lprologue.js/functionCall")) { + /* invoking Function.prototype.call as a constructor results in a TypeError + * see ECMA-262 5.1, 15: "None of the built-in functions described in this clause that + * are not constructors shall implement the [[Construct]] internal method unless otherwise + * specified" */ + if(!site.getDeclaredTarget().equals(JavaScriptMethods.ctorReference)) { + return getFunctionCallTarget(caller, site, receiver); + } else { + // TODO: we know that this invocation would lead to a type error; how do we express this as a call target? + if(WARN_ABOUT_NEW_CALL) { + IntIterator indices = caller.getIR().getCallInstructionIndices(site).intIterator(); + IMethod callerMethod = caller.getMethod(); + Position pos = null; + if(indices.hasNext() && callerMethod instanceof AstMethod) { + pos = ((AstMethod)callerMethod).getSourcePosition(indices.next()); + } + System.err.println("Detected constructor call to Function.prototype.call " + + (pos == null ? "" : "at position " + pos) + + "; this is likely caused by call graph imprecision."); + } + } +>>>>>>> Improved target selector for Function.prototype.call to handle cases } } return base.getCalleeTarget(caller, site, receiver); } - + private static final boolean SEPARATE_SYNTHETIC_METHOD_PER_SITE = true; /** @@ -78,6 +114,8 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele */ private IMethod getFunctionCallTarget(CGNode caller, CallSiteReference site, IClass receiver) { int nargs = getNumberOfArgsPassed(caller, site); + if(nargs < 2) + Assertions.UNREACHABLE("Call to Function.prototype.call without receiver; this shouldn't be possible."); Object key = getKey(nargs, caller, site); if (callModels.containsKey(key)) { return callModels.get(key); From ca1792a6b84e3de938f5f07857c010a6c662cf47 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:36:10 +0000 Subject: [PATCH 086/238] add unit test for recursive lexical scopes git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4373 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/recursive_lexical.js | 10 ++++++++++ .../wala/cast/js/test/TestSimpleCallGraphShape.java | 6 ++++++ 2 files changed, 16 insertions(+) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/recursive_lexical.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/recursive_lexical.js b/com.ibm.wala.cast.js.test/examples-src/tests/recursive_lexical.js new file mode 100644 index 000000000..91dbb4d72 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/recursive_lexical.js @@ -0,0 +1,10 @@ +var m = function f() { + var x = {}; + function g() { + x["foo"] = {}; + f(); + } + g(); +} + +m(); \ 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 1eb091b10..9905eea0c 100644 --- 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 @@ -161,6 +161,12 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { verifyGraphAssertions(CG, assertionsForSimpleLexical); } + @Test + public void testRecursiveLexical() throws IOException, IllegalArgumentException, CancelException { + // just checking that we have a sufficient bailout to ensure termination + Util.makeScriptCG("tests", "recursive_lexical.js"); + } + private static final Object[][] assertionsForTry = new Object[][] { new Object[] { ROOT, new String[] { "tests/try.js" } }, new Object[] { "tests/try.js", From 22fa1d46925b7ffabb90512bb049c7cae2186423 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:36:23 +0000 Subject: [PATCH 087/238] initial version of bug fix for wrap2.js; needs to be commented / polished git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4374 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/ir/translator/AstTranslator.java | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java index d402eb611..a189324ff 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java @@ -291,34 +291,44 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle * @param name * @return */ - protected int doLexicallyScopedRead(CAstNode node, WalkContext context, String name) { + protected int doLexicallyScopedRead(CAstNode node, WalkContext context, final String name) { + if (name.equals("self")) { + System.err.println("wow"); + } // record in declaring scope that the name is exposed to a nested scope Symbol S = context.currentScope().lookup(name); - CAstEntity E = S.getDefiningScope().getEntity(); - addExposedName(E, E, name, S.getDefiningScope().lookup(name).valueNumber(), false); + Scope definingScope = S.getDefiningScope(); + CAstEntity E = definingScope.getEntity(); + addExposedName(E, E, name, definingScope.lookup(name).valueNumber(), false); - int vn = S.valueNumber(); + String entityName = getEntityName(E); if (useLocalValuesForLexicalVars()) { - // lexically-scoped variables can be given a single vn in a method - Access A = new Access(name, getEntityName(E), vn); // (context.top() is current entity) // record the name as exposed for the current entity, since if the name is // updated via a call to a nested function, SSA for the current entity may // need to be updated with the new definition - addExposedName(context.top(), E, name, vn, false); + Scope curScope = context.currentScope(); + while (!curScope.equals(definingScope)) { + // lexically-scoped variables can be given a single vn in a method + Symbol curSymbol = curScope.lookup(name); + final int vn = curSymbol.valueNumber(); + Access A = new Access(name, entityName, vn); + CAstEntity entity = curScope.getEntity(); + addExposedName(entity, E, name, vn, false); + // record the access; later, the Accesses in the instruction + // defining vn will be adjusted based on this information; see + // patchLexicalAccesses() + addAccess(entity, A); + curScope = curScope.getParent(); + } - // record the access; later, the Accesses in the instruction - // defining vn will be adjusted based on this information; see - // patchLexicalAccesses() - addAccess(context.top(), A); - - return vn; + return S.valueNumber(); } else { // lexically-scoped variables should be read from their scope each time int result = context.currentScope().allocateTempValue(); - Access A = new Access(name, getEntityName(E), result); + Access A = new Access(name, entityName, result); context.cfg().addInstruction(new AstLexicalRead(A)); return result; } @@ -511,7 +521,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle public static final boolean DEBUG_CFG = DEBUG_ALL || false; - public static final boolean DEBUG_NAMES = DEBUG_ALL || false; + public static final boolean DEBUG_NAMES = DEBUG_ALL || true; public static final boolean DEBUG_LEXICAL = DEBUG_ALL || false; @@ -2299,6 +2309,9 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle AstLexicalInformation(String entityName, Scope scope, SSAInstruction[] instrs, Set, Integer>> exposedNamesForReadSet, Set, Integer>> exposedNamesForWriteSet, Set accesses) { + if (entityName.contains("wrapper")) { + System.err.println("wow"); + } this.functionLexicalName = entityName; Pair, Integer>[] EN = null; From eb508d52f14f08d0c3394f06962b8c784d76326b Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:36:37 +0000 Subject: [PATCH 088/238] polishing of fix for wrap2.js issue git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4375 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/ir/translator/AstTranslator.java | 129 ++++++++++-------- 1 file changed, 72 insertions(+), 57 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java index a189324ff..079ec41c8 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java @@ -118,7 +118,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle protected boolean topLevelFunctionsInGlobalScope() { return true; } - + /** * for a block that catches all exceptions, what is the root exception type * that it can catch? E.g., for Java, java.lang.Throwable @@ -292,36 +292,17 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle * @return */ protected int doLexicallyScopedRead(CAstNode node, WalkContext context, final String name) { - if (name.equals("self")) { - System.err.println("wow"); - } - // record in declaring scope that the name is exposed to a nested scope Symbol S = context.currentScope().lookup(name); Scope definingScope = S.getDefiningScope(); CAstEntity E = definingScope.getEntity(); + // record in declaring scope that the name is exposed to a nested scope addExposedName(E, E, name, definingScope.lookup(name).valueNumber(), false); - String entityName = getEntityName(E); + final String entityName = getEntityName(E); if (useLocalValuesForLexicalVars()) { + // lexically-scoped variables can be given a single vn in a method - // (context.top() is current entity) - // record the name as exposed for the current entity, since if the name is - // updated via a call to a nested function, SSA for the current entity may - // need to be updated with the new definition - Scope curScope = context.currentScope(); - while (!curScope.equals(definingScope)) { - // lexically-scoped variables can be given a single vn in a method - Symbol curSymbol = curScope.lookup(name); - final int vn = curSymbol.valueNumber(); - Access A = new Access(name, entityName, vn); - CAstEntity entity = curScope.getEntity(); - addExposedName(entity, E, name, vn, false); - // record the access; later, the Accesses in the instruction - // defining vn will be adjusted based on this information; see - // patchLexicalAccesses() - addAccess(entity, A); - curScope = curScope.getParent(); - } + markExposedInEnclosingEntities(context, name, definingScope, E, entityName, false); return S.valueNumber(); @@ -334,33 +315,63 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle } } + /** + * record name as exposed for the current entity and for all enclosing + * entities up to that of the defining scope, since if the name is updated via + * a call to a nested function, SSA for these entities may need to be updated + * with the new definition + * + * @param context + * @param name + * @param definingScope + * @param E + * @param entityName + * @param isWrite + */ + private void markExposedInEnclosingEntities(WalkContext context, final String name, Scope definingScope, CAstEntity E, + final String entityName, boolean isWrite) { + Scope curScope = context.currentScope(); + while (!curScope.equals(definingScope)) { + final Symbol curSymbol = curScope.lookup(name); + final int vn = curSymbol.valueNumber(); + final Access A = new Access(name, entityName, vn); + final CAstEntity entity = curScope.getEntity(); + addExposedName(entity, E, name, vn, isWrite); + // record the access; later, the Accesses in the instruction + // defining vn will be adjusted based on this information; see + // patchLexicalAccesses() + addAccess(entity, A); + curScope = curScope.getParent(); + } + } + /** * Note that the caller is responsible for ensuring that name is defined in a * lexical scope. * */ protected void doLexicallyScopedWrite(WalkContext context, String name, int rval) { - // record in declaring scope that the name is exposed Symbol S = context.currentScope().lookup(name); - CAstEntity E = S.getDefiningScope().getEntity(); - addExposedName(E, E, name, S.getDefiningScope().lookup(name).valueNumber(), true); + Scope definingScope = S.getDefiningScope(); + CAstEntity E = definingScope.getEntity(); + // record in declaring scope that the name is exposed to a nested scope + addExposedName(E, E, name, definingScope.lookup(name).valueNumber(), true); - // lexically-scoped variables can be given a single vn in a method, or if (useLocalValuesForLexicalVars()) { + // lexically-scoped variables can be given a single vn in a method + + markExposedInEnclosingEntities(context, name, definingScope, E, getEntityName(E), true); + int vn = S.valueNumber(); Access A = new Access(name, getEntityName(E), vn); - - addExposedName(context.top(), E, name, vn, true); - addAccess(context.top(), A); - context.cfg().addInstruction(new AssignInstruction(vn, rval)); // we add write instructions at every access for now // eventually, we may restructure the method to do a single combined write // before exit context.cfg().addInstruction(new AstLexicalWrite(A)); - // lexically-scoped variables can be read from their scope each time } else { + // lexically-scoped variables must be written in their scope each time Access A = new Access(name, getEntityName(E), rval); context.cfg().addInstruction(new AstLexicalWrite(A)); } @@ -521,7 +532,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle public static final boolean DEBUG_CFG = DEBUG_ALL || false; - public static final boolean DEBUG_NAMES = DEBUG_ALL || true; + public static final boolean DEBUG_NAMES = DEBUG_ALL || false; public static final boolean DEBUG_LEXICAL = DEBUG_ALL || false; @@ -2188,10 +2199,11 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle */ public static class AstLexicalInformation implements LexicalInformation { /** - * the name of this function, as it appears in the definer portion of a lexical name + * the name of this function, as it appears in the definer portion of a + * lexical name */ private final String functionLexicalName; - + /** * names possibly accessed in a nested lexical scope, represented as pairs * (name,nameOfDefiningEntity) @@ -2224,15 +2236,15 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle */ private MutableIntSet allExposedUses = null; - /** + /** * names of exposed variables of this method that cannot be written outside */ private final Set readOnlyNames; - + @SuppressWarnings("unchecked") public AstLexicalInformation(AstLexicalInformation original) { this.functionLexicalName = original.functionLexicalName; - + if (original.exposedNames != null) { exposedNames = new Pair[original.exposedNames.length]; for (int i = 0; i < exposedNames.length; i++) { @@ -2270,7 +2282,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle } else { scopingParents = null; } - + readOnlyNames = original.readOnlyNames; } @@ -2306,14 +2318,14 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle } @SuppressWarnings("unchecked") - AstLexicalInformation(String entityName, Scope scope, SSAInstruction[] instrs, Set, Integer>> exposedNamesForReadSet, - Set, Integer>> exposedNamesForWriteSet, - Set accesses) { + AstLexicalInformation(String entityName, Scope scope, SSAInstruction[] instrs, + Set, Integer>> exposedNamesForReadSet, + Set, Integer>> exposedNamesForWriteSet, Set accesses) { if (entityName.contains("wrapper")) { System.err.println("wow"); } this.functionLexicalName = entityName; - + Pair, Integer>[] EN = null; if (exposedNamesForReadSet != null || exposedNamesForWriteSet != null) { Set, Integer>> exposedNamesSet = new HashSet, Integer>>(); @@ -2328,13 +2340,13 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle if (exposedNamesForReadSet != null) { Set readOnlyNames = new HashSet(); - for(Pair,Integer> v : exposedNamesForReadSet) { + for (Pair, Integer> v : exposedNamesForReadSet) { if (entityName != null && entityName.equals(v.fst.snd)) { readOnlyNames.add(v.fst.fst); } } if (exposedNamesForWriteSet != null) { - for(Pair,Integer> v : exposedNamesForWriteSet) { + for (Pair, Integer> v : exposedNamesForWriteSet) { if (entityName != null && entityName.equals(v.fst.snd)) { readOnlyNames.remove(v.fst.fst); } @@ -2344,7 +2356,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle } else { this.readOnlyNames = null; } - + this.exposedNames = buildLexicalNamesArray(EN); // the value numbers stored in exitLexicalUses and instructionLexicalUses @@ -2396,9 +2408,9 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle } private static final int[] NONE = new int[0]; - + public int[] getExposedUses(int instructionOffset) { - return instructionLexicalUses[instructionOffset]==null? NONE: instructionLexicalUses[instructionOffset]; + return instructionLexicalUses[instructionOffset] == null ? NONE : instructionLexicalUses[instructionOffset]; } public IntSet getAllExposedUses() { @@ -2447,7 +2459,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle } public String getScopingName() { - return functionLexicalName; + return functionLexicalName; } }; @@ -2537,7 +2549,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle */ private void addExposedName(CAstEntity entity, CAstEntity declaration, String name, int valueNumber, boolean isWrite) { Pair, Integer> newVal = Pair.make(Pair.make(name, getEntityName(declaration)), valueNumber); - MapUtil.findOrCreateSet(isWrite? exposedNamesForWrite: exposedNamesForRead, entity).add(newVal); + MapUtil.findOrCreateSet(isWrite ? exposedNamesForWrite : exposedNamesForRead, entity).add(newVal); } private String getEntityName(CAstEntity e) { @@ -2844,8 +2856,8 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle // (put here to allow subclasses to handle stuff in scoped entities) // assemble lexical information patchLexicalAccesses(cfg.getInstructions(), accesses.get(n)); - AstLexicalInformation LI = new AstLexicalInformation(getEntityName(n), (AbstractScope) functionContext.currentScope(), cfg.getInstructions(), - exposedNamesForRead.get(n), exposedNamesForWrite.get(n), accesses.get(n)); + AstLexicalInformation LI = new AstLexicalInformation(getEntityName(n), (AbstractScope) functionContext.currentScope(), + cfg.getInstructions(), exposedNamesForRead.get(n), exposedNamesForWrite.get(n), accesses.get(n)); DebuggingInformation DBG = new AstDebuggingInformation(n.getPosition(), line, nms); @@ -2875,7 +2887,8 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle // FIXME: should it be possible to override visit() instead to do the below // and then call super.visit? /** - * to record for which CAstNodes we need to pop the position stack when post-processing + * to record for which CAstNodes we need to pop the position stack when + * post-processing * * @see #enterNode(CAstNode, Context, CAstVisitor) * @see #postProcessNode(CAstNode, Context, CAstVisitor) @@ -2888,7 +2901,8 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle if (context.getSourceMap() != null) { CAstSourcePositionMap.Position p = context.getSourceMap().getPosition(n); if (p != null) { - // store the current position (if any) on the stack, and then set it to be p + // store the current position (if any) on the stack, and then set it to + // be p if (context.cfg().getCurrentPosition() != null) { positions.push(context.cfg().getCurrentPosition()); popPosition = true; @@ -2941,11 +2955,12 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle // FIXME: handle redefinitions of functions Scope cs = context.currentScope(); if (cs.contains(fn.getName()) && !cs.isLexicallyScoped(cs.lookup(fn.getName())) && !cs.isGlobal(cs.lookup(fn.getName()))) { - // if we already have a local with the function's name, write the function value to that local + // if we already have a local with the function's name, write the function + // value to that local assignValue(n, context, cs.lookup(fn.getName()), fn.getName(), result); } else if (topLevelFunctionsInGlobalScope() && context.top().getKind() == CAstEntity.SCRIPT_ENTITY) { globalScope.declare(new FinalCAstSymbol(fn.getName())); - assignValue(n, context, cs.lookup(fn.getName()), fn.getName(), result); + assignValue(n, context, cs.lookup(fn.getName()), fn.getName(), result); } else { context.currentScope().declare(new FinalCAstSymbol(fn.getName()), result); } From ed37d9ee5d9453db68ef1436f327a5a12749d622 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:36:59 +0000 Subject: [PATCH 089/238] another failing test case for scoping and closures git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4376 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/wrap3.js | 24 +++++++++++++++++++ .../js/test/TestSimpleCallGraphShape.java | 10 ++++++++ .../cast/ir/translator/AstTranslator.java | 3 --- 3 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js new file mode 100644 index 000000000..743831d9f --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js @@ -0,0 +1,24 @@ +function f_wrap() { + var y = null; + return function wrapper() { + return { set: function set(p) { + y = p; + }, get: function get() { + return y; + } + } + } + +} + +var w = f_wrap(); + +var x = w(); + +var s = function i_am_reachable() {}; + +x.set(s); + +var t = x.get(); + +t(); 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 9905eea0c..e2ef70e2e 100644 --- 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 @@ -364,6 +364,16 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { verifyGraphAssertions(CG, assertionsForWrap2); } + private static final Object[][] assertionsForWrap3 = new Object[][] { + new Object[] { ROOT, new String[] { "tests/wrap3.js" } }, + new Object[] { "suffix:wrap3.js", new String[] { "suffix:i_am_reachable" } } }; + + @Test + public void testWrap3() throws IllegalArgumentException, IOException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "wrap3.js"); + verifyGraphAssertions(CG, assertionsForWrap3); + } + private static final Object[][] assertionsForComplexCall = new Object[][] { new Object[] { ROOT, new String[] { "tests/complex_call.js" } }, new Object[] { "suffix:call.js", new String[] { "suffix:f3" } } }; diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java index 079ec41c8..7c663eaa5 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java @@ -2321,9 +2321,6 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle AstLexicalInformation(String entityName, Scope scope, SSAInstruction[] instrs, Set, Integer>> exposedNamesForReadSet, Set, Integer>> exposedNamesForWriteSet, Set accesses) { - if (entityName.contains("wrapper")) { - System.err.println("wow"); - } this.functionLexicalName = entityName; Pair, Integer>[] EN = null; From 6051baf5fbfe23a7cc14fafd1a75040b7cee5b05 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:37:13 +0000 Subject: [PATCH 090/238] fix bug exposed by wrap3.js: we were not recusring properly in ScopeMappingInstanceKey.getFunargNodes() git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4377 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../callgraph/ScopeMappingInstanceKeys.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java index de6e31b01..41a081420 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java @@ -13,11 +13,11 @@ package com.ibm.wala.cast.ipa.callgraph; import java.util.Iterator; import com.ibm.wala.cast.ipa.callgraph.LexicalScopingResolverContexts.LexicalScopingResolver; -import com.ibm.wala.cast.loader.AstMethod.LexicalParent; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.NewSiteReference; import com.ibm.wala.classLoader.ProgramCounter; import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.InstanceKeyFactory; import com.ibm.wala.ipa.callgraph.propagation.PointerKey; @@ -74,12 +74,6 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory { */ private final CGNode creator; - /** - * compute the {@link CGNode} correspond to each specified - * {@link LexicalParent} of {@link #base}, populating {@link #scopeMap} - * - */ - private ScopeMappingInstanceKey(CGNode creator, InstanceKey base) { this.creator = creator; this.base = base; @@ -107,6 +101,18 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory { } } + // with multiple levels of nested functions, the creator itself may have + // been invoked by a function represented by a SMIK. E.g., see + // wrap3.js; the constructor of set() is invoked by wrapper(), and + // the wrapper() function object is a SMIK. In such cases, we need to + // recurse to find all the relevant CGNodes. + ContextItem nested = creator.getContext().get(ScopeMappingKeysContextSelector.scopeKey); + if (nested != null) { + result = new CompoundIterator(result, ((ScopeMappingInstanceKey) nested).getFunargNodes(name)); + } + + // TODO what does this code do??? commenting out does not cause any + // regression failures --MS PointerKey funcKey = builder.getPointerKeyForLocal(creator, 1); OrdinalSet funcPtrs = builder.getPointerAnalysis().getPointsToSet(funcKey); for (InstanceKey x : funcPtrs) { From 16317238ff7b02399bcb609d1a64e5924bc4dee5 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:37:27 +0000 Subject: [PATCH 091/238] Print call graph information more compactly. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4378 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/ipa/callgraph/Util.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) mode change 100644 => 100755 com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java old mode 100644 new mode 100755 index 5a4fce41c..a8fa5a9d0 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -19,6 +19,7 @@ import java.util.Iterator; import com.ibm.wala.cast.ir.ssa.AstIRFactory; import com.ibm.wala.cast.loader.SingleClassLoaderFactory; +import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.Language; import com.ibm.wala.classLoader.SourceFileModule; import com.ibm.wala.classLoader.SourceModule; @@ -75,16 +76,35 @@ public class Util { public static AnalysisCache makeCache() { return new AnalysisCache(AstIRFactory.makeDefaultFactory()); } + + public static String getShortName(CGNode nd) { + IMethod method = nd.getMethod(); + return getShortName(method); + } + + public static String getShortName(IMethod method) { + String name = method.getName().toString(); + if(name.equals("do") || name.equals("ctor")) + name = method.getDeclaringClass().getName().toString(); + name = name.substring(name.lastIndexOf('/')+1); + return name; + } @SuppressWarnings("unused") public static void dumpCG(PointerAnalysis PA, CallGraph CG) { if (AVOID_DUMP) return; for (Iterator x = CG.iterator(); x.hasNext();) { CGNode N = (CGNode) x.next(); - System.err.println("\ncallees of node " + N.getMethod() + " " + N.getGraphNodeId()); + System.err.print("callees of node " + getShortName(N) + " : ["); + boolean fst = true; for(Iterator ns = CG.getSuccNodes(N); ns.hasNext(); ) { - System.err.println("\n " + ns.next().getGraphNodeId()); + if(fst) + fst = false; + else + System.err.print(", "); + System.err.print(getShortName(ns.next())); } + System.err.println("]"); System.err.println("\nIR of node " + N.getGraphNodeId()); IR ir = N.getIR(); if (ir != null) { From 5608a3ce7319f7432cb11033e37e2573daee32ee Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:37:36 +0000 Subject: [PATCH 092/238] Function is a function. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4379 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js/dat/prologue.js | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 com.ibm.wala.cast.js/dat/prologue.js diff --git a/com.ibm.wala.cast.js/dat/prologue.js b/com.ibm.wala.cast.js/dat/prologue.js old mode 100644 new mode 100755 index b1ae2bc87..8c8f6df5b --- a/com.ibm.wala.cast.js/dat/prologue.js +++ b/com.ibm.wala.cast.js/dat/prologue.js @@ -104,6 +104,8 @@ Object.prototype = { /* Function properties, see spec 15.3 */ /************************************************************************/ +Function.__proto__ = Function.prototype; + Function.prototype = { constructor: Function, From 0486cea6bb6a89154fd8a392348bf2659d0c0213 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:37:49 +0000 Subject: [PATCH 093/238] Warn about call graph imprecision if an unlikely use of Function.prototype.call is detected. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4380 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- ...vaScriptFunctionDotCallTargetSelector.java | 89 +++++++++++-------- 1 file changed, 51 insertions(+), 38 deletions(-) mode change 100644 => 100755 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java old mode 100644 new mode 100755 index 9953b6525..e4f482a84 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionDotCallTargetSelector.java @@ -38,9 +38,17 @@ import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; * */ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSelector { - // whether to warn about what looks like constructor invocations of Function.prototype.call - // while not impossible, such invocations always result in a TypeError and thus are likely due to imprecise call graph information - public static final boolean WARN_ABOUT_NEW_CALL = true; + /* + * Call graph imprecision often leads to spurious invocations of Function.prototype.call; two common + * patterns are invocations of "new" on Function.prototype.call (which in reality would lead to a + * type error), and self-applications of Function.prototype.call. + * + * While neither of these situations is a priori impossible, they are most likely due to analysis + * imprecision. If this flag is set to true, we emit a warning when seeing them. + */ + public static final boolean WARN_ABOUT_IMPRECISE_CALLGRAPH = true; + + public static final boolean DEBUG_SYNTHETIC_CALL_METHODS = false; private final MethodTargetSelector base; @@ -59,42 +67,39 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele */ @Override public IMethod getCalleeTarget(CGNode caller, CallSiteReference site, IClass receiver) { -<<<<<<< HEAD IMethod method = receiver.getMethod(AstMethodReference.fnSelector); if (method != null) { String s = method.getReference().getDeclaringClass().getName().toString(); if (s.equals("Lprologue.js/functionCall")) { - return getFunctionCallTarget(caller, site, receiver); -======= - if (cha.isSubclassOf(receiver, cha.lookupClass(JavaScriptTypes.CodeBody))) { - // TODO better way to do this test? - String s = receiver.toString(); - if (s.equals("function Lprologue.js/functionCall")) { /* invoking Function.prototype.call as a constructor results in a TypeError * see ECMA-262 5.1, 15: "None of the built-in functions described in this clause that * are not constructors shall implement the [[Construct]] internal method unless otherwise * specified" */ if(!site.getDeclaredTarget().equals(JavaScriptMethods.ctorReference)) { - return getFunctionCallTarget(caller, site, receiver); - } else { - // TODO: we know that this invocation would lead to a type error; how do we express this as a call target? - if(WARN_ABOUT_NEW_CALL) { - IntIterator indices = caller.getIR().getCallInstructionIndices(site).intIterator(); - IMethod callerMethod = caller.getMethod(); - Position pos = null; - if(indices.hasNext() && callerMethod instanceof AstMethod) { - pos = ((AstMethod)callerMethod).getSourcePosition(indices.next()); - } - System.err.println("Detected constructor call to Function.prototype.call " + - (pos == null ? "" : "at position " + pos) + - "; this is likely caused by call graph imprecision."); - } + IMethod target = getFunctionCallTarget(caller, site, receiver); + if(target != null) + return target; } ->>>>>>> Improved target selector for Function.prototype.call to handle cases + // if we get here, we either saw an invocation of "call" as a constructor, or an invocation + // without receiver object; in either case, this is likely due to bad call graph info + if(WARN_ABOUT_IMPRECISE_CALLGRAPH) + warnAboutImpreciseCallGraph(caller, site); } } return base.getCalleeTarget(caller, site, receiver); } + + protected void warnAboutImpreciseCallGraph(CGNode caller, CallSiteReference site) { + IntIterator indices = caller.getIR().getCallInstructionIndices(site).intIterator(); + IMethod callerMethod = caller.getMethod(); + Position pos = null; + if(indices.hasNext() && callerMethod instanceof AstMethod) { + pos = ((AstMethod)callerMethod).getSourcePosition(indices.next()); + } + System.err.println("Detected improbable call to Function.prototype.call " + + (pos == null ? "in function " + caller.getMethod() : "at position " + pos) + + "; this is likely caused by call graph imprecision."); + } private static final boolean SEPARATE_SYNTHETIC_METHOD_PER_SITE = true; @@ -115,14 +120,28 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele private IMethod getFunctionCallTarget(CGNode caller, CallSiteReference site, IClass receiver) { int nargs = getNumberOfArgsPassed(caller, site); if(nargs < 2) - Assertions.UNREACHABLE("Call to Function.prototype.call without receiver; this shouldn't be possible."); - Object key = getKey(nargs, caller, site); + return null; + String key = getKey(nargs, caller, site); if (callModels.containsKey(key)) { return callModels.get(key); } JSInstructionFactory insts = (JSInstructionFactory) receiver.getClassLoader().getInstructionFactory(); MethodReference ref = genSyntheticMethodRef(receiver, nargs, key); JavaScriptSummary S = new JavaScriptSummary(ref, nargs); + + if(WARN_ABOUT_IMPRECISE_CALLGRAPH && caller.getMethod().getName().toString().contains(SYNTHETIC_CALL_METHOD_PREFIX)) + warnAboutImpreciseCallGraph(caller, site); + + // print information about where the method was created if desired + if(DEBUG_SYNTHETIC_CALL_METHODS) { + IMethod method = caller.getMethod(); + if(method instanceof AstMethod) { + int line = ((AstMethod)method).getLineNumber(caller.getIR().getCallInstructionIndices(site).intIterator().next()); + System.err.println("creating " + ref.getName() + " at line " + line + " in " + caller); + } else { + System.err.println("creating " + ref.getName() + " in " + method.getName()); + } + } // generate invocation instruction for the real method being invoked int resultVal = nargs + 2; @@ -147,24 +166,18 @@ public class JavaScriptFunctionDotCallTargetSelector implements MethodTargetSele public static final String SYNTHETIC_CALL_METHOD_PREFIX = "$$ call_"; - private MethodReference genSyntheticMethodRef(IClass receiver, int nargs, Object key) { - Atom atom = null; - if (key instanceof Pair) { - Pair p = (Pair) key; - atom = Atom.findOrCreateUnicodeAtom(SYNTHETIC_CALL_METHOD_PREFIX + p.fst + "_" + p.snd); - } else { - atom = Atom.findOrCreateUnicodeAtom(SYNTHETIC_CALL_METHOD_PREFIX + nargs); - } + private MethodReference genSyntheticMethodRef(IClass receiver, int nargs, String key) { + Atom atom = Atom.findOrCreateUnicodeAtom(SYNTHETIC_CALL_METHOD_PREFIX + key); Descriptor desc = Descriptor.findOrCreateUTF8(JavaScriptLoader.JS, "()LRoot;"); MethodReference ref = MethodReference.findOrCreate(receiver.getReference(), atom, desc); return ref; } - private Object getKey(int nargs, CGNode caller, CallSiteReference site) { + private String getKey(int nargs, CGNode caller, CallSiteReference site) { if (SEPARATE_SYNTHETIC_METHOD_PER_SITE) { - return Pair.make(caller.getGraphNodeId(), site.getProgramCounter()); + return Util.getShortName(caller) + "_" + caller.getGraphNodeId() + "_" + site.getProgramCounter(); } else { - return nargs; + return ""+nargs; } } From e149af8a13f7e5e63d81072036b017af215d26ef Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:41:57 +0000 Subject: [PATCH 094/238] Some more tests. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4381 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js.test/.classpath | 0 com.ibm.wala.cast.js.test/.cvsignore | 0 .../WALA-CAst-JS-Test-Downloads.launch | 0 .../com.ibm.wala.cast.js.test-JUnit.launch | 0 com.ibm.wala.cast.js.test/.project | 0 .../.settings/org.eclipse.jdt.core.prefs | 0 .../.settings/org.eclipse.jdt.ui.prefs | 0 .../META-INF/MANIFEST.MF | 0 com.ibm.wala.cast.js.test/build.properties | 0 .../examples-src/pages/2.js | 0 .../examples-src/pages/apollo-example.html | 0 .../examples-src/pages/collection.js | 0 .../examples-src/pages/crawl.html | 0 .../examples-src/pages/crawl/15.js | 0 .../examples-src/pages/crawl/16.js | 0 .../examples-src/pages/crawl/17.js | 0 .../examples-src/pages/crawl/page11.html | 0 .../examples-src/pages/crawl/page11b.html | 0 .../examples-src/pages/crawl/page12.html | 0 .../examples-src/pages/crawl/page13.html | 0 .../examples-src/pages/crawl/page15.html | 0 .../examples-src/pages/crawl/page16.html | 0 .../examples-src/pages/crawl/page17.html | 0 .../examples-src/pages/iframeTest2.html | 0 .../examples-src/pages/jquery.html | 0 .../examples-src/pages/jquery_hacked.html | 0 .../examples-src/pages/list.html | 0 .../examples-src/pages/mochitest/Makefile.in | 0 .../pages/mochitest/MochiKit/Async.js | 0 .../pages/mochitest/MochiKit/Base.js | 0 .../pages/mochitest/MochiKit/Color.js | 0 .../pages/mochitest/MochiKit/Controls.js | 0 .../pages/mochitest/MochiKit/DOM.js | 0 .../pages/mochitest/MochiKit/DateTime.js | 0 .../pages/mochitest/MochiKit/DragAndDrop.js | 0 .../pages/mochitest/MochiKit/Format.js | 0 .../pages/mochitest/MochiKit/Iter.js | 0 .../pages/mochitest/MochiKit/LICENSE.txt | 0 .../pages/mochitest/MochiKit/Logging.js | 0 .../pages/mochitest/MochiKit/LoggingPane.js | 0 .../pages/mochitest/MochiKit/Makefile.in | 0 .../pages/mochitest/MochiKit/MochiKit.js | 0 .../pages/mochitest/MochiKit/MockDOM.js | 0 .../pages/mochitest/MochiKit/New.js | 0 .../pages/mochitest/MochiKit/Signal.js | 0 .../pages/mochitest/MochiKit/Sortable.js | 0 .../pages/mochitest/MochiKit/Style.js | 0 .../pages/mochitest/MochiKit/Test.js | 0 .../pages/mochitest/MochiKit/Visual.js | 0 .../pages/mochitest/MochiKit/__package__.js | 0 .../pages/mochitest/MochiKit/packed.js | 0 .../examples-src/pages/mochitest/README.txt | 0 .../pages/mochitest/browser-harness.xul | 0 .../pages/mochitest/browser-test-overlay.xul | 0 .../pages/mochitest/browser-test.js | 0 .../pages/mochitest/chrome/Makefile.in | 0 .../pages/mochitest/chrome/test_sample.xul | 0 .../pages/mochitest/gen_template.pl | 0 .../pages/mochitest/harness-a11y.xul | 0 .../pages/mochitest/harness-overlay.xul | 0 .../examples-src/pages/mochitest/harness.xul | 0 .../pages/mochitest/mozillaBug439164.html | 0 .../pages/mochitest/mozillaBug488233.html | 0 .../mochitest/mozillaBug488233NoExtJS.html | 0 .../pages/mochitest/mozillaBug490152.html | 0 .../mochitest/mozillaBug490152NoExtJS.html | 0 .../pages/mochitest/mozillaBug625562.html | 0 .../mochitest/mozillaBug625562NoExtJS.html | 0 .../pages/mochitest/redirect-a11y.html | 0 .../pages/mochitest/redirect.html | 0 .../examples-src/pages/mochitest/redirect.js | 0 .../pages/mochitest/runtests.pl.in | 0 .../pages/mochitest/runtests.py.in | 0 .../examples-src/pages/mochitest/server.js | 0 .../pages/mochitest/ssltunnel/Makefile.in | 0 .../pages/mochitest/ssltunnel/ssltunnel.cpp | 0 .../pages/mochitest/static/Makefile.in | 0 .../mochitest/static/bug100533_iframe.html | 0 .../mochitest/static/bug100533_load.html | 0 .../mochitest/static/bug277724_iframe1.html | 0 .../mochitest/static/bug277724_iframe2.xhtml | 0 .../mochitest/static/bug340800_iframe.txt | 0 .../mochitest/static/bug344830_testembed.svg | 0 .../mochitest/static/chrome.template.txt | 0 .../pages/mochitest/static/harness.css | 0 .../pages/mochitest/static/nnc_lockup.gif | Bin .../pages/mochitest/static/test.template.txt | 0 .../pages/mochitest/static/xhtml.template.txt | 0 .../pages/mochitest/static/xul.template.txt | 0 .../pages/mochitest/tests/FakeJSAN.js | 0 .../pages/mochitest/tests/Makefile.in | 0 .../mochitest/tests/SimpleTest/EventUtils.js | 0 .../mochitest/tests/SimpleTest/Makefile.in | 0 .../tests/SimpleTest/MozillaFileLogger.js | 0 .../mochitest/tests/SimpleTest/SimpleTest.js | 0 .../mochitest/tests/SimpleTest/TestRunner.js | 0 .../pages/mochitest/tests/SimpleTest/quit.js | 0 .../pages/mochitest/tests/SimpleTest/setup.js | 0 .../pages/mochitest/tests/SimpleTest/test.css | 0 .../pages/mochitest/tests/browser/Makefile.in | 0 .../mochitest/tests/browser/browser_async.js | 0 .../mochitest/tests/browser/browser_fail.js | 0 .../tests/browser/browser_fail_async_throw.js | 0 .../tests/browser/browser_fail_fp.js | 0 .../tests/browser/browser_fail_pf.js | 0 .../tests/browser/browser_fail_throw.js | 0 .../tests/browser/browser_fail_timeout.js | 0 .../mochitest/tests/browser/browser_pass.js | 0 .../mochitest/tests/browser/browser_scope.js | 0 .../examples-src/pages/mochitest/tests/cli.js | 0 .../pages/mochitest/tests/index.html | 0 .../pages/mochitest/tests/standalone.js | 0 .../pages/mochitest/tests/test_Base.js | 0 .../pages/mochitest/tests/test_Color.js | 0 .../pages/mochitest/tests/test_DateTime.js | 0 .../pages/mochitest/tests/test_DragAndDrop.js | 0 .../pages/mochitest/tests/test_Format.js | 0 .../pages/mochitest/tests/test_Iter.js | 0 .../pages/mochitest/tests/test_Logging.js | 0 .../mochitest/tests/test_MochiKit-Async.html | 0 .../mochitest/tests/test_MochiKit-Async.json | 0 .../mochitest/tests/test_MochiKit-Base.html | 0 .../mochitest/tests/test_MochiKit-Color.html | 0 .../mochitest/tests/test_MochiKit-DOM.html | 0 .../tests/test_MochiKit-DateTime.html | 0 .../tests/test_MochiKit-DragAndDrop.html | 0 .../mochitest/tests/test_MochiKit-Format.html | 0 .../mochitest/tests/test_MochiKit-Iter.html | 0 .../mochitest/tests/test_MochiKit-JSAN.html | 0 .../tests/test_MochiKit-Logging.html | 0 .../tests/test_MochiKit-MochiKit.html | 0 .../mochitest/tests/test_MochiKit-Signal.html | 0 .../mochitest/tests/test_MochiKit-Style.html | 0 .../mochitest/tests/test_MochiKit-Visual.html | 0 .../pages/mochitest/tests/test_Signal.js | 0 .../pages/mochitest/tests/test_bug100533.html | 0 .../pages/mochitest/tests/test_bug1297.html | 0 .../pages/mochitest/tests/test_bug1366.html | 0 .../pages/mochitest/tests/test_bug1400.html | 0 .../pages/mochitest/tests/test_bug1682.html | 0 .../pages/mochitest/tests/test_bug172261.html | 0 .../pages/mochitest/tests/test_bug1823.html | 0 .../pages/mochitest/tests/test_bug2082.html | 0 .../pages/mochitest/tests/test_bug218236.html | 0 .../pages/mochitest/tests/test_bug218277.html | 0 .../pages/mochitest/tests/test_bug237071.html | 0 .../pages/mochitest/tests/test_bug238409.html | 0 .../pages/mochitest/tests/test_bug24958.html | 0 .../pages/mochitest/tests/test_bug277724.html | 0 .../mochitest/tests/test_bug300691-1.html | 0 .../mochitest/tests/test_bug300691-2.html | 0 .../mochitest/tests/test_bug300691-3.xhtml | 0 .../pages/mochitest/tests/test_bug302186.html | 0 .../pages/mochitest/tests/test_bug308484.html | 0 .../pages/mochitest/tests/test_bug308856.html | 0 .../pages/mochitest/tests/test_bug311681.html | 0 .../mochitest/tests/test_bug311681.xhtml | 0 .../pages/mochitest/tests/test_bug311681.xml | 0 .../pages/mochitest/tests/test_bug311681.xul | 0 .../pages/mochitest/tests/test_bug319381.html | 0 .../mochitest/tests/test_bug332848.xhtml | 0 .../pages/mochitest/tests/test_bug333983.html | 0 .../pages/mochitest/tests/test_bug3348.html | 0 .../pages/mochitest/tests/test_bug337124.html | 0 .../pages/mochitest/tests/test_bug337631.html | 0 .../mochitest/tests/test_bug338541.xhtml | 0 .../pages/mochitest/tests/test_bug338679.html | 0 .../mochitest/tests/test_bug339350.xhtml | 0 .../pages/mochitest/tests/test_bug339494.html | 0 .../mochitest/tests/test_bug339494.xhtml | 0 .../pages/mochitest/tests/test_bug339494.xul | 0 .../pages/mochitest/tests/test_bug340800.html | 0 .../pages/mochitest/tests/test_bug342448.html | 0 .../pages/mochitest/tests/test_bug343596.html | 0 .../pages/mochitest/tests/test_bug344830.html | 0 .../pages/mochitest/tests/test_bug344861.html | 0 .../pages/mochitest/tests/test_bug345521.html | 0 .../pages/mochitest/tests/test_bug348497.html | 0 .../pages/mochitest/tests/test_bug351601.html | 0 .../pages/mochitest/tests/test_bug352728.html | 0 .../mochitest/tests/test_bug352728.xhtml | 0 .../pages/mochitest/tests/test_bug355026.html | 0 .../pages/mochitest/tests/test_bug357509.html | 0 .../pages/mochitest/tests/test_bug358660.html | 0 .../pages/mochitest/tests/test_bug358797.html | 0 .../pages/mochitest/tests/test_bug359657.html | 0 .../pages/mochitest/tests/test_bug359754.xul | 0 .../pages/mochitest/tests/test_bug360220.xul | 0 .../mochitest/tests/test_bug362391.xhtml | 0 .../mochitest/tests/test_bug362788.xhtml | 0 .../mochitest/tests/test_bug364092.xhtml | 0 .../mochitest/tests/test_bug364413.xhtml | 0 .../pages/mochitest/tests/test_bug365773.xul | 0 .../mochitest/tests/test_bug366645.xhtml | 0 .../pages/mochitest/tests/test_bug367164.html | 0 .../pages/mochitest/tests/test_bug51034.html | 0 .../pages/mochitest/tests/test_bug5141.html | 0 .../pages/mochitest/tests/test_bug589.html | 0 .../pages/mochitest/tests/test_bug6296.html | 0 .../pages/mochitest/tests/test_bug691.html | 0 .../pages/mochitest/tests/test_bug694.html | 0 .../pages/mochitest/tests/test_bug696.html | 0 .../examples-src/pages/nojs.html | 0 .../examples-src/pages/page1.html | 0 .../examples-src/pages/page2.html | 0 .../examples-src/pages/page3.html | 0 .../examples-src/pages/page4.html | 0 .../examples-src/pages/windowx.html | 0 .../examples-src/tests/214631.js | 0 .../tests/Function_is_a_function.js | 1 + .../examples-src/tests/badforin.js | 0 .../examples-src/tests/badforin2.js | 0 .../examples-src/tests/calls.js | 0 .../examples-src/tests/complex_call.js | 0 .../examples-src/tests/crash1.js | 0 .../examples-src/tests/crash2.js | 0 .../examples-src/tests/extjs_switch.js | 0 .../examples-src/tests/forin.js | 0 .../examples-src/tests/function_apply.js | 0 .../examples-src/tests/function_apply2.js | 0 .../examples-src/tests/function_call.js | 0 .../examples-src/tests/global_object.js | 0 .../examples-src/tests/global_object2.js | 3 ++ .../examples-src/tests/inherit.js | 0 .../examples-src/tests/instanceof.js | 0 .../examples-src/tests/lexical-ctor.js | 0 .../examples-src/tests/more-control-flow.js | 0 .../examples-src/tests/multivar.js | 0 .../examples-src/tests/nested.js | 0 .../examples-src/tests/newfn.js | 0 .../tests/portal-example-simple.html | 0 .../tests/prototype_contamination_bug.js | 0 .../examples-src/tests/repr.js | 0 .../examples-src/tests/return_this.js | 6 +++ .../examples-src/tests/return_this2.js | 15 ++++++ .../rewrite_does_not_change_lables_bug.js | 0 .../examples-src/tests/rhino_crash1.js | 0 .../examples-src/tests/rhino_crash2.js | 0 .../examples-src/tests/simple-lexical.js | 0 .../examples-src/tests/simpler.js | 0 .../tests/stack_overflow_on_ssa_conversion.js | 0 .../examples-src/tests/string-op.js | 0 .../examples-src/tests/string-prims.js | 0 .../examples-src/tests/try.js | 0 .../examples-src/tests/upward.js | 0 .../examples-src/tests/with.js | 0 .../examples-src/tests/wrap1.js | 0 .../examples-src/tests/wrap2.js | 0 .../cast/js/test/JavaScriptTestPlugin.java | 0 .../js/test/TestAjaxsltCallGraphShape.java | 0 .../wala/cast/js/test/TestForInLoopHack.java | 0 .../cast/js/test/TestJSCallGraphShape.java | 0 .../js/test/TestMediawikiCallGraphShape.java | 0 .../cast/js/test/TestMozillaBugPages.java | 0 .../js/test/TestSimpleCallGraphShape.java | 49 ++++++++++++++++++ .../js/test/TestSimplePageCallGraphShape.java | 0 .../ibm/wala/cast/js/test/TestWebUtil.java | 0 .../com/ibm/wala/cast/js/test/Util.java | 0 com.ibm.wala.cast.js.test/temp.js | 0 .../tests/TestSimpleCallGraphShape.launch | 0 260 files changed, 74 insertions(+) mode change 100644 => 100755 com.ibm.wala.cast.js.test/.classpath mode change 100644 => 100755 com.ibm.wala.cast.js.test/.cvsignore mode change 100644 => 100755 com.ibm.wala.cast.js.test/.launchConfigurations/WALA-CAst-JS-Test-Downloads.launch mode change 100644 => 100755 com.ibm.wala.cast.js.test/.launchConfigurations/com.ibm.wala.cast.js.test-JUnit.launch mode change 100644 => 100755 com.ibm.wala.cast.js.test/.project mode change 100644 => 100755 com.ibm.wala.cast.js.test/.settings/org.eclipse.jdt.core.prefs mode change 100644 => 100755 com.ibm.wala.cast.js.test/.settings/org.eclipse.jdt.ui.prefs mode change 100644 => 100755 com.ibm.wala.cast.js.test/META-INF/MANIFEST.MF mode change 100644 => 100755 com.ibm.wala.cast.js.test/build.properties mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/apollo-example.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/collection.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/15.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/16.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/17.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/page11.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/page11b.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/page12.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/page13.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/page15.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/page16.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/crawl/page17.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/iframeTest2.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/jquery.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/jquery_hacked.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/list.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Async.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Base.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Color.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Controls.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DOM.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DateTime.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DragAndDrop.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Format.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Iter.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/LICENSE.txt mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Logging.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/LoggingPane.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/MochiKit.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/MockDOM.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/New.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Signal.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Sortable.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Style.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Test.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Visual.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/__package__.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/packed.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/README.txt mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-harness.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-test-overlay.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-test.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/chrome/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/chrome/test_sample.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/gen_template.pl mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness-a11y.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness-overlay.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug439164.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug488233.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug488233NoExtJS.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug490152.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug490152NoExtJS.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug625562.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug625562NoExtJS.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect-a11y.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/runtests.pl.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/runtests.py.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/server.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/ssltunnel/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/ssltunnel/ssltunnel.cpp mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug100533_iframe.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug100533_load.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug277724_iframe1.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug277724_iframe2.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug340800_iframe.txt mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug344830_testembed.svg mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/chrome.template.txt mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/harness.css mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/nnc_lockup.gif mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/test.template.txt mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/xhtml.template.txt mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/xul.template.txt mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/FakeJSAN.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/EventUtils.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/MozillaFileLogger.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/SimpleTest.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/TestRunner.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/quit.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/setup.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/test.css mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/Makefile.in mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_async.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_async_throw.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_fp.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_pf.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_throw.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_timeout.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_pass.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_scope.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/cli.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/index.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/standalone.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Base.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Color.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_DateTime.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_DragAndDrop.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Format.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Iter.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Logging.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Async.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Async.json mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Base.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Color.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DOM.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DateTime.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DragAndDrop.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Format.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Iter.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-JSAN.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Logging.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-MochiKit.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Signal.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Style.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Visual.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Signal.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug100533.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1297.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1366.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1400.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1682.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug172261.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1823.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug2082.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug218236.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug218277.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug237071.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug238409.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug24958.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug277724.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-1.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-2.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-3.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug302186.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug308484.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug308856.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug319381.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug332848.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug333983.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug3348.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug337124.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug337631.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug338541.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug338679.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339350.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug340800.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug342448.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug343596.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug344830.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug344861.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug345521.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug348497.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug351601.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug352728.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug352728.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug355026.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug357509.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug358660.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug358797.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug359657.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug359754.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug360220.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug362391.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug362788.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug364092.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug364413.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug365773.xul mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug366645.xhtml mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug367164.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug51034.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug5141.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug589.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug6296.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug691.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug694.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug696.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/nojs.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/page1.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/page2.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/page3.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/page4.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/pages/windowx.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/214631.js create mode 100755 com.ibm.wala.cast.js.test/examples-src/tests/Function_is_a_function.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/badforin.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/badforin2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/calls.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/complex_call.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/crash1.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/crash2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/extjs_switch.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/forin.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/function_apply2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/function_call.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/global_object.js create mode 100755 com.ibm.wala.cast.js.test/examples-src/tests/global_object2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/inherit.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/instanceof.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/lexical-ctor.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/more-control-flow.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/multivar.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/nested.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/newfn.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/portal-example-simple.html mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/prototype_contamination_bug.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/repr.js create mode 100755 com.ibm.wala.cast.js.test/examples-src/tests/return_this.js create mode 100755 com.ibm.wala.cast.js.test/examples-src/tests/return_this2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/rewrite_does_not_change_lables_bug.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/rhino_crash1.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/rhino_crash2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/simple-lexical.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/simpler.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/stack_overflow_on_ssa_conversion.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/string-op.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/string-prims.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/try.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/upward.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/with.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/JavaScriptTestPlugin.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestJSCallGraphShape.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimpleCallGraphShape.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestWebUtil.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java mode change 100644 => 100755 com.ibm.wala.cast.js.test/temp.js mode change 100644 => 100755 com.ibm.wala.cast.js.test/tests/TestSimpleCallGraphShape.launch diff --git a/com.ibm.wala.cast.js.test/.classpath b/com.ibm.wala.cast.js.test/.classpath old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/.cvsignore b/com.ibm.wala.cast.js.test/.cvsignore old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/.launchConfigurations/WALA-CAst-JS-Test-Downloads.launch b/com.ibm.wala.cast.js.test/.launchConfigurations/WALA-CAst-JS-Test-Downloads.launch old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/.launchConfigurations/com.ibm.wala.cast.js.test-JUnit.launch b/com.ibm.wala.cast.js.test/.launchConfigurations/com.ibm.wala.cast.js.test-JUnit.launch old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/.project b/com.ibm.wala.cast.js.test/.project old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/.settings/org.eclipse.jdt.core.prefs b/com.ibm.wala.cast.js.test/.settings/org.eclipse.jdt.core.prefs old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/.settings/org.eclipse.jdt.ui.prefs b/com.ibm.wala.cast.js.test/.settings/org.eclipse.jdt.ui.prefs old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js.test/META-INF/MANIFEST.MF old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/build.properties b/com.ibm.wala.cast.js.test/build.properties old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/2.js b/com.ibm.wala.cast.js.test/examples-src/pages/2.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/apollo-example.html b/com.ibm.wala.cast.js.test/examples-src/pages/apollo-example.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/collection.js b/com.ibm.wala.cast.js.test/examples-src/pages/collection.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/15.js b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/15.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/16.js b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/16.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/17.js b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/17.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page11.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page11.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page11b.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page11b.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page12.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page12.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page13.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page13.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page15.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page15.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page16.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page16.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page17.html b/com.ibm.wala.cast.js.test/examples-src/pages/crawl/page17.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/iframeTest2.html b/com.ibm.wala.cast.js.test/examples-src/pages/iframeTest2.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/jquery.html b/com.ibm.wala.cast.js.test/examples-src/pages/jquery.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/jquery_hacked.html b/com.ibm.wala.cast.js.test/examples-src/pages/jquery_hacked.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/list.html b/com.ibm.wala.cast.js.test/examples-src/pages/list.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Async.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Async.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Base.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Base.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Color.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Color.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Controls.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Controls.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DOM.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DOM.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DateTime.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DateTime.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DragAndDrop.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/DragAndDrop.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Format.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Format.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Iter.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Iter.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/LICENSE.txt b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/LICENSE.txt old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Logging.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Logging.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/LoggingPane.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/LoggingPane.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/MochiKit.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/MochiKit.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/MockDOM.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/MockDOM.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/New.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/New.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Signal.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Signal.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Sortable.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Sortable.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Style.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Style.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Test.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Test.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Visual.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/Visual.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/__package__.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/__package__.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/packed.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/MochiKit/packed.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/README.txt b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/README.txt old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-harness.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-harness.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-test-overlay.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-test-overlay.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-test.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/browser-test.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/chrome/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/chrome/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/chrome/test_sample.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/chrome/test_sample.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/gen_template.pl b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/gen_template.pl old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness-a11y.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness-a11y.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness-overlay.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness-overlay.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/harness.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug439164.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug439164.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug488233.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug488233.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug488233NoExtJS.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug488233NoExtJS.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug490152.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug490152.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug490152NoExtJS.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug490152NoExtJS.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug625562.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug625562.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug625562NoExtJS.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/mozillaBug625562NoExtJS.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect-a11y.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect-a11y.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/redirect.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/runtests.pl.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/runtests.pl.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/runtests.py.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/runtests.py.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/server.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/server.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/ssltunnel/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/ssltunnel/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/ssltunnel/ssltunnel.cpp b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/ssltunnel/ssltunnel.cpp old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug100533_iframe.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug100533_iframe.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug100533_load.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug100533_load.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug277724_iframe1.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug277724_iframe1.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug277724_iframe2.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug277724_iframe2.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug340800_iframe.txt b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug340800_iframe.txt old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug344830_testembed.svg b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/bug344830_testembed.svg old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/chrome.template.txt b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/chrome.template.txt old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/harness.css b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/harness.css old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/nnc_lockup.gif b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/nnc_lockup.gif old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/test.template.txt b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/test.template.txt old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/xhtml.template.txt b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/xhtml.template.txt old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/xul.template.txt b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/static/xul.template.txt old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/FakeJSAN.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/FakeJSAN.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/EventUtils.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/EventUtils.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/MozillaFileLogger.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/MozillaFileLogger.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/SimpleTest.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/SimpleTest.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/TestRunner.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/TestRunner.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/quit.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/quit.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/setup.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/setup.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/test.css b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/SimpleTest/test.css old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/Makefile.in b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/Makefile.in old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_async.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_async.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_async_throw.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_async_throw.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_fp.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_fp.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_pf.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_pf.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_throw.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_throw.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_timeout.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_fail_timeout.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_pass.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_pass.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_scope.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/browser/browser_scope.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/cli.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/cli.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/index.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/index.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/standalone.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/standalone.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Base.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Base.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Color.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Color.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_DateTime.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_DateTime.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_DragAndDrop.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_DragAndDrop.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Format.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Format.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Iter.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Iter.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Logging.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Logging.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Async.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Async.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Async.json b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Async.json old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Base.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Base.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Color.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Color.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DOM.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DOM.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DateTime.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DateTime.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DragAndDrop.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-DragAndDrop.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Format.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Format.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Iter.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Iter.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-JSAN.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-JSAN.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Logging.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Logging.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-MochiKit.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-MochiKit.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Signal.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Signal.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Style.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Style.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Visual.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_MochiKit-Visual.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Signal.js b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_Signal.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug100533.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug100533.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1297.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1297.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1366.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1366.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1400.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1400.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1682.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1682.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug172261.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug172261.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1823.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug1823.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug2082.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug2082.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug218236.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug218236.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug218277.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug218277.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug237071.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug237071.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug238409.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug238409.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug24958.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug24958.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug277724.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug277724.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-1.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-1.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-2.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-2.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-3.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug300691-3.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug302186.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug302186.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug308484.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug308484.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug308856.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug308856.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug311681.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug319381.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug319381.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug332848.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug332848.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug333983.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug333983.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug3348.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug3348.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug337124.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug337124.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug337631.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug337631.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug338541.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug338541.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug338679.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug338679.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339350.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339350.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug339494.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug340800.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug340800.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug342448.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug342448.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug343596.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug343596.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug344830.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug344830.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug344861.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug344861.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug345521.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug345521.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug348497.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug348497.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug351601.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug351601.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug352728.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug352728.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug352728.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug352728.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug355026.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug355026.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug357509.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug357509.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug358660.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug358660.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug358797.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug358797.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug359657.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug359657.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug359754.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug359754.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug360220.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug360220.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug362391.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug362391.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug362788.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug362788.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug364092.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug364092.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug364413.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug364413.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug365773.xul b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug365773.xul old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug366645.xhtml b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug366645.xhtml old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug367164.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug367164.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug51034.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug51034.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug5141.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug5141.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug589.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug589.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug6296.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug6296.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug691.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug691.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug694.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug694.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug696.html b/com.ibm.wala.cast.js.test/examples-src/pages/mochitest/tests/test_bug696.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/nojs.html b/com.ibm.wala.cast.js.test/examples-src/pages/nojs.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/page1.html b/com.ibm.wala.cast.js.test/examples-src/pages/page1.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/page2.html b/com.ibm.wala.cast.js.test/examples-src/pages/page2.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/page3.html b/com.ibm.wala.cast.js.test/examples-src/pages/page3.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/page4.html b/com.ibm.wala.cast.js.test/examples-src/pages/page4.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/pages/windowx.html b/com.ibm.wala.cast.js.test/examples-src/pages/windowx.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/214631.js b/com.ibm.wala.cast.js.test/examples-src/tests/214631.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/Function_is_a_function.js b/com.ibm.wala.cast.js.test/examples-src/tests/Function_is_a_function.js new file mode 100755 index 000000000..42206d196 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/Function_is_a_function.js @@ -0,0 +1 @@ +Function.call(); \ No newline at end of file diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/badforin.js b/com.ibm.wala.cast.js.test/examples-src/tests/badforin.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/badforin2.js b/com.ibm.wala.cast.js.test/examples-src/tests/badforin2.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/calls.js b/com.ibm.wala.cast.js.test/examples-src/tests/calls.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/complex_call.js b/com.ibm.wala.cast.js.test/examples-src/tests/complex_call.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/crash1.js b/com.ibm.wala.cast.js.test/examples-src/tests/crash1.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/crash2.js b/com.ibm.wala.cast.js.test/examples-src/tests/crash2.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/extjs_switch.js b/com.ibm.wala.cast.js.test/examples-src/tests/extjs_switch.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/forin.js b/com.ibm.wala.cast.js.test/examples-src/tests/forin.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_apply2.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_apply2.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js b/com.ibm.wala.cast.js.test/examples-src/tests/function_call.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/global_object.js b/com.ibm.wala.cast.js.test/examples-src/tests/global_object.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/global_object2.js b/com.ibm.wala.cast.js.test/examples-src/tests/global_object2.js new file mode 100755 index 000000000..3dfa6560a --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/global_object2.js @@ -0,0 +1,3 @@ +this.f = function foo() {}; + +f(); \ No newline at end of file diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/inherit.js b/com.ibm.wala.cast.js.test/examples-src/tests/inherit.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/instanceof.js b/com.ibm.wala.cast.js.test/examples-src/tests/instanceof.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/lexical-ctor.js b/com.ibm.wala.cast.js.test/examples-src/tests/lexical-ctor.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/more-control-flow.js b/com.ibm.wala.cast.js.test/examples-src/tests/more-control-flow.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/multivar.js b/com.ibm.wala.cast.js.test/examples-src/tests/multivar.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/nested.js b/com.ibm.wala.cast.js.test/examples-src/tests/nested.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/newfn.js b/com.ibm.wala.cast.js.test/examples-src/tests/newfn.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/portal-example-simple.html b/com.ibm.wala.cast.js.test/examples-src/tests/portal-example-simple.html old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/prototype_contamination_bug.js b/com.ibm.wala.cast.js.test/examples-src/tests/prototype_contamination_bug.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/repr.js b/com.ibm.wala.cast.js.test/examples-src/tests/repr.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/return_this.js b/com.ibm.wala.cast.js.test/examples-src/tests/return_this.js new file mode 100755 index 000000000..3ed67f03f --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/return_this.js @@ -0,0 +1,6 @@ +var o = { + f: function foo() { return this; }, + g: function bar() {} +} + +o.f().g(); diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/return_this2.js b/com.ibm.wala.cast.js.test/examples-src/tests/return_this2.js new file mode 100755 index 000000000..f60928db7 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/return_this2.js @@ -0,0 +1,15 @@ +function A() {} +A.prototype.f = function foo() { + return this; +}; + +var a1 = new A(), a2 = new A(); + +a1.g = function bar1() {}; +a2.g = function bar2() {}; + +var x1 = a1.f(); +var x2 = a2.f(); + +(function test1() { x1.g(); })(); +(function test2() { x2.g(); })(); \ No newline at end of file diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/rewrite_does_not_change_lables_bug.js b/com.ibm.wala.cast.js.test/examples-src/tests/rewrite_does_not_change_lables_bug.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/rhino_crash1.js b/com.ibm.wala.cast.js.test/examples-src/tests/rhino_crash1.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/rhino_crash2.js b/com.ibm.wala.cast.js.test/examples-src/tests/rhino_crash2.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/simple-lexical.js b/com.ibm.wala.cast.js.test/examples-src/tests/simple-lexical.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/simpler.js b/com.ibm.wala.cast.js.test/examples-src/tests/simpler.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/stack_overflow_on_ssa_conversion.js b/com.ibm.wala.cast.js.test/examples-src/tests/stack_overflow_on_ssa_conversion.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/string-op.js b/com.ibm.wala.cast.js.test/examples-src/tests/string-op.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/string-prims.js b/com.ibm.wala.cast.js.test/examples-src/tests/string-prims.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/try.js b/com.ibm.wala.cast.js.test/examples-src/tests/try.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/upward.js b/com.ibm.wala.cast.js.test/examples-src/tests/upward.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/with.js b/com.ibm.wala.cast.js.test/examples-src/tests/with.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap1.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap2.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/JavaScriptTestPlugin.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/JavaScriptTestPlugin.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInLoopHack.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestJSCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestJSCallGraphShape.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMediawikiCallGraphShape.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestMozillaBugPages.java old mode 100644 new mode 100755 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 old mode 100644 new mode 100755 index e2ef70e2e..4c6b4e6bd --- 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 @@ -396,7 +396,56 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { CallGraph CG = Util.makeScriptCG("tests", "global_object.js"); verifyGraphAssertions(CG, assertionsForGlobalObj); } + + private static final Object[][] assertionsForGlobalObj2 = new Object[][] { + new Object[] { ROOT, new String[] { "tests/global_object2.js" } }, + new Object[] { "suffix:global_object2.js", new String[] { "suffix:foo" } } }; + @Test + public void testGlobalObj2() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "global_object2.js"); + verifyGraphAssertions(CG, assertionsForGlobalObj2); + } + + private static final Object[][] assertionsForReturnThis = new Object[][] { + new Object[] { ROOT, new String[] { "tests/return_this.js" } }, + new Object[] { "suffix:return_this.js", new String[] { "suffix:foo" } }, + new Object[] { "suffix:return_this.js", new String[] { "suffix:bar" } } }; + + @Test + public void testReturnThis() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "return_this.js"); + verifyGraphAssertions(CG, assertionsForReturnThis); + } + + private static final Object[][] assertionsForReturnThis2 = new Object[][] { + new Object[] { ROOT, new String[] { "tests/return_this2.js" } }, + new Object[] { "suffix:return_this2.js", new String[] { "suffix:A" } }, + new Object[] { "suffix:return_this2.js", new String[] { "suffix:foo" } }, + new Object[] { "suffix:return_this2.js", new String[] { "suffix:test1" } }, + new Object[] { "suffix:return_this2.js", new String[] { "suffix:test2" } }, + new Object[] { "suffix:test1", new String[] { "suffix:bar1" } }, + new Object[] { "suffix:test2", new String[] { "suffix:bar2" } } + }; + // when using the ObjectSensitivityContextSelector, we additionally know that test1 does not call bar2, + // and test2 does not call bar1 + + @Test + public void testReturnThis2() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "return_this2.js"); + verifyGraphAssertions(CG, assertionsForReturnThis2); + } + + private static final Object[][] assertionsForFunctionIsAFunction = new Object[][] { + new Object[] { ROOT, new String[] { "tests/Function_is_a_function.js" } }, + new Object[] { "suffix:Function_is_a_function.js", new String[] { "suffix:functionCall" } } }; + + @Test + public void testFunctionIsAFunction() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "Function_is_a_function.js"); + verifyGraphAssertions(CG, assertionsForFunctionIsAFunction); + } + protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestSimplePageCallGraphShape.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestWebUtil.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestWebUtil.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/temp.js b/com.ibm.wala.cast.js.test/temp.js old mode 100644 new mode 100755 diff --git a/com.ibm.wala.cast.js.test/tests/TestSimpleCallGraphShape.launch b/com.ibm.wala.cast.js.test/tests/TestSimpleCallGraphShape.launch old mode 100644 new mode 100755 From ec28aca253e6a3fd750c0b4d4f0500a3817e550d Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:42:18 +0000 Subject: [PATCH 095/238] Bug fix for translation of 'in' expressions. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4382 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../source/org/mozilla/javascript/RhinoToAstTranslator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java old mode 100644 new mode 100755 index 543e5f8c3..16feff72b --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -1550,7 +1550,7 @@ public class RhinoToAstTranslator { case Token.IN: { Node value = n.getFirstChild(); Node property = value.getNext(); - return Ast.makeNode(CAstNode.IS_DEFINED_EXPR, walkNodes(value, context), walkNodes(property, context)); + return Ast.makeNode(CAstNode.IS_DEFINED_EXPR, walkNodes(property, context), walkNodes(value, context)); } default: { From ee11f7481a6973c7adc6e2e64a29be53a725403b Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:42:31 +0000 Subject: [PATCH 096/238] Some temporary hacks to make MooTools analyse. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4383 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../js/ipa/callgraph/ForInContextSelector.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) mode change 100644 => 100755 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java old mode 100644 new mode 100755 index 0205254a7..77a3952f9 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -63,7 +63,7 @@ public class ForInContextSelector implements ContextSelector { // if this flag is set to true, functions are given ForInContexts based on their name // if it is false, any function that uses its first argument as a property name will be given a ForInContext - public static final boolean USE_NAME_TO_SELECT_CONTEXT = true; + public static final boolean USE_NAME_TO_SELECT_CONTEXT = false; public static boolean USE_CPA_IN_BODIES = false; @@ -185,8 +185,8 @@ public class ForInContextSelector implements ContextSelector { } private final HashMap forInOnFirstArg_cache = HashMapFactory.make(); - private final HashMap du_cache = HashMapFactory.make(); - private final IRFactory factory = AstIRFactory.makeDefaultFactory(); + public static final HashMap du_cache = HashMapFactory.make(); + public static final IRFactory factory = AstIRFactory.makeDefaultFactory(); // determine whether the method performs a for-in loop over the properties of its first argument private boolean forInOnFirstArg(IMethod method) { @@ -207,7 +207,7 @@ public class ForInContextSelector implements ContextSelector { return false; } - protected DefUse getDefUse(IMethod method) { + public static DefUse getDefUse(IMethod method) { MethodReference mref = method.getReference(); DefUse du = du_cache.get(mref); if(du == null) { @@ -278,15 +278,17 @@ public class ForInContextSelector implements ContextSelector { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, final InstanceKey[] receiver) { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); + String calleeFullName = callee.getDeclaringClass().getName().toString(); + String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); + if(calleeShortName.contains("kill_contexts")) + return Everywhere.EVERYWHERE; if(USE_NAME_TO_SELECT_CONTEXT) { - String calleeFullName = callee.getDeclaringClass().getName().toString(); - String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); - if(calleeShortName.contains(HACK_METHOD_STR)) { + if(calleeShortName.contains(HACK_METHOD_STR) && receiver.length > 2) { // we assume that the argument is only used as a property name, so we can do ToString return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); } } else if(receiver.length > 2) { - Frequency f = usesFirstArgAsPropertyName(callee); + Frequency f = calleeShortName.contains("make_for_in_sensitive") ? Frequency.SOMETIMES : usesFirstArgAsPropertyName(callee); if(f == Frequency.ALWAYS) { return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); } else if(receiver[2] != null && (f == Frequency.SOMETIMES || forInOnFirstArg(callee))) { From fbbd401c9a95091bd3b6dcbc738e596243406d3d Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:42:47 +0000 Subject: [PATCH 097/238] Added optional object sensitivity for functions returning 'this'. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4384 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 4 + .../ObjectSensitivityContextSelector.java | 95 +++++++++++++++++++ 2 files changed, 99 insertions(+) mode change 100644 => 100755 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java create mode 100755 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java old mode 100644 new mode 100755 index 0c296b2e7..f6500096a --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -31,6 +31,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; public class JSZeroOrOneXCFABuilder extends JSCFABuilder { private static final boolean HANDLE_FUNCTION_APPLY = true; + private static final boolean USE_OBJECT_SENSITIVITY = true; public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { @@ -51,6 +52,9 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); + if (USE_OBJECT_SENSITIVITY) { + contextSelector = new ObjectSensitivityContextSelector(contextSelector); + } if (HANDLE_FUNCTION_APPLY) { contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java new file mode 100755 index 000000000..64e57b86d --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java @@ -0,0 +1,95 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import java.util.HashMap; + +import com.ibm.wala.classLoader.CallSiteReference; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ipa.callgraph.CGNode; +import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.ContextItem; +import com.ibm.wala.ipa.callgraph.ContextKey; +import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.impl.Everywhere; +import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey; +import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ssa.SSAInstruction; +import com.ibm.wala.ssa.SSAOptions; +import com.ibm.wala.ssa.SSAReturnInstruction; +import com.ibm.wala.types.MethodReference; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.intset.IntSet; +import com.ibm.wala.util.intset.IntSetUtil; + +public class ObjectSensitivityContextSelector implements ContextSelector { + private final ContextSelector base; + + public ObjectSensitivityContextSelector(ContextSelector base) { + this.base = base; + } + + private final HashMap returnsThis_cache = HashMapFactory.make(); + + // determine whether the method returns "this" + private boolean returnsThis(IMethod method) { + MethodReference mref = method.getReference(); + if(method.getNumberOfParameters() < 1) + return false; + Boolean b = returnsThis_cache.get(mref); + if(b != null) + return b; + for(SSAInstruction inst : ForInContextSelector.factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions()).getInstructions()) { + if(inst instanceof SSAReturnInstruction) { + SSAReturnInstruction ret = (SSAReturnInstruction)inst; + if(ret.getResult() == 2) { + returnsThis_cache.put(mref, true); + return true; + } + } + } + returnsThis_cache.put(mref, false); + return false; + } + + @Override + public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] arguments) { + Context baseContext = base.getCalleeTarget(caller, site, callee, arguments); + if(returnsThis(callee)) { + if(arguments.length > 1 && arguments[1] != null) { + return new ArgumentInstanceContext(baseContext, 1, arguments[1]); + } + } + return baseContext; + } + + @Override + public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { + if (caller.getIR().getCalls(site)[0].getNumberOfUses() > 1) { + return IntSetUtil.make(new int[]{1}).union(base.getRelevantParameters(caller, site)); + } else { + return base.getRelevantParameters(caller, site); + } + } + +} + +class ArgumentInstanceContext implements Context { + private final Context base; + private final int index; + private final InstanceKey instanceKey; + + public ArgumentInstanceContext(Context base, int index, InstanceKey instanceKey) { + this.base = base; + this.index = index; + this.instanceKey = instanceKey; + } + + @Override + public ContextItem get(ContextKey name) { + /*if(name == ContextKey.RECEIVER && index == 1) + return instanceKey;*/ + if(name == ContextKey.PARAMETERS[index]) + return new FilteredPointerKey.SingleInstanceFilter(instanceKey); + return base.get(name); + } + +} \ No newline at end of file From 4c4d83ed5bf94b96440df350fc7a85c4652393e8 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:43:00 +0000 Subject: [PATCH 098/238] Getting rid of two low-level hacks for now. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4385 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 77a3952f9..ef4a60d06 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -280,15 +280,13 @@ public class ForInContextSelector implements ContextSelector { Context baseContext = base.getCalleeTarget(caller, site, callee, receiver); String calleeFullName = callee.getDeclaringClass().getName().toString(); String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); - if(calleeShortName.contains("kill_contexts")) - return Everywhere.EVERYWHERE; if(USE_NAME_TO_SELECT_CONTEXT) { if(calleeShortName.contains(HACK_METHOD_STR) && receiver.length > 2) { // we assume that the argument is only used as a property name, so we can do ToString return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); } } else if(receiver.length > 2) { - Frequency f = calleeShortName.contains("make_for_in_sensitive") ? Frequency.SOMETIMES : usesFirstArgAsPropertyName(callee); + Frequency f = usesFirstArgAsPropertyName(callee); if(f == Frequency.ALWAYS) { return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); } else if(receiver[2] != null && (f == Frequency.SOMETIMES || forInOnFirstArg(callee))) { From df30320720ea3599b3d11fcacb462c5014bec734 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:43:09 +0000 Subject: [PATCH 099/238] Cosmetic change. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4386 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js/dat/prologue.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/dat/prologue.js b/com.ibm.wala.cast.js/dat/prologue.js index 8c8f6df5b..8ac292b27 100755 --- a/com.ibm.wala.cast.js/dat/prologue.js +++ b/com.ibm.wala.cast.js/dat/prologue.js @@ -104,8 +104,6 @@ Object.prototype = { /* Function properties, see spec 15.3 */ /************************************************************************/ -Function.__proto__ = Function.prototype; - Function.prototype = { constructor: Function, @@ -126,6 +124,7 @@ Function.prototype = { } }; +Function.__proto__ = Function.prototype; /************************************************************************/ /* Array properties, see spec 15.4 */ From 5f6fc748365a8b2ae8cc799270b4ecfc13070f9f Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:43:22 +0000 Subject: [PATCH 100/238] Forgot to add equals/hashCode to ArgumentInstanceContext before. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4387 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ObjectSensitivityContextSelector.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java index 64e57b86d..652f0dbc4 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ObjectSensitivityContextSelector.java @@ -91,5 +91,39 @@ class ArgumentInstanceContext implements Context { return new FilteredPointerKey.SingleInstanceFilter(instanceKey); return base.get(name); } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((base == null) ? 0 : base.hashCode()); + result = prime * result + index; + result = prime * result + ((instanceKey == null) ? 0 : instanceKey.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ArgumentInstanceContext other = (ArgumentInstanceContext) obj; + if (base == null) { + if (other.base != null) + return false; + } else if (!base.equals(other.base)) + return false; + if (index != other.index) + return false; + if (instanceKey == null) { + if (other.instanceKey != null) + return false; + } else if (!instanceKey.equals(other.instanceKey)) + return false; + return true; + } } \ No newline at end of file From 13202e726e9479b951ad1bdf0a129a048e48bb76 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:43:37 +0000 Subject: [PATCH 101/238] Added test case for handling of arguments array. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4388 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/arguments.js | 15 +++++++++++++++ .../cast/js/test/TestSimpleCallGraphShape.java | 12 ++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/arguments.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/arguments.js b/com.ibm.wala.cast.js.test/examples-src/tests/arguments.js new file mode 100644 index 000000000..4b413e373 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/arguments.js @@ -0,0 +1,15 @@ +function f() { + arguments[0].g(); +} +f.g = function g1() {}; + +var o = { + f: f, + g: function g2() { } +} + +var oo = { + g: function g3() { } +} + +o.f(oo); \ 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 4c6b4e6bd..fd62f88dc 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 @@ -436,6 +436,18 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { verifyGraphAssertions(CG, assertionsForReturnThis2); } + private static final Object[][] assertionsForArguments = new Object[][] { + new Object[] { ROOT, new String[] { "tests/arguments.js" } }, + new Object[] { "suffix:arguments.js", new String[] { "suffix:f" } }, + new Object[] { "suffix:f", new String[] { "suffix:g3" } } // but neither "suffix:g1" nor "suffix:g2" + }; + + @Test + public void testArguments() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "arguments.js"); + verifyGraphAssertions(CG, assertionsForArguments); + } + private static final Object[][] assertionsForFunctionIsAFunction = new Object[][] { new Object[] { ROOT, new String[] { "tests/Function_is_a_function.js" } }, new Object[] { "suffix:Function_is_a_function.js", new String[] { "suffix:functionCall" } } }; From 082607327d61eeb59239250aa331c05aebdf95a5 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:43:58 +0000 Subject: [PATCH 102/238] test case for bad recursion check bug git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4389 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../tests/lexical_multiple_calls.js | 23 +++++++++++++ .../js/test/TestSimpleCallGraphShape.java | 13 +++++++ .../com/ibm/wala/cast/ipa/callgraph/Util.java | 34 +++++++++++++------ 3 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/lexical_multiple_calls.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/lexical_multiple_calls.js b/com.ibm.wala.cast.js.test/examples-src/tests/lexical_multiple_calls.js new file mode 100644 index 000000000..3e413f17e --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/lexical_multiple_calls.js @@ -0,0 +1,23 @@ +var propName = "f"; +var reachable1 = function reachable1() { return 3; }; +var reachable2 = function reachable2() { return 4; }; +var m = function m(x,y) { + function n(a,b,p,r1,r2) { + var n_inner = function n_inner(p_inner) { + this[p_inner] = this.f1; + return this; + } + a.f1 = r1; + n_inner.call(a,p); + b.f1 = r2; + n_inner.call(b,p) + } + n(x,y,propName,reachable1,reachable2); +} + +var a = {}; +var b = {}; + +m(a,b); +var p = a[propName](); +var q = b[propName](); \ 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 fd62f88dc..73c6fc4d2 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 @@ -166,7 +166,19 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { // just checking that we have a sufficient bailout to ensure termination Util.makeScriptCG("tests", "recursive_lexical.js"); } + + private static final Object[][] assertionsForLexicalMultiple = new Object[][] { + new Object[] { ROOT, new String[] { "tests/lexical_multiple_calls.js" } }, + new Object[] { "suffix:lexical_multiple_calls.js", new String[] { "suffix:reachable1" } }, + new Object[] { "suffix:lexical_multiple_calls.js", new String[] { "suffix:reachable2" } }}; + + @Test + public void testLexicalMultiple() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "lexical_multiple_calls.js"); + verifyGraphAssertions(CG, assertionsForLexicalMultiple); + } + private static final Object[][] assertionsForTry = new Object[][] { new Object[] { ROOT, new String[] { "tests/try.js" } }, new Object[] { "tests/try.js", @@ -406,6 +418,7 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { CallGraph CG = Util.makeScriptCG("tests", "global_object2.js"); verifyGraphAssertions(CG, assertionsForGlobalObj2); } + private static final Object[][] assertionsForReturnThis = new Object[][] { new Object[] { ROOT, new String[] { "tests/return_this.js" } }, diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java index a8fa5a9d0..9d5dcc11c 100755 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/Util.java @@ -38,7 +38,7 @@ public class Util { * flag to prevent dumping of verbose call graph / pointer analysis output */ private static final boolean AVOID_DUMP = true; - + public static SourceFileModule makeSourceModule(URL script, String dir, String name) { // DO NOT use File.separator here, since this name is matched against // URLs. It seems that, in DOS, URL.getFile() does not return a @@ -76,29 +76,43 @@ public class Util { public static AnalysisCache makeCache() { return new AnalysisCache(AstIRFactory.makeDefaultFactory()); } - + public static String getShortName(CGNode nd) { IMethod method = nd.getMethod(); return getShortName(method); } public static String getShortName(IMethod method) { - String name = method.getName().toString(); - if(name.equals("do") || name.equals("ctor")) - name = method.getDeclaringClass().getName().toString(); - name = name.substring(name.lastIndexOf('/')+1); - return name; + String origName = method.getName().toString(); + String result = origName; + if (origName.equals("do") || origName.equals("ctor")) { + result = method.getDeclaringClass().getName().toString(); + result = result.substring(result.lastIndexOf('/') + 1); + if (origName.equals("ctor")) { + if (result.equals("LFunction")) { + String s = method.toString(); + if (s.indexOf('(') != -1) { + String functionName = s.substring(s.indexOf('(') + 1, s.indexOf(')')); + functionName = functionName.substring(functionName.lastIndexOf('/') + 1); + result += " " + functionName; + } + } + result = "ctor of " + result; + } + } + return result; } @SuppressWarnings("unused") public static void dumpCG(PointerAnalysis PA, CallGraph CG) { - if (AVOID_DUMP) return; + if (AVOID_DUMP) + return; for (Iterator x = CG.iterator(); x.hasNext();) { CGNode N = (CGNode) x.next(); System.err.print("callees of node " + getShortName(N) + " : ["); boolean fst = true; - for(Iterator ns = CG.getSuccNodes(N); ns.hasNext(); ) { - if(fst) + for (Iterator ns = CG.getSuccNodes(N); ns.hasNext();) { + if (fst) fst = false; else System.err.print(", "); From 2a61536747ac221fbeeda22d67a71bb167ee516b Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:44:11 +0000 Subject: [PATCH 103/238] fixed recursion check for lexical scoping contexts git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4390 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../LexicalScopingResolverContexts.java | 41 +++++++++++-------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index cf962aa0d..83431ccaa 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -14,6 +14,7 @@ import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; @@ -292,16 +293,16 @@ public final class LexicalScopingResolverContexts implements ContextSelector { } } -// @Override -// public String toString() { -// StringBuilder result = new StringBuilder(); -// result.append("CGNodeResolver[myDefiner="); -// result.append(myDefiner); -// result.append(",\n parent="); -// result.append(parent); -// result.append("]"); -// return result.toString(); -// } + // @Override + // public String toString() { + // StringBuilder result = new StringBuilder(); + // result.append("CGNodeResolver[myDefiner="); + // result.append(myDefiner); + // result.append(",\n parent="); + // result.append(parent); + // result.append("]"); + // return result.toString(); + // } } @@ -483,14 +484,20 @@ public final class LexicalScopingResolverContexts implements ContextSelector { this.builder = builder; } - private Context checkForRecursion(IMethod target, LexicalScopingResolver srcResolver) { - while (srcResolver != null) { - for (CGNode n : builder.getCallGraph().getNodes(target.getReference())) { - if (n.getContext().get(RESOLVER) == srcResolver) { - return n.getContext(); + private Context checkForRecursion(CGNode caller, CallSiteReference site, IMethod target, LexicalScopingResolver srcResolver) { + if (srcResolver != null) { + ExplicitCallGraph cg = builder.getCallGraph(); + Set callerNodes = cg.getNodes(caller.getMethod().getReference()); + while (srcResolver != null) { + for (CGNode possibleCaller : callerNodes) { + for (CGNode n : cg.getPossibleTargets(possibleCaller, site)) { + if (n.getContext().get(RESOLVER) == srcResolver) { + return n.getContext(); + } + } } + srcResolver = srcResolver.getParent(); } - srcResolver = srcResolver.getParent(); } return null; } @@ -512,7 +519,7 @@ public final class LexicalScopingResolverContexts implements ContextSelector { Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters); LexicalScopingResolver resolver = (LexicalScopingResolver) caller.getContext().get(RESOLVER); - Context recursiveParent = checkForRecursion(callee, resolver); + Context recursiveParent = checkForRecursion(caller, site, callee, resolver); if (recursiveParent != null) { return recursiveParent; } From ce72e0fb93ff47ffd542fbbc920dfe949861e38d Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:44:25 +0000 Subject: [PATCH 104/238] make __proto__ not enumerable git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4391 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSSSAPropagationCallGraphBuilder.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java index a02bc84e8..25f9b5826 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java @@ -15,6 +15,7 @@ import java.util.Set; import com.ibm.wala.analysis.typeInference.TypeInference; import com.ibm.wala.cast.ipa.callgraph.AstSSAPropagationCallGraphBuilder; +import com.ibm.wala.cast.ir.ssa.AbstractReflectivePut; import com.ibm.wala.cast.ir.ssa.AstGlobalRead; import com.ibm.wala.cast.ir.ssa.AstGlobalWrite; import com.ibm.wala.cast.ir.ssa.AstIsDefinedInstruction; @@ -40,6 +41,7 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph; import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey; import com.ibm.wala.ipa.callgraph.propagation.ConstantKey; @@ -54,6 +56,7 @@ import com.ibm.wala.ipa.callgraph.propagation.PointsToMap; import com.ibm.wala.ipa.callgraph.propagation.PointsToSetVariable; import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; import com.ibm.wala.ipa.callgraph.propagation.PropagationSystem; +import com.ibm.wala.ipa.callgraph.propagation.FilteredPointerKey.SingleInstanceFilter; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.shrikeBT.BinaryOpInstruction; import com.ibm.wala.shrikeBT.IUnaryOpInstruction; @@ -153,7 +156,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph return true; } return "prototype".equals(fieldName) || "constructor".equals(fieldName) || "arguments".equals(fieldName) - || "class".equals(fieldName) || "$value".equals(fieldName); + || "class".equals(fieldName) || "$value".equals(fieldName) || "__proto__".equals(fieldName); } // /////////////////////////////////////////////////////////////////////////// @@ -162,7 +165,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph // // /////////////////////////////////////////////////////////////////////////// - private final GlobalObjectKey globalObject = new GlobalObjectKey(cha.lookupClass(JavaScriptTypes.Object)); + public final GlobalObjectKey globalObject = new GlobalObjectKey(cha.lookupClass(JavaScriptTypes.Object)); protected ExplicitCallGraph createEmptyCallGraph(IClassHierarchy cha, AnalysisOptions options) { return new JSCallGraph(cha, options, getAnalysisCache()); @@ -649,6 +652,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph protected void processCallingConstraints(CGNode caller, SSAAbstractInvokeInstruction instruction, CGNode target, InstanceKey[][] constParams, PointerKey uniqueCatchKey) { + IR sourceIR = getCFAContextInterpreter().getIR(caller); SymbolTable sourceST = sourceIR.getSymbolTable(); From f8132eab218b50b7065064472e24f32e04cadab9 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:44:39 +0000 Subject: [PATCH 105/238] optimize recursion check git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4392 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../LexicalScopingResolverContexts.java | 84 +++++++++++++++---- 1 file changed, 68 insertions(+), 16 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index 83431ccaa..0a762cc82 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -2,6 +2,7 @@ package com.ibm.wala.cast.ipa.callgraph; import java.util.Collections; import java.util.Iterator; +import java.util.List; import java.util.Map; import java.util.Set; @@ -14,7 +15,6 @@ import com.ibm.wala.ipa.callgraph.Context; import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; -import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; @@ -484,16 +484,61 @@ public final class LexicalScopingResolverContexts implements ContextSelector { this.builder = builder; } - private Context checkForRecursion(CGNode caller, CallSiteReference site, IMethod target, LexicalScopingResolver srcResolver) { - if (srcResolver != null) { - ExplicitCallGraph cg = builder.getCallGraph(); - Set callerNodes = cg.getNodes(caller.getMethod().getReference()); - while (srcResolver != null) { - for (CGNode possibleCaller : callerNodes) { - for (CGNode n : cg.getPossibleTargets(possibleCaller, site)) { - if (n.getContext().get(RESOLVER) == srcResolver) { - return n.getContext(); - } + private static class RecursionKey { + private final IMethod caller; + private final CallSiteReference site; + private final IMethod target; + + public RecursionKey(IMethod caller, CallSiteReference site, IMethod target) { + super(); + this.caller = caller; + this.site = site; + this.target = target; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + caller.hashCode(); + result = prime * result + site.hashCode(); + result = prime * result + target.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + RecursionKey other = (RecursionKey) obj; + if (!caller.equals(other.caller)) + return false; + if (!site.equals(other.site)) + return false; + if (!target.equals(other.target)) + return false; + return true; + } + + } + + /** + * cache for recursion checks + */ + private final Map> key2Contexts = HashMapFactory.make(); + + private Context checkForRecursion(RecursionKey key, LexicalScopingResolver srcResolver) { + List calleeContexts = key2Contexts.get(key); + if (calleeContexts != null) { + // globalResolver better be at the top of any parent chain + while (srcResolver != globalResolver) { + for (LexicalScopingResolverContext c : calleeContexts) { + if (c.governingCallSites == srcResolver) { + return c; } } srcResolver = srcResolver.getParent(); @@ -519,17 +564,24 @@ public final class LexicalScopingResolverContexts implements ContextSelector { Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters); LexicalScopingResolver resolver = (LexicalScopingResolver) caller.getContext().get(RESOLVER); - Context recursiveParent = checkForRecursion(caller, site, callee, resolver); - if (recursiveParent != null) { - return recursiveParent; + final RecursionKey key = new RecursionKey(caller.getMethod(), site, callee); + if (resolver != null) { + Context recursiveParent = checkForRecursion(key, resolver); + if (recursiveParent != null) { + return recursiveParent; + } } if (caller.getMethod() instanceof AstMethod && hasExposedUses(caller, site)) { - return new LexicalScopingResolverContext(caller, site, baseContext); + LexicalScopingResolverContext result = new LexicalScopingResolverContext(caller, site, baseContext); + MapUtil.findOrCreateList(key2Contexts, key).add(result); + return result; } else if (resolver != null) { - return new LexicalScopingResolverContext(resolver, baseContext); + LexicalScopingResolverContext result = new LexicalScopingResolverContext(resolver, baseContext); + MapUtil.findOrCreateList(key2Contexts, key).add(result); + return result; } else { From 723cab3e42f534fd9e540c8bbb31c5b042875647 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:44:53 +0000 Subject: [PATCH 106/238] don't add a bunch of irrelevant Java-specific context selectors git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4393 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index f6500096a..5425a7f9e 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -16,7 +16,7 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.ContextSelector; -import com.ibm.wala.ipa.callgraph.impl.DefaultContextSelector; +import com.ibm.wala.ipa.callgraph.impl.ContextInsensitiveSelector; import com.ibm.wala.ipa.callgraph.impl.DelegatingContextSelector; import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; import com.ibm.wala.ipa.callgraph.propagation.cfa.DelegatingSSAContextInterpreter; @@ -48,7 +48,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { .getMethodTargetSelector()))); options.setSelector(new LoadFileTargetSelector(options.getMethodTargetSelector(), this)); - ContextSelector def = new DefaultContextSelector(options, cha); + ContextSelector def = new ContextInsensitiveSelector(); ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); contextSelector = new ScopeMappingKeysContextSelector(contextSelector); contextSelector = new JavaScriptConstructorContextSelector(contextSelector); From b3f6bfb18cead49fde9684199a3e588ec337b9d6 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:45:08 +0000 Subject: [PATCH 107/238] better formatting git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4394 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js b/com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js index 743831d9f..688178db7 100644 --- a/com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js +++ b/com.ibm.wala.cast.js.test/examples-src/tests/wrap3.js @@ -2,11 +2,11 @@ function f_wrap() { var y = null; return function wrapper() { return { set: function set(p) { - y = p; - }, get: function get() { - return y; - } - } + y = p; + }, get: function get() { + return y; + } + }; } } From caf83a78572063a451f2f6838dd093ab5f2da04c Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:45:22 +0000 Subject: [PATCH 108/238] don't use lexical scoping contexts for the array constructor git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4395 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/ipa/callgraph/LexicalScopingResolverContexts.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index 0a762cc82..d046e0f4c 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -18,6 +18,7 @@ import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; +import com.ibm.wala.ipa.summaries.SummarizedMethod; import com.ibm.wala.util.collections.CompoundIterator; import com.ibm.wala.util.collections.EmptyIterator; import com.ibm.wala.util.collections.HashMapFactory; @@ -562,6 +563,11 @@ public final class LexicalScopingResolverContexts implements ContextSelector { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) { Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters); + if (callee instanceof SummarizedMethod) { + if (callee.getReference().toString().equals("< JavaScriptLoader, LArray, ctor()LRoot; >")) { + return baseContext; + } + } LexicalScopingResolver resolver = (LexicalScopingResolver) caller.getContext().get(RESOLVER); final RecursionKey key = new RecursionKey(caller.getMethod(), site, callee); From 48fd56f3ee84c7756550287c32747b54c37451bd Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:45:35 +0000 Subject: [PATCH 109/238] use call string contexts for constructors rather than the enclosing CGNode. also, fix an imprecision with passing ScopeMappingContexts git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4396 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../JavaScriptConstructorContextSelector.java | 34 ++++++++++++++----- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java index cab4b2570..4384de05e 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java @@ -6,9 +6,11 @@ import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; +import com.ibm.wala.ipa.callgraph.ContextItem; +import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; -import com.ibm.wala.ipa.callgraph.propagation.cfa.OneLevelSiteContextSelector; +import com.ibm.wala.ipa.callgraph.propagation.cfa.nCFAContextSelector; import com.ibm.wala.util.intset.IntSet; public class JavaScriptConstructorContextSelector implements ContextSelector { @@ -18,7 +20,7 @@ public class JavaScriptConstructorContextSelector implements ContextSelector { public JavaScriptConstructorContextSelector(ContextSelector base) { this.base = base; - this.oneLevel = new OneLevelSiteContextSelector(base); + this.oneLevel = new nCFAContextSelector(1, base); } @@ -27,16 +29,32 @@ public class JavaScriptConstructorContextSelector implements ContextSelector { } - public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { + public Context getCalleeTarget(final CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { + final Context baseCtxt = base.getCalleeTarget(caller, site, callee, receiver); if (callee instanceof JavaScriptConstructor) { - if (caller.getContext() instanceof ScopeMappingContext) { - return caller.getContext(); + final Context oneLevelContext = oneLevel.getCalleeTarget(caller, site, callee, receiver); + final Context callerContext = caller.getContext(); + if (callerContext instanceof ScopeMappingContext) { + return new Context() { + + @Override + public ContextItem get(ContextKey name) { + ContextItem result = callerContext.get(name); + if (result == null) { + result = oneLevelContext.get(name); + if (result == null) { + result = baseCtxt.get(name); + } + } + return result; + } + }; } else { - // use one-level of call-site sensitivity for constructors always - return oneLevel.getCalleeTarget(caller, site, callee, receiver); + // use one-level of call-string sensitivity for constructors always + return oneLevelContext; } } else { - return base.getCalleeTarget(caller, site, callee, receiver); + return baseCtxt; } } From 67b2103a491da6dbc833bc6416bff3c1bf49dc79 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:45:49 +0000 Subject: [PATCH 110/238] no scoping contexts for built-in Object and Array constructors git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4397 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/ipa/callgraph/LexicalScopingResolverContexts.java | 4 +++- .../ipa/callgraph/ScopeMappingKeysContextSelector.java | 7 +++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java index d046e0f4c..6ffcf7142 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/LexicalScopingResolverContexts.java @@ -564,7 +564,9 @@ public final class LexicalScopingResolverContexts implements ContextSelector { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] actualParameters) { Context baseContext = base.getCalleeTarget(caller, site, callee, actualParameters); if (callee instanceof SummarizedMethod) { - if (callee.getReference().toString().equals("< JavaScriptLoader, LArray, ctor()LRoot; >")) { + final String calleeName = callee.getReference().toString(); + // TODO create a sub-class in the cast.js projects so we're not checking strings here + if (calleeName.equals("< JavaScriptLoader, LArray, ctor()LRoot; >") || calleeName.equals("< JavaScriptLoader, LObject, ctor()LRoot; >")) { return baseContext; } } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingKeysContextSelector.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingKeysContextSelector.java index ff5b93830..349493f32 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingKeysContextSelector.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingKeysContextSelector.java @@ -9,6 +9,7 @@ import com.ibm.wala.ipa.callgraph.ContextItem; import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; +import com.ibm.wala.ipa.summaries.SummarizedMethod; import com.ibm.wala.util.intset.IntSet; import com.ibm.wala.util.intset.IntSetUtil; @@ -63,6 +64,12 @@ public class ScopeMappingKeysContextSelector implements ContextSelector { public Context getCalleeTarget(CGNode caller, CallSiteReference site, IMethod callee, InstanceKey[] receiver) { Context bc = base.getCalleeTarget(caller, site, callee, receiver); + if (callee instanceof SummarizedMethod) { + final String calleeName = callee.getReference().toString(); + if (calleeName.equals("< JavaScriptLoader, LArray, ctor()LRoot; >") || calleeName.equals("< JavaScriptLoader, LObject, ctor()LRoot; >")) { + return bc; + } + } if (receiver[0] instanceof ScopeMappingInstanceKey) { return new ScopeMappingContext(bc, (ScopeMappingInstanceKey) receiver[0]); } else { From 9e386ff3107021dad24dcfb40332869818520204 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:46:08 +0000 Subject: [PATCH 111/238] re-implement delegating context, to ensure we have a proper equals() and hashCode() git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4398 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../JavaScriptConstructorContextSelector.java | 20 +----- .../wala/ipa/callgraph/DelegatingContext.java | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+), 17 deletions(-) create mode 100644 com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java index 4384de05e..7d1740da1 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptConstructorContextSelector.java @@ -6,9 +6,8 @@ import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.Context; -import com.ibm.wala.ipa.callgraph.ContextItem; -import com.ibm.wala.ipa.callgraph.ContextKey; import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.DelegatingContext; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.cfa.nCFAContextSelector; import com.ibm.wala.util.intset.IntSet; @@ -35,22 +34,9 @@ public class JavaScriptConstructorContextSelector implements ContextSelector { final Context oneLevelContext = oneLevel.getCalleeTarget(caller, site, callee, receiver); final Context callerContext = caller.getContext(); if (callerContext instanceof ScopeMappingContext) { - return new Context() { - - @Override - public ContextItem get(ContextKey name) { - ContextItem result = callerContext.get(name); - if (result == null) { - result = oneLevelContext.get(name); - if (result == null) { - result = baseCtxt.get(name); - } - } - return result; - } - }; + return new DelegatingContext(callerContext, new DelegatingContext(oneLevelContext, baseCtxt)); } else { - // use one-level of call-string sensitivity for constructors always + // use at least one-level of call-string sensitivity for constructors always return oneLevelContext; } } else { diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java new file mode 100644 index 000000000..857c912e8 --- /dev/null +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 2007 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.ipa.callgraph; + +/** + * A context that first checks with A, then defaults to B. + */ + +public class DelegatingContext implements Context { + + private final Context A; + + private final Context B; + + public DelegatingContext(Context A, Context B) { + this.A = A; + this.B = B; + if (A == null) { + throw new IllegalArgumentException("null A"); + } + if (B == null) { + throw new IllegalArgumentException("null B"); + } + } + + public ContextItem get(ContextKey name) { + ContextItem result = A.get(name); + if (result == null) { + result = B.get(name); + } + return result; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + A.hashCode(); + result = prime * result + B.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DelegatingContext other = (DelegatingContext) obj; + if (!A.equals(other.A)) + return false; + if (!B.equals(other.B)) + return false; + return true; + } + +} From 2f86937ae18af79fc9eb77a6cc14ce471c9e675f Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:46:27 +0000 Subject: [PATCH 112/238] some more diagnostic code in TestUtil, related changes git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4399 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java | 4 ++++ .../src/com/ibm/wala/ipa/callgraph/DelegatingContext.java | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java index 41a081420..4e3423393 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ScopeMappingInstanceKeys.java @@ -136,6 +136,10 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory { public String toString() { return "SMIK:" + base + "@" + creator; } + + public InstanceKey getBase() { + return base; + } } public InstanceKey getInstanceKeyForAllocation(CGNode creatorNode, NewSiteReference allocationSite) { diff --git a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java index 857c912e8..4baff8f3c 100644 --- a/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java +++ b/com.ibm.wala.core/src/com/ibm/wala/ipa/callgraph/DelegatingContext.java @@ -64,4 +64,11 @@ public class DelegatingContext implements Context { return true; } + @Override + public String toString() { + return "DelegatingContext [A=" + A + ", B=" + B + "]"; + } + + + } From 59fae9a7e95e1e26f30f55e231f3bc126de1af26 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:46:36 +0000 Subject: [PATCH 113/238] Added very crude handling of addEventListener. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4400 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- com.ibm.wala.cast.js/dat/preamble.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/com.ibm.wala.cast.js/dat/preamble.js b/com.ibm.wala.cast.js/dat/preamble.js index a3408ac6d..b5fd30cdd 100644 --- a/com.ibm.wala.cast.js/dat/preamble.js +++ b/com.ibm.wala.cast.js/dat/preamble.js @@ -117,6 +117,9 @@ DOMNode = function DOMNode() { // An impostor for the Node class } this.childNodes.collect(predicate, result); } + this.addEventListener = function(name, fn) { + fn(); + }; } DOMDocument = function DOMDocument() { @@ -171,6 +174,9 @@ DOMWindow = function DOMWindow(){ this.open = function window_open(url, stuff) { note_url(url); }; + this.addEventListener = function(name, fn) { + fn(); + }; } DOJOObj = function DOJOObj(){ From 207d40811fd642ef0045b45be5dbcb983a629f8a Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:46:50 +0000 Subject: [PATCH 114/238] add flag to disable handling of Function.prototype.call git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4401 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 5425a7f9e..964f31eb0 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -16,6 +16,7 @@ import com.ibm.wala.ipa.callgraph.AnalysisCache; import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.ContextSelector; +import com.ibm.wala.ipa.callgraph.MethodTargetSelector; import com.ibm.wala.ipa.callgraph.impl.ContextInsensitiveSelector; import com.ibm.wala.ipa.callgraph.impl.DelegatingContextSelector; import com.ibm.wala.ipa.callgraph.propagation.SSAContextInterpreter; @@ -30,7 +31,9 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; */ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { - private static final boolean HANDLE_FUNCTION_APPLY = true; + private static final boolean HANDLE_FUNCTION_PROTOTYPE_CALL = true; + + private static final boolean HANDLE_FUNCTION_PROTOTYPE_APPLY = true; private static final boolean USE_OBJECT_SENSITIVITY = true; public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, @@ -38,15 +41,19 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { super(cha, options, cache); SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha); - if (HANDLE_FUNCTION_APPLY) { + if (HANDLE_FUNCTION_PROTOTYPE_APPLY) { contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache), contextInterpreter); } setContextInterpreter(contextInterpreter); - options.setSelector(new JavaScriptFunctionDotCallTargetSelector(new JavaScriptConstructTargetSelector(cha, options - .getMethodTargetSelector()))); - options.setSelector(new LoadFileTargetSelector(options.getMethodTargetSelector(), this)); + MethodTargetSelector targetSelector = new JavaScriptConstructTargetSelector(cha, options + .getMethodTargetSelector()); + if (HANDLE_FUNCTION_PROTOTYPE_CALL) { + targetSelector = new JavaScriptFunctionDotCallTargetSelector(targetSelector); + } + targetSelector = new LoadFileTargetSelector(targetSelector, this); + options.setSelector(targetSelector); ContextSelector def = new ContextInsensitiveSelector(); ContextSelector contextSelector = appContextSelector == null ? def : new DelegatingContextSelector(appContextSelector, def); @@ -55,7 +62,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { if (USE_OBJECT_SENSITIVITY) { contextSelector = new ObjectSensitivityContextSelector(contextSelector); } - if (HANDLE_FUNCTION_APPLY) { + if (HANDLE_FUNCTION_PROTOTYPE_APPLY) { contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); } contextSelector = new LexicalScopingResolverContexts(this, contextSelector); From a12194cc92295d65d30273cf52002ede3efd882b Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:47:09 +0000 Subject: [PATCH 115/238] fix handling of Function.prototype.apply. Disable testAjaxslt, which blows up with the fix enabled git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4402 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../js/test/TestAjaxsltCallGraphShape.java | 2 + ...ScriptFunctionApplyContextInterpreter.java | 9 +-- ...avaScriptFunctionApplyContextSelector.java | 81 +++++++++++++------ 3 files changed, 61 insertions(+), 31 deletions(-) diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java index e8ee1a420..0be47055c 100755 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java @@ -13,6 +13,7 @@ package com.ibm.wala.cast.js.test; import java.io.IOException; import java.net.URL; +import org.junit.Ignore; import org.junit.Test; import com.ibm.wala.ipa.callgraph.CallGraph; @@ -28,6 +29,7 @@ public abstract class TestAjaxsltCallGraphShape extends TestJSCallGraphShape { }; + @Ignore("handling Function.prototype.apply makes this test blow up. TODO: investigate") @Test public void testAjaxslt() throws IOException, IllegalArgumentException, CancelException { URL url = getClass().getClassLoader().getResource("ajaxslt/test/xslt.html"); CallGraph CG = Util.makeHTMLCG(url); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java index 83ac727ca..f546e51b6 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextInterpreter.java @@ -1,7 +1,7 @@ package com.ibm.wala.cast.js.ipa.callgraph; import com.ibm.wala.cast.ipa.callgraph.AstContextInsensitiveSSAContextInterpreter; -import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptFunctionApplyContextSelector.ApplyContext; +import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptFunctionApplyContextSelector.BooleanContextItem; import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummarizedFunction; import com.ibm.wala.cast.js.ipa.summaries.JavaScriptSummary; import com.ibm.wala.cast.js.loader.JSCallSiteReference; @@ -30,15 +30,14 @@ public class JavaScriptFunctionApplyContextInterpreter extends AstContextInsensi @Override public boolean understands(CGNode node) { - return node.getContext() instanceof ApplyContext; + return node.getContext().get(JavaScriptFunctionApplyContextSelector.APPLY_NON_NULL_ARGS) != null; } @Override public IR getIR(CGNode node) { assert understands(node); - ApplyContext applyContext = (ApplyContext) node.getContext(); - boolean isNonNullArray = applyContext.isNonNullArray(); - if (isNonNullArray) { + BooleanContextItem isNonNullArray = (BooleanContextItem) node.getContext().get(JavaScriptFunctionApplyContextSelector.APPLY_NON_NULL_ARGS); + if (isNonNullArray.val) { return makeIRForArgList(node); } else { return makeIRForNoArgList(node); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java index 795c9d331..a227ec194 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JavaScriptFunctionApplyContextSelector.java @@ -22,6 +22,45 @@ import com.ibm.wala.util.intset.IntSetUtil; */ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { + public static final ContextKey APPLY_NON_NULL_ARGS = new ContextKey() { + }; + + public static class BooleanContextItem implements ContextItem { + final boolean val; + + BooleanContextItem(boolean val) { + this.val = val; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (val ? 1231 : 1237); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + BooleanContextItem other = (BooleanContextItem) obj; + if (val != other.val) + return false; + return true; + } + + @Override + public String toString() { + return "BooleanContextItem [val=" + val + "]"; + } + + } + private final ContextSelector base; public JavaScriptFunctionApplyContextSelector(ContextSelector base) { @@ -42,35 +81,31 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { public static class ApplyContext implements Context { private final Context delegate; - private final CallSiteReference site; - /** * was the argsList argument a non-null Array? */ - private final boolean isNonNullArray; + private final BooleanContextItem isNonNullArray; - ApplyContext(Context delegate, CallSiteReference site, boolean isNonNullArray) { + ApplyContext(Context delegate, boolean isNonNullArray) { this.delegate = delegate; - this.site = site; - this.isNonNullArray = isNonNullArray; + this.isNonNullArray = new BooleanContextItem(isNonNullArray); } @Override public ContextItem get(ContextKey name) { - return delegate.get(name); - } - - public boolean isNonNullArray() { - return isNonNullArray; + if (APPLY_NON_NULL_ARGS.equals(name)) { + return isNonNullArray; + } else { + return delegate.get(name); + } } @Override public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + ((delegate == null) ? 0 : delegate.hashCode()); - result = prime * result + (isNonNullArray ? 1231 : 1237); - result = prime * result + ((site == null) ? 0 : site.hashCode()); + result = prime * result + delegate.hashCode(); + result = prime * result + isNonNullArray.hashCode(); return result; } @@ -83,25 +118,19 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { if (getClass() != obj.getClass()) return false; ApplyContext other = (ApplyContext) obj; - if (delegate == null) { - if (other.delegate != null) - return false; - } else if (!delegate.equals(other.delegate)) + if (!delegate.equals(other.delegate)) return false; - if (isNonNullArray != other.isNonNullArray) - return false; - if (site == null) { - if (other.site != null) - return false; - } else if (!site.equals(other.site)) + if (!isNonNullArray.equals(other.isNonNullArray)) return false; return true; } @Override public String toString() { - return "ApplyContext [delegate=" + delegate + ", site=" + site + ", isNonNullArray=" + isNonNullArray + "]"; + return "ApplyContext [delegate=" + delegate + ", isNonNullArray=" + isNonNullArray + "]"; } + + } @@ -118,7 +147,7 @@ public class JavaScriptFunctionApplyContextSelector implements ContextSelector { isNonNullArray = true; } } - return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), site, isNonNullArray); + return new ApplyContext(base.getCalleeTarget(caller, site, callee, receiver), isNonNullArray); } } return base.getCalleeTarget(caller, site, callee, receiver); From 7d6fe1d943cd0b10735b8b459e059c22cc2f2367 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:47:23 +0000 Subject: [PATCH 116/238] make field private again git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4403 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java index 25f9b5826..aaffd2866 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSSSAPropagationCallGraphBuilder.java @@ -165,7 +165,7 @@ public class JSSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraph // // /////////////////////////////////////////////////////////////////////////// - public final GlobalObjectKey globalObject = new GlobalObjectKey(cha.lookupClass(JavaScriptTypes.Object)); + private final GlobalObjectKey globalObject = new GlobalObjectKey(cha.lookupClass(JavaScriptTypes.Object)); protected ExplicitCallGraph createEmptyCallGraph(IClassHierarchy cha, AnalysisOptions options) { return new JSCallGraph(cha, options, getAnalysisCache()); From bbbc93d8c6ddee477c775713762957a56384d58e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:47:37 +0000 Subject: [PATCH 117/238] Introduced extra switch to turn off the LoadFileTargetSelector. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4404 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../js/ipa/callgraph/JSZeroOrOneXCFABuilder.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 964f31eb0..9f8ce4bf5 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -30,11 +30,13 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; * "uninteresting" types */ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { + private static final boolean SIMPLE = false; - private static final boolean HANDLE_FUNCTION_PROTOTYPE_CALL = true; + private static final boolean HANDLE_FUNCTION_PROTOTYPE_CALL = !SIMPLE && true; + private static final boolean HANDLE_FUNCTION_PROTOTYPE_APPLY = !SIMPLE && true; + private static final boolean USE_OBJECT_SENSITIVITY = !SIMPLE && true; - private static final boolean HANDLE_FUNCTION_PROTOTYPE_APPLY = true; - private static final boolean USE_OBJECT_SENSITIVITY = true; + private static final boolean USE_LOAD_FILE_TARGET_SELECTOR = false; public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { @@ -52,7 +54,9 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { if (HANDLE_FUNCTION_PROTOTYPE_CALL) { targetSelector = new JavaScriptFunctionDotCallTargetSelector(targetSelector); } - targetSelector = new LoadFileTargetSelector(targetSelector, this); + if (USE_LOAD_FILE_TARGET_SELECTOR) { + targetSelector = new LoadFileTargetSelector(targetSelector, this); + } options.setSelector(targetSelector); ContextSelector def = new ContextInsensitiveSelector(); From ea7be296c83ca06bfc8fd3dec88507128221d1c2 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:48:01 +0000 Subject: [PATCH 118/238] create JSAnalysisOptions, and use to add proper option to disable handling of call / apply git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4405 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../com/ibm/wala/cast/js/test/Util.java | 4 +-- .../js/client/JavaScriptAnalysisEngine.java | 3 +- .../js/client/impl/OneCFABuilderFactory.java | 4 +-- .../js/client/impl/ZeroCFABuilderFactory.java | 4 +-- .../js/ipa/callgraph/JSAnalysisOptions.java | 33 +++++++++++++++++++ .../ipa/callgraph/JSZeroOrOneXCFABuilder.java | 16 ++++----- .../ibm/wala/cast/js/ipa/callgraph/Util.java | 5 ++- .../source/dumpCallGraph.java | 4 +-- 8 files changed, 51 insertions(+), 22 deletions(-) create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java index 583f35e05..d33ee1f65 100755 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java @@ -21,6 +21,7 @@ import junit.framework.Assert; import com.ibm.wala.cast.js.html.MappedSourceModule; import com.ibm.wala.cast.js.html.WebPageLoaderFactory; import com.ibm.wala.cast.js.html.WebUtil; +import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder; import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder; import com.ibm.wala.cast.js.loader.JavaScriptLoader; @@ -28,7 +29,6 @@ import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory; import com.ibm.wala.classLoader.SourceFileModule; import com.ibm.wala.classLoader.SourceModule; import com.ibm.wala.ipa.callgraph.AnalysisCache; -import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.Entrypoint; @@ -116,7 +116,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { IClassHierarchy cha = makeHierarchy(scope, loaders); com.ibm.wala.cast.test.Util.checkForFrontEndErrors(cha); Iterable roots = makeScriptRoots(cha); - AnalysisOptions options = makeOptions(scope, cha, roots); + JSAnalysisOptions options = makeOptions(scope, cha, roots); AnalysisCache cache = makeCache(); JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, useOneCFA); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/JavaScriptAnalysisEngine.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/JavaScriptAnalysisEngine.java index 2b323f9a2..72259e869 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/JavaScriptAnalysisEngine.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/JavaScriptAnalysisEngine.java @@ -17,6 +17,7 @@ import java.util.jar.JarFile; import com.ibm.wala.cast.ipa.callgraph.CAstAnalysisScope; import com.ibm.wala.cast.ir.ssa.AstIRFactory; import com.ibm.wala.cast.js.client.impl.ZeroCFABuilderFactory; +import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.cast.js.ipa.callgraph.JavaScriptEntryPoints; import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory; @@ -98,6 +99,6 @@ public class JavaScriptAnalysisEngine extends AbstractAnalysisEngine { @Override protected CallGraphBuilder getCallGraphBuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache) { - return new ZeroCFABuilderFactory().make(options, cache, cha, scope, false); + return new ZeroCFABuilderFactory().make((JSAnalysisOptions) options, cache, cha, scope, false); } } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/OneCFABuilderFactory.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/OneCFABuilderFactory.java index ad6cd1259..7149e9349 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/OneCFABuilderFactory.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/OneCFABuilderFactory.java @@ -11,9 +11,9 @@ package com.ibm.wala.cast.js.client.impl; import com.ibm.wala.cast.ipa.callgraph.StandardFunctionTargetSelector; +import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder; import com.ibm.wala.ipa.callgraph.AnalysisCache; -import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.CallGraphBuilder; import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys; @@ -26,7 +26,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; */ public class OneCFABuilderFactory { - public CallGraphBuilder make(AnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, AnalysisScope scope, + public CallGraphBuilder make(JSAnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, AnalysisScope scope, boolean keepPointsTo) { com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha); options.setSelector(new StandardFunctionTargetSelector(cha, options.getMethodTargetSelector())); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/ZeroCFABuilderFactory.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/ZeroCFABuilderFactory.java index 6a4ce7a5a..43f574a4c 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/ZeroCFABuilderFactory.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/client/impl/ZeroCFABuilderFactory.java @@ -11,9 +11,9 @@ package com.ibm.wala.cast.js.client.impl; import com.ibm.wala.cast.ipa.callgraph.StandardFunctionTargetSelector; +import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder; import com.ibm.wala.ipa.callgraph.AnalysisCache; -import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.CallGraphBuilder; import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys; @@ -26,7 +26,7 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; */ public class ZeroCFABuilderFactory { - public CallGraphBuilder make(AnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, AnalysisScope scope, + public CallGraphBuilder make(JSAnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, AnalysisScope scope, boolean keepPointsTo) { com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha); options.setSelector(new StandardFunctionTargetSelector(cha, options.getMethodTargetSelector())); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java new file mode 100644 index 000000000..96e583920 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java @@ -0,0 +1,33 @@ +package com.ibm.wala.cast.js.ipa.callgraph; + +import com.ibm.wala.ipa.callgraph.AnalysisOptions; +import com.ibm.wala.ipa.callgraph.AnalysisScope; +import com.ibm.wala.ipa.callgraph.Entrypoint; + +/** + * call graph construction options specific to JavaScript. + */ +public class JSAnalysisOptions extends AnalysisOptions { + + /** + * should the analysis model the semantics of Function.prototype.call / apply? + * Defaults to true. + */ + private boolean handleCallApply = true; + + public JSAnalysisOptions(AnalysisScope scope, Iterable e) { + super(scope, e); + } + + /** + * should the analysis model the semantics of Function.prototype.call / apply? + */ + public boolean handleCallApply() { + return handleCallApply; + } + + public void setHandleCallApply(boolean handleCallApply) { + this.handleCallApply = handleCallApply; + } + +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 9f8ce4bf5..32c8376b9 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -13,7 +13,6 @@ package com.ibm.wala.cast.js.ipa.callgraph; import com.ibm.wala.cast.ipa.callgraph.LexicalScopingResolverContexts; import com.ibm.wala.cast.ipa.callgraph.ScopeMappingKeysContextSelector; import com.ibm.wala.ipa.callgraph.AnalysisCache; -import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.ContextSelector; import com.ibm.wala.ipa.callgraph.MethodTargetSelector; @@ -30,20 +29,17 @@ import com.ibm.wala.ipa.cha.IClassHierarchy; * "uninteresting" types */ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { - private static final boolean SIMPLE = false; - private static final boolean HANDLE_FUNCTION_PROTOTYPE_CALL = !SIMPLE && true; - private static final boolean HANDLE_FUNCTION_PROTOTYPE_APPLY = !SIMPLE && true; - private static final boolean USE_OBJECT_SENSITIVITY = !SIMPLE && true; + private static final boolean USE_OBJECT_SENSITIVITY = false; private static final boolean USE_LOAD_FILE_TARGET_SELECTOR = false; - public JSZeroOrOneXCFABuilder(IClassHierarchy cha, AnalysisOptions options, AnalysisCache cache, + public JSZeroOrOneXCFABuilder(IClassHierarchy cha, JSAnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { super(cha, options, cache); SSAContextInterpreter contextInterpreter = makeDefaultContextInterpreters(appContextInterpreter, options, cha); - if (HANDLE_FUNCTION_PROTOTYPE_APPLY) { + if (options.handleCallApply()) { contextInterpreter = new DelegatingSSAContextInterpreter(new JavaScriptFunctionApplyContextInterpreter(options, cache), contextInterpreter); } @@ -51,7 +47,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { MethodTargetSelector targetSelector = new JavaScriptConstructTargetSelector(cha, options .getMethodTargetSelector()); - if (HANDLE_FUNCTION_PROTOTYPE_CALL) { + if (options.handleCallApply()) { targetSelector = new JavaScriptFunctionDotCallTargetSelector(targetSelector); } if (USE_LOAD_FILE_TARGET_SELECTOR) { @@ -66,7 +62,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { if (USE_OBJECT_SENSITIVITY) { contextSelector = new ObjectSensitivityContextSelector(contextSelector); } - if (HANDLE_FUNCTION_PROTOTYPE_APPLY) { + if (options.handleCallApply()) { contextSelector = new JavaScriptFunctionApplyContextSelector(contextSelector); } contextSelector = new LexicalScopingResolverContexts(this, contextSelector); @@ -95,7 +91,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { * deployment descriptor abstraction * @return a 0-1-Opt-CFA Call Graph Builder. */ - public static JSCFABuilder make(AnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, ClassLoader cl, + public static JSCFABuilder make(JSAnalysisOptions options, AnalysisCache cache, IClassHierarchy cha, ClassLoader cl, AnalysisScope scope, String[] xmlFiles, byte instancePolicy, boolean doOneCFA) { com.ibm.wala.ipa.callgraph.impl.Util.addDefaultSelectors(options, cha); for (int i = 0; i < xmlFiles.length; i++) { diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java index 3a2b3e8d1..2899257cc 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java @@ -38,7 +38,6 @@ import com.ibm.wala.cfg.AbstractCFG; import com.ibm.wala.classLoader.ClassLoaderFactory; import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.SourceURLModule; -import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; @@ -82,8 +81,8 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util { Util.preprocessor = preprocessor; } - public static AnalysisOptions makeOptions(AnalysisScope scope, IClassHierarchy cha, Iterable roots) { - final AnalysisOptions options = new AnalysisOptions(scope, /* + public static JSAnalysisOptions makeOptions(AnalysisScope scope, IClassHierarchy cha, Iterable roots) { + final JSAnalysisOptions options = new JSAnalysisOptions(scope, /* * AstIRFactory. * makeDefaultFactory * (keepIRs), diff --git a/com.ibm.wala.cast.js/source/dumpCallGraph.java b/com.ibm.wala.cast.js/source/dumpCallGraph.java index 428cc802e..ddaf77cf9 100755 --- a/com.ibm.wala.cast.js/source/dumpCallGraph.java +++ b/com.ibm.wala.cast.js/source/dumpCallGraph.java @@ -8,13 +8,13 @@ * Contributors: * IBM Corporation - initial API and implementation *****************************************************************************/ +import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.cast.js.ipa.callgraph.JSCFABuilder; import com.ibm.wala.cast.js.ipa.callgraph.JSZeroOrOneXCFABuilder; import com.ibm.wala.cast.js.ipa.callgraph.Util; import com.ibm.wala.cast.js.loader.JavaScriptLoader; import com.ibm.wala.cast.js.loader.JavaScriptLoaderFactory; import com.ibm.wala.ipa.callgraph.AnalysisCache; -import com.ibm.wala.ipa.callgraph.AnalysisOptions; import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.Entrypoint; @@ -29,7 +29,7 @@ class dumpCallGraph { AnalysisScope scope = Util.makeScope(args, loaders, JavaScriptLoader.JS); IClassHierarchy cha = Util.makeHierarchy(scope, loaders); Iterable roots = Util.makeScriptRoots(cha); - AnalysisOptions options = Util.makeOptions(scope, cha, roots); + JSAnalysisOptions options = Util.makeOptions(scope, cha, roots); AnalysisCache cache = Util.makeCache(); JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, false); From 1f5c0996e5031b95f3d079308c36093e61177723 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:48:14 +0000 Subject: [PATCH 119/238] re-enable ajaxslt test with call / apply handling disabled git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4406 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java index 0be47055c..00f9c2f09 100755 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java @@ -16,7 +16,9 @@ import java.net.URL; import org.junit.Ignore; import org.junit.Test; +import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.ipa.callgraph.CallGraph; +import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; import com.ibm.wala.util.CancelException; public abstract class TestAjaxsltCallGraphShape extends TestJSCallGraphShape { @@ -29,10 +31,11 @@ public abstract class TestAjaxsltCallGraphShape extends TestJSCallGraphShape { }; - @Ignore("handling Function.prototype.apply makes this test blow up. TODO: investigate") @Test public void testAjaxslt() throws IOException, IllegalArgumentException, CancelException { URL url = getClass().getClassLoader().getResource("ajaxslt/test/xslt.html"); - CallGraph CG = Util.makeHTMLCG(url); + PropagationCallGraphBuilder b = Util.makeHTMLCGBuilder(url); + ((JSAnalysisOptions) b.getOptions()).setHandleCallApply(false); + CallGraph CG = b.makeCallGraph(b.getOptions()); verifyGraphAssertions(CG, assertionsForAjaxslt); } From da746ac8a45ad4d97391d193afbbf5624bc8bf89 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:48:28 +0000 Subject: [PATCH 120/238] add disabling of load target selector to options git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4407 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../wala/cast/js/ipa/callgraph/JSAnalysisOptions.java | 9 +++++++++ .../cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java | 3 +-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java index 96e583920..03f922bd7 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSAnalysisOptions.java @@ -14,6 +14,8 @@ public class JSAnalysisOptions extends AnalysisOptions { * Defaults to true. */ private boolean handleCallApply = true; + + private boolean useLoadFileTargetSelector = true; public JSAnalysisOptions(AnalysisScope scope, Iterable e) { super(scope, e); @@ -30,4 +32,11 @@ public class JSAnalysisOptions extends AnalysisOptions { this.handleCallApply = handleCallApply; } + public boolean useLoadFileTargetSelector() { + return useLoadFileTargetSelector; + } + + public void setUseLoadFileTargetSelector(boolean useIt) { + this.useLoadFileTargetSelector = useIt; + } } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java index 32c8376b9..bf645e833 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/JSZeroOrOneXCFABuilder.java @@ -32,7 +32,6 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { private static final boolean USE_OBJECT_SENSITIVITY = false; - private static final boolean USE_LOAD_FILE_TARGET_SELECTOR = false; public JSZeroOrOneXCFABuilder(IClassHierarchy cha, JSAnalysisOptions options, AnalysisCache cache, ContextSelector appContextSelector, SSAContextInterpreter appContextInterpreter, int instancePolicy, boolean doOneCFA) { @@ -50,7 +49,7 @@ public class JSZeroOrOneXCFABuilder extends JSCFABuilder { if (options.handleCallApply()) { targetSelector = new JavaScriptFunctionDotCallTargetSelector(targetSelector); } - if (USE_LOAD_FILE_TARGET_SELECTOR) { + if (options.useLoadFileTargetSelector()) { targetSelector = new LoadFileTargetSelector(targetSelector, this); } options.setSelector(targetSelector); From c18cc405f7728061ef60eda40cd61947f5eab842 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:48:53 +0000 Subject: [PATCH 121/238] fix disabling of call / apply for ajaxslt test git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4408 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/js/vis/JsViewerDriver.java | 2 +- .../js/test/TestAjaxsltCallGraphShape.java | 9 +++---- .../com/ibm/wala/cast/js/test/Util.java | 26 ++++++++++++------- .../ibm/wala/cast/js/ipa/callgraph/Util.java | 4 +-- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java index 58d527391..64ecc1daa 100644 --- a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/vis/JsViewerDriver.java @@ -40,7 +40,7 @@ public class JsViewerDriver extends Util { SourceModule[] sources = getSources(domless, url); - JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false); + JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory), sources, false, true); builder.setBaseURL(url); CallGraph cg = builder.makeCallGraph(builder.getOptions()); diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java index 00f9c2f09..6d76fae3c 100755 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestAjaxsltCallGraphShape.java @@ -13,12 +13,9 @@ package com.ibm.wala.cast.js.test; import java.io.IOException; import java.net.URL; -import org.junit.Ignore; import org.junit.Test; -import com.ibm.wala.cast.js.ipa.callgraph.JSAnalysisOptions; import com.ibm.wala.ipa.callgraph.CallGraph; -import com.ibm.wala.ipa.callgraph.propagation.PropagationCallGraphBuilder; import com.ibm.wala.util.CancelException; public abstract class TestAjaxsltCallGraphShape extends TestJSCallGraphShape { @@ -33,9 +30,9 @@ public abstract class TestAjaxsltCallGraphShape extends TestJSCallGraphShape { @Test public void testAjaxslt() throws IOException, IllegalArgumentException, CancelException { URL url = getClass().getClassLoader().getResource("ajaxslt/test/xslt.html"); - PropagationCallGraphBuilder b = Util.makeHTMLCGBuilder(url); - ((JSAnalysisOptions) b.getOptions()).setHandleCallApply(false); - CallGraph CG = b.makeCallGraph(b.getOptions()); + // don't handle call / apply; it makes things blow up + CallGraph CG = Util.makeHTMLCG(url, false); + verifyGraphAssertions(CG, assertionsForAjaxslt); } diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java index d33ee1f65..5793e3fcf 100755 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java @@ -37,8 +37,10 @@ import com.ibm.wala.ipa.callgraph.propagation.cfa.ZeroXInstanceKeys; import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.util.CancelException; -import com.ibm.wala.util.MonitorUtil.IProgressMonitor; +/** + * TODO this class is a mess. rewrite. + */ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { public static JSCFABuilder makeScriptCGBuilder(String dir, String name, boolean useOneCFA) throws IOException { @@ -57,7 +59,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { scope = makeScope(new SourceFileModule[] { makeSourceModule(script, dir, name) }, loaders, JavaScriptLoader.JS); } - return makeCG(loaders, scope, useOneCFA); + return makeCG(loaders, scope, useOneCFA, true); } public static JSCFABuilder makeScriptCGBuilder(String dir, String name) throws IOException { @@ -78,16 +80,19 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { public static CallGraph makeScriptCG(SourceModule[] scripts, boolean useOneCFA) throws IOException, IllegalArgumentException, CancelException { - PropagationCallGraphBuilder b = makeCGBuilder(makeLoaders(), scripts, useOneCFA); + PropagationCallGraphBuilder b = makeCGBuilder(makeLoaders(), scripts, useOneCFA, true); CallGraph CG = b.makeCallGraph(b.getOptions()); dumpCG(b.getPointerAnalysis(), CG); return CG; } public static JSCFABuilder makeHTMLCGBuilder(URL url) throws IOException { + return makeHTMLCGBuilder(url, true); + } + public static JSCFABuilder makeHTMLCGBuilder(URL url, boolean handleCallApply) throws IOException { JavaScriptLoader.addBootstrapFile(WebUtil.preamble); Set script = WebUtil.extractScriptFromHTML(url); - JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory, preprocessor), script.toArray(new SourceModule[script.size()]), false); + JSCFABuilder builder = makeCGBuilder(new WebPageLoaderFactory(translatorFactory, preprocessor), script.toArray(new SourceModule[script.size()]), false, handleCallApply); builder.setBaseURL(url); return builder; } @@ -99,24 +104,25 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { return CG; } - public static CallGraph makeHTMLCG(URL url, IProgressMonitor monitor) throws IOException, IllegalArgumentException, + public static CallGraph makeHTMLCG(URL url, boolean handleCallApply) throws IOException, IllegalArgumentException, CancelException { - PropagationCallGraphBuilder b = makeHTMLCGBuilder(url); - CallGraph CG = b.makeCallGraph(b.getOptions(), monitor); + PropagationCallGraphBuilder b = makeHTMLCGBuilder(url, handleCallApply); + CallGraph CG = b.makeCallGraph(b.getOptions()); return CG; } - public static JSCFABuilder makeCGBuilder(JavaScriptLoaderFactory loaders, SourceModule[] scripts, boolean useOneCFA) throws IOException { + public static JSCFABuilder makeCGBuilder(JavaScriptLoaderFactory loaders, SourceModule[] scripts, boolean useOneCFA, boolean handleCallApply) throws IOException { AnalysisScope scope = makeScope(scripts, loaders, JavaScriptLoader.JS); - return makeCG(loaders, scope, useOneCFA); + return makeCG(loaders, scope, useOneCFA, handleCallApply); } - protected static JSCFABuilder makeCG(JavaScriptLoaderFactory loaders, AnalysisScope scope, boolean useOneCFA) throws IOException { + protected static JSCFABuilder makeCG(JavaScriptLoaderFactory loaders, AnalysisScope scope, boolean useOneCFA, boolean handleCallApply) throws IOException { try { IClassHierarchy cha = makeHierarchy(scope, loaders); com.ibm.wala.cast.test.Util.checkForFrontEndErrors(cha); Iterable roots = makeScriptRoots(cha); JSAnalysisOptions options = makeOptions(scope, cha, roots); + options.setHandleCallApply(handleCallApply); AnalysisCache cache = makeCache(); JSCFABuilder builder = new JSZeroOrOneXCFABuilder(cha, options, cache, null, null, ZeroXInstanceKeys.ALLOCATIONS, useOneCFA); diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java index 2899257cc..01f30ad86 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/Util.java @@ -58,12 +58,12 @@ public class Util extends com.ibm.wala.cast.ipa.callgraph.Util { * the translator factory to be used for analysis TODO: pass the factory where * needed instead of using a global? */ - protected static JavaScriptTranslatorFactory translatorFactory; + public static JavaScriptTranslatorFactory translatorFactory; /** * preprocessor to run generated CAst trees through, null if none */ - protected static CAstRewriterFactory preprocessor; + public static CAstRewriterFactory preprocessor; /** * Set up the translator factory. This method should be called before invoking From 30dbcd1e0b04f4bf8cb38baad56d6522f5786aaa Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:49:08 +0000 Subject: [PATCH 122/238] ForInContextSelector can now be parameterised on the argument index on which to specialise. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4409 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ipa/callgraph/ForInContextSelector.java | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index ef4a60d06..b30692f90 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -14,6 +14,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import com.ibm.wala.analysis.reflection.IllegalArgumentExceptionContext; import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; import com.ibm.wala.cast.ir.ssa.AstIRFactory; import com.ibm.wala.cast.ir.ssa.AstIsDefinedInstruction; @@ -51,13 +52,9 @@ import com.ibm.wala.util.intset.MutableIntSet; public class ForInContextSelector implements ContextSelector { - public final static ContextKey FORIN_KEY = new ContextKey() { - - }; + public final static ContextKey FORIN_KEY = new ContextKey() { }; - public static final ContextItem FORIN_MARKER = new ContextItem() { - - }; + public static final ContextItem FORIN_MARKER = new ContextItem() { }; public static final String HACK_METHOD_STR = "_forin_body"; @@ -121,10 +118,10 @@ public class ForInContextSelector implements ContextSelector { } - public static class ForInContext extends SelectiveCPAContext { + public class ForInContext extends SelectiveCPAContext { ForInContext(Context base, InstanceKey obj) { - super(base, Collections.singletonMap(ContextKey.PARAMETERS[2], obj)); + super(base, Collections.singletonMap(ContextKey.PARAMETERS[index], obj)); } public ContextItem get(ContextKey key) { @@ -137,14 +134,14 @@ public class ForInContextSelector implements ContextSelector { @Override public String toString() { - return "for in hack filter for " + get(ContextKey.PARAMETERS[2]) + " over " + this.base; + return "for in hack filter for " + get(ContextKey.PARAMETERS[index]) + " over " + this.base; } } private final ContextSelector base; - private final ContextSelector oneLevel; + private final int index; private void collectValues(DefUse du, SSAInstruction inst, MutableIntSet values) { if (inst instanceof SSAGetInstruction) { @@ -180,6 +177,11 @@ public class ForInContextSelector implements ContextSelector { } public ForInContextSelector(ContextSelector base) { + this(2, base); + } + + public ForInContextSelector(int index, ContextSelector base) { + this.index = index; this.base = base; this.oneLevel = new OneLevelSiteContextSelector(base); } @@ -188,10 +190,10 @@ public class ForInContextSelector implements ContextSelector { public static final HashMap du_cache = HashMapFactory.make(); public static final IRFactory factory = AstIRFactory.makeDefaultFactory(); - // determine whether the method performs a for-in loop over the properties of its first argument + // determine whether the method performs a for-in loop over the properties of its index'th argument private boolean forInOnFirstArg(IMethod method) { MethodReference mref = method.getReference(); - if(method.getNumberOfParameters() < 2) + if(method.getNumberOfParameters() < index) return false; Boolean b = forInOnFirstArg_cache.get(mref); if(b != null) @@ -223,7 +225,7 @@ public class ForInContextSelector implements ContextSelector { // determine whether the method never/sometimes/always uses its first argument as a property name private Frequency usesFirstArgAsPropertyName(IMethod method) { MethodReference mref = method.getReference(); - if(method.getNumberOfParameters() < 2) + if(method.getNumberOfParameters() < index) return Frequency.NEVER; Frequency f = usesFirstArgAsPropertyName_cache.get(mref); if(f != null) @@ -259,19 +261,22 @@ public class ForInContextSelector implements ContextSelector { // simulate effect of ToString conversion on key private InstanceKey simulateToString(IClassHierarchy cha, InstanceKey key) { IClass stringClass = cha.lookupClass(JavaScriptTypes.String); + IClass numberClass = cha.lookupClass(JavaScriptTypes.Number); if(key instanceof ConstantKey) { Object value = ((ConstantKey)key).getValue(); if(value instanceof String) { return key; } else if(value instanceof Number) { - Integer ival = ((Number)value).intValue(); - return new ConstantKey(ival.toString(), stringClass); + Double dval = ((Number)value).doubleValue(); + return new ConstantKey(dval, numberClass); } else if(value instanceof Boolean) { Boolean bval = (Boolean)value; return new ConstantKey(bval.toString(), stringClass); } else if(value == null) { return new ConstantKey("null", stringClass); } + } else if(key != null && key.getConcreteType() == numberClass) { + return key; } return new ConcreteTypeKey(stringClass); } @@ -281,16 +286,20 @@ public class ForInContextSelector implements ContextSelector { String calleeFullName = callee.getDeclaringClass().getName().toString(); String calleeShortName = calleeFullName.substring(calleeFullName.lastIndexOf('/')+1); if(USE_NAME_TO_SELECT_CONTEXT) { - if(calleeShortName.contains(HACK_METHOD_STR) && receiver.length > 2) { + if(calleeShortName.contains(HACK_METHOD_STR) && receiver.length > index) { // we assume that the argument is only used as a property name, so we can do ToString - return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); + return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index])); } - } else if(receiver.length > 2) { + } else if(receiver.length > index) { + // TODO: figure out why this happens sometimes and what to do about it; for now we just assume it's due to call graph + // imprecision and prune + if(receiver[index] == null) + return new IllegalArgumentExceptionContext(); Frequency f = usesFirstArgAsPropertyName(callee); if(f == Frequency.ALWAYS) { - return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[2])); - } else if(receiver[2] != null && (f == Frequency.SOMETIMES || forInOnFirstArg(callee))) { - return new ForInContext(baseContext, receiver[2]); + return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index])); + } else if(f == Frequency.SOMETIMES || forInOnFirstArg(callee)) { + return new ForInContext(baseContext, receiver[index]); } } if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { @@ -308,8 +317,8 @@ public class ForInContextSelector implements ContextSelector { public IntSet getRelevantParameters(CGNode caller, CallSiteReference site) { if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { return identifyDependentParameters(caller, site); - } else if (caller.getIR().getCalls(site)[0].getNumberOfUses() > 2) { - return IntSetUtil.make(new int[]{2}).union(base.getRelevantParameters(caller, site)); + } else if (caller.getIR().getCalls(site)[0].getNumberOfUses() > index) { + return IntSetUtil.make(new int[]{index}).union(base.getRelevantParameters(caller, site)); } else { return base.getRelevantParameters(caller, site); } From d33880c5ce398ba7bba135c4de3ddc0079af44ad Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:49:19 +0000 Subject: [PATCH 123/238] Storing more position information. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4410 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../mozilla/javascript/RhinoToAstTranslator.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java index 16feff72b..beb096460 100755 --- a/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/org/mozilla/javascript/RhinoToAstTranslator.java @@ -686,9 +686,12 @@ public class RhinoToAstTranslator { private final CAstControlFlowMap map; private final CAstSourcePositionMap pos; + + private final Position mypos; ScriptOrFnEntity(ScriptOrFnNode n, Map> subs, CAstNode ast, CAstControlFlowMap map, CAstSourcePositionMap pos) { + mypos = makePosition(n); if (n instanceof FunctionNode) { String x = ((FunctionNode) n).getFunctionName(); if (x == null || "".equals(x)) { @@ -773,7 +776,7 @@ public class RhinoToAstTranslator { } public CAstSourcePositionMap.Position getPosition() { - return null; + return mypos; } public CAstNodeTypeMap getNodeTypeMap() { @@ -859,10 +862,18 @@ public class RhinoToAstTranslator { private CAstNode noteSourcePosition(WalkContext context, CAstNode n, Node p) { if (p.getLineno() != -1 && context.pos().getPosition(n) == null) { - context.pos().setPosition(n, makePosition(p)); + propagateSourcePosition(n, p, context.pos()); } return n; } + + private void propagateSourcePosition(CAstNode n, Node p, CAstSourcePositionRecorder poss) { + if(poss.getPosition(n) == null) { + poss.setPosition(n, makePosition(p)); + for(int i=0;i Date: Fri, 6 Jan 2012 21:49:48 +0000 Subject: [PATCH 124/238] Extraction of correlated read/write pairs needs to be done _before_ property read expansion. Extended TranslatorToCAst to support this. Various other changes to make it possible to plug in the correlated pair extractor. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4411 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../js/translator/CAstRhinoTranslator.java | 38 ++++++++++++++----- .../ipa/callgraph/ForInContextSelector.java | 4 +- .../wala/cast/js/loader/JavaScriptLoader.java | 20 +++------- .../cast/ir/translator/TranslatorToCAst.java | 4 ++ 4 files changed, 40 insertions(+), 26 deletions(-) diff --git a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java index 6bb9d1d18..c919a4e7c 100644 --- a/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java +++ b/com.ibm.wala.cast.js.rhino/source/com/ibm/wala/cast/js/translator/CAstRhinoTranslator.java @@ -11,22 +11,42 @@ package com.ibm.wala.cast.js.translator; import java.io.IOException; +import java.util.LinkedList; +import java.util.List; import org.mozilla.javascript.RhinoToAstTranslator; import com.ibm.wala.cast.ir.translator.TranslatorToCAst; +import com.ibm.wala.cast.js.translator.PropertyReadExpander.ExpanderKey; +import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.impl.CAstImpl; +import com.ibm.wala.cast.tree.impl.CAstRewriter; +import com.ibm.wala.cast.tree.impl.CAstRewriter.CopyKey; +import com.ibm.wala.cast.tree.impl.CAstRewriter.RewriteContext; +import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.classLoader.SourceFileModule; import com.ibm.wala.classLoader.SourceModule; public class CAstRhinoTranslator implements TranslatorToCAst { - + private final List rewriters = new LinkedList(); private final SourceModule M; - - public CAstRhinoTranslator(SourceModule M) { + + public CAstRhinoTranslator(SourceModule M) { this.M = M; - } + this.addRewriter(new CAstRewriterFactory() { + public CAstRewriter createCAstRewriter(CAst ast) { + return new PropertyReadExpander(ast); + } + }, true); + } + + public , K extends CopyKey> void addRewriter(CAstRewriterFactory factory, boolean prepend) { + if(prepend) + rewriters.add(0, factory); + else + rewriters.add(factory); + } public CAstEntity translateToCAst() throws IOException { String N; @@ -37,9 +57,9 @@ public class CAstRhinoTranslator implements TranslatorToCAst { } CAstImpl Ast = new CAstImpl(); - - return - new PropertyReadExpander(Ast).rewrite( - new RhinoToAstTranslator(Ast, M, N).translate()); - } + CAstEntity entity = new RhinoToAstTranslator(Ast, M, N).translate(); + for(CAstRewriterFactory rwf : rewriters) + entity = rwf.createCAstRewriter(Ast).rewrite(entity); + return entity; + } } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index b30692f90..38783d860 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -275,9 +275,9 @@ public class ForInContextSelector implements ContextSelector { } else if(value == null) { return new ConstantKey("null", stringClass); } - } else if(key != null && key.getConcreteType() == numberClass) { + } /*else if(key != null && key.getConcreteType() == numberClass) { return key; - } + }*/ return new ConcreteTypeKey(stringClass); } diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java index 98eed7c68..88f7ff997 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/loader/JavaScriptLoader.java @@ -10,7 +10,6 @@ *****************************************************************************/ package com.ibm.wala.cast.js.loader; -import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Collection; import java.util.Collections; @@ -58,7 +57,6 @@ import com.ibm.wala.cast.tree.CAst; import com.ibm.wala.cast.tree.CAstEntity; import com.ibm.wala.cast.tree.CAstQualifier; import com.ibm.wala.cast.tree.CAstSourcePositionMap; -import com.ibm.wala.cast.tree.impl.CAstRewriter; import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; import com.ibm.wala.cast.types.AstMethodReference; import com.ibm.wala.cfg.AbstractCFG; @@ -868,21 +866,13 @@ public class JavaScriptLoader extends CAstAbstractModuleLoader { super.init(all); } + @SuppressWarnings("unchecked") @Override protected TranslatorToCAst getTranslatorToCAst(final CAst ast, SourceModule module) { - final TranslatorToCAst baseTranslator = translatorFactory.make(ast, module); - return new TranslatorToCAst() { - - @Override - public CAstEntity translateToCAst() throws IOException { - CAstEntity e = baseTranslator.translateToCAst(); - if(preprocessor != null) { - CAstRewriter rewriter = preprocessor.createCAstRewriter(ast); - e = rewriter.rewrite(e); - } - return e; - } - }; + TranslatorToCAst translator = translatorFactory.make(ast, module); + if(preprocessor != null) + translator.addRewriter(preprocessor, true); + return translator; } @Override diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java index 8330c37d1..f9fce498b 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/TranslatorToCAst.java @@ -3,8 +3,12 @@ package com.ibm.wala.cast.ir.translator; import java.io.IOException; import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.impl.CAstRewriter.CopyKey; +import com.ibm.wala.cast.tree.impl.CAstRewriter.RewriteContext; +import com.ibm.wala.cast.tree.impl.CAstRewriterFactory; public interface TranslatorToCAst { + public , K extends CopyKey> void addRewriter(CAstRewriterFactory factory, boolean prepend); public CAstEntity translateToCAst() throws IOException; From b9ff3d0857e9e8a922e8d552c8da8de3bd7e2d4d Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:50:08 +0000 Subject: [PATCH 125/238] Removed bailout on null argument, which breaks jQuery tests. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4412 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../wala/cast/js/ipa/callgraph/ForInContextSelector.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 38783d860..180c8cec7 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -291,14 +291,13 @@ public class ForInContextSelector implements ContextSelector { return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index])); } } else if(receiver.length > index) { - // TODO: figure out why this happens sometimes and what to do about it; for now we just assume it's due to call graph - // imprecision and prune - if(receiver[index] == null) - return new IllegalArgumentExceptionContext(); + // TODO: figure out why we sometimes get receiver[index] == null, and what to do about it; + // we used to assume that this is due to call graph imprecision and return an IllegalArgumentExceptionContext + // to prune this CG edge away, but that led to ArrayIndexOutOfBoundBoundsExceptions on the jquery tests Frequency f = usesFirstArgAsPropertyName(callee); if(f == Frequency.ALWAYS) { return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index])); - } else if(f == Frequency.SOMETIMES || forInOnFirstArg(callee)) { + } else if(receiver[index] != null && (f == Frequency.SOMETIMES || forInOnFirstArg(callee))) { return new ForInContext(baseContext, receiver[index]); } } From 44426834214bc9acc328854023ea860625fda550 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:50:22 +0000 Subject: [PATCH 126/238] Better fix for the issue with null instance keys in the ForInContextSelector: turn them into ConcreteTypeKeys for LUndefined. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4413 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../cast/js/ipa/callgraph/ForInContextSelector.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java index 180c8cec7..f6a9976d3 100755 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ForInContextSelector.java @@ -291,14 +291,16 @@ public class ForInContextSelector implements ContextSelector { return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index])); } } else if(receiver.length > index) { - // TODO: figure out why we sometimes get receiver[index] == null, and what to do about it; - // we used to assume that this is due to call graph imprecision and return an IllegalArgumentExceptionContext - // to prune this CG edge away, but that led to ArrayIndexOutOfBoundBoundsExceptions on the jquery tests Frequency f = usesFirstArgAsPropertyName(callee); if(f == Frequency.ALWAYS) { return new ForInContext(baseContext, simulateToString(caller.getClassHierarchy(), receiver[index])); - } else if(receiver[index] != null && (f == Frequency.SOMETIMES || forInOnFirstArg(callee))) { - return new ForInContext(baseContext, receiver[index]); + } else if(f == Frequency.SOMETIMES || forInOnFirstArg(callee)) { + if(receiver[index] == null) { + IClass undef = caller.getClassHierarchy().lookupClass(JavaScriptTypes.Undefined); + return new ForInContext(baseContext, new ConcreteTypeKey(undef)); + } else { + return new ForInContext(baseContext, receiver[index]); + } } } if (USE_CPA_IN_BODIES && FORIN_MARKER.equals(caller.getContext().get(FORIN_KEY))) { From 533344e43fc23dc1d5ec6c5ee57d309e1c196304 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:50:36 +0000 Subject: [PATCH 127/238] Amended toString of ReflectedFieldPointerKeys to also print information about the container object. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4414 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../ibm/wala/cast/ipa/callgraph/ReflectedFieldPointerKey.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ReflectedFieldPointerKey.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ReflectedFieldPointerKey.java index a770f2986..bfb1631c8 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ReflectedFieldPointerKey.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ipa/callgraph/ReflectedFieldPointerKey.java @@ -43,7 +43,7 @@ public abstract class ReflectedFieldPointerKey extends AbstractFieldPointerKey { return getFieldIdentifier().hashCode() ^ getInstanceKey().hashCode(); } - public String toString() { return "field:" + getFieldIdentifier(); } + public String toString() { return "[" + getInstanceKey() + "; " + getFieldIdentifier() + "]"; } public static ReflectedFieldPointerKey literal(final String lit, InstanceKey instance) { return new ReflectedFieldPointerKey(instance) { From c8c12436a70fc5be30331234b103b1fe4a2e2001 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:50:52 +0000 Subject: [PATCH 128/238] Added test exposing a weird IR generation bug. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4415 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/lexical_broken.js | 12 ++++++++++++ .../wala/cast/js/test/TestSimpleCallGraphShape.java | 12 ++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/lexical_broken.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/lexical_broken.js b/com.ibm.wala.cast.js.test/examples-src/tests/lexical_broken.js new file mode 100644 index 000000000..9d6c01a72 --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/lexical_broken.js @@ -0,0 +1,12 @@ +var o = { h: function() {} }; + +function f(g) { + g(); + o.h(function() { + g; + }); +} + +function g() {} + +f(g); \ 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 73c6fc4d2..eb13ef322 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 @@ -471,6 +471,18 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { verifyGraphAssertions(CG, assertionsForFunctionIsAFunction); } + private static final Object[][] assertionsForLexicalBroken = new Object[][] { + new Object[] { ROOT, new String[] { "tests/lexical_broken.js" } }, + new Object[] { "suffix:lexical_broken.js", new String[] { "suffix:f" } }, + new Object[] { "suffix:f", new String[] { "suffix:g" } } + }; + + @Test + public void testLexicalBroken() throws IOException, IllegalArgumentException, CancelException { + CallGraph CG = Util.makeScriptCG("tests", "lexical_broken.js"); + verifyGraphAssertions(CG, assertionsForLexicalBroken); + } + protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. From aa5cf116beb16cf10889364bad6d985dbb857d5f Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:51:11 +0000 Subject: [PATCH 129/238] Bug fix for lexical_broken.js git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4416 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../wala/cast/ir/translator/AstTranslator.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java index 7c663eaa5..8858d644e 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/ir/translator/AstTranslator.java @@ -336,11 +336,13 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle final int vn = curSymbol.valueNumber(); final Access A = new Access(name, entityName, vn); final CAstEntity entity = curScope.getEntity(); - addExposedName(entity, E, name, vn, isWrite); - // record the access; later, the Accesses in the instruction - // defining vn will be adjusted based on this information; see - // patchLexicalAccesses() - addAccess(entity, A); + if (entity != definingScope.getEntity()) { + addExposedName(entity, E, name, vn, isWrite); + // record the access; later, the Accesses in the instruction + // defining vn will be adjusted based on this information; see + // patchLexicalAccesses() + addAccess(entity, A); + } curScope = curScope.getParent(); } } @@ -1514,7 +1516,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle if (isGlobal(s)) return false; else - return ((AbstractScope) s.getDefiningScope()).getEntityScope() != this; + return ((AbstractScope) s.getDefiningScope()).getEntity() != getEntity(); } public CAstEntity getEntity() { @@ -1601,7 +1603,7 @@ public abstract class AstTranslator extends CAstVisitor implements ArrayOpHandle if (isGlobal(s)) return false; else - return ((AbstractScope) s.getDefiningScope()).getEntityScope() != this; + return ((AbstractScope) s.getDefiningScope()).getEntity() != getEntity(); } public CAstEntity getEntity() { From a2c146b2d8db94d2d38ad8f4c416644eaf7d6858 Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:51:26 +0000 Subject: [PATCH 130/238] New failing test case dead_phi git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4417 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../examples-src/tests/dead_phi.js | 12 ++++++++++++ .../wala/cast/js/test/TestSimpleCallGraphShape.java | 5 +++++ 2 files changed, 17 insertions(+) create mode 100644 com.ibm.wala.cast.js.test/examples-src/tests/dead_phi.js diff --git a/com.ibm.wala.cast.js.test/examples-src/tests/dead_phi.js b/com.ibm.wala.cast.js.test/examples-src/tests/dead_phi.js new file mode 100644 index 000000000..6b4d4112c --- /dev/null +++ b/com.ibm.wala.cast.js.test/examples-src/tests/dead_phi.js @@ -0,0 +1,12 @@ +var x; + +function f() { + do { + if (f()) { + x++; + break; + } + } while (false); +} + +f(); \ 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 eb13ef322..0e24d586e 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 @@ -483,6 +483,11 @@ public abstract class TestSimpleCallGraphShape extends TestJSCallGraphShape { verifyGraphAssertions(CG, assertionsForLexicalBroken); } + @Test + public void testDeadPhi() throws IllegalArgumentException, IOException, CancelException { + Util.makeScriptCG("tests", "dead_phi.js"); + } + protected IVector>> computeIkIdToVns(PointerAnalysis pa) { // Created by reversing the points to mapping for local pointer keys. From 8b547b4812e080de1778e33fef838e927990c28e Mon Sep 17 00:00:00 2001 From: msridhar1 Date: Fri, 6 Jan 2012 21:52:26 +0000 Subject: [PATCH 131/238] Split up ForInLoopRewriter in preparation for merging changes back into open-source WALA. The extraction code is now in com.ibm.wala.cast.js, with some more general stuff moved to com.ibm.wala.cast and com.ibm.wala.util. The tests are in com.ibm.wala.cast.js.test and com.ibm.wala.cast.js.rhino.test. ForInLoopRewriter itself only contains the framework specific tests and the copies of the frameworks themselves. git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4418 f5eafffb-2e1d-0410-98e4-8ec43c5233c4 --- .../TestCorrelatedPairExtractionRhino.java | 34 + .../js/test/TestForInBodyExtractionRhino.java | 29 + .../META-INF/MANIFEST.MF | 3 +- .../com/ibm/wala/cast/js/test/CAstDumper.java | 162 ++++ .../js/test/TestCorrelatedPairExtraction.java | 485 +++++++++++ .../cast/js/test/TestForInBodyExtraction.java | 762 ++++++++++++++++++ .../com/ibm/wala/cast/js/test/Util.java | 2 +- com.ibm.wala.cast.js/META-INF/MANIFEST.MF | 3 + .../callgraph/correlations/Correlation.java | 38 + .../correlations/CorrelationFinder.java | 272 +++++++ .../correlations/CorrelationSummary.java | 59 ++ .../correlations/CorrelationVisitor.java | 24 + .../correlations/EscapeCorrelation.java | 60 ++ .../correlations/ReadWriteCorrelation.java | 54 ++ .../correlations/SSASourcePositionMap.java | 37 + .../extraction/CAstRewriterExt.java | 245 ++++++ .../correlations/extraction/ChildPos.java | 92 +++ .../extraction/ClosureExtractor.java | 727 +++++++++++++++++ .../CorrelatedPairExtractionPolicy.java | 258 ++++++ .../CorrelatedPairExtractorFactory.java | 52 ++ .../extraction/ExtractedFunction.java | 183 +++++ .../extraction/ExtractionPolicy.java | 26 + .../extraction/ExtractionPolicyFactory.java | 18 + .../extraction/ExtractionPos.java | 216 +++++ .../extraction/ExtractionRegion.java | 52 ++ .../extraction/ForInBodyExtractionPolicy.java | 71 ++ .../correlations/extraction/NodeLabeller.java | 58 ++ .../correlations/extraction/NodePos.java | 51 ++ .../correlations/extraction/PosSwitch.java | 18 + .../correlations/extraction/RootPos.java | 29 + .../extraction/TwoLevelExtractionRegion.java | 32 + .../com/ibm/wala/cast/js/util/Util.java | 41 + com.ibm.wala.cast/META-INF/MANIFEST.MF | 1 + .../ibm/wala/cast/tree/pattern/AnyNode.java | 26 + .../wala/cast/tree/pattern/NodeOfKind.java | 45 ++ .../wala/cast/tree/pattern/NodePattern.java | 24 + .../wala/cast/tree/pattern/SomeConstant.java | 40 + .../wala/cast/tree/pattern/SubtreeOfKind.java | 31 + .../src/com/ibm/wala/util/io/FileUtil.java | 12 + 39 files changed, 4370 insertions(+), 2 deletions(-) create mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java create mode 100644 com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java create mode 100644 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/CAstDumper.java create mode 100644 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtraction.java create mode 100644 com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtraction.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/Correlation.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationFinder.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationSummary.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationVisitor.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/EscapeCorrelation.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/ReadWriteCorrelation.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/SSASourcePositionMap.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/CAstRewriterExt.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ChildPos.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ClosureExtractor.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/CorrelatedPairExtractionPolicy.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/CorrelatedPairExtractorFactory.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ExtractedFunction.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ExtractionPolicy.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ExtractionPolicyFactory.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ExtractionPos.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ExtractionRegion.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ForInBodyExtractionPolicy.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/NodeLabeller.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/NodePos.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/PosSwitch.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/RootPos.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/TwoLevelExtractionRegion.java create mode 100644 com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/util/Util.java create mode 100644 com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/pattern/AnyNode.java create mode 100644 com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/pattern/NodeOfKind.java create mode 100644 com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/pattern/NodePattern.java create mode 100644 com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/pattern/SomeConstant.java create mode 100644 com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/pattern/SubtreeOfKind.java diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java new file mode 100644 index 000000000..9c79a5a7e --- /dev/null +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestCorrelatedPairExtractionRhino.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.test; + +import java.io.IOException; + +import com.ibm.wala.cast.js.ipa.callgraph.correlations.CorrelationFinder; +import com.ibm.wala.cast.js.translator.CAstRhinoTranslatorFactory; +import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.impl.CAstImpl; +import com.ibm.wala.classLoader.SourceModule; +import org.mozilla.javascript.RhinoToAstTranslator; + +public class TestCorrelatedPairExtractionRhino extends TestCorrelatedPairExtraction { + protected CorrelationFinder makeCorrelationFinder() { + return new CorrelationFinder(new CAstRhinoTranslatorFactory()); + } + + protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { + RhinoToAstTranslator.resetGensymCounters(); + RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); + CAstEntity entity = translator.translate(); + return entity; + } +} diff --git a/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java new file mode 100644 index 000000000..661221223 --- /dev/null +++ b/com.ibm.wala.cast.js.rhino.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtractionRhino.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.test; + +import java.io.IOException; + +import org.mozilla.javascript.RhinoToAstTranslator; + +import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.impl.CAstImpl; +import com.ibm.wala.classLoader.SourceModule; + +public class TestForInBodyExtractionRhino extends TestForInBodyExtraction { + protected CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException { + RhinoToAstTranslator.resetGensymCounters(); + RhinoToAstTranslator translator = new RhinoToAstTranslator(ast, module, module.getName()); + CAstEntity entity = translator.translate(); + return entity; + } +} diff --git a/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF index 425d4531f..947ffa5fb 100644 --- a/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF +++ b/com.ibm.wala.cast.js.rhino/META-INF/MANIFEST.MF @@ -11,4 +11,5 @@ Require-Bundle: org.eclipse.core.runtime, com.ibm.wala.core;bundle-version="1.1.3" Bundle-RequiredExecutionEnvironment: J2SE-1.5 Bundle-ActivationPolicy: lazy -Export-Package: com.ibm.wala.cast.js.translator +Export-Package: com.ibm.wala.cast.js.translator, + org.mozilla.javascript diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/CAstDumper.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/CAstDumper.java new file mode 100644 index 000000000..0311db161 --- /dev/null +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/CAstDumper.java @@ -0,0 +1,162 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Map; +import java.util.Map.Entry; + +import com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction.NodeLabeller; +import com.ibm.wala.cast.tree.CAstControlFlowMap; +import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.CAstNode; +import com.ibm.wala.cast.util.CAstPrinter; +import com.ibm.wala.util.collections.HashMapFactory; + +/** + * A class for dumping a textual representation of a CAst syntax tree. + * + *

Similar to {@link CAstPrinter}, but additionally prints control flow information.

+ * + *

It also suppresses certain kinds of spurious nodes such as empty statements within a block or + * block expressions with a single child, which are simply artifacts of the translation process. This + * is not nice, but needed for our tests.

+ * + * @author mschaefer + * + */ +public class CAstDumper { + private final NodeLabeller labeller; + + public CAstDumper() { + labeller = new NodeLabeller(); + } + + public CAstDumper(NodeLabeller labeller) { + this.labeller = labeller; + } + + private static String indent(int indent) { + StringBuilder buf = new StringBuilder(); + for(int i=0;i scopedEntities = Collections.emptySet(); + if(entity.getKind() == CAstEntity.SCRIPT_ENTITY) { + buf.append(indent(indent) + entity.getName() + ":\n"); + scopedEntities = dumpScopedEntities(entity, indent+2, buf); + dump(entity.getAST(), indent, buf, entity.getControlFlow()); + } else if(entity.getKind() == CAstEntity.FUNCTION_ENTITY) { + buf.append(indent(indent) + "function " + entity.getName() + "("); + for(int i=0;i0) + buf.append(", "); + buf.append(entity.getArgumentNames()[i]); + } + buf.append(") {\n"); + scopedEntities = dumpScopedEntities(entity, indent+2, buf); + dump(entity.getAST(), indent+2, buf, entity.getControlFlow()); + buf.append(indent(indent) + "}\n\n"); + } else { + throw new Error("Unknown entity kind " + entity.getKind()); + } + for(CAstEntity scopedEntity : scopedEntities) + dump(scopedEntity, indent, buf); + } + + private Collection dumpScopedEntities(CAstEntity entity, int indent, StringBuilder buf) { + ArrayList scopedEntities = new ArrayList(); + Map m = HashMapFactory.make(); + for(Entry> e : entity.getAllScopedEntities().entrySet()) + for(CAstEntity scopedEntity : e.getValue()) { + scopedEntities.add(scopedEntity); + m.put(scopedEntity, e.getKey()); + } + Collections.sort(scopedEntities, new Comparator() { + public int compare(CAstEntity o1, CAstEntity o2) { + return o1.getName().compareTo(o2.getName()); + } + }); + + buf.append(indent(indent) + "> "); + boolean first = true; + for(CAstEntity scopedEntity : scopedEntities) { + if(first) + first = false; + else + buf.append(", "); + buf.append(scopedEntity.getName() + "@" + labeller.addNode(m.get(scopedEntity))); + } + buf.append("\n"); + return scopedEntities; + } + + private void dump(CAstNode node, int indent, StringBuilder buf, CAstControlFlowMap cfg) { + // normalise away single-child block expressions + if(node.getKind() == CAstNode.BLOCK_EXPR && node.getChildCount() == 1) { + dump(node.getChild(0), indent, buf, cfg); + } else { + buf.append(indent(indent) + labeller.addNode(node) + ": "); + if(node.getKind() == CAstNode.CONSTANT) { + if(node.getValue() == null) + buf.append("null"); + else if(node.getValue() instanceof Integer) + buf.append(node.getValue()+""); + else + buf.append("\"" + node.getValue() + "\""); + } else if(node.getKind() == CAstNode.OPERATOR) { + buf.append(node.getValue().toString()); + } else { + buf.append(CAstPrinter.kindAsString(node.getKind())); + } + Collection labels = cfg.getTargetLabels(node); + if(!labels.isEmpty()) { + buf.append(" ["); + boolean first = true; + for(Object label : labels) { + CAstNode target = cfg.getTarget(node, label); + if(first) { + first = false; + } else { + buf.append(", "); + } + if(label instanceof CAstNode) + buf.append("CAstNode@" + labeller.addNode((CAstNode)label) + ": "); + else + buf.append(label + ": "); + buf.append(labeller.addNode(target)); + } + buf.append("]"); + } + buf.append("\n"); + for(int i=0;i summaries = makeCorrelationFinder().findCorrelatedAccesses(Collections.singleton(new SourceURLModule(tmp.toURI().toURL()))); + CAstImpl ast = new CAstImpl(); + CAstEntity inEntity = parseJS(tmp, ast); + + ExtractionPolicyFactory policyFactory = new ExtractionPolicyFactory() { + @Override + public ExtractionPolicy createPolicy(CAstEntity entity) { + CorrelatedPairExtractionPolicy policy = CorrelatedPairExtractionPolicy.make(entity, summaries); + Assert.assertNotNull(policy); + return policy; + } + }; + String actual = new CAstDumper().dump(new ClosureExtractor(ast, policyFactory).rewrite(inEntity)); + + FileUtil.writeFile(tmp, out); + String expected = new CAstDumper().dump(parseJS(tmp, ast)); + + if(ASSERT_EQUALS) { + Assert.assertEquals(testName, expected, actual); + } else { + FileUtil.writeFile(new File("expected.dump"), expected); + FileUtil.writeFile(new File("actual.dump"), actual); + } + } catch (IOException e) { + e.printStackTrace(); + } catch (ClassHierarchyException e) { + e.printStackTrace(); + } finally { + if(tmp != null && tmp.exists()) + tmp.delete(); + } + } + + protected CAstEntity parseJS(File tmp, CAstImpl ast) throws IOException { + String moduleName = tmp.getName(); + SourceFileModule module = new SourceFileModule(tmp, moduleName); + return parseJS(ast, module); + } + + protected abstract CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException; + protected abstract CorrelationFinder makeCorrelationFinder(); + + // example from the paper + @Test + public void test1() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " dest[p] = src[p];\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + " }\n" + + "}"); + } + + // example from the paper, but with single-statement loop body + @Test + public void test2() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src)\n" + + " dest[p] = src[p];\n" + + "}", + "function extend(dest, src) {\n" + + " for(var p in src)\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + "}"); + } + + // example from the paper, but without var decl + // currently fails because the loop index is a global variable + @Test @Ignore + public void test3() { + testRewriter("function extend(dest, src) {\n" + + " for(p in src)\n" + + " dest[p] = src[p];\n" + + "}", + "function extend(dest, src) {\n" + + " for(p in src)\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + "}"); + } + + // example from the paper, but with separate var decl + @Test + public void test4() { + testRewriter("function extend(dest, src) {\n" + + " var p;\n" + + " for(p in src)\n" + + " dest[p] = src[p];\n" + + "}", + "function extend(dest, src) {\n" + + " var p;\n" + + " for(p in src)\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + "}"); + } + + // example from the paper, but with weirdly placed var decl + @Test + public void test5() { + testRewriter("function extend(dest, src) {\n" + + " for(p in src) {\n" + + " var p;\n" + + " dest[p] = src[p];\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " for(p in src) {\n" + + " var p;\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + " }\n" + + "}"); + } + + // example from the paper, but with weirdly placed var decl in a different place + @Test + public void test6() { + testRewriter("function extend(dest, src) {\n" + + " for(p in src) {\n" + + " dest[p] = src[p];\n" + + " var p;\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " for(p in src) {\n" + + " var p;\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + " }\n" + + "}"); + } + + // example where loop variable is referenced after the loop + // currently fails because the check is not implemented yet + @Test @Ignore + public void test7() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " dest[p] = src[p];\n" + + " p = true;\n" + + " }\n" + + " return p;\n" + + "}", + null); + } + + // example with "this" + @Test + public void test8() { + testRewriter("Object.prototype.extend = function(src) {\n" + + " for(var p in src)\n" + + " this[p] = src[p];\n" + + "}", + "Object.prototype.extend = function(src) {\n" + + " for(var p in src)\n" + + " (function _forin_body_0(p, thi$) {\n" + + " thi$[p] = src[p];\n" + + " })(p, this);\n" + + "}"); + } + + // another example with "this" + @Test + public void test9() { + testRewriter("function defglobals(globals) {\n" + + " for(var p in globals) {\n" + + " (function() {\n" + + " this[p] = globals[p];\n" + + " })();\n" + + " }\n" + + "}", + "function defglobals(globals) {\n" + + " for(var p in globals) {\n" + + " (function() {\n" + + " (function _forin_body_0(p, thi$) {\n" + + " thi$[p] = globals[p];\n" + + " })(p, this)\n" + + " })();\n" + + " }\n" + + "}"); + } + + // an example with "break" + @Test + public void test10() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " if(p == \"stop\")\n" + + " break;\n" + + " dest[p] = src[p];\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " if(p == \"stop\")\n" + + " break;" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + " }\n" + + "}"); + } + + // another example with "break" + @Test + public void test11() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " while(true) {\n" + + " dest[p] = src[p];\n" + + " break;\n" + + " }\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " while(true) {\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + " break;\n" + + " }\n" + + " }\n" + + "}"); + } + + // an example with labelled "break" + @Test + public void test12() { + testRewriter("function extend(dest, src) {\n" + + " outer: for(var p in src) {\n" + + " while(true) {\n" + + " dest[p] = src[p];\n" + + " break outer;\n" + + " }\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " outer: for(var p in src) {\n" + + " while(true) {\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);" + + " break outer;\n" + + " }\n" + + " }\n" + + "}"); + } + + // an example with exceptions + @Test + public void test13() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " if(p == '__proto__')\n" + + " throw new Exception('huh?');\n" + + " dest[p] = src[p];\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " for(var p in src) {\n" + + " if(p == '__proto__')\n" + + " throw new Exception('huh?');\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + " }\n" + + "}"); + + } + + // an example with a "with" block + @Test + public void test14() { + testRewriter("function extend(dest, src) {\n" + + " var o = { dest: dest };\n" + + " with(o) {\n" + + " for(var p in src) {\n" + + " dest[p] = src[p];\n" + + " }\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " var o = { dest: dest };\n" + + " with(o) {\n" + + " for(var p in src) {\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + " }\n" + + " }\n" + + "}"); + } + + // example with two functions + @Test + public void test15() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src)\n" + + " dest[p] = src[p];\n" + + "}\n" + + "function foo() {\n" + + " extend({}, {});\n" + + "}\n" + + "foo();", + "function extend(dest, src) {\n" + + " for(var p in src)\n" + + " (function _forin_body_0(p) {\n" + + " dest[p] = src[p];\n" + + " })(p);\n" + + "}\n" + + "function foo() {\n" + + " extend({}, {});\n" + + "}\n" + + "foo();"); + } + + @Test + public void test16() { + testRewriter("function ext(dest, src) {\n" + + " for(var p in src)\n" + + " do_ext(dest, p, src);\n" + + "}\n" + + "function do_ext(x, p, y) { x[p] = y[p]; }", + "function ext(dest, src) {\n" + + " for(var p in src)\n" + + " do_ext(dest, p, src);\n" + + "}\n" + + "function do_ext(x, p, y) { x[p] = y[p]; }"); + } + + @Test + public void test17() { + testRewriter("function implement(dest, src) {\n" + + " for(var p in src) {\n" + + " dest.prototype[p] = src[p];\n" + + " }\n" + + "}", + "function implement(dest, src) {\n" + + " for(var p in src) {\n" + + " (function _forin_body_0(p) {\n" + + " dest.prototype[p] = src[p];\n" + + " })(p);\n" + + " }\n" + + "}"); + } + + // fails since the assignment to "value" in the extracted version gets a (spurious) reference error CFG edge + @Test @Ignore + public void test18() { + testRewriter("function addMethods(source) {\n" + + " var properties = Object.keys(source);\n" + + " for (var i = 0, length = properties.length; i < length; i++) {\n" + + " var property = properties[i], value = source[property];\n" + + " this.prototype[property] = value;\n" + + " }\n" + + " return this;\n" + + "}", + "function addMethods(source) {\n" + + " var properties = Object.keys(source);\n" + + " for (var i = 0, length = properties.length; i < length; i++) {\n" + + " var property = properties[i], value; (function _forin_body_0(property, thi$) { value = source[property];\n" + + " thi$.prototype[property] = value; })(property, this);\n" + + " }\n" + + " return this;\n" + + "}"); + } + + @Test + public void test19() { + testRewriter("function extend(dest, src) {\n" + + " for(var p in src)\n" + + " if(foo(p)) write.call(dest, p, src[p]);\n" + + "}\n" + + "function write(p, v) { this[p] = v; }", + "function extend(dest, src) {\n" + + " for(var p in src)\n" + + " if(foo(p)) (function _forin_body_0(p) { write.call(dest, p, src[p]); })(p);\n" + + "}\n" + + "function write(p, v) { this[p] = v; }"); + } + + @Test + public void test20() { + testRewriter("function every(object, fn, bind) {\n" + + " for(var key in object)\n" + + " if(hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return false;\n" + + "}", + "function every(object, fn, bind) {\n" + + " for(var key in object) {\n" + + " re$ = (function _forin_body_0(key) {\n" + + " if (hasOwnProperty.call(object, key) && !fn.call(bind, object[key], key)) return { type: 'return', value: false };\n" + + " })(key);\n" + + " if(re$) { if(re$.type == 'return') return re$.value; }\n" + + " }\n" + + "}"); + } + + @Test + public void test21() { + testRewriter("function extend(dest, src) {\n" + + " var x, y;\n" + + " for(var name in src) {\n" + + " x = dest[name];\n" + + " y = src[name];\n" + + " dest[name] = join(x,y);\n" + + " }\n" + + "}", + "function extend(dest, src) {\n" + + " var x, y;\n" + + " for(var name in src) {\n" + + " (function _forin_body_0(name) { { x = dest[name];\n" + + " y = src[name];\n" + + " dest[name] = join(x,y); } })(name);\n" + + " }\n" + + "}"); + } +} diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtraction.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtraction.java new file mode 100644 index 000000000..83e9bc178 --- /dev/null +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/TestForInBodyExtraction.java @@ -0,0 +1,762 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.test; + +import java.io.File; +import java.io.IOException; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +import com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction.ClosureExtractor; +import com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction.ForInBodyExtractionPolicy; +import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.impl.CAstImpl; +import com.ibm.wala.classLoader.SourceFileModule; +import com.ibm.wala.classLoader.SourceModule; +import com.ibm.wala.util.io.FileUtil; + +public abstract class TestForInBodyExtraction { + public void testRewriter(String in, String out) { + testRewriter(null, in, out); + } + + public void testRewriter(String testName, String in, String out) { + File tmp = null; + try { + tmp = File.createTempFile("test", ".js"); + FileUtil.writeFile(tmp, in); + CAstImpl ast = new CAstImpl(); + String actual = new CAstDumper().dump(new ClosureExtractor(ast, ForInBodyExtractionPolicy.FACTORY).rewrite(parseJS(tmp, ast))); + + FileUtil.writeFile(tmp, out); + String expected = new CAstDumper().dump(parseJS(tmp, ast)); + + Assert.assertEquals(testName, expected, actual); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if(tmp != null && tmp.exists()) + tmp.delete(); + } + } + + protected CAstEntity parseJS(File tmp, CAstImpl ast) throws IOException { + String moduleName = tmp.getName(); + SourceFileModule module = new SourceFileModule(tmp, moduleName); + return parseJS(ast, module); + } + + protected abstract CAstEntity parseJS(CAstImpl ast, SourceModule module) throws IOException; + + // example from the paper + @Test + public void test1() { + testRewriter("function extend(dest, src) {" + + " for(var p in src) {" + + " dest[p] = src[p];" + + " }" + + "}", + "function extend(dest, src) {" + + " for(var p in src) {" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + " }" + + "}"); + } + + // example from the paper, but with single-statement loop body + @Test + public void test2() { + testRewriter("function extend(dest, src) {" + + " for(var p in src)" + + " dest[p] = src[p];" + + "}", + "function extend(dest, src) {" + + " for(var p in src)" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + "}"); + } + + // example from the paper, but without var decl + @Test + public void test3() { + testRewriter("function extend(dest, src) {" + + " for(p in src)" + + " dest[p] = src[p];" + + "}", + "function extend(dest, src) {" + + " for(p in src)" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + "}"); + } + + // example from the paper, but with separate var decl + @Test + public void test4() { + testRewriter("function extend(dest, src) {" + + " var p;" + + " for(p in src)" + + " dest[p] = src[p];" + + "}", + "function extend(dest, src) {" + + " var p;" + + " for(p in src)" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + "}"); + } + + // example from the paper, but with weirdly placed var decl + @Test + public void test5() { + testRewriter("function extend(dest, src) {" + + " for(p in src) {" + + " var p;" + + " dest[p] = src[p];" + + " }" + + "}", + "function extend(dest, src) {" + + " for(p in src) {" + + " var p;" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + " }" + + "}"); + } + + // example from the paper, but with weirdly placed var decl in a different place + @Test + public void test6() { + testRewriter("function extend(dest, src) {" + + " for(p in src) {" + + " dest[p] = src[p];" + + " var p;" + + " }" + + "}", + "function extend(dest, src) {" + + " for(p in src) {" + + " var p;" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + " }" + + "}"); + } + + // example where loop variable is referenced after the loop + // this isn't currently handled, hence the test fails + @Test @Ignore + public void test7() { + testRewriter("function extend(dest, src) {" + + " for(var p in src) {" + + " dest[p] = src[p];" + + " p = true;" + + " }" + + " return p;" + + "}", + "function extend(dest, src) {" + + " for(var p in src)" + + " (function _let_0(_let_parm_0) {" + + " (function _forin_body_0(p) {" + + " try {" + + " dest[p] = src[p];" + + " p = true;" + + " } finally {" + + " _let_parm_0 = p;" + + " }" + + " })(p);" + + " p = _let_parm_0;" + + " })(p);" + + " return p;" + + "}"); + } + + // example with "this" + @Test + public void test8() { + testRewriter("Object.prototype.extend = function(src) {" + + " for(var p in src)" + + " this[p] = src[p];" + + "}", + "Object.prototype.extend = function(src) {" + + " for(var p in src)" + + " (function _forin_body_0(p, thi$) {" + + " thi$[p] = src[p];" + + " })(p, this);" + + "}"); + } + + // another example with "this" + @Test + public void test9() { + testRewriter("function defglobals(globals) {" + + " for(var p in globals) {" + + " (function() {" + + " this[p] = globals[p];" + + " })();" + + " }" + + "}", + "function defglobals(globals) {" + + " for(var p in globals) {" + + " (function _forin_body_0(p) {" + + " (function() {" + + " this[p] = globals[p];" + + " })()" + + " })(p);" + + " }" + + "}"); + } + + // an example with "break" + @Test + public void test10() { + testRewriter("function extend(dest, src) {" + + " for(var p in src) {" + + " if(p == \"stop\")" + + " break;" + + " dest[p] = src[p];" + + " }" + + "}", + "function extend(dest, src) {" + + " for(var p in src) {" + + " re$ = (function _forin_body_0(p) {" + + " if(p == \"stop\")" + + " return {type: 'goto', target: 0};" + + " dest[p] = src[p];" + + " })(p);" + + " if(re$) {" + + " if(re$.type == 'goto') {" + + " if(re$.target == 0)" + + " break;" + + " }" + + " }" + + " }" + + "}"); + } + + // another example with "break" + @Test + public void test11() { + testRewriter("function extend(dest, src) {" + + " for(var p in src) {" + + " while(true) {" + + " dest[p] = src[p];" + + " break;" + + " }" + + " }" + + "}", + "function extend(dest, src) {" + + " for(var p in src) {" + + " (function _forin_body_0(p) {" + + " while(true) {" + + " dest[p] = src[p];" + + " break;" + + " }" + + " })(p);" + + " }" + + "}"); + } + + // an example with labelled "break" + @Test + public void test12() { + testRewriter("function extend(dest, src) {" + + " outer: for(var p in src) {" + + " while(true) {" + + " dest[p] = src[p];" + + " break outer;" + + " }" + + " }" + + "}", + "function extend(dest, src) {" + + " outer: for(var p in src) {" + + " re$ = (function _forin_body_0(p) {" + + " while(true) {" + + " dest[p] = src[p];" + + " return {type: 'goto', target: 0};" + + " }" + + " })(p);" + + " if(re$) {" + + " if(re$.type == 'goto') {" + + " if(re$.target == 0)" + + " break outer;" + + " }" + + " }" + + " }" + + "}"); + } + + // an example with exceptions + @Test + public void test13() { + testRewriter("function extend(dest, src) {" + + " for(var p in src) {" + + " if(p == '__proto__')" + + " throw new Exception('huh?');" + + " dest[p] = src[p];" + + " }" + + "}", + "function extend(dest, src) {" + + " for(var p in src) {" + + " (function _forin_body_0(p) {" + + " if(p == '__proto__')" + + " throw new Exception('huh?');" + + " dest[p] = src[p];" + + " })(p);" + + " }" + + "}"); + + } + + // an example with a var decl + // this test fails due to a trivial difference between transformed and expected CAst that isn't semantically relevant + @Test @Ignore + public void test14() { + testRewriter("x = 23;" + + "function foo() {" + + " x = 42;" + + " for(var p in {toString : 23}) {" + + " var x = 56;" + + " alert(x);" + + " }" + + " alert(x);" + + "}" + + "foo();" + + "alert(x);", + "x = 23;" + + "function foo() {" + + " x = 42;" + + " for(var p in {toString : 23}) {" + + " var x;" + + " (function _forin_body_0(p) {" + + " x = 56;" + + " alert(x);" + + " })(p);" + + " }" + + " alert(x);" + + "}" + + "foo();" + + "alert(x);"); + } + + // another example with a var decl + @Test + public void test15() { + testRewriter("x = 23;" + + "function foo() {" + + " x = 42;" + + " for(var p in {toString : 23}) {" + + " (function() {" + + " var x = 56;" + + " alert(x);" + + " })();" + + " }" + + " alert(x);" + + "}" + + "foo();" + + "alert(x);", + "x = 23;" + + "function foo() {" + + " x = 42;" + + " for(var p in {toString : 23}) {" + + " (function _forin_body_0(p) {" + + " (function() {" + + " var x = 56;" + + " alert(x);" + + " })();" + + " })(p);" + + " }" + + " alert(x);" + + "}" + + "foo();" + + "alert(x);"); + } + + // an example with a "with" block + @Test + public void test16() { + testRewriter("function extend(dest, src) {" + + " var o = { dest: dest };" + + " with(o) {" + + " for(var p in src) {" + + " dest[p] = src[p];" + + " }" + + " }" + + "}", + "function extend(dest, src) {" + + " var o = { dest: dest };" + + " with(o) {" + + " for(var p in src) {" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + " }" + + " }" + + "}"); + } + + // top-level for-in loop + @Test + public void test17() { + testRewriter("var o = {x:23};" + + "for(x in o) {" + + " o[x] += 19;" + + "}", + "var o = {x:23};" + + "for(x in o) {" + + " (function _forin_body_0(x) {" + + " o[x] += 19;" + + " })(x);" + + "}"); + } + + + // nested for-in loops + @Test + public void test18() { + testRewriter("var o = {x:{y:23}};" + + "for(x in o) {" + + " for(y in o[x]) {" + + " o[x][y] += 19;" + + " }" + + "}", + "var o = {x:{y:23}};" + + "for(x in o) {" + + " (function _forin_body_0(x) {" + + " for(y in o[x]) {" + + " (function _forin_body_1(y) {" + + " o[x][y] += 19;" + + " })(y);" + + " }" + + " })(x);" + + "}"); + } + + // return in loop body + @Test + public void test19() { + testRewriter("function foo(x) {" + + " for(var p in x) {" + + " if(p == 'ret')" + + " return x[p];" + + " x[p]++;" + + " }" + + "}", + "function foo(x) {" + + " for(var p in x) {" + + " re$ = (function _forin_body_0(p) {" + + " if(p == 'ret')" + + " return {type: 'return', value: x[p]};" + + " x[p]++;" + + " })(p);" + + " if(re$) {" + + " if(re$.type == 'return')" + + " return re$.value;" + + " }" + + " }" + + "}"); + } + + // example with two functions + @Test + public void test20() { + testRewriter("function extend(dest, src) {" + + " for(var p in src)" + + " dest[p] = src[p];" + + "}" + + "function foo() {" + + " extend({}, {});" + + "}" + + "foo();", + "function extend(dest, src) {" + + " for(var p in src)" + + " (function _forin_body_0(p) {" + + " dest[p] = src[p];" + + " })(p);" + + "}" + + "function foo() {" + + " extend({}, {});" + + "}" + + "foo();"); + } + + // example with nested for-in loops and this (adapted from MooTools) + @Test + public void test21() { + testRewriter("function foo() {" + + " var result = [];" + + " for(var style in Element.ShortStyles) {" + + " for(var s in Element.ShortStyles[style]) {" + + " result.push(this.getStyle(s));" + + " }" + + " }" + + "}", + "function foo() {" + + " var result = [];" + + " for(var style in Element.ShortStyles) {" + + " var s;" + + " (function _forin_body_0(style, thi$) {" + + " for(s in Element.ShortStyles[style]) {" + + " (function _forin_body_1(s) {" + + " result.push(thi$.getStyle(s));" + + " })(s);" + + " }" + + " })(style, this);" + + " }" + + "}"); + } + + // example with nested for-in loops and continue (adapted from MooTools) + @Test + public void test22() { + testRewriter("function foo(property) {" + + " var result = [];" + + " for(var style in Element.ShortStyles) {" + + " if(property != style) continue; " + + " for(var s in Element.ShortStyles[style]) {" + + " ;" + + " }" + + " }" + + "}", + "function foo(property) {" + + " var result = [];" + + " for(var style in Element.ShortStyles) {" + + " var s;" + + " re$ = (function _forin_body_0(style) {" + + " if(property != style) return {type:'goto', target:0}; " + + " for(s in Element.ShortStyles[style]) {" + + " (function _forin_body_1(s) {" + + " ;" + + " })(s);" + + " }" + + " })(style);" + + " if(re$) {" + + " if(re$.type == 'goto') {" + + " if(re$.target == 0)" + + " continue;" + + " }" + + " }" + + " }" + + "}"); + } + + @Test + public void test23() { + testRewriter("function foo(obj) {" + + " for(var p in obj) {" + + " if(p != 'bar')" + + " continue;" + + " return obj[p];" + + " }" + + "}", + "function foo(obj) {" + + " for(var p in obj) {" + + " re$ = (function _forin_body_0(p) {" + + " if(p != 'bar')" + + " return {type:'goto', target:0};" + + " return {type:'return', value:obj[p]};" + + " })(p);" + + " if(re$) {" + + " if(re$.type == 'return')" + + " return re$.value;" + + " if(re$.type == 'goto') {" + + " if(re$.target == 0)" + + " continue;" + + " }" + + " }" + + " }" + + "}"); + } + + // this test fails since the rewritten CAst contains one more level of blocks + @Test @Ignore + public void test24() { + testRewriter("var addSlickPseudos = function() {" + + " for(var name in pseudos)" + + " if(pseudos.hasOwnProperty(name)) {" + + " ;" + + " }" + + "}", + "var addSlickPseudos = function() {" + + " for(var name in pseudos)" + + " (function _forin_body_0(name) {" + + " if(pseudos.hasOwnProperty(name)) {" + + " ;" + + " }" + + " })(name);" + + "}"); + } + + @Test + public void test25() { + testRewriter("function ext(dest, src) {" + + " for(var p in src)" + + " do_ext(dest, p, src);" + + "}" + + "function do_ext(x, p, y) { x[p] = y[p]; }", + "function ext(dest, src) {" + + " for(var p in src)" + + " (function _forin_body_0(p) {" + + " do_ext(dest, p, src);" + + " })(p);" + + "}" + + "function do_ext(x, p, y) { x[p] = y[p]; }"); + } + + @Test + public void test26() { + testRewriter("function foo(x) {" + + " for(p in x) {" + + " for(q in p[x]) {" + + " if(b)" + + " return 23;" + + " }" + + " }" + + "}", + "function foo(x) {" + + " for(p in x) {" + + " re$ = (function _forin_body_0(p) {" + + " for(q in p[x]) {" + + " re$ = (function _forin_body_1(q) {" + + " if(b)" + + " return { type: 'return', value: 23 };" + + " })(q);" + + " if(re$) {" + + " return re$;" + + " }" + + " }" + + " })(p);" + + " if(re$) {" + + " if(re$.type == 'return')" + + " return re$.value;" + + " }" + + " }" + + "}"); + } + + // variation of test22 + @Test + public void test27() { + testRewriter("function foo(property) {" + + " var result = [];" + + " outer: for(var style in Element.ShortStyles) {" + + " for(var s in Element.ShortStyles[style]) {" + + " if(s != style) continue outer;" + + " }" + + " }" + + "}", + "function foo(property) {" + + " var result = [];" + + " outer: for(var style in Element.ShortStyles) {" + + " var s;" + + " re$ = (function _forin_body_0(style) {" + + " for(s in Element.ShortStyles[style]) {" + + " re$ = (function _forin_body_1(s) {" + + " if(s != style) return {type:'goto', target:0};" + + " })(s);" + + " if(re$) {" + + " return re$;" + + " }" + + " }" + + " })(style);" + + " if(re$) {" + + " if(re$.type == 'goto') {" + + " if(re$.target == 0)" + + " continue outer;" + + " }" + + " }" + + " }" + + "}"); + } + + // another variation of test22 + @Test + public void test28() { + testRewriter("function foo(property) {" + + " var result = [];" + + " outer: for(var style in Element.ShortStyles) {" + + " for(var s in Element.ShortStyles[style]) {" + + " if(s != style) continue;" + + " }" + + " }" + + "}", + "function foo(property) {" + + " var result = [];" + + " outer: for(var style in Element.ShortStyles) {" + + " var s;" + + " (function _forin_body_0(style) {" + + " for(s in Element.ShortStyles[style]) {" + + " re$ = (function _forin_body_1(s) {" + + " if(s != style) return {type:'goto', target:0};" + + " })(s);" + + " if(re$) {" + + " if(re$.type == 'goto') {" + + " if(re$.target == 0)" + + " continue;" + + " }" + + " }" + + " }" + + " })(style);" + + " }" + + "}"); + } + + // test where the same entity (namely the inner function "copy") is rewritten more than once + // this probably shouldn't happen + @Test + public void test29() { + testRewriter("Element.addMethods = function(methods) {" + + " function copy() {" + + " for (var property in methods) {" + + " }" + + " }" + + " for (var tag in methods) {" + + " }" + + "};", + "Element.addMethods = function(methods) {" + + " function copy() {" + + " for (var property in methods) {" + + " (function _forin_body_1(property) {" + + " })(property);" + + " }" + + " }" + + " for (var tag in methods) {" + + " (function _forin_body_0(tag){ })(tag);" + + " }" + + "};"); + } + + @Test + public void test30() { + testRewriter("try {" + + " for(var i in {}) {" + + " f();" + + " }" + + "} catch(_) {}", + "try {" + + " for(var i in {}) {" + + " (function _forin_body_0(i) {" + + " f();" + + " })(i);" + + " }" + + "} catch(_) {}"); + } +} diff --git a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java index 5793e3fcf..1e2121b67 100755 --- a/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java +++ b/com.ibm.wala.cast.js.test/harness-src/com/ibm/wala/cast/js/test/Util.java @@ -119,7 +119,7 @@ public class Util extends com.ibm.wala.cast.js.ipa.callgraph.Util { protected static JSCFABuilder makeCG(JavaScriptLoaderFactory loaders, AnalysisScope scope, boolean useOneCFA, boolean handleCallApply) throws IOException { try { IClassHierarchy cha = makeHierarchy(scope, loaders); - com.ibm.wala.cast.test.Util.checkForFrontEndErrors(cha); + com.ibm.wala.cast.js.util.Util.checkForFrontEndErrors(cha); Iterable roots = makeScriptRoots(cha); JSAnalysisOptions options = makeOptions(scope, cha, roots); options.setHandleCallApply(handleCallApply); diff --git a/com.ibm.wala.cast.js/META-INF/MANIFEST.MF b/com.ibm.wala.cast.js/META-INF/MANIFEST.MF index e5b9d9e7e..f93b2ee2d 100644 --- a/com.ibm.wala.cast.js/META-INF/MANIFEST.MF +++ b/com.ibm.wala.cast.js/META-INF/MANIFEST.MF @@ -17,11 +17,14 @@ Export-Package: com.ibm.wala.cast.js, com.ibm.wala.cast.js.html, com.ibm.wala.cast.js.html.jericho, com.ibm.wala.cast.js.ipa.callgraph, + com.ibm.wala.cast.js.ipa.callgraph.correlations, + com.ibm.wala.cast.js.ipa.callgraph.correlations.extraction, com.ibm.wala.cast.js.ipa.summaries, com.ibm.wala.cast.js.loader, com.ibm.wala.cast.js.ssa, com.ibm.wala.cast.js.translator, com.ibm.wala.cast.js.types, + com.ibm.wala.cast.js.util, com.ibm.wala.cast.js.vis Require-Bundle: com.ibm.wala.cast, com.ibm.wala.core, diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/Correlation.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/Correlation.java new file mode 100644 index 000000000..2a0c215db --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/Correlation.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations; + +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; + +/** + * A correlation exists between a dynamic property read r and a dynamic property write w such that + * the value read in r may flow into w, and r and w are guaranteed to access a property of the same name. + * + * @author mschaefer + * + */ +public abstract class Correlation { + private final String indexName; + + protected Correlation(String indexName) { + this.indexName = indexName; + } + + public String getIndexName() { + return indexName; + } + + public abstract Position getStartPosition(SSASourcePositionMap positions); + public abstract Position getEndPosition(SSASourcePositionMap positions); + public abstract String pp(SSASourcePositionMap positions); + public abstract T accept(CorrelationVisitor visitor); +} \ No newline at end of file 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 new file mode 100644 index 000000000..6614a61dc --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationFinder.java @@ -0,0 +1,272 @@ +/****************************************************************************** + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.ibm.wala.cast.ipa.callgraph.CAstAnalysisScope; +import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; +import com.ibm.wala.cast.ir.ssa.AbstractReflectivePut; +import com.ibm.wala.cast.ir.ssa.AstIRFactory; +import com.ibm.wala.cast.js.html.WebPageLoaderFactory; +import com.ibm.wala.cast.js.html.WebUtil; +import com.ibm.wala.cast.js.loader.JavaScriptLoader; +import com.ibm.wala.cast.js.translator.JavaScriptTranslatorFactory; +import com.ibm.wala.cast.js.util.Util; +import com.ibm.wala.cast.loader.AstMethod; +import com.ibm.wala.cast.loader.AstMethod.LexicalInformation; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; +import com.ibm.wala.classLoader.IClass; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.classLoader.SourceModule; +import com.ibm.wala.ipa.callgraph.impl.Everywhere; +import com.ibm.wala.ipa.cha.ClassHierarchy; +import com.ibm.wala.ipa.cha.ClassHierarchyException; +import com.ibm.wala.ipa.cha.IClassHierarchy; +import com.ibm.wala.shrikeBT.IBinaryOpInstruction; +import com.ibm.wala.shrikeBT.IBinaryOpInstruction.IOperator; +import com.ibm.wala.ssa.DefUse; +import com.ibm.wala.ssa.IR; +import com.ibm.wala.ssa.IRFactory; +import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; +import com.ibm.wala.ssa.SSABinaryOpInstruction; +import com.ibm.wala.ssa.SSAInstruction; +import com.ibm.wala.ssa.SSAOptions; +import com.ibm.wala.ssa.SSAPhiInstruction; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.collections.Iterator2Iterable; +import com.ibm.wala.util.collections.ObjectArrayMapping; +import com.ibm.wala.util.collections.Pair; +import com.ibm.wala.util.intset.BitVectorIntSet; +import com.ibm.wala.util.intset.MutableIntSet; +import com.ibm.wala.util.intset.OrdinalSetMapping; +import com.ibm.wala.util.io.FileProvider; + +/** + * Helper class for identifying correlated read/write pairs. + * + * @author mschaefer + * + */ +public class CorrelationFinder { + private final static boolean TRACK_ESCAPES = true; + private final static boolean IGNORE_NUMERIC_INDICES = false; + + private final JavaScriptTranslatorFactory translatorFactory; + + @SuppressWarnings("unused") + private CorrelationSummary findCorrelatedAccesses(IMethod method, IR ir) { + AstMethod astMethod = (AstMethod)method; + DefUse du = new DefUse(ir); + OrdinalSetMapping instrIndices = new ObjectArrayMapping(ir.getInstructions()); + CorrelationSummary summary = new CorrelationSummary(method, instrIndices); + + // collect all dynamic property writes in the method + LinkedList puts = new LinkedList(); + for(SSAInstruction inst : Iterator2Iterable.make(ir.iterateNormalInstructions())) + if(inst instanceof AbstractReflectivePut) + puts.addFirst((AbstractReflectivePut)inst); + + instrs: for(SSAInstruction inst : Iterator2Iterable.make(ir.iterateNormalInstructions())) + 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); + if(indexName == null) + continue instrs; + + // check that "index" is not accessed in an inner function + LexicalInformation lexicalInfo = astMethod.lexicalInfo(); + if (lexicalInfo.getExposedNames() != null) { + for(Pair n : lexicalInfo.getExposedNames()) { + if (n.fst.equals(indexName) && lexicalInfo.getScopingName().equals(n.snd)) + 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()); + // saturate reached by following def-use chains through phi instructions and across function calls + LinkedList worklist = new LinkedList(); + MutableIntSet done = new BitVectorIntSet(); + worklist.add(get.getDef()); + while(!worklist.isEmpty()) { + Integer i = worklist.pop(); + done.add(i); + for(SSAInstruction inst2 : Iterator2Iterable.make(du.getUses(i))) { + if(inst2 instanceof SSAPhiInstruction) { + int def = inst2.getDef(); + if(reached.add(def) && !done.contains(def)) + worklist.add(def); + } else if(inst2 instanceof SSAAbstractInvokeInstruction) { + int def = inst2.getDef(); + if(reached.add(def) && !done.contains(def)) + worklist.add(def); + // if the index also flows into this invocation, record an escape correlation + if(TRACK_ESCAPES) { + for(int j=0;j worklist = new LinkedList(); + MutableIntSet done = new BitVectorIntSet(); + worklist.add(v); + while(!worklist.isEmpty()) { + int i = worklist.pop(); + done.add(i); + if(ir.getSymbolTable().isConstant(i) && ir.getSymbolTable().getConstantValue(i) instanceof Number) + continue; + SSAInstruction inst2 = du.getDef(i); + if(inst2 instanceof SSAPhiInstruction) { + for(int j=0;j summaries = findCorrelatedAccesses(url); + List> correlations = new ArrayList>(); + for(CorrelationSummary summary : summaries.values()) + correlations.addAll(summary.pp()); + + Collections.sort(correlations, new Comparator>() { + @SuppressWarnings("unchecked") + @Override + public int compare(Pair o1, Pair o2) { + return o1.fst.compareTo(o2.fst); + } + }); + int i = 0; + for(Pair p : correlations) + System.out.println((i++) + " -- " + p.fst + ": " + p.snd); + } + + public Map findCorrelatedAccesses(URL url) throws IOException, ClassHierarchyException { + JavaScriptLoader.addBootstrapFile(WebUtil.preamble); + Set script = WebUtil.extractScriptFromHTML(url); + Map summaries = findCorrelatedAccesses(script); + return summaries; + } + + public Map findCorrelatedAccesses(Set script) throws IOException, + ClassHierarchyException { + SourceModule[] scripts = script.toArray(new SourceModule[script.size()]); + WebPageLoaderFactory loaders = new WebPageLoaderFactory(translatorFactory); + CAstAnalysisScope scope = new CAstAnalysisScope(scripts, loaders, Collections.singleton(JavaScriptLoader.JS)); + IClassHierarchy cha = ClassHierarchy.make(scope, loaders, JavaScriptLoader.JS); + Util.checkForFrontEndErrors(cha); + IRFactory factory = AstIRFactory.makeDefaultFactory(); + + Map correlations = HashMapFactory.make(); + for(IClass klass : cha) { + for(IMethod method : klass.getAllMethods()) { + IR ir = factory.makeIR(method, Everywhere.EVERYWHERE, SSAOptions.defaultOptions()); + CorrelationSummary summary = findCorrelatedAccesses(method, ir); + if(!summary.getCorrelations().isEmpty()) + correlations.put(method, summary); + } + } + return correlations; + } + + @SuppressWarnings("unused") + private URL toUrl(String src) throws MalformedURLException { + // first try interpreting as local file name, if that doesn't work just assume it's a URL + try { + File f = FileProvider.getFileFromClassLoader(src, this.getClass().getClassLoader()); + URL url = f.toURI().toURL(); + return url; + } catch(FileNotFoundException fnfe) { + return new URL(src); + } + } + + public CorrelationFinder(JavaScriptTranslatorFactory translatorFactory) { + this.translatorFactory = translatorFactory; + } +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationSummary.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationSummary.java new file mode 100644 index 000000000..f7b51dacd --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationSummary.java @@ -0,0 +1,59 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import com.ibm.wala.cast.loader.AstMethod; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; +import com.ibm.wala.classLoader.IMethod; +import com.ibm.wala.ssa.SSAInstruction; +import com.ibm.wala.util.collections.HashSetFactory; +import com.ibm.wala.util.collections.Pair; +import com.ibm.wala.util.intset.OrdinalSetMapping; + +/** + * A utility class holding information about correlations identified by a {@link CorrelationFinder}. + * + * @author mschaefer + * + */ +public final class CorrelationSummary { + private final SSASourcePositionMap positions; + private final Set correlations = HashSetFactory.make(); + + public CorrelationSummary(IMethod method, OrdinalSetMapping instrIndices) { + positions = new SSASourcePositionMap((AstMethod)method, instrIndices); + } + + public void addCorrelation(Correlation correlation) { + correlations.add(correlation); + } + + public List> pp() { + List> res = new ArrayList>(); + for(Correlation correlation : correlations) { + res.add(Pair.make(correlation.getStartPosition(positions), correlation.pp(positions))); + } + return res; + } + + public Set getCorrelations() { + return correlations; + } + + public SSASourcePositionMap getPositions() { + return positions; + } +} \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationVisitor.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationVisitor.java new file mode 100644 index 000000000..f36ebecc3 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/CorrelationVisitor.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations; + +/** + * Visitor class for performing case analysis on {@link Correlation}s. + * + * @author mschaefer + * + * @param + */ +public interface CorrelationVisitor { + public T visitReadWriteCorrelation(ReadWriteCorrelation rwc); + public T visitEscapeCorrelation(EscapeCorrelation ec); +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/EscapeCorrelation.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/EscapeCorrelation.java new file mode 100644 index 000000000..583dfac67 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/EscapeCorrelation.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations; + +import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; +import com.ibm.wala.ssa.SSAAbstractInvokeInstruction; + +/** + * An escape correlation conservatively captures inter-procedural correlated pairs: for a dynamic property + * read r of the form e[p], if both the result of r and the value of p + * flow into a function call c, we consider r and c to be a correlated pair to account + * for the fact that the function called by c may perform a write of property p. + * + * @author mschaefer + * + */ +public class EscapeCorrelation extends Correlation { + private final AbstractReflectiveGet get; + private final SSAAbstractInvokeInstruction invoke; + + public EscapeCorrelation(AbstractReflectiveGet get, SSAAbstractInvokeInstruction invoke, String indexName) { + super(indexName); + this.get = get; + this.invoke = invoke; + } + + @Override + public Position getStartPosition(SSASourcePositionMap positions) { + return positions.getPosition(get); + } + + @Override + public Position getEndPosition(SSASourcePositionMap positions) { + return positions.getPosition(invoke); + } + + public int getNumberOfArguments() { + return invoke.getNumberOfParameters() - 2; // deduct one for the function object, one for the receiver + } + + @Override + public String pp(SSASourcePositionMap positions) { + return get + "@" + positions.getPosition(get) + " [" + getIndexName() + "] ->? " + invoke + "@" + positions.getPosition(invoke); + } + + @Override + public T accept(CorrelationVisitor visitor) { + return visitor.visitEscapeCorrelation(this); + } +} \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/ReadWriteCorrelation.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/ReadWriteCorrelation.java new file mode 100644 index 000000000..49bd39f30 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/ReadWriteCorrelation.java @@ -0,0 +1,54 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations; + +import com.ibm.wala.cast.ir.ssa.AbstractReflectiveGet; +import com.ibm.wala.cast.ir.ssa.AbstractReflectivePut; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; + +/** + * The most basic form of correlation: an intra-procedurally correlated pair of a dynamic property read + * and a dynamic property write. + * + * @author mschaefer + * + */ +public class ReadWriteCorrelation extends Correlation { + private final AbstractReflectiveGet get; + private final AbstractReflectivePut put; + + public ReadWriteCorrelation(AbstractReflectiveGet get, AbstractReflectivePut put, String indexName) { + super(indexName); + this.get = get; + this.put = put; + } + + @Override + public Position getStartPosition(SSASourcePositionMap positions) { + return positions.getPosition(get); + } + + @Override + public Position getEndPosition(SSASourcePositionMap positions) { + return positions.getPosition(put); + } + + @Override + public String pp(SSASourcePositionMap positions) { + return get + "@" + positions.getPosition(get) + " [" + getIndexName() + "]-> " + put + "@" + positions.getPosition(put); + } + + @Override + public T accept(CorrelationVisitor visitor) { + return visitor.visitReadWriteCorrelation(this); + } +} \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/SSASourcePositionMap.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/SSASourcePositionMap.java new file mode 100644 index 000000000..b373d5304 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/SSASourcePositionMap.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations; + +import com.ibm.wala.cast.loader.AstMethod; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; +import com.ibm.wala.ssa.SSAInstruction; +import com.ibm.wala.util.intset.OrdinalSetMapping; + +/** + * Utility class used by {@link CorrelationSummary} to map SSA instructions to source positions. + * + * @author mschaefer + * + */ +public class SSASourcePositionMap { + private final AstMethod method; + private final OrdinalSetMapping instrIndices; + + public SSASourcePositionMap(AstMethod method, OrdinalSetMapping instrIndices) { + this.method = method; + this.instrIndices = instrIndices; + } + + public Position getPosition(SSAInstruction inst) { + return method.getSourcePosition(instrIndices.getMappedIndex(inst)); + } +} \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/CAstRewriterExt.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/CAstRewriterExt.java new file mode 100644 index 000000000..4d14b51a8 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/CAstRewriterExt.java @@ -0,0 +1,245 @@ +/****************************************************************************** + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations.extraction; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Stack; + +import com.ibm.wala.cast.tree.CAst; +import com.ibm.wala.cast.tree.CAstControlFlowMap; +import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.CAstNode; +import com.ibm.wala.cast.tree.CAstSourcePositionMap; +import com.ibm.wala.cast.tree.impl.CAstBasicRewriter.NoKey; +import com.ibm.wala.cast.tree.impl.CAstControlFlowRecorder; +import com.ibm.wala.cast.tree.impl.CAstRewriter; +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.debug.Assertions; + +/** + * Extension of {@link CAstRewriter} which allows adding or deleting control flow edges, and keeps track of + * the current entity. + * + * TODO: This class is an unholy mess. It should be restructured considerably. + * + * @author mschaefer + * + */ +public abstract class CAstRewriterExt extends CAstRewriter { + + /** + * A control flow edge to be added to the CFG. + * + * @author mschaefer + */ + protected static class Edge { + private CAstNode from; + private Object label; + private CAstNode to; + + public Edge(CAstNode from, Object label, CAstNode to) { + assert from != null; + assert to != null; + this.from = from; + this.label = label; + this.to = to; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime + from.hashCode(); + result = prime * result + ((label == null) ? 0 : label.hashCode()); + result = prime * result + to.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if(!(obj instanceof Edge)) + return false; + Edge that = (Edge)obj; + return this.from.equals(that.from) && + (this.label == null ? that.label == null : this.label.equals(that.label)) && + this.to.equals(that.to); + } + } + + private final Map> extra_nodes = HashMapFactory.make(); + private final Map> extra_flow = HashMapFactory.make(); + private final Map> flow_to_delete = HashMapFactory.make(); + + // information about an entity to add to the AST + private static class Entity { + private final CAstNode anchor; + private final CAstEntity me; + public Entity(CAstNode anchor, CAstEntity me) { + assert me != null; + this.anchor = anchor; + this.me = me; + } + @Override + public int hashCode() { + final int prime = 31; + int result = prime + ((anchor == null) ? 0 : anchor.hashCode()); + return prime * result + me.hashCode(); + } + } + private final HashSet entities_to_add = HashSetFactory.make(); + private final Stack entities = new Stack(); + + public CAstNode addNode(CAstNode node, CAstControlFlowMap flow) { + Set nodes = extra_nodes.get(flow); + if(nodes == null) + extra_nodes.put(flow, nodes = HashSetFactory.make()); + nodes.add(node); + return node; + } + + public CAstNode addFlow(CAstNode node, Object label, CAstNode target, CAstControlFlowMap flow) { + Set edges = extra_flow.get(flow); + if(edges == null) + extra_flow.put(flow, edges = HashSetFactory.make()); + edges.add(new Edge(node, label, target)); + return node; + } + + public void deleteFlow(CAstNode node, CAstEntity entity) { + CAstControlFlowMap flow = entity.getControlFlow(); + Set tmp = flow_to_delete.get(flow); + if(tmp == null) + flow_to_delete.put(flow, tmp = HashSetFactory.make()); + tmp.add(node); + } + + protected boolean isFlowDeleted(CAstNode node, CAstEntity entity) { + CAstControlFlowMap flow = entity.getControlFlow(); + return flow_to_delete.containsKey(flow) && flow_to_delete.get(flow).contains(node); + } + + public CAstEntity getCurrentEntity() { + return entities.peek(); + } + + public Iterable getEnclosingEntities() { + return entities; + } + + public void addEntity(CAstNode anchor, CAstEntity entity) { + entities_to_add.add(new Entity(anchor, entity)); + } + + @Override + protected Map> copyChildren(CAstNode root, Map,CAstNode> nodeMap, Map> children) { + Map> map = super.copyChildren(root, nodeMap, children); + // extend with local mapping information + for(Iterator es = entities_to_add.iterator(); es.hasNext(); ) { + Entity e = es.next(); + boolean relevant = NodePos.inSubtree(e.anchor, nodeMap.get(Pair.make(root, null))) || NodePos.inSubtree(e.anchor, root); + if(relevant) { + Collection c = map.get(e.anchor); + if(c == null) + map.put(e.anchor, c = HashSetFactory.make()); + c.add(e.me); + es.remove(); + } + } + return map; + } + + @Override + protected CAstNode flowOutTo(Map, CAstNode> nodeMap, + CAstNode oldSource, Object label, CAstNode oldTarget, + CAstControlFlowMap orig, CAstSourcePositionMap src) { + if(oldTarget == CAstControlFlowMap.EXCEPTION_TO_EXIT) + return oldTarget; + Assertions.UNREACHABLE(); + return super.flowOutTo(nodeMap, oldSource, label, oldTarget, orig, src); + } + + @Override + protected CAstControlFlowMap copyFlow(Map,CAstNode> nodeMap, CAstControlFlowMap orig, CAstSourcePositionMap newSrc) { + Map,CAstNode> nodeMapCopy = HashMapFactory.make(nodeMap); + // delete flow if necessary + // TODO: this is bad; what if one of the deleted nodes occurs as a cflow target? + if(flow_to_delete.containsKey(orig)) { + for(CAstNode node : flow_to_delete.get(orig)) { + nodeMapCopy.remove(Pair.make(node, null)); + } + //flow_to_delete.remove(orig); + } + CAstControlFlowRecorder flow = (CAstControlFlowRecorder)super.copyFlow(nodeMapCopy, orig, newSrc); + // extend with local flow information + if(extra_nodes.containsKey(orig)) { + for(CAstNode nd : extra_nodes.get(orig)) + flow.map(nd, nd); + } + if(extra_flow.containsKey(orig)) { + for(Edge e : extra_flow.get(orig)) { + CAstNode from = e.from; + Object label = e.label; + CAstNode to = e.to; + if(nodeMap.containsKey(Pair.make(from, null))) + from = nodeMap.get(Pair.make(from, null)); + if(nodeMap.containsKey(Pair.make(to, null))) + to = nodeMap.get(Pair.make(to, null)); + if(!flow.isMapped(from)) + flow.map(from, from); + if(!flow.isMapped(to)) + flow.map(to, to); + flow.add(from, to, label); + } + /* + * Here, we would like to say extra_flow.remove(orig) to get rid of the extra control flow + * information, but that would not be correct: a single old cfg may be carved up into several + * new ones, each of which needs to be extended with the appropriate extra flow from the old cfg. + * + * Unfortunately, we now end up extending _every_ new cfg with _all_ the extra flow from the old + * cfg, which doesn't sound right either. + */ + } + return flow; + } + + Map rewrite_cache = HashMapFactory.make(); + @Override + public CAstEntity rewrite(CAstEntity root) { + // avoid rewriting the same entity more than once + // TODO: figure out why this happens in the first place + if(rewrite_cache.containsKey(root)) { + return rewrite_cache.get(root); + } else { + entities.push(root); + enterEntity(root); + CAstEntity entity = super.rewrite(root); + rewrite_cache.put(root, entity); + leaveEntity(root); + entities.pop(); + return entity; + } + } + + protected void enterEntity(CAstEntity entity) {} + protected void leaveEntity(CAstEntity entity) {} + + public CAstRewriterExt(CAst Ast, boolean recursive, NodePos rootContext) { + super(Ast, recursive, rootContext); + } + +} \ No newline at end of file diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ChildPos.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ChildPos.java new file mode 100644 index 000000000..8f82005be --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ChildPos.java @@ -0,0 +1,92 @@ +/****************************************************************************** + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations.extraction; + +import com.ibm.wala.cast.tree.CAstNode; + +/** + * A {@link NodePos} for a non-root node; includes information about the parent node, the child index, and + * the position of the parent node. + * + * @author mschaefer + * + */ +public class ChildPos extends NodePos { + private CAstNode parent; + private int index; + private NodePos parent_pos; + + public ChildPos(CAstNode parent, int index, NodePos parent_pos) { + this.parent = parent; + this.index = index; + this.parent_pos = parent_pos; + } + + public CAstNode getParent() { + return parent; + } + + public int getIndex() { + return index; + } + + public NodePos getParentPos() { + return parent_pos; + } + + public CAstNode getChild() { + return parent.getChild(index); + } + + public ChildPos getChildPos(int index) { + return new ChildPos(this.getChild(), index, this); + } + + @Override + public A accept(PosSwitch ps) { + return ps.caseChildPos(this); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + index; + result = prime * result + ((parent == null) ? 0 : parent.hashCode()); + result = prime * result + ((parent_pos == null) ? 0 : parent_pos.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ChildPos other = (ChildPos) obj; + if (index != other.index) + return false; + if (parent == null) { + if (other.parent != null) + return false; + } else if (!parent.equals(other.parent)) + return false; + if (parent_pos == null) { + if (other.parent_pos != null) + return false; + } else if (!parent_pos.equals(other.parent_pos)) + return false; + return true; + } +} diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ClosureExtractor.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ClosureExtractor.java new file mode 100644 index 000000000..a41fba314 --- /dev/null +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/correlations/extraction/ClosureExtractor.java @@ -0,0 +1,727 @@ +/****************************************************************************** + * Copyright (c) 2011 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.cast.js.ipa.callgraph.correlations.extraction; + +import static com.ibm.wala.cast.tree.CAstNode.ASSIGN; +import static com.ibm.wala.cast.tree.CAstNode.BINARY_EXPR; +import static com.ibm.wala.cast.tree.CAstNode.BLOCK_STMT; +import static com.ibm.wala.cast.tree.CAstNode.BREAK; +import static com.ibm.wala.cast.tree.CAstNode.CALL; +import static com.ibm.wala.cast.tree.CAstNode.CONSTANT; +import static com.ibm.wala.cast.tree.CAstNode.CONTINUE; +import static com.ibm.wala.cast.tree.CAstNode.EMPTY; +import static com.ibm.wala.cast.tree.CAstNode.FUNCTION_EXPR; +import static com.ibm.wala.cast.tree.CAstNode.FUNCTION_STMT; +import static com.ibm.wala.cast.tree.CAstNode.GOTO; +import static com.ibm.wala.cast.tree.CAstNode.IFGOTO; +import static com.ibm.wala.cast.tree.CAstNode.LABEL_STMT; +import static com.ibm.wala.cast.tree.CAstNode.LOOP; +import static com.ibm.wala.cast.tree.CAstNode.OBJECT_LITERAL; +import static com.ibm.wala.cast.tree.CAstNode.OBJECT_REF; +import static com.ibm.wala.cast.tree.CAstNode.OPERATOR; +import static com.ibm.wala.cast.tree.CAstNode.RETURN; +import static com.ibm.wala.cast.tree.CAstNode.SWITCH; +import static com.ibm.wala.cast.tree.CAstNode.THROW; +import static com.ibm.wala.cast.tree.CAstNode.TRY; +import static com.ibm.wala.cast.tree.CAstNode.VAR; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import com.ibm.wala.cast.js.types.JavaScriptTypes; +import com.ibm.wala.cast.tree.CAst; +import com.ibm.wala.cast.tree.CAstControlFlowMap; +import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.CAstNode; +import com.ibm.wala.cast.tree.CAstNodeTypeMap; +import com.ibm.wala.cast.tree.CAstSourcePositionMap; +import com.ibm.wala.cast.tree.impl.CAstBasicRewriter.NoKey; +import com.ibm.wala.cast.tree.impl.CAstOperator; +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.debug.UnimplementedError; + +/** + * A CAst rewriter for extracting bits of code into one-shot closures. What to extract is determined + * by an {@link ExtractionPolicy}. + * + *

For instance, a {@link ForInBodyExtractionPolicy} extracts the body of every for-in loop in + * the program, whereas a {@link CorrelatedPairExtractionPolicy} extracts pieces of code containing + * correlated property reads and writes of the same property.

+ * + *

As an example, consider the following function:

+ *
+ *   function extend(dest, src) {
+ *     for(var p in src)
+ *       dest[p] = src[p];
+ *   }
+ * 
+ *

Under both {@link ForInBodyExtractionPolicy} and {@link CorrelatedPairExtractionPolicy}, this + * should be transformed into

+ *
+ *   function extend(dest, src) {
+ *     for(var p in src)
+ *       (function _forin_body_0(p) {
+ *         dest[p] = src[p];
+ *       })(p);
+ *   }
+ * 
+ * + *

There are four issues to be considered here.

+ *
    + *
  • References to this: + *

    If the code to extract contains references to this, these references have to be + * rewritten; otherwise they would refer to the global object in the transformed code.

    + *

    We do this by giving the extracted function an extra parameter thi$, and rewriting + * this to thi$ within the extracted code.

    + *

    For instance,

    + *
    + *   Object.prototype.extend = function(src) {
    + *     for(var p in src)
    + *       this[p] = src[p];
    + *   }
    + *   
    + *

    becomes

    + *
    + *   Object.prototype.extend = function(src) {
    + *     for(var p in src)
    + *       (function _forin_body_0(p, thi$) {
    + *         thi$[p] = src[p];
    + *       })(p, this);
    + *   }
    + *   
    + *
  • + *
  • Local variable declarations: + *

    Local variable declarations inside the extracted code have to be hoisted to the enclosing function; + * otherwise they would become local variables of the extracted function instead.

    + *

    This is already taken care of by the translation from Rhino's AST to CAst.

    + *
  • + *
  • break,continue,return: + *

    A break or continue statement within the extracted loop body that refers + * to the loop itself or an enclosing loop would become invalid in the transformed code. A return + * statement would no longer return from the enclosing function, but instead from the extracted function.

    + *

    We transform all three statements into return statements returning an object literal with a + * property type indicating whether this is a 'goto' (i.e., break or return) + * or a 'return'. In the former case, the 'target' property contains an integer identifying the jump target; in + * the latter case, the 'value' property contains the value to return.

    + *

    The return value of the extracted function is then examined to determine whether it completed normally + * (i.e., returned undefined), or whether it returned an object indicating special control flow.

    + *

    For example, consider this code from MooTools:

    + *
    + *   for(var style in Element.ShortStyles) {
    + *     if(property != style)
    + *       continue;
    + *     for(var s in Element.ShortStyles[style])
    + *       result.push(this.getStyle(s));
    + *     return result.join(' ');
    + *   }
    + *   
    + *

    Under {@link ForInBodyExtractionPolicy}, this is transformed into

    + *
    + *   for(var style in Element.ShortStyles) {
    + *     var s;
    + *     re$ = (function _forin_body_0(style, thi$) {
    + *       if(property != style)
    + *         return { type: 'goto', target: 1 };
    + *       for(s in Element.ShortStyles[style]) {
    + *         (function _forin_body_2(s) {
    + *           result.push(thi$.getStyle(s));
    + *         })(s);
    + *       }
    + *       return { type: 'return', value: result.join(' ') };
    + *     })(style, this);
    + *     if(re$) {
    + *       if(re$.type == 'return')
    + *         return re$.value;
    + *       if(re$.type == 'goto') {
    + *         if(re$.target == 1)
    + *           continue;
    + *       }
    + *     }
    + *   }
    + *   
    + *

    Note that at the CAst level, break and continue are represented as goto + * statements, which simplifies the translation somewhat. The numerical encoding of jump targets does not matter + * as long as the extracted function and the fixup code agree on which number represents which label.

    + *
  • + *
  • Assignment to loop variable: + *

    The loop body may assign to the loop variable. If the variable is referenced after the loop, this assignment + * needs to be propagated back to the enclosing function in the extracted code.

    + *

    TODO: This is not handled at the moment.

    + *
  • + *
+ * + *

Finally, note that exceptions do not need to be handled specially.

+ * + * @author mschaefer + * + */ +public class ClosureExtractor extends CAstRewriterExt { + private LinkedList policies = new LinkedList(); + private final ExtractionPolicyFactory policyFactory; + + // names for extracted functions are built from this string with a number appended + private static final String EXTRACTED_FUN_BASENAME = "_forin_body_"; + + private NodeLabeller labeller = new NodeLabeller(); + + public ClosureExtractor(CAst Ast, ExtractionPolicyFactory policyFactory) { + super(Ast, true, new RootPos()); + this.policyFactory = policyFactory; + } + + @Override + protected void enterEntity(CAstEntity entity) { + policies.push(policyFactory.createPolicy(entity)); + } + + @Override + protected void leaveEntity(CAstEntity entity) { + policies.pop(); + } + + @Override + protected CAstNode copyNodes(CAstNode root, NodePos context, Map, CAstNode> nodeMap) { + switch(root.getKind()) { + case OPERATOR: + return root; + case CONSTANT: + return copyConstant(root, context, nodeMap); + case BLOCK_STMT: + return copyBlock(root, context, nodeMap); + case RETURN: + return copyReturn(root, context, nodeMap); + case VAR: + return copyVar(root, context, nodeMap); + case GOTO: + return copyGoto(root, context, nodeMap); + default: + return copyNode(root, context, nodeMap); + } + } + + /* Constants are not affected by the rewriting, they are just copied. */ + private CAstNode copyConstant(CAstNode root, NodePos context, Map, CAstNode> nodeMap) { + CAstNode newNode = Ast.makeConstant(root.getValue()); + nodeMap.put(Pair.make(root, context.key()), newNode); + return newNode; + } + + /* Ask the policy whether it wants anything extracted from this block; otherwise the node is simply copied. */ + private CAstNode copyBlock(CAstNode root, NodePos context, Map, CAstNode> nodeMap) { + List regions = policies.getFirst().extract(root); + if(regions == null) { + return copyNode(root, context, nodeMap); + } else { + ArrayList copied_children = new ArrayList(); + int next_child = 0; + // code in between regions is handled by invoking copyNodes, the regions themselves by extractRegion + for(ExtractionRegion region : regions) { + for(;next_child, CAstNode> nodeMap) { + /* + * If this node is a "this" reference, the outermost enclosing extracted function needs to pass in + * the value of "this" as a parameter. + * + * NB: This has to be done by the _outermost_ function. If it were done by an inner function instead, + * the outermost one may not pass in the value of "this" at all, so the inner one would + * get the wrong value. + */ + if(root.getChild(0).getValue().equals("this")) { + ExtractionPos epos = ExtractionPos.getOutermostEnclosingExtractionPos(context); + if(epos != null) { + epos.addThis(); + CAstNode newNode = makeVarRef(epos.getThisParmName()); + addExnFlow(newNode, JavaScriptTypes.ReferenceError, getCurrentEntity(), context); + nodeMap.put(Pair.make(root, context.key()), newNode); + return newNode; + } else { + return copyNode(root, context, nodeMap); + } + } else { + return copyNode(root, context, nodeMap); + } + } + + /* + * 'break' and 'continue' statements are both encoded as GOTO. If they refer to a target outside the innermost + * enclosing extracted function body, they are rewritten into a 'return' statement. + */ + private CAstNode copyGoto(CAstNode root, NodePos context, Map, CAstNode> nodeMap) { + CAstNode target = getCurrentEntity().getControlFlow().getTarget(root, null); + ExtractionPos epos = ExtractionPos.getEnclosingExtractionPos(context); + if(epos != null && !NodePos.inSubtree(target, epos.getParent())) { + epos.addGotoTarget(target); + int label = labeller.addNode(target); + // return { type: 'goto', target: