more global object handling; needs documentation

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@4324 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
msridhar1 2012-01-06 21:23:56 +00:00
parent 549c3d2775
commit 8ce7db97ea
6 changed files with 56 additions and 16 deletions

View File

@ -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));
}

View File

@ -1 +1,5 @@
z = (function foo() { return this; })();
function biz(p) { return p; }
var z = (function foo() { return this; })();
var x = z.biz(3);

View File

@ -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<Set<Pair<CGNode, Integer>>> computeIkIdToVns(PointerAnalysis pa) {
// Created by reversing the points to mapping for local pointer keys.

View File

@ -19,4 +19,7 @@ public class GlobalObjectKey implements InstanceKey {
return concreteType;
}
public String toString() {
return "JS Global Object";
}
}

View File

@ -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<InstanceKey>(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()) {

View File

@ -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