Added source position information for entire code bodies as a whole

Rewrote to the mechanism for invoking the callbacks for lexical scoping to not suck as much as before, i.e. it is somewhat less inefficient

adapt to filter instance key changes

bug fixes to IR generation for switch statements


git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@839 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
dolby-oss 2007-03-12 02:00:43 +00:00
parent 2dc8f805d4
commit 25a4b64c12
5 changed files with 127 additions and 33 deletions

View File

@ -84,22 +84,48 @@ public class AstCallGraph extends ExplicitCallGraph {
}
}
public void addCallback(Function<Object,Object> callback) {
if (callbacks == null)
callbacks = new HashSet<Function<Object,Object>>(1);
callbacks.add(callback);
private boolean hasCallback(Function<Object,Object> callback) {
return callbacks != null && callbacks.contains(callback);
}
private void fireCallbacksTransitive() {
for (Iterator<CGNode> nodes = DFS.iterateFinishTime(AstCallGraph.this, new NonNullSingletonIterator<CGNode>(this)); nodes
.hasNext();) {
((AstCGNode) nodes.next()).fireCallbacks();
private boolean hasAllCallbacks(Set<Function<Object,Object>> callbacks) {
return callbacks != null && callbacks.containsAll(callbacks);
}
public void addCallback(Function<Object,Object> callback) {
if (! hasCallback(callback)) {
if (callbacks == null) {
callbacks = new HashSet<Function<Object,Object>>(1);
}
callbacks.add(callback);
for(Iterator ps = getPredNodes(this); ps.hasNext(); ) {
((AstCGNode)ps.next()).addCallback(callback);
}
}
}
public void addAllCallbacks(Set<Function<Object,Object>> callback) {
if (! hasAllCallbacks(callbacks)) {
if (callbacks == null) {
callbacks = new HashSet<Function<Object,Object>>(1);
}
callbacks.addAll(callbacks);
for(Iterator ps = getPredNodes(this); ps.hasNext(); ) {
((AstCGNode)ps.next()).addAllCallbacks(callbacks);
}
}
}
public boolean addTarget(CallSiteReference site, CGNode node) {
if (super.addTarget(site, node)) {
fireCallbacksTransitive();
if (((AstCGNode)node).callbacks != null) {
((AstCGNode)node).fireCallbacks();
addAllCallbacks(((AstCGNode)node).callbacks);
}
return true;
} else {
return false;

View File

@ -309,18 +309,47 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
return NOT_CHANGED;
}
abstract void action(PointerKey lexicalKey, int vn);
abstract protected void action(PointerKey lexicalKey, int vn);
public String toString() {
return "lexical op";
}
public boolean equals(Object o) {
return o == this;
if (! (o instanceof LexicalOperator)) {
return false;
} else {
LexicalOperator other = (LexicalOperator) o;
if (isLoad != other.isLoad) {
return false;
} else if (! node.equals(other.node)) {
return false;
} else if (accesses.length != other.accesses.length) {
return false;
} else {
for(int i = 0; i < accesses.length; i++) {
if (! accesses[i].equals(other.accesses[i])) {
return false;
}
}
for(int i = 0; i < accesses.length; i++) {
if (! accesses[i].equals(other.accesses[i])) {
return false;
}
}
return true;
}
}
}
public int hashCode() {
return System.identityHashCode(this);
return node.hashCode() * accesses[0].hashCode() * accesses.length;
}
}
@ -906,17 +935,34 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
system.newSideEffect(op, function);
}
((AstCGNode) node).addCallback(new Function<Object,Object>() {
class LexicalScopingCallback implements Function<Object,Object> {
public Object apply(Object ignore) {
op.doLexicalPointerKeys();
return null;
}
});
private LexicalOperator getOperator() {
return op;
}
public int hashCode() {
return op.hashCode();
}
public boolean equals(Object o) {
return
(o instanceof LexicalScopingCallback)
&&
((LexicalScopingCallback)o).getOperator().equals(op);
}
}
((AstCGNode) node).addCallback(new LexicalScopingCallback());
}
public void visitAstLexicalRead(AstLexicalRead instruction) {
visitLexical(new LexicalOperator((AstCGNode) node, instruction.getAccesses(), true) {
void action(PointerKey lexicalKey, int vn) {
protected void action(PointerKey lexicalKey, int vn) {
PointerKey lval = getPointerKeyForLocal(node, vn);
if (lexicalKey instanceof LocalPointerKey) {
CGNode lnode = ((LocalPointerKey) lexicalKey).getNode();
@ -943,7 +989,7 @@ public abstract class AstSSAPropagationCallGraphBuilder extends SSAPropagationCa
public void visitAstLexicalWrite(AstLexicalWrite instruction) {
visitLexical(new LexicalOperator((AstCGNode) node, instruction.getAccesses(), false) {
void action(PointerKey lexicalKey, int vn) {
protected void action(PointerKey lexicalKey, int vn) {
PointerKey rval = getPointerKeyForLocal(node, vn);
if (contentsAreInvariant(symbolTable, du, vn)) {
InstanceKey[] ik = getInvariantContents(symbolTable, du, node, vn, AstSSAPropagationCallGraphBuilder.this);

View File

@ -29,11 +29,7 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
return base.getPointerKeyForLocal(node, valueNumber);
}
public FilteredPointerKey getFilteredPointerKeyForLocal(CGNode node, int valueNumber, IClass filter) {
return base.getFilteredPointerKeyForLocal(node, valueNumber, filter);
}
public InstanceFilteredPointerKey getFilteredPointerKeyForLocal(CGNode node, int valueNumber, InstanceKey filter) {
public FilteredPointerKey getFilteredPointerKeyForLocal(CGNode node, int valueNumber, FilteredPointerKey.TypeFilter filter) {
return base.getFilteredPointerKeyForLocal(node, valueNumber, filter);
}

View File

@ -278,11 +278,18 @@ public abstract class AstTranslator extends CAstVisitor {
}
private static class AstDebuggingInformation implements DebuggingInformation {
private Position codeBodyPosition;
private String[][] valueNumberNames;
private Position[] instructionPositions;
AstDebuggingInformation(Position[] instructionPositions, String[] names) {
AstDebuggingInformation(Position codeBodyPosition,
Position[] instructionPositions,
String[] names)
{
this.codeBodyPosition = codeBodyPosition;
this.instructionPositions = instructionPositions;
valueNumberNames = new String[names.length][];
@ -295,6 +302,10 @@ public abstract class AstTranslator extends CAstVisitor {
}
}
public Position getCodeBodyPosition() {
return codeBodyPosition;
}
public Position getInstructionPosition(int instructionOffset) {
return instructionPositions[instructionOffset];
}
@ -1941,7 +1952,7 @@ public abstract class AstTranslator extends CAstVisitor {
}
}
private String[] makeNameMap(Set<Scope> scopes) {
private String[] makeNameMap(CAstEntity n, Set<Scope> scopes) {
// all scopes share the same underlying symtab, which is what
// size really refers to.
String[] map = new String[scopes.iterator().next().size() + 1];
@ -1960,8 +1971,15 @@ public abstract class AstTranslator extends CAstVisitor {
if ("ctor temp".equals(nm))
continue;
Assertions._assert(map[v.valueNumber()] == null || map[v.valueNumber()].equals(nm), "value number " + v.valueNumber()
+ " mapped to multiple names in translator: " + nm + " and " + map[v.valueNumber()]);
// constants can flow to multiple variables
if (scope.isConstant( v.valueNumber() ))
continue;
Assertions._assert(
map[v.valueNumber()] == null || map[v.valueNumber()].equals(nm),
"value number " + v.valueNumber() +
" mapped to multiple names in " + n.getName() + ": " +
nm + " and " + map[v.valueNumber()]);
map[v.valueNumber()] = nm;
@ -2088,7 +2106,7 @@ public abstract class AstTranslator extends CAstVisitor {
AbstractCFG cfg = new AstCFG(n, functionContext.cfg(), symtab);
Position[] line = functionContext.cfg().getLinePositionMap();
boolean katch = functionContext.cfg().hasCatchBlock();
String[] nms = makeNameMap(functionContext.entityScopes());
String[] nms = makeNameMap(n, functionContext.entityScopes());
/*
* Set reachableBlocks = DFS.getReachableNodes(cfg,
@ -2105,7 +2123,7 @@ public abstract class AstTranslator extends CAstVisitor {
new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(), exposedNames.get(n), accesses
.get(n));
DebuggingInformation DBG = new AstDebuggingInformation(line, nms);
DebuggingInformation DBG = new AstDebuggingInformation(n.getPosition(), line, nms);
// actually make code body
defineFunction(n, parentContext, cfg, symtab, katch, catchTypes, LI, DBG);
@ -2809,7 +2827,6 @@ public abstract class AstTranslator extends CAstVisitor {
private void doSimpleSwitch(CAstNode n, WalkContext context, CAstVisitor visitor) {
PreBasicBlock defaultHackBlock = null;
CAstControlFlowMap ctrl = context.getControlFlow();
context.cfg().addPreNode(n, context.getUnwindState());
CAstNode switchValue = n.getChild(0);
visitor.visit(switchValue, context, visitor);
@ -2826,19 +2843,22 @@ public abstract class AstTranslator extends CAstVisitor {
int defaultBlock = context.cfg().getCurrentBlock().getGraphNodeId() + 1;
context.cfg().addInstruction(SSAInstructionFactory.SwitchInstruction(v, defaultBlock, casesAndLabels));
context.cfg().addPreNode(n, context.getUnwindState());
// PreBasicBlock switchB = context.cfg().getCurrentBlock();
context.cfg().newBlock(true);
if (hasExplicitDefault) {
context.cfg().addInstruction(SSAInstructionFactory.GotoInstruction());
defaultHackBlock = context.cfg().getCurrentBlock();
context.cfg().newBlock(false);
}
context.cfg().addInstruction(SSAInstructionFactory.GotoInstruction());
defaultHackBlock = context.cfg().getCurrentBlock();
context.cfg().newBlock(false);
CAstNode switchBody = n.getChild(1);
visitor.visit(switchBody, context, visitor);
context.cfg().newBlock(true);
if (! hasExplicitDefault) {
context.cfg().addEdge(defaultHackBlock, context.cfg().getCurrentBlock());
}
int cn = 0;
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
Object x = kases.next();

View File

@ -31,6 +31,8 @@ public abstract class AstMethod implements IMethod {
public interface DebuggingInformation {
Position getCodeBodyPosition();
Position getInstructionPosition(int instructionOffset);
String[][] getSourceNamesForValues();
@ -217,6 +219,10 @@ public abstract class AstMethod implements IMethod {
}
}
public Position getSourcePosition() {
return debugInfo.getCodeBodyPosition();
}
public Position getSourcePosition(int instructionIndex) {
return debugInfo.getInstructionPosition(instructionIndex);
}