add support for lexical writes

This commit is contained in:
Manu Sridharan 2013-01-03 16:09:48 -08:00
parent 26e7eb50ba
commit 5aa3a16587
2 changed files with 41 additions and 11 deletions

View File

@ -32,17 +32,23 @@ public abstract class TestTransitiveLexicalAccesses {
JSCFABuilder b = JSCallGraphBuilderUtil.makeScriptCGBuilder("tests", "simple-lexical.js");
CallGraph CG = b.makeCallGraph(b.getOptions());
TransitiveLexicalAccesses lexAccesses = TransitiveLexicalAccesses.make(CG, b.getPointerAnalysis());
Map<CGNode, OrdinalSet<Pair<CGNode, String>>> result = lexAccesses.computeLexVarsRead();
for (CGNode n : result.keySet()) {
Map<CGNode, OrdinalSet<Pair<CGNode, String>>> readResult = lexAccesses.computeLexVarsRead();
Map<CGNode, OrdinalSet<Pair<CGNode, String>>> writeResult = lexAccesses.computeLexVarsWritten();
for (CGNode n : readResult.keySet()) {
if (n.toString().contains("Node: <Code body of function Ltests/simple-lexical.js/outer/inner>")) {
// function "inner" reads exactly x and z
OrdinalSet<Pair<CGNode, String>> readVars = result.get(n);
OrdinalSet<Pair<CGNode, String>> readVars = readResult.get(n);
Assert.assertEquals(2, readVars.size());
Assert.assertEquals("[[Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,x], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,z]]", readVars.toString());
// writes x and z as well
OrdinalSet<Pair<CGNode, String>> writtenVars = writeResult.get(n);
Assert.assertEquals(2, writtenVars.size());
Assert.assertEquals("[[Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,x], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,z]]", writtenVars.toString());
}
if (n.toString().contains("Node: <Code body of function Ltests/simple-lexical.js/outer/inner2>")) {
// function "inner3" reads exactly innerName, inner3, and x and z via callees
OrdinalSet<Pair<CGNode, String>> readVars = result.get(n);
OrdinalSet<Pair<CGNode, String>> readVars = readResult.get(n);
Assert.assertEquals(4, readVars.size());
Assert.assertEquals("[[Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,inner3], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,innerName], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,x], [Node: <Code body of function Ltests/simple-lexical.js/outer> Context: Everywhere,z]]", readVars.toString());
}

View File

@ -16,6 +16,7 @@ import java.util.Map;
import com.ibm.wala.cast.ipa.callgraph.ScopeMappingInstanceKeys.ScopeMappingInstanceKey;
import com.ibm.wala.cast.ir.ssa.AstLexicalAccess.Access;
import com.ibm.wala.cast.ir.ssa.AstLexicalRead;
import com.ibm.wala.cast.ir.ssa.AstLexicalWrite;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.CallGraphTransitiveClosure;
@ -58,17 +59,23 @@ public class TransitiveLexicalAccesses {
}
public Map<CGNode, OrdinalSet<Pair<CGNode, String>>> computeLexVarsRead() {
Map<CGNode, Collection<Pair<CGNode, String>>> scan = scanForLexReads();
return CallGraphTransitiveClosure.transitiveClosure(cg, scan);
}
private Map<CGNode, Collection<Pair<CGNode, String>>> scanForLexReads() {
return CallGraphTransitiveClosure.collectNodeResults(cg, new Function<CGNode, Collection<Pair<CGNode,String>>>() {
Map<CGNode, Collection<Pair<CGNode, String>>> scan = CallGraphTransitiveClosure.collectNodeResults(cg, new Function<CGNode, Collection<Pair<CGNode,String>>>() {
public Collection<Pair<CGNode, String>> apply(CGNode n) {
return scanNodeForLexReads(n);
}
});
return CallGraphTransitiveClosure.transitiveClosure(cg, scan);
}
public Map<CGNode, OrdinalSet<Pair<CGNode, String>>> computeLexVarsWritten() {
Map<CGNode, Collection<Pair<CGNode, String>>> scan = CallGraphTransitiveClosure.collectNodeResults(cg, new Function<CGNode, Collection<Pair<CGNode,String>>>() {
public Collection<Pair<CGNode, String>> apply(CGNode n) {
return scanNodeForLexWrites(n);
}
});
return CallGraphTransitiveClosure.transitiveClosure(cg, scan);
}
protected Collection<Pair<CGNode, String>> scanNodeForLexReads(CGNode n) {
@ -88,6 +95,23 @@ public class TransitiveLexicalAccesses {
return result;
}
protected Collection<Pair<CGNode, String>> scanNodeForLexWrites(CGNode n) {
Collection<Pair<CGNode, String>> result = HashSetFactory.make();
IR ir = n.getIR();
if (ir != null) {
for (SSAInstruction instr: Iterator2Iterable.make(ir.iterateNormalInstructions())) {
if (instr instanceof AstLexicalWrite) {
AstLexicalWrite write = (AstLexicalWrite) instr;
for (Access a : write.getAccesses()) {
Pair<String, String> nameAndDefiner = a.getName();
result.addAll(getNodeNamePairsForAccess(n, nameAndDefiner));
}
}
}
}
return result;
}
private Collection<Pair<CGNode, String>> getNodeNamePairsForAccess(CGNode n, Pair<String, String> nameAndDefiner) {
Collection<Pair<CGNode, String>> result = HashSetFactory.make();
// use scope-mapping instance keys in pointer analysis. may need a different