first cut at handling inner classes properly; moving around of code for analysis engines to make them provide a default way to build a call graph
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@657 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
76a937a3e2
commit
55e7a45e53
|
@ -23,6 +23,7 @@ Export-Package: com.ibm.wala.cast.java,
|
|||
com.ibm.wala.cast.java.types,
|
||||
java_cup,
|
||||
java_cup.runtime,
|
||||
java_cup.simple_calc,
|
||||
polyglot.ast,
|
||||
polyglot.ext.param,
|
||||
polyglot.ext.param.types,
|
||||
|
@ -38,3 +39,6 @@ Export-Package: com.ibm.wala.cast.java,
|
|||
polyglot.util,
|
||||
polyglot.util.typedump,
|
||||
polyglot.visit
|
||||
Bundle-ClassPath: lib/java_cup.jar,
|
||||
lib/polyglot.jar,
|
||||
.
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
.,\
|
||||
lib/java_cup.jar,\
|
||||
lib/polyglot.jar
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.ibm.wala.ipa.cha.*;
|
|||
import com.ibm.wala.shrikeBT.BinaryOpInstruction;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
public class AstJavaTypeInference extends AstTypeInference {
|
||||
|
||||
|
@ -42,6 +43,16 @@ public class AstJavaTypeInference extends AstTypeInference {
|
|||
}
|
||||
}
|
||||
|
||||
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
|
||||
TypeReference type = inst.getEnclosingType();
|
||||
IClass klass = cha.lookupClass(type);
|
||||
if (klass == null) {
|
||||
Assertions.UNREACHABLE();
|
||||
} else {
|
||||
result = new DeclaredTypeOperator(new ConeType(klass, cha));
|
||||
}
|
||||
}
|
||||
|
||||
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
|
||||
TypeReference type = instruction.getDeclaredResultType();
|
||||
if (type.isReferenceType()) {
|
||||
|
|
|
@ -135,38 +135,10 @@ public class EclipseProjectSourceAnalysisEngine extends
|
|||
return cha;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the call graph for the analysis scope in effect, using all of entry points
|
||||
* on the given entry set of "entry classes".
|
||||
* <p>Prerequisite: you must have either supplied an IJavaProject at construction time,
|
||||
* or called addSource/Compiled/SystemModule() to set up the analysis scope.
|
||||
* @param entryClassNames an array of class names, each main method of which is to be
|
||||
* used as an entry point during call graph construction.
|
||||
*/
|
||||
public CallGraph buildDefaultCallGraph(String[] entryClassNames) {
|
||||
buildAnalysisScope();
|
||||
ClassHierarchy cha= buildClassHierarchy();
|
||||
setClassHierarchy(cha);
|
||||
Entrypoints entryPoints= Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE_REF, cha, entryClassNames);
|
||||
AnalysisOptions options= getDefaultOptions(entryPoints);
|
||||
CallGraphBuilder cgb= buildCallGraph(cha, options, true);
|
||||
CallGraph cg= cgb.makeCallGraph(options);
|
||||
return cg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the call graph for the analysis scope in effect, using all of the given entry points.
|
||||
* <p>Prerequisite: you must have either supplied an IJavaProject at construction time,
|
||||
* or called addSource/Compiled/SystemModule() to set up the analysis scope.
|
||||
*/
|
||||
public CallGraph buildDefaultCallGraph(Entrypoints entryPoints) {
|
||||
buildAnalysisScope();
|
||||
ClassHierarchy cha= buildClassHierarchy();
|
||||
setClassHierarchy(cha);
|
||||
AnalysisOptions options= getDefaultOptions(entryPoints);
|
||||
CallGraphBuilder cgb= buildCallGraph(cha, options, true);
|
||||
CallGraph cg= cgb.makeCallGraph(options);
|
||||
return cg;
|
||||
protected Entrypoints
|
||||
makeDefaultEntrypoints(AnalysisScope scope, ClassHierarchy cha)
|
||||
{
|
||||
return Util.makeMainEntrypoints(JavaSourceAnalysisScope.SOURCE_REF, cha);
|
||||
}
|
||||
|
||||
public AnalysisOptions getDefaultOptions(Entrypoints entrypoints) {
|
||||
|
|
|
@ -10,20 +10,22 @@
|
|||
*****************************************************************************/
|
||||
package com.ibm.wala.cast.java.ipa.callgraph;
|
||||
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.analysis.typeInference.TypeInference;
|
||||
import com.ibm.wala.classLoader.*;
|
||||
import com.ibm.wala.cast.ipa.callgraph.AstSSAPropagationCallGraphBuilder;
|
||||
import com.ibm.wala.cast.ir.ssa.*;
|
||||
import com.ibm.wala.cast.java.analysis.typeInference.AstJavaTypeInference;
|
||||
import com.ibm.wala.cast.java.ssa.AstJavaInstructionVisitor;
|
||||
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
|
||||
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl.JavaClass;
|
||||
import com.ibm.wala.cast.java.ssa.*;
|
||||
import com.ibm.wala.ipa.callgraph.*;
|
||||
import com.ibm.wala.ipa.callgraph.impl.ExplicitCallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.*;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.DefUse;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.ssa.SSACFG.BasicBlock;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
import com.ibm.wala.util.intset.*;
|
||||
import com.ibm.wala.util.warnings.WarningSet;
|
||||
|
||||
public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCallGraphBuilder {
|
||||
|
@ -47,6 +49,35 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
|
|||
return false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// enclosing object pointer flow support
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public class EnclosingObjectReferenceKey extends AbstractFieldPointerKey {
|
||||
private final IClass outer;
|
||||
|
||||
private EnclosingObjectReferenceKey(InstanceKey inner, IClass outer) {
|
||||
super(inner);
|
||||
this.outer = outer;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return getInstanceKey().hashCode() * outer.hashCode();
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
return
|
||||
(o instanceof EnclosingObjectReferenceKey)
|
||||
&&
|
||||
((EnclosingObjectReferenceKey)o).outer.equals(outer)
|
||||
&&
|
||||
((EnclosingObjectReferenceKey)o)
|
||||
.getInstanceKey().equals(getInstanceKey());
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// top-level node constraint generation
|
||||
|
@ -81,6 +112,10 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
|
|||
super(vn);
|
||||
}
|
||||
|
||||
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
|
||||
Assertions.UNREACHABLE();
|
||||
}
|
||||
|
||||
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
|
||||
bingo = true;
|
||||
}
|
||||
|
@ -106,6 +141,10 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
|
|||
super(node, ir, bb);
|
||||
}
|
||||
|
||||
public void visitEnclosingObjectReference(EnclosingObjectReference x) {
|
||||
|
||||
}
|
||||
|
||||
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
|
||||
|
||||
}
|
||||
|
@ -142,7 +181,60 @@ public class AstJavaSSAPropagationCallGraphBuilder extends AstSSAPropagationCall
|
|||
public AstJavaConstraintVisitor(ExplicitCallGraph.ExplicitNode node, IR ir, ExplicitCallGraph callGraph, DefUse du) {
|
||||
super(node, ir, callGraph, du);
|
||||
}
|
||||
|
||||
|
||||
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
|
||||
SymbolTable symtab = ir.getSymbolTable();
|
||||
final PointerKey lvalKey = getPointerKeyForLocal(node, inst.getDef());
|
||||
PointerKey objKey = getPointerKeyForLocal(node, 1);
|
||||
final IClass cls = cha.lookupClass( inst.getEnclosingType() );
|
||||
|
||||
if (contentsAreInvariant(symtab, du, 1)) {
|
||||
system.recordImplicitPointsToSet(objKey);
|
||||
|
||||
InstanceKey[] objs = getInvariantContents(symtab, du, node, 1, AstJavaSSAPropagationCallGraphBuilder.this);
|
||||
|
||||
for(int i = 0; i < objs.length; i++) {
|
||||
PointerKey enclosing = new EnclosingObjectReferenceKey(objs[i], cls);
|
||||
system.newConstraint(lvalKey, assignOperator, enclosing);
|
||||
}
|
||||
|
||||
} else {
|
||||
PointsToSetVariable tv = system.findOrCreatePointsToSet( objKey );
|
||||
tv.getValue().foreach(new IntSetAction() {
|
||||
public void act(int ptr) {
|
||||
InstanceKey iKey = system.getInstanceKey(ptr);
|
||||
PointerKey enclosing = new EnclosingObjectReferenceKey(iKey, cls);
|
||||
system.newConstraint(lvalKey, assignOperator, enclosing);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void visitNew(SSANewInstruction instruction) {
|
||||
super.visitNew(instruction);
|
||||
InstanceKey iKey =
|
||||
getInstanceKeyForAllocation(node, instruction.getNewSite());
|
||||
|
||||
if (iKey != null) {
|
||||
IClass klass = iKey.getConcreteType();
|
||||
|
||||
if (klass instanceof JavaClass) {
|
||||
IClass enclosingClass = ((JavaClass)klass).getEnclosingClass();
|
||||
if (enclosingClass != null) {
|
||||
Assertions._assert(
|
||||
cha.isSubclassOf(
|
||||
node.getMethod().getDeclaringClass(),
|
||||
enclosingClass));
|
||||
|
||||
PointerKey objKey = getPointerKeyForLocal(node, 1);
|
||||
PointerKey x =
|
||||
new EnclosingObjectReferenceKey(iKey, enclosingClass);
|
||||
system.newConstraint(x, assignOperator, objKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitJavaInvoke(AstJavaInvokeInstruction instruction) {
|
||||
visitInvokeInternal(instruction);
|
||||
}
|
||||
|
|
|
@ -127,6 +127,10 @@ public abstract class JavaSourceLoaderImpl extends ClassLoaderImpl {
|
|||
declaredFields.put(Util.fieldEntityToAtom(fieldEntity), new JavaField(fieldEntity, JavaSourceLoaderImpl.this, this));
|
||||
}
|
||||
|
||||
public IClass getEnclosingClass() {
|
||||
return enclosingClass;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (enclosingClass == null) {
|
||||
return "<src-class: " + getName().toString() + ">";
|
||||
|
|
|
@ -21,4 +21,8 @@ public class AstJavaAbstractInstructionVisitor
|
|||
|
||||
}
|
||||
|
||||
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,4 +16,6 @@ public interface AstJavaInstructionVisitor extends AstInstructionVisitor {
|
|||
|
||||
public void visitJavaInvoke(AstJavaInvokeInstruction instruction);
|
||||
|
||||
public void visitEnclosingObjectReference(EnclosingObjectReference inst);
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package com.ibm.wala.cast.java.ssa;
|
||||
|
||||
import com.ibm.wala.ssa.*;
|
||||
import com.ibm.wala.types.*;
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class EnclosingObjectReference extends SSAInstruction {
|
||||
private final TypeReference type;
|
||||
private final int lval;
|
||||
|
||||
public EnclosingObjectReference(int lval, TypeReference type) {
|
||||
this.lval = lval;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public boolean hasDef() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getDef() {
|
||||
return lval;
|
||||
}
|
||||
|
||||
public int getDef(int i) {
|
||||
Assertions._assert(i == 0);
|
||||
return lval;
|
||||
}
|
||||
|
||||
public int getNumberOfDefs() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public TypeReference getEnclosingType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
|
||||
return new EnclosingObjectReference(defs==null? lval: defs[0], type);
|
||||
}
|
||||
|
||||
public String toString(SymbolTable symbolTable, ValueDecorator d) {
|
||||
return getValueString(symbolTable, d, lval) + " = enclosing " + type.getName();
|
||||
}
|
||||
|
||||
public void visit(IVisitor v) {
|
||||
((AstJavaInstructionVisitor)v).visitEnclosingObjectReference(this);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return lval * type.hashCode();
|
||||
}
|
||||
|
||||
public Collection getExceptionTypes() {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
|
||||
public boolean isFallThrough() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
|
@ -18,7 +18,7 @@ import java.util.Iterator;
|
|||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.cast.ir.translator.AstTranslator;
|
||||
import com.ibm.wala.cast.java.loader.JavaSourceLoaderImpl;
|
||||
import com.ibm.wala.cast.java.ssa.AstJavaInvokeInstruction;
|
||||
import com.ibm.wala.cast.java.ssa.*;
|
||||
import com.ibm.wala.cast.loader.AstMethod.DebuggingInformation;
|
||||
import com.ibm.wala.cast.loader.AstMethod.LexicalInformation;
|
||||
import com.ibm.wala.cast.tree.CAstControlFlowMap;
|
||||
|
@ -306,6 +306,17 @@ public class JavaCAst2IRTranslator extends AstTranslator {
|
|||
((JavaSourceLoaderImpl)loader).defineType(type, type.getType().getName(), parentType);
|
||||
}
|
||||
|
||||
protected void leaveThis(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
if (n.getChildCount() == 0) {
|
||||
super.leaveThis(n, c, visitor);
|
||||
} else {
|
||||
WalkContext wc = (WalkContext)c;
|
||||
int result = wc.currentScope().allocateTempValue();
|
||||
setValue(n, result);
|
||||
wc.cfg().addInstruction(new EnclosingObjectReference(result, (TypeReference)n.getChild(0).getValue()));
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean visitCast(CAstNode n, Context c, CAstVisitor visitor) {
|
||||
WalkContext context = (WalkContext)c;
|
||||
int result = context.currentScope().allocateTempValue();
|
||||
|
|
|
@ -591,21 +591,20 @@ public class PolyglotJava2CAstTranslator implements TranslatorToCAst {
|
|||
}
|
||||
|
||||
public CAstNode visit(Special s, WalkContext wc) {
|
||||
Type owningType;
|
||||
if (s.qualifier() != null) {
|
||||
Type owningType= s.qualifier().type();
|
||||
TypeName owningTypeName =
|
||||
TypeName.string2TypeName(typeToTypeID(owningType));
|
||||
TypeReference owningTypeRef =
|
||||
TypeReference.findOrCreate(fClassLoaderRef, owningTypeName);
|
||||
|
||||
if (s.qualifier() != null) {
|
||||
owningType= s.qualifier().type();
|
||||
} else {
|
||||
owningType= s.type();
|
||||
return makeNode(wc, fFactory, s,
|
||||
s.kind() == Special.THIS ? CAstNode.THIS: CAstNode.SUPER,
|
||||
fFactory.makeConstant(owningTypeRef));
|
||||
} else {
|
||||
return makeNode(wc, fFactory, s,
|
||||
s.kind() == Special.THIS ? CAstNode.THIS : CAstNode.SUPER);
|
||||
}
|
||||
|
||||
TypeName owningTypeName = TypeName.string2TypeName(typeToTypeID(owningType));
|
||||
TypeReference owningTypeRef = TypeReference.findOrCreate(fClassLoaderRef, owningTypeName);
|
||||
|
||||
// Figure out whether we want a new type of node specifically for refs to
|
||||
// outer class, e.g. CAstNode.OUTER_THIS.
|
||||
return makeNode(wc, fFactory, s, s.kind() == Special.THIS ? CAstNode.THIS : CAstNode.SUPER,
|
||||
fFactory.makeConstant(owningTypeRef));
|
||||
}
|
||||
|
||||
public CAstNode visit(Unary u, WalkContext wc) {
|
||||
|
|
Loading…
Reference in New Issue