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:
dolby-oss 2007-02-07 18:51:19 +00:00
parent 76a937a3e2
commit 55e7a45e53
11 changed files with 217 additions and 53 deletions

View File

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

View File

@ -1,4 +1,6 @@
source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.
.,\
lib/java_cup.jar,\
lib/polyglot.jar

View File

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

View File

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

View File

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

View File

@ -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() + ">";

View File

@ -21,4 +21,8 @@ public class AstJavaAbstractInstructionVisitor
}
public void visitEnclosingObjectReference(EnclosingObjectReference inst) {
}
}

View File

@ -16,4 +16,6 @@ public interface AstJavaInstructionVisitor extends AstInstructionVisitor {
public void visitJavaInvoke(AstJavaInvokeInstruction instruction);
public void visitEnclosingObjectReference(EnclosingObjectReference inst);
}

View File

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

View File

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

View File

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