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:
parent
2dc8f805d4
commit
25a4b64c12
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue