diff --git a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ArgumentSpecialization.java b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ArgumentSpecialization.java index 5f1f55c8f..a8c8b20f4 100644 --- a/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ArgumentSpecialization.java +++ b/com.ibm.wala.cast.js/source/com/ibm/wala/cast/js/ipa/callgraph/ArgumentSpecialization.java @@ -27,6 +27,7 @@ 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.rewrite.CAstBasicRewriter; +import com.ibm.wala.cast.tree.rewrite.CAstBasicRewriter.NonCopyingContext; import com.ibm.wala.cast.util.CAstPattern; import com.ibm.wala.cast.util.CAstPattern.Segments; import com.ibm.wala.cfg.AbstractCFG; @@ -183,12 +184,12 @@ public class ArgumentSpecialization { if (v != null) { final JavaScriptLoader myloader = (JavaScriptLoader) method.getDeclaringClass().getClassLoader(); - class FixedArgumentsRewriter extends CAstBasicRewriter { + class FixedArgumentsRewriter extends CAstBasicRewriter { private final CAstEntity e; private final Map argRefs = HashMapFactory.make(); public FixedArgumentsRewriter(CAst Ast) { - super(Ast, false); + super(Ast, new NonCopyingContext(), false); this.e = m.getEntity(); for(Segments s : CAstPattern.findAll(destructuredAccessPattern, m.getEntity())) { argRefs.put(s.getSingle("name").getValue().toString(), s.getSingle("value")); diff --git a/com.ibm.wala.cast.test/harness-src/java/com/ibm/wala/cast/test/TestConstantCollector.java b/com.ibm.wala.cast.test/harness-src/java/com/ibm/wala/cast/test/TestConstantCollector.java new file mode 100644 index 000000000..f5b095e2f --- /dev/null +++ b/com.ibm.wala.cast.test/harness-src/java/com/ibm/wala/cast/test/TestConstantCollector.java @@ -0,0 +1,192 @@ +package com.ibm.wala.cast.test; + +import java.util.Collection; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; + +import org.junit.Test; + +import com.ibm.wala.cast.tree.CAst; +import com.ibm.wala.cast.tree.CAstAnnotation; +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.CAstQualifier; +import com.ibm.wala.cast.tree.CAstSourcePositionMap; +import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; +import com.ibm.wala.cast.tree.CAstType; +import com.ibm.wala.cast.tree.impl.CAstImpl; +import com.ibm.wala.cast.tree.impl.CAstOperator; +import com.ibm.wala.cast.tree.rewrite.AstConstantFolder; +import com.ibm.wala.cast.util.AstConstantCollector; +import com.ibm.wala.cast.util.CAstPattern; +import com.ibm.wala.cast.util.CAstPattern.Segments; +import com.ibm.wala.util.collections.EmptyIterator; + +public class TestConstantCollector { + + private CAst ast = new CAstImpl(); + + private static CAstEntity fakeEntity(CAstNode root) { + return new CAstEntity() { + + @Override + public int getKind() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public String getName() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String getSignature() { + // TODO Auto-generated method stub + return null; + } + + @Override + public String[] getArgumentNames() { + // TODO Auto-generated method stub + return null; + } + + @Override + public CAstNode[] getArgumentDefaults() { + // TODO Auto-generated method stub + return null; + } + + @Override + public int getArgumentCount() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public Map> getAllScopedEntities() { + return Collections.emptyMap(); + } + + @Override + public Iterator getScopedEntities(CAstNode construct) { + return EmptyIterator.instance(); + } + + @Override + public CAstNode getAST() { + return root; + } + + @Override + public CAstControlFlowMap getControlFlow() { + // TODO Auto-generated method stub + return null; + } + + @Override + public CAstSourcePositionMap getSourceMap() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Position getPosition() { + // TODO Auto-generated method stub + return null; + } + + @Override + public CAstNodeTypeMap getNodeTypeMap() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getQualifiers() { + // TODO Auto-generated method stub + return null; + } + + @Override + public CAstType getType() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Collection getAnnotations() { + // TODO Auto-generated method stub + return null; + } + }; + } + + private CAstNode root1 = + ast.makeNode(CAstNode.BLOCK_STMT, + ast.makeNode(CAstNode.ASSIGN, + ast.makeNode(CAstNode.VAR, + ast.makeConstant("var1")), + ast.makeConstant(15))); + + @Test + public void testSegmentsRoot1() { + Collection x = CAstPattern.findAll(AstConstantCollector.simpleValuePattern, fakeEntity(root1)); + assert x.size() == 1; + } + + @Test + public void testRoot1() { + Map x = AstConstantCollector.collectConstants(fakeEntity(root1)); + assert x.size() == 1; + } + + private CAstNode root2 = + ast.makeNode(CAstNode.BLOCK_STMT, + ast.makeNode(CAstNode.ASSIGN, + ast.makeNode(CAstNode.VAR, + ast.makeConstant("var1")), + ast.makeConstant(15)), + ast.makeNode(CAstNode.ASSIGN, + ast.makeNode(CAstNode.VAR, + ast.makeConstant("var1")), + ast.makeConstant(14))); + + @Test + public void testSegmentsRoot2() { + Collection x = CAstPattern.findAll(AstConstantCollector.simpleValuePattern, fakeEntity(root2)); + assert x.size() == 2; + } + + @Test + public void testRoot2() { + Map x = AstConstantCollector.collectConstants(fakeEntity(root2)); + assert x.size() == 0; + } + + private CAstNode root3 = + ast.makeNode(CAstNode.BLOCK_EXPR, + ast.makeNode(CAstNode.ASSIGN, + ast.makeNode(CAstNode.VAR, + ast.makeConstant("var1")), + ast.makeConstant(15)), + ast.makeNode(CAstNode.BINARY_EXPR, + CAstOperator.OP_ADD, + ast.makeConstant(10), + ast.makeNode(CAstNode.VAR, ast.makeConstant("var1")))); + + public static final CAstPattern toCodePattern3 = CAstPattern.parse("BINARY_EXPR(*,\"10\",\"15\")"); + + @Test + public void testRoot3() { + CAstEntity ce = fakeEntity(root3); + CAstEntity nce = AstConstantFolder.fold(ce); + Collection matches = CAstPattern.findAll(toCodePattern3, nce); + assert matches.size() == 1; + } +} 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 be5cfe20f..cf031dd9e 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 @@ -4604,7 +4604,7 @@ public abstract class AstTranslator extends CAstVisitor { protected ConstantFoldingRewriter(CAst Ast) { - super(Ast, true); + super(Ast, new NonCopyingContext(), true); } protected abstract Object eval(CAstOperator op, Object lhs, Object rhs); diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/AstConstantFolder.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/AstConstantFolder.java new file mode 100644 index 000000000..1a94dcbe0 --- /dev/null +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/AstConstantFolder.java @@ -0,0 +1,85 @@ +package com.ibm.wala.cast.tree.rewrite; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +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.CAstImpl; +import com.ibm.wala.cast.tree.impl.DelegatingEntity; +import com.ibm.wala.cast.tree.rewrite.CAstBasicRewriter.NonCopyingContext; +import com.ibm.wala.cast.tree.rewrite.CAstRewriter.Rewrite; +import com.ibm.wala.cast.util.AstConstantCollector; +import com.ibm.wala.util.collections.EmptyIterator; +import com.ibm.wala.util.collections.HashSetFactory; +import com.ibm.wala.util.collections.Pair; + +public class AstConstantFolder { + static class AssignSkipContext extends NonCopyingContext { + private Set skip = HashSetFactory.make(); + } + + public static CAstEntity fold(CAstEntity ce) { + Map constants = AstConstantCollector.collectConstants(ce); + if (constants.isEmpty()) { + return ce; + } else { + Rewrite nce = new CAstCloner(new CAstImpl(), new AssignSkipContext(), true) { + + @Override + protected CAstNode copyNodes(CAstNode root, CAstControlFlowMap cfg, NonCopyingContext c, + Map, CAstNode> nodeMap) { + + if (root.getKind() == CAstNode.ASSIGN) { + ((AssignSkipContext)c).skip.add(root.getChild(0)); + } + + if (root.getKind() == CAstNode.VAR && constants.containsKey(root.getChild(0).getValue()) && ! ((AssignSkipContext)c).skip.contains(root)) { + return Ast.makeConstant(constants.get(root.getChild(0).getValue())); + } else { + return super.copyNodes(root, cfg, c, nodeMap); + } + } + + }.rewrite(ce.getAST(), ce.getControlFlow(), ce.getSourceMap(), ce.getNodeTypeMap(), ce.getAllScopedEntities()); + return new DelegatingEntity(ce) { + + @Override + public CAstNode getAST() { + return nce.newRoot(); + } + + @Override + public CAstControlFlowMap getControlFlow() { + return nce.newCfg(); + } + + @Override + public CAstSourcePositionMap getSourceMap() { + return nce.newPos(); + } + + @Override + public CAstNodeTypeMap getNodeTypeMap() { + return nce.newTypes(); + } + + @Override + public Map> getAllScopedEntities() { + return nce.newChildren(); + } + + @Override + public Iterator getScopedEntities(CAstNode construct) { + Collection children = nce.newChildren().get(construct); + return children==null? EmptyIterator.instance(): children.iterator(); + } + }; + } + } +} diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstBasicRewriter.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstBasicRewriter.java index aa1f1311f..2347202b1 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstBasicRewriter.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstBasicRewriter.java @@ -23,8 +23,8 @@ import com.ibm.wala.util.debug.Assertions; * abstract base class for {@link CAstRewriter}s that do no cloning of nodes * */ -public abstract class CAstBasicRewriter - extends CAstRewriter + extends CAstRewriter { @@ -69,11 +69,11 @@ public abstract class CAstBasicRewriter } } - protected CAstBasicRewriter(CAst Ast, boolean recursive) { - super(Ast, recursive, new NonCopyingContext()); + protected CAstBasicRewriter(CAst Ast, T context, boolean recursive) { + super(Ast, recursive, context); } @Override - protected abstract CAstNode copyNodes(CAstNode root, final CAstControlFlowMap cfg, NonCopyingContext context, Map, CAstNode> nodeMap); + protected abstract CAstNode copyNodes(CAstNode root, final CAstControlFlowMap cfg, T context, Map, CAstNode> nodeMap); } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstCloner.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstCloner.java index 5c4c85f84..8902fd012 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstCloner.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstCloner.java @@ -22,25 +22,22 @@ import com.ibm.wala.cast.tree.CAstSourcePositionMap; import com.ibm.wala.cast.tree.impl.CAstOperator; import com.ibm.wala.util.collections.Pair; -public class CAstCloner extends CAstBasicRewriter { +public class CAstCloner extends CAstBasicRewriter { public CAstCloner(CAst Ast, boolean recursive) { - super(Ast, recursive); + this(Ast, new NonCopyingContext(), recursive); } public CAstCloner(CAst Ast) { this(Ast, false); } + protected CAstCloner(CAst Ast, NonCopyingContext context, boolean recursive) { + super(Ast, context, recursive); + } + @Override protected CAstNode copyNodes(CAstNode root, final CAstControlFlowMap cfg, NonCopyingContext c, Map, CAstNode> nodeMap) { - return copyNodesHackForEclipse(root, cfg, c, nodeMap); - } - - /** - * what is the hack here? --MS - */ - protected CAstNode copyNodesHackForEclipse(CAstNode root, final CAstControlFlowMap cfg, NonCopyingContext c, Map, CAstNode> nodeMap) { final Pair pairKey = Pair.make(root, c.key()); if (root instanceof CAstOperator) { nodeMap.put(pairKey, root); diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstRewriter.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstRewriter.java index 427f20320..7a95c2015 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstRewriter.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/tree/rewrite/CAstRewriter.java @@ -361,7 +361,7 @@ public abstract class CAstRewriter, K e @Override public CAstControlFlowMap newCfg() { - if (theCfg == null) + if (theCfg == null && cfg != null) theCfg = copyFlow(nodes, cfg, newPos()); return theCfg; } @@ -375,7 +375,7 @@ public abstract class CAstRewriter, K e @Override public CAstNodeTypeMap newTypes() { - if (theTypes == null) + if (theTypes == null && types != null) theTypes = copyTypes(nodes, types); return theTypes; } diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/AstConstantCollector.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/AstConstantCollector.java new file mode 100644 index 000000000..8d57bc16f --- /dev/null +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/AstConstantCollector.java @@ -0,0 +1,64 @@ +package com.ibm.wala.cast.util; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import com.ibm.wala.cast.tree.CAstEntity; +import com.ibm.wala.cast.tree.CAstNode; +import com.ibm.wala.cast.util.CAstPattern.Segments; +import com.ibm.wala.util.collections.HashMapFactory; +import com.ibm.wala.util.collections.HashSetFactory; + +public class AstConstantCollector { + + public static final CAstPattern simplePreUpdatePattern = CAstPattern.parse("ASSIGN_PRE_OP(VAR(CONSTANT()),**)"); + + public static final CAstPattern simplePostUpdatePattern = CAstPattern.parse("ASSIGN_POST_OP(VAR(CONSTANT()),**)"); + + public static final CAstPattern simpleValuePattern = CAstPattern.parse("ASSIGN(VAR(CONSTANT()),*)"); + + public static Map collectConstants(CAstEntity function, Map values) { + if (function.getAST() != null) { + Set bad = HashSetFactory.make(); + for(Segments s : CAstPattern.findAll(simplePreUpdatePattern, function)) { + bad.add((String) s.getSingle("name").getValue()); + } + for(Segments s : CAstPattern.findAll(simplePostUpdatePattern, function)) { + bad.add((String) s.getSingle("name").getValue()); + } + for(Segments s : CAstPattern.findAll(simpleValuePattern, function)) { + String var = (String) s.getSingle("name").getValue(); + if (s.getSingle("value").getKind() != CAstNode.CONSTANT) { + bad.add(var); + } else { + Object val = s.getSingle("value").getValue(); + if (! bad.contains(var)) { + if (values.containsKey(var)) { + if (!values.get(var).equals(val)) { + values.remove(var); + bad.add(var); + } + } else { + values.put(var, val); + } + } + } + } + } + + for(Collection ces : function.getAllScopedEntities().values()) { + for(CAstEntity ce : ces) { + collectConstants(ce, values); + } + } + + return values; + } + + public static Map collectConstants(CAstEntity function) { + Map values = HashMapFactory.make(); + collectConstants(function, values); + return values; + } +} diff --git a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPattern.java b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPattern.java index 385094438..64f428a7d 100644 --- a/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPattern.java +++ b/com.ibm.wala.cast/source/java/com/ibm/wala/cast/util/CAstPattern.java @@ -408,6 +408,13 @@ public class CAstPattern { visit(top, c, this); return result; } + + @Override + protected boolean doVisit(CAstNode n, Context context, CAstVisitor visitor) { + return true; + } + + } private static class Parser { diff --git a/com.ibm.wala.core.tests/build.properties b/com.ibm.wala.core.tests/build.properties index 84faea788..1855b099a 100644 --- a/com.ibm.wala.core.tests/build.properties +++ b/com.ibm.wala.core.tests/build.properties @@ -3,6 +3,5 @@ source.. = src/,\ output.. = bin/test bin.includes = META-INF/,\ .,\ - plugin.xml,\ - plugin.properties + plugin.properties javacProjectSettings = true diff --git a/com.ibm.wala.core.tests/plugin.xml b/com.ibm.wala.core.tests/plugin.xml deleted file mode 100644 index 1d3dd8bf1..000000000 --- a/com.ibm.wala.core.tests/plugin.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - 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 20ea62235..838bd861e 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 @@ -118,7 +118,7 @@ public class AnalysisScope { */ private SetOfClasses exclusions; - final protected LinkedHashMap loadersByName = new LinkedHashMap<>(); + public final LinkedHashMap loadersByName = new LinkedHashMap<>(); /** * Special class loader for array instances