some generics

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@692 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
sjfink 2007-02-08 20:45:07 +00:00
parent e89006e2c9
commit a92bff31bb
35 changed files with 1070 additions and 1063 deletions

View File

@ -62,7 +62,7 @@ public class AstCallGraph extends ExplicitCallGraph {
} }
class AstCGNode extends ExplicitNode { class AstCGNode extends ExplicitNode {
private Set callbacks; private Set<Function> callbacks;
private AstCGNode(IMethod method, Context context) { private AstCGNode(IMethod method, Context context) {
super(method, context); super(method, context);
@ -73,8 +73,8 @@ public class AstCallGraph extends ExplicitCallGraph {
boolean done = false; boolean done = false;
while (!done) { while (!done) {
try { try {
for (Iterator x = callbacks.iterator(); x.hasNext();) { for (Iterator<Function> x = callbacks.iterator(); x.hasNext();) {
((Function) x.next()).apply(null); x.next().apply(null);
} }
} catch (ConcurrentModificationException e) { } catch (ConcurrentModificationException e) {
done = false; done = false;
@ -87,12 +87,12 @@ public class AstCallGraph extends ExplicitCallGraph {
public void addCallback(Function callback) { public void addCallback(Function callback) {
if (callbacks == null) if (callbacks == null)
callbacks = new HashSet(1); callbacks = new HashSet<Function>(1);
callbacks.add(callback); callbacks.add(callback);
} }
private void fireCallbacksTransitive() { private void fireCallbacksTransitive() {
for(Iterator nodes = DFS.iterateFinishTime(AstCallGraph.this, new NonNullSingletonIterator<CGNode>(this)); for(Iterator<CGNode> nodes = DFS.iterateFinishTime(AstCallGraph.this, new NonNullSingletonIterator<CGNode>(this));
nodes.hasNext(); ) nodes.hasNext(); )
{ {
((AstCGNode)nodes.next()).fireCallbacks(); ((AstCGNode)nodes.next()).fireCallbacks();

View File

@ -10,17 +10,20 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.ipa.callgraph; package com.ibm.wala.cast.ipa.callgraph;
import com.ibm.wala.cast.loader.*; import java.util.Iterator;
import com.ibm.wala.classLoader.*;
import com.ibm.wala.ipa.callgraph.*; import com.ibm.wala.cast.loader.AstMethod;
import com.ibm.wala.ipa.callgraph.propagation.cfa.*; import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.ipa.cha.*; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ssa.*; import com.ibm.wala.ipa.callgraph.AnalysisOptions;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.propagation.cfa.ContextInsensitiveSSAInterpreter;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ssa.IR;
import com.ibm.wala.util.collections.EmptyIterator; import com.ibm.wala.util.collections.EmptyIterator;
import com.ibm.wala.util.warnings.WarningSet; import com.ibm.wala.util.warnings.WarningSet;
import java.util.*;
public class AstContextInsensitiveSSAContextInterpreter public class AstContextInsensitiveSSAContextInterpreter
extends ContextInsensitiveSSAInterpreter extends ContextInsensitiveSSAInterpreter
{ {
@ -33,7 +36,7 @@ public class AstContextInsensitiveSSAContextInterpreter
return method instanceof AstMethod; return method instanceof AstMethod;
} }
public Iterator iterateCallSites(CGNode N, WarningSet warnings) { public Iterator<CallSiteReference> iterateCallSites(CGNode N, WarningSet warnings) {
IR ir = getIR(N, warnings); IR ir = getIR(N, warnings);
if (ir == null) { if (ir == null) {
return EmptyIterator.instance(); return EmptyIterator.instance();

View File

@ -16,9 +16,9 @@ import java.util.*;
public interface AstPointerKeyFactory extends PointerKeyFactory { public interface AstPointerKeyFactory extends PointerKeyFactory {
Iterator getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F); Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F);
Iterator getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F); Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F);
PointerKey getPointerKeyForObjectCatalog(InstanceKey I); PointerKey getPointerKeyForObjectCatalog(InstanceKey I);

View File

@ -105,14 +105,14 @@ public abstract class AstSSAPropagationCallGraphBuilder
.getPointerKeyForObjectCatalog(I); .getPointerKeyForObjectCatalog(I);
} }
public Iterator public Iterator<PointerKey>
getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F)
{ {
return ((AstPointerKeyFactory)pointerKeyFactory) return ((AstPointerKeyFactory)pointerKeyFactory)
.getPointerKeysForReflectedFieldRead(I, F); .getPointerKeysForReflectedFieldRead(I, F);
} }
public Iterator public Iterator<PointerKey>
getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F)
{ {
return ((AstPointerKeyFactory)pointerKeyFactory) return ((AstPointerKeyFactory)pointerKeyFactory)
@ -290,10 +290,10 @@ public abstract class AstSSAPropagationCallGraphBuilder
if (AstTranslator.DEBUG_LEXICAL) if (AstTranslator.DEBUG_LEXICAL)
Trace.println("looking up lexical parent " + definer); Trace.println("looking up lexical parent " + definer);
for(Iterator DS = getLexicalDefiners(node, definer).iterator(); for(Iterator<CGNode> DS = getLexicalDefiners(node, definer).iterator();
DS.hasNext(); ) DS.hasNext(); )
{ {
final CGNode D = (CGNode) DS.next(); final CGNode D = DS.next();
Iterator PS = new NumberedDFSDiscoverTimeIterator(callGraph, node) { Iterator PS = new NumberedDFSDiscoverTimeIterator(callGraph, node) {
/** /**
@ -346,12 +346,12 @@ public abstract class AstSSAPropagationCallGraphBuilder
public int hashCode() { return System.identityHashCode(this); } public int hashCode() { return System.identityHashCode(this); }
} }
private Set getLexicalDefiners(final CGNode opNode, final String definer) { private Set<CGNode> getLexicalDefiners(final CGNode opNode, final String definer) {
if (definer == null) { if (definer == null) {
return Collections.singleton(callGraph.getFakeRootNode()); return Collections.singleton(callGraph.getFakeRootNode());
} else { } else {
final Set result = new HashSet(); final Set<CGNode> result = new HashSet<CGNode>();
PointerKey F = getPointerKeyForLocal(opNode, 1); PointerKey F = getPointerKeyForLocal(opNode, 1);
IR ir = getCFAContextInterpreter().getIR(opNode, getWarnings()); IR ir = getCFAContextInterpreter().getIR(opNode, getWarnings());
@ -391,7 +391,7 @@ public abstract class AstSSAPropagationCallGraphBuilder
if (a == null) return b==null; else return a.equals(b); if (a == null) return b==null; else return a.equals(b);
} }
private Set discoveredUpwardFunargs = new HashSet(); private Set<PointerKey> discoveredUpwardFunargs = new HashSet<PointerKey>();
private void addUpwardFunargConstraints(PointerKey lhs, private void addUpwardFunargConstraints(PointerKey lhs,
String name, String name,
@ -680,21 +680,21 @@ public abstract class AstSSAPropagationCallGraphBuilder
PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]); PointerKey objCatalog = getPointerKeyForObjectCatalog(objKeys[o]);
for(int f = 0; f < fieldsKeys.length; f++) { for(int f = 0; f < fieldsKeys.length; f++) {
if (isLoadOperation) { if (isLoadOperation) {
for(Iterator keys = for(Iterator<PointerKey> keys =
getPointerKeysForReflectedFieldRead(objKeys[o], fieldsKeys[f]); getPointerKeysForReflectedFieldRead(objKeys[o], fieldsKeys[f]);
keys.hasNext(); ) keys.hasNext(); )
{ {
PointerKey key = (PointerKey)keys.next(); PointerKey key = keys.next();
if (DEBUG_PROPERTIES) action.dump( key, true, true ); if (DEBUG_PROPERTIES) action.dump( key, true, true );
action.action( key ); action.action( key );
} }
} else { } else {
system.newConstraint(objCatalog, fieldsKeys[f]); system.newConstraint(objCatalog, fieldsKeys[f]);
for(Iterator keys = for(Iterator<PointerKey> keys =
getPointerKeysForReflectedFieldWrite(objKeys[o],fieldsKeys[f]); getPointerKeysForReflectedFieldWrite(objKeys[o],fieldsKeys[f]);
keys.hasNext(); ) keys.hasNext(); )
{ {
PointerKey key = (PointerKey)keys.next(); PointerKey key = keys.next();
if (DEBUG_PROPERTIES) action.dump( key, true, true ); if (DEBUG_PROPERTIES) action.dump( key, true, true );
action.action( key ); action.action( key );
} }
@ -768,21 +768,21 @@ public abstract class AstSSAPropagationCallGraphBuilder
getPointerKeyForObjectCatalog(object); getPointerKeyForObjectCatalog(object);
for(int f = 0; f < fieldsKeys.length; f++) { for(int f = 0; f < fieldsKeys.length; f++) {
if (isLoadOperation) { if (isLoadOperation) {
for(Iterator keys = for(Iterator<PointerKey> keys =
getPointerKeysForReflectedFieldRead(object, fieldsKeys[f]); getPointerKeysForReflectedFieldRead(object, fieldsKeys[f]);
keys.hasNext(); ) keys.hasNext(); )
{ {
PointerKey key = (PointerKey)keys.next(); PointerKey key = keys.next();
if (DEBUG_PROPERTIES) action.dump(key, true, false); if (DEBUG_PROPERTIES) action.dump(key, true, false);
action.action( key ); action.action( key );
} }
} else { } else {
system.newConstraint(objCatalog, fieldsKeys[f]); system.newConstraint(objCatalog, fieldsKeys[f]);
for(Iterator keys = for(Iterator<PointerKey> keys =
getPointerKeysForReflectedFieldWrite(object,fieldsKeys[f]); getPointerKeysForReflectedFieldWrite(object,fieldsKeys[f]);
keys.hasNext(); ) keys.hasNext(); )
{ {
PointerKey key = (PointerKey)keys.next(); PointerKey key = keys.next();
if (DEBUG_PROPERTIES) action.dump(key, true, false); if (DEBUG_PROPERTIES) action.dump(key, true, false);
action.action( key ); action.action( key );
} }

View File

@ -130,8 +130,8 @@ public class CAstAnalysisScope extends AnalysisScope {
/** /**
* @return an Iterator <ClassLoaderReference>over the loaders. * @return an Iterator <ClassLoaderReference>over the loaders.
*/ */
public Iterator getLoaders() { public Iterator<ClassLoaderReference> getLoaders() {
return new NonNullSingletonIterator( theLoader ); return new NonNullSingletonIterator<ClassLoaderReference>( theLoader );
} }
/** /**

View File

@ -37,7 +37,7 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
return base.getFilteredPointerKeyForLocal(node, valueNumber, filter); return base.getFilteredPointerKeyForLocal(node, valueNumber, filter);
} }
public PointerKey getPointerKeyForReturnValue(CGNode node){ public PointerKey getPointerKeyForReturnValue(CGNode node) {
return base.getPointerKeyForReturnValue(node); return base.getPointerKeyForReturnValue(node);
} }
@ -53,16 +53,17 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
return new ObjectPropertyCatalogKey(I); return new ObjectPropertyCatalogKey(I);
} }
private final Map specificStringKeys = new HashMap(); private final Map<IField, Set<PointerKey>> specificStringKeys = new HashMap<IField, Set<PointerKey>>();
// private final Map specificIndexKeys = new HashMap();
// private final Map specificIndexKeys = new HashMap();
public PointerKey getPointerKeyForInstanceField(InstanceKey I, IField f) { public PointerKey getPointerKeyForInstanceField(InstanceKey I, IField f) {
PointerKey fk = base.getPointerKeyForInstanceField(I, f); PointerKey fk = base.getPointerKeyForInstanceField(I, f);
if (! specificStringKeys.containsKey(f)) { if (!specificStringKeys.containsKey(f)) {
specificStringKeys.put(f, new HashSet()); specificStringKeys.put(f, new HashSet<PointerKey>());
} }
((Set)specificStringKeys.get(f)).add(fk); specificStringKeys.get(f).add(fk);
return fk; return fk;
} }
@ -71,35 +72,33 @@ public class DelegatingAstPointerKeys implements AstPointerKeyFactory {
return base.getPointerKeyForArrayContents(I); return base.getPointerKeyForArrayContents(I);
} }
public Iterator getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) { public Iterator<PointerKey> getPointerKeysForReflectedFieldRead(InstanceKey I, InstanceKey F) {
List result = new LinkedList(); List<PointerKey> result = new LinkedList<PointerKey>();
// FIXME: current only constant string are handled // FIXME: current only constant string are handled
if (F instanceof ConstantKey) { if (F instanceof ConstantKey) {
Object v = ((ConstantKey)F).getValue(); Object v = ((ConstantKey) F).getValue();
if (v instanceof String) { if (v instanceof String) {
IField f = IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String)v)); result.add(getPointerKeyForInstanceField(I, f));
result.add( getPointerKeyForInstanceField(I, f) );
} }
} }
result.add(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I)); result.add(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I));
return result.iterator(); return result.iterator();
} }
public Iterator getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) { public Iterator<PointerKey> getPointerKeysForReflectedFieldWrite(InstanceKey I, InstanceKey F) {
// FIXME: current only constant string are handled // FIXME: current only constant string are handled
if (F instanceof ConstantKey) { if (F instanceof ConstantKey) {
Object v = ((ConstantKey)F).getValue(); Object v = ((ConstantKey) F).getValue();
if (v instanceof String) { if (v instanceof String) {
IField f = IField f = I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String) v));
I.getConcreteType().getField(Atom.findOrCreateUnicodeAtom((String)v)); return new NonNullSingletonIterator<PointerKey>(getPointerKeyForInstanceField(I, f));
return new NonNullSingletonIterator(getPointerKeyForInstanceField(I, f));
} }
} }
return new NonNullSingletonIterator(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I)); return new NonNullSingletonIterator<PointerKey>(ReflectedFieldPointerKey.mapped(new ConcreteTypeKey(F.getConcreteType()), I));
} }
} }

View File

@ -30,7 +30,7 @@ import com.ibm.wala.util.warnings.WarningSet;
public class MiscellaneousHacksContextSelector implements ContextSelector public class MiscellaneousHacksContextSelector implements ContextSelector
{ {
private final Set methodsToSpecialize; private final Set<MethodReference> methodsToSpecialize;
private final ContextSelector specialPolicy; private final ContextSelector specialPolicy;
private final ContextSelector basePolicy; private final ContextSelector basePolicy;
@ -42,7 +42,7 @@ public class MiscellaneousHacksContextSelector implements ContextSelector
{ {
basePolicy = base; basePolicy = base;
specialPolicy = special; specialPolicy = special;
methodsToSpecialize = new HashSet(); methodsToSpecialize = new HashSet<MethodReference>();
for(int i = 0; i < descriptors.length; i++) { for(int i = 0; i < descriptors.length; i++) {
String[] descr = descriptors[i]; String[] descr = descriptors[i];
switch (descr.length) { switch (descr.length) {

View File

@ -10,7 +10,6 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.ipa.callgraph; package com.ibm.wala.cast.ipa.callgraph;
import com.ibm.wala.cast.ir.translator.*; import com.ibm.wala.cast.ir.translator.*;
import com.ibm.wala.cast.loader.AstMethod.*; import com.ibm.wala.cast.loader.AstMethod.*;
import com.ibm.wala.classLoader.*; import com.ibm.wala.classLoader.*;
@ -29,78 +28,83 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
protected abstract boolean needsScopeMappingKey(InstanceKey base); protected abstract boolean needsScopeMappingKey(InstanceKey base);
private final PropagationCallGraphBuilder builder; private final PropagationCallGraphBuilder builder;
private final InstanceKeyFactory basic; private final InstanceKeyFactory basic;
public class ScopeMappingInstanceKey implements InstanceKey { public class ScopeMappingInstanceKey implements InstanceKey {
private final InstanceKey base; private final InstanceKey base;
private final CGNode creator; private final CGNode creator;
private final ScopeMap map; private final ScopeMap map;
private class ScopeMap extends HashMap { private class ScopeMap extends HashMap {
private static final long serialVersionUID = 3645910671551712906L; private static final long serialVersionUID = 3645910671551712906L;
private void scan(int level, int toDo, LexicalParent parents[], CGNode node, Set parentNodes) { private void scan(int level, int toDo, LexicalParent parents[], CGNode node, Set<CGNode> parentNodes) {
if (toDo > 0) { if (toDo > 0) {
int restoreIndex = -1; int restoreIndex = -1;
LexicalParent restoreParent = null; LexicalParent restoreParent = null;
if (AstTranslator.DEBUG_LEXICAL) if (AstTranslator.DEBUG_LEXICAL)
Trace.println(level + ": searching " + node + " for parents"); Trace.println(level + ": searching " + node + " for parents");
for(int i = 0; i < parents.length; i++) { for (int i = 0; i < parents.length; i++) {
if (parents[i] == null) continue; if (parents[i] == null)
continue;
if (AstTranslator.DEBUG_LEXICAL) if (AstTranslator.DEBUG_LEXICAL)
Trace.println(level + ": searching " + parents[i]); Trace.println(level + ": searching " + parents[i]);
if (node.getMethod() == parents[i].getMethod()) {
if (containsKey(parents[i].getName()))
Assertions._assert(get(parents[i].getName()) == node);
else {
put( parents[i].getName(), node );
if (AstTranslator.DEBUG_LEXICAL)
Trace.println(level + ": Adding lexical parent " + parents[i].getName() + " for " + base + " at " + creator + "(toDo is now " + toDo +")");
}
toDo--; if (node.getMethod() == parents[i].getMethod()) {
restoreIndex = i; if (containsKey(parents[i].getName()))
restoreParent = parents[i]; Assertions._assert(get(parents[i].getName()) == node);
parents[i] = null; else {
} put(parents[i].getName(), node);
} if (AstTranslator.DEBUG_LEXICAL)
Trace.println(level + ": Adding lexical parent " + parents[i].getName() + " for " + base + " at " + creator
CallGraph CG = builder.getCallGraph(); + "(toDo is now " + toDo + ")");
}
Assertions._assert(CG.getPredNodes(node).hasNext() || toDo==0);
for(Iterator PS = CG.getPredNodes(node); PS.hasNext(); ) { toDo--;
CGNode pred = (CGNode) PS.next(); restoreIndex = i;
if (pred != creator && !parentNodes.contains(pred)) { restoreParent = parents[i];
parentNodes.add( pred ); parents[i] = null;
scan(level+1, toDo, parents, pred, parentNodes); }
parentNodes.remove(pred); }
}
}
if (restoreIndex != -1) { CallGraph CG = builder.getCallGraph();
parents[restoreIndex] = restoreParent;
} Assertions._assert(CG.getPredNodes(node).hasNext() || toDo == 0);
}
for (Iterator PS = CG.getPredNodes(node); PS.hasNext();) {
CGNode pred = (CGNode) PS.next();
if (pred != creator && !parentNodes.contains(pred)) {
parentNodes.add(pred);
scan(level + 1, toDo, parents, pred, parentNodes);
parentNodes.remove(pred);
}
}
if (restoreIndex != -1) {
parents[restoreIndex] = restoreParent;
}
}
} }
private ScopeMap() { private ScopeMap() {
LexicalParent[] parents = getParents(base); LexicalParent[] parents = getParents(base);
if (AstTranslator.DEBUG_LEXICAL) if (AstTranslator.DEBUG_LEXICAL)
Trace.println("starting search for parents at " + creator); Trace.println("starting search for parents at " + creator);
scan( 0, parents.length, parents, creator, new HashSet(5)); scan(0, parents.length, parents, creator, new HashSet<CGNode>(5));
} }
CGNode getDefiningNode(String definer) { CGNode getDefiningNode(String definer) {
return (CGNode) get(definer); return (CGNode) get(definer);
} }
} }
@ -115,21 +119,20 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
} }
CGNode getDefiningNode(String definer) { CGNode getDefiningNode(String definer) {
return map.getDefiningNode( definer ); return map.getDefiningNode(definer);
} }
public int hashCode() { public int hashCode() {
return base.hashCode()*creator.hashCode(); return base.hashCode() * creator.hashCode();
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof ScopeMappingInstanceKey) && return (o instanceof ScopeMappingInstanceKey) && ((ScopeMappingInstanceKey) o).base.equals(base)
((ScopeMappingInstanceKey)o).base.equals(base) && && ((ScopeMappingInstanceKey) o).creator.equals(creator);
((ScopeMappingInstanceKey)o).creator.equals(creator);
} }
public String toString() { public String toString() {
return "SMIK:"+base+"@"+creator; return "SMIK:" + base + "@" + creator;
} }
} }
@ -162,10 +165,7 @@ abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
return basic.getInstanceKeyForClassObject(type); return basic.getInstanceKeyForClassObject(type);
} }
public ScopeMappingInstanceKeys( public ScopeMappingInstanceKeys(PropagationCallGraphBuilder builder, InstanceKeyFactory basic) {
PropagationCallGraphBuilder builder,
InstanceKeyFactory basic)
{
this.basic = basic; this.basic = basic;
this.builder = builder; this.builder = builder;
} }

View File

@ -66,8 +66,8 @@ public abstract class ScriptEntryPoints implements Entrypoints {
this.scriptType = scriptType; this.scriptType = scriptType;
} }
public Iterator iterator() { public Iterator<ScriptEntryPoint> iterator() {
Set ES = new HashSet(); Set<ScriptEntryPoint> ES = new HashSet<ScriptEntryPoint>();
Iterator classes = scriptType.getClassLoader().iterateAllClasses(); Iterator classes = scriptType.getClassLoader().iterateAllClasses();
while ( classes.hasNext() ) { while ( classes.hasNext() ) {
IClass cls = (IClass)classes.next(); IClass cls = (IClass)classes.next();

View File

@ -18,9 +18,7 @@ import com.ibm.wala.util.intset.BitVector;
import java.util.*; import java.util.*;
public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock> public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock> implements ControlFlowGraph {
implements ControlFlowGraph
{
protected final ControlFlowGraph parent; protected final ControlFlowGraph parent;
@ -28,46 +26,56 @@ public class DelegatingCFG extends AbstractNumberedGraph<IBasicBlock>
this.parent = parent; this.parent = parent;
} }
protected NodeManager getNodeManager() { protected NodeManager<IBasicBlock> getNodeManager() {
return parent; return parent;
} }
protected EdgeManager getEdgeManager() { protected EdgeManager<IBasicBlock> getEdgeManager() {
return parent; return parent;
} }
public IBasicBlock entry() { return parent.entry(); } public IBasicBlock entry() {
return parent.entry();
}
public IBasicBlock exit() { return parent.exit(); } public IBasicBlock exit() {
return parent.exit();
}
public BitVector getCatchBlocks() { return parent.getCatchBlocks(); } public BitVector getCatchBlocks() {
return parent.getCatchBlocks();
}
public IBasicBlock getBlockForInstruction(int index) { public IBasicBlock getBlockForInstruction(int index) {
return parent.getBlockForInstruction( index ); return parent.getBlockForInstruction(index);
} }
public IInstruction[] getInstructions() { return parent.getInstructions(); } public IInstruction[] getInstructions() {
return parent.getInstructions();
}
public int getProgramCounter(int index) { public int getProgramCounter(int index) {
return parent.getProgramCounter( index ); return parent.getProgramCounter(index);
} }
public IMethod getMethod() { return parent.getMethod(); } public IMethod getMethod() {
return parent.getMethod();
public Collection getExceptionalSuccessors(IBasicBlock b) {
return parent.getExceptionalSuccessors( b );
} }
public Collection getNormalSuccessors(IBasicBlock b) { public Collection<IBasicBlock> getExceptionalSuccessors(IBasicBlock b) {
return parent.getNormalSuccessors( b ); return parent.getExceptionalSuccessors(b);
}
public Collection getExceptionalPredecessors(IBasicBlock b) {
return parent.getExceptionalPredecessors( b );
} }
public Collection getNormalPredecessors(IBasicBlock b) { public Collection<IBasicBlock> getNormalSuccessors(IBasicBlock b) {
return parent.getNormalPredecessors( b ); return parent.getNormalSuccessors(b);
}
public Collection<IBasicBlock> getExceptionalPredecessors(IBasicBlock b) {
return parent.getExceptionalPredecessors(b);
}
public Collection<IBasicBlock> getNormalPredecessors(IBasicBlock b) {
return parent.getNormalPredecessors(b);
} }
} }

View File

@ -47,60 +47,60 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
} }
private static class FilteredCFGEdges implements NumberedEdgeManager { private static class FilteredCFGEdges implements NumberedEdgeManager<IBasicBlock> {
private final ControlFlowGraph cfg; private final ControlFlowGraph cfg;
private final NumberedNodeManager currentCFGNodes; private final NumberedNodeManager<IBasicBlock> currentCFGNodes;
private final EdgeFilter filter; private final EdgeFilter filter;
FilteredCFGEdges(ControlFlowGraph cfg, NumberedNodeManager currentCFGNodes, EdgeFilter filter) { FilteredCFGEdges(ControlFlowGraph cfg, NumberedNodeManager<IBasicBlock> currentCFGNodes, EdgeFilter filter) {
this.cfg = cfg; this.cfg = cfg;
this.filter = filter; this.filter = filter;
this.currentCFGNodes = currentCFGNodes; this.currentCFGNodes = currentCFGNodes;
} }
public Iterator getExceptionalSuccessors(final IBasicBlock N) { public Iterator<IBasicBlock> getExceptionalSuccessors(final IBasicBlock N) {
return new FilterIterator(cfg.getExceptionalSuccessors(N).iterator(), new Filter() { return new FilterIterator<IBasicBlock>(cfg.getExceptionalSuccessors(N).iterator(), new Filter() {
public boolean accepts(Object o) { public boolean accepts(Object o) {
return currentCFGNodes.containsNode(o) && filter.hasExceptionalEdge((IBasicBlock) N, (IBasicBlock) o); return currentCFGNodes.containsNode((IBasicBlock) o) && filter.hasExceptionalEdge((IBasicBlock) N, (IBasicBlock) o);
} }
}); });
} }
public Iterator getNormalSuccessors(final IBasicBlock N) { public Iterator<IBasicBlock> getNormalSuccessors(final IBasicBlock N) {
return new FilterIterator(cfg.getNormalSuccessors(N).iterator(), new Filter() { return new FilterIterator<IBasicBlock>(cfg.getNormalSuccessors(N).iterator(), new Filter() {
public boolean accepts(Object o) { public boolean accepts(Object o) {
return currentCFGNodes.containsNode(o) && filter.hasNormalEdge((IBasicBlock) N, (IBasicBlock) o); return currentCFGNodes.containsNode((IBasicBlock)o) && filter.hasNormalEdge((IBasicBlock) N, (IBasicBlock) o);
} }
}); });
} }
public Iterator getExceptionalPredecessors(final IBasicBlock N) { public Iterator<IBasicBlock> getExceptionalPredecessors(final IBasicBlock N) {
return new FilterIterator(cfg.getExceptionalPredecessors(N).iterator(), new Filter() { return new FilterIterator<IBasicBlock>(cfg.getExceptionalPredecessors(N).iterator(), new Filter() {
public boolean accepts(Object o) { public boolean accepts(Object o) {
return currentCFGNodes.containsNode(o) && filter.hasExceptionalEdge((IBasicBlock) o, (IBasicBlock) N); return currentCFGNodes.containsNode((IBasicBlock)o) && filter.hasExceptionalEdge((IBasicBlock) o, (IBasicBlock) N);
} }
}); });
} }
public Iterator getNormalPredecessors(final IBasicBlock N) { public Iterator<IBasicBlock> getNormalPredecessors(final IBasicBlock N) {
return new FilterIterator(cfg.getNormalPredecessors(N).iterator(), new Filter() { return new FilterIterator<IBasicBlock>(cfg.getNormalPredecessors(N).iterator(), new Filter() {
public boolean accepts(Object o) { public boolean accepts(Object o) {
return currentCFGNodes.containsNode(o) && filter.hasNormalEdge((IBasicBlock) o, (IBasicBlock) N); return currentCFGNodes.containsNode((IBasicBlock)o) && filter.hasNormalEdge((IBasicBlock) o, (IBasicBlock) N);
} }
}); });
} }
public Iterator getSuccNodes(Object N) { public Iterator<IBasicBlock> getSuccNodes(IBasicBlock N) {
return new CompoundIterator(getNormalSuccessors((IBasicBlock) N), getExceptionalSuccessors((IBasicBlock) N)); return new CompoundIterator<IBasicBlock>(getNormalSuccessors((IBasicBlock) N), getExceptionalSuccessors((IBasicBlock) N));
} }
public int getSuccNodeCount(Object N) { public int getSuccNodeCount(IBasicBlock N) {
return new Iterator2Collection(getSuccNodes(N)).size(); return new Iterator2Collection<IBasicBlock>(getSuccNodes(N)).size();
} }
public IntSet getSuccNodeNumbers(Object N) { public IntSet getSuccNodeNumbers(IBasicBlock N) {
MutableIntSet bits = IntSetUtil.make(); MutableIntSet bits = IntSetUtil.make();
for (Iterator EE = getSuccNodes(N); EE.hasNext();) { for (Iterator EE = getSuccNodes(N); EE.hasNext();) {
bits.add(((IBasicBlock) EE.next()).getNumber()); bits.add(((IBasicBlock) EE.next()).getNumber());
@ -109,15 +109,15 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
return bits; return bits;
} }
public Iterator getPredNodes(Object N) { public Iterator<IBasicBlock> getPredNodes(IBasicBlock N) {
return new CompoundIterator(getNormalPredecessors((IBasicBlock) N), getExceptionalPredecessors((IBasicBlock) N)); return new CompoundIterator<IBasicBlock>(getNormalPredecessors((IBasicBlock) N), getExceptionalPredecessors((IBasicBlock) N));
} }
public int getPredNodeCount(Object N) { public int getPredNodeCount(IBasicBlock N) {
return new Iterator2Collection(getPredNodes(N)).size(); return new Iterator2Collection<IBasicBlock>(getPredNodes(N)).size();
} }
public IntSet getPredNodeNumbers(Object N) { public IntSet getPredNodeNumbers(IBasicBlock N) {
MutableIntSet bits = IntSetUtil.make(); MutableIntSet bits = IntSetUtil.make();
for (Iterator EE = getPredNodes(N); EE.hasNext();) { for (Iterator EE = getPredNodes(N); EE.hasNext();) {
bits.add(((IBasicBlock) EE.next()).getNumber()); bits.add(((IBasicBlock) EE.next()).getNumber());
@ -126,7 +126,7 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
return bits; return bits;
} }
public boolean hasEdge(Object src, Object dst) { public boolean hasEdge(IBasicBlock src, IBasicBlock dst) {
for (Iterator EE = getSuccNodes(src); EE.hasNext();) { for (Iterator EE = getSuccNodes(src); EE.hasNext();) {
if (EE.next().equals(dst)) { if (EE.next().equals(dst)) {
return true; return true;
@ -136,46 +136,46 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
return false; return false;
} }
public void addEdge(Object src, Object dst) { public void addEdge(IBasicBlock src, IBasicBlock dst) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public void removeEdge(Object src, Object dst) { public void removeEdge(IBasicBlock src, IBasicBlock dst) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public void removeAllIncidentEdges(Object node) { public void removeAllIncidentEdges(IBasicBlock node) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public void removeIncomingEdges(Object node) { public void removeIncomingEdges(IBasicBlock node) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public void removeOutgoingEdges(Object node) { public void removeOutgoingEdges(IBasicBlock node) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
private static class FilteredNodes implements NumberedNodeManager { private static class FilteredNodes implements NumberedNodeManager<IBasicBlock> {
private final NumberedNodeManager nodes; private final NumberedNodeManager<IBasicBlock> nodes;
private final Set subset; private final Set subset;
FilteredNodes(NumberedNodeManager nodes, Set subset) { FilteredNodes(NumberedNodeManager<IBasicBlock> nodes, Set subset) {
this.nodes = nodes; this.nodes = nodes;
this.subset = subset; this.subset = subset;
} }
public int getNumber(Object N) { public int getNumber(IBasicBlock N) {
if (subset.contains(N)) if (subset.contains(N))
return nodes.getNumber(N); return nodes.getNumber(N);
else else
return -1; return -1;
} }
public Object getNode(int number) { public IBasicBlock getNode(int number) {
Object N = nodes.getNode(number); IBasicBlock N = nodes.getNode(number);
if (subset.contains(N)) if (subset.contains(N))
return N; return N;
else else
@ -184,8 +184,8 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
public int getMaxNumber() { public int getMaxNumber() {
int max = -1; int max = -1;
for (Iterator NS = nodes.iterateNodes(); NS.hasNext();) { for (Iterator<? extends IBasicBlock> NS = nodes.iterateNodes(); NS.hasNext();) {
Object N = NS.next(); IBasicBlock N = NS.next();
if (subset.contains(N) && getNumber(N) > max) { if (subset.contains(N) && getNumber(N) > max) {
max = getNumber(N); max = getNumber(N);
} }
@ -194,19 +194,19 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
return max; return max;
} }
private Iterator filterNodes(Iterator nodeIterator) { private Iterator<IBasicBlock> filterNodes(Iterator nodeIterator) {
return new FilterIterator(nodeIterator, new Filter() { return new FilterIterator<IBasicBlock>(nodeIterator, new Filter() {
public boolean accepts(Object o) { public boolean accepts(Object o) {
return subset.contains(o); return subset.contains(o);
} }
}); });
} }
public Iterator iterateNodes(IntSet s) { public Iterator<IBasicBlock> iterateNodes(IntSet s) {
return filterNodes(nodes.iterateNodes(s)); return filterNodes(nodes.iterateNodes(s));
} }
public Iterator iterateNodes() { public Iterator<IBasicBlock> iterateNodes() {
return filterNodes(nodes.iterateNodes()); return filterNodes(nodes.iterateNodes());
} }
@ -214,15 +214,15 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
return subset.size(); return subset.size();
} }
public void addNode(Object n) { public void addNode(IBasicBlock n) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public void removeNode(Object n) { public void removeNode(IBasicBlock n) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
public boolean containsNode(Object N) { public boolean containsNode(IBasicBlock N) {
return subset.contains(N); return subset.contains(N);
} }
} }
@ -236,47 +236,47 @@ public class PrunedCFG extends AbstractNumberedGraph<IBasicBlock> implements Con
public PrunedCFG(final ControlFlowGraph cfg, final EdgeFilter filter) { public PrunedCFG(final ControlFlowGraph cfg, final EdgeFilter filter) {
this.cfg = cfg; this.cfg = cfg;
Graph<IBasicBlock> temp = new AbstractNumberedGraph<IBasicBlock>() { Graph<IBasicBlock> temp = new AbstractNumberedGraph<IBasicBlock>() {
private final EdgeManager edges = new FilteredCFGEdges(cfg, cfg, filter); private final EdgeManager<IBasicBlock> edges = new FilteredCFGEdges(cfg, cfg, filter);
protected NodeManager getNodeManager() { protected NodeManager<IBasicBlock> getNodeManager() {
return cfg; return cfg;
} }
protected EdgeManager getEdgeManager() { protected EdgeManager<IBasicBlock> getEdgeManager() {
return edges; return edges;
} }
}; };
Set reachable = DFS.getReachableNodes(temp, Collections.singleton(cfg.entry())); Set<IBasicBlock> reachable = DFS.getReachableNodes(temp, Collections.singleton(cfg.entry()));
Set back = DFS.getReachableNodes(GraphInverter.invert(temp), Collections.singleton(cfg.exit())); Set<IBasicBlock> back = DFS.getReachableNodes(GraphInverter.invert(temp), Collections.singleton(cfg.exit()));
reachable.retainAll(back); reachable.retainAll(back);
this.nodes = new FilteredNodes(cfg, reachable); this.nodes = new FilteredNodes(cfg, reachable);
this.edges = new FilteredCFGEdges(cfg, nodes, filter); this.edges = new FilteredCFGEdges(cfg, nodes, filter);
} }
protected NodeManager getNodeManager() { protected NodeManager<IBasicBlock> getNodeManager() {
return nodes; return nodes;
} }
protected EdgeManager getEdgeManager() { protected EdgeManager<IBasicBlock> getEdgeManager() {
return edges; return edges;
} }
public Collection getExceptionalSuccessors(final IBasicBlock N) { public Collection<IBasicBlock> getExceptionalSuccessors(final IBasicBlock N) {
return new Iterator2Collection(edges.getExceptionalSuccessors(N)); return new Iterator2Collection<IBasicBlock>(edges.getExceptionalSuccessors(N));
} }
public Collection getNormalSuccessors(final IBasicBlock N) { public Collection<IBasicBlock> getNormalSuccessors(final IBasicBlock N) {
return new Iterator2Collection(edges.getNormalSuccessors(N)); return new Iterator2Collection<IBasicBlock>(edges.getNormalSuccessors(N));
} }
public Collection getExceptionalPredecessors(final IBasicBlock N) { public Collection<IBasicBlock> getExceptionalPredecessors(final IBasicBlock N) {
return new Iterator2Collection(edges.getExceptionalPredecessors(N)); return new Iterator2Collection<IBasicBlock>(edges.getExceptionalPredecessors(N));
} }
public Collection getNormalPredecessors(final IBasicBlock N) { public Collection<IBasicBlock> getNormalPredecessors(final IBasicBlock N) {
return new Iterator2Collection(edges.getNormalPredecessors(N)); return new Iterator2Collection<IBasicBlock>(edges.getNormalPredecessors(N));
} }
public IBasicBlock entry() { public IBasicBlock entry() {

View File

@ -21,30 +21,29 @@ import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SSAOptions; import com.ibm.wala.ssa.SSAOptions;
import com.ibm.wala.ssa.SSAPhiInstruction; import com.ibm.wala.ssa.SSAPhiInstruction;
import com.ibm.wala.ssa.SymbolTable; import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.SSACFG.BasicBlock;
import com.ibm.wala.ssa.SSAOptions.DefaultValues; import com.ibm.wala.ssa.SSAOptions.DefaultValues;
import com.ibm.wala.util.collections.IntStack; import com.ibm.wala.util.collections.IntStack;
import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.graph.DominanceFrontiers; import com.ibm.wala.util.graph.DominanceFrontiers;
import com.ibm.wala.util.graph.Graph; import com.ibm.wala.util.graph.Graph;
/** /**
* Abstract core of traditional SSA conversion (Cytron et al.). * Abstract core of traditional SSA conversion (Cytron et al.).
* *
* This implementation is abstract in the sense that it is designed * This implementation is abstract in the sense that it is designed to work over
* to work over the instrutions and CFG of a Domo IR, but it is * the instrutions and CFG of a Domo IR, but it is abstract with respect to
* abstract with respect to several integral portions of the * several integral portions of the traditional algorithm:
* traditional algorithm:
* <UL> * <UL>
* <LI> The notion of uses and defs of a given instruction. * <LI> The notion of uses and defs of a given instruction.
* <LI> Assignments (<def> := <use>) that are be copy-propagated away * <LI> Assignments (<def> := <use>) that are be copy-propagated away
* <LI> Which values are constants---i.e. have no definition. * <LI> Which values are constants---i.e. have no definition.
* <LI> Any value numbers to be skipped during SSA construction * <LI> Any value numbers to be skipped during SSA construction
* <LI> Special initialization and exit block processing. * <LI> Special initialization and exit block processing.
* </UL> * </UL>
* *
* @author Julian dolby (dolby@us.ibm.com) * @author Julian dolby (dolby@us.ibm.com)
* *
*/ */
public abstract class AbstractSSAConversion { public abstract class AbstractSSAConversion {
@ -56,10 +55,8 @@ public abstract class AbstractSSAConversion {
protected abstract int getUse(SSAInstruction inst, int index); protected abstract int getUse(SSAInstruction inst, int index);
protected abstract boolean isAssignInstruction(SSAInstruction inst); protected abstract boolean isAssignInstruction(SSAInstruction inst);
protected abstract int getMaxValueNumber(); protected abstract int getMaxValueNumber();
protected abstract boolean isLive(SSACFG.BasicBlock Y, int V); protected abstract boolean isLive(SSACFG.BasicBlock Y, int V);
@ -68,15 +65,12 @@ public abstract class AbstractSSAConversion {
protected abstract boolean isConstant(int valueNumber); protected abstract boolean isConstant(int valueNumber);
protected abstract int getNextNewValueNumber(); protected abstract int getNextNewValueNumber();
protected abstract void initializeVariables(); protected abstract void initializeVariables();
protected abstract void repairExit(); protected abstract void repairExit();
protected abstract void placeNewPhiAt(int value, SSACFG.BasicBlock Y); protected abstract void placeNewPhiAt(int value, SSACFG.BasicBlock Y);
protected abstract SSAPhiInstruction getPhi(SSACFG.BasicBlock B, int index); protected abstract SSAPhiInstruction getPhi(SSACFG.BasicBlock B, int index);
@ -87,34 +81,41 @@ public abstract class AbstractSSAConversion {
protected abstract void repairPhiUse(SSACFG.BasicBlock BB, int phiIndex, int rvalIndex, int newRval); protected abstract void repairPhiUse(SSACFG.BasicBlock BB, int phiIndex, int rvalIndex, int newRval);
protected abstract void repairInstructionUses(SSAInstruction inst, int index, int[] newUses); protected abstract void repairInstructionUses(SSAInstruction inst, int index, int[] newUses);
protected abstract void repairInstructionDefs(SSAInstruction inst, int index, int[] newDefs, int[] newUses); protected abstract void repairInstructionDefs(SSAInstruction inst, int index, int[] newDefs, int[] newUses);
protected abstract void pushAssignment(SSAInstruction inst, int index, int newRhs); protected abstract void pushAssignment(SSAInstruction inst, int index, int newRhs);
protected abstract void popAssignment(SSAInstruction inst, int index); protected abstract void popAssignment(SSAInstruction inst, int index);
protected final SSACFG CFG; protected final SSACFG CFG;
protected final DominanceFrontiers<IBasicBlock> DF; protected final DominanceFrontiers<IBasicBlock> DF;
private final Graph dominatorTree; private final Graph dominatorTree;
protected final int[] phiCounts; protected final int[] phiCounts;
protected final SSAInstruction[] instructions; protected final SSAInstruction[] instructions;
private final int flags[]; private final int flags[];
protected final SymbolTable symbolTable; protected final SymbolTable symbolTable;
protected final DefaultValues defaultValues; protected final DefaultValues defaultValues;
protected IntStack S[]; protected IntStack S[];
protected int C[]; protected int C[];
protected int valueMap[]; protected int valueMap[];
private Set[] assignmentMap; private Set[] assignmentMap;
protected AbstractSSAConversion(IR ir, SSAOptions options) { protected AbstractSSAConversion(IR ir, SSAOptions options) {
this.CFG = ir.getControlFlowGraph(); this.CFG = ir.getControlFlowGraph();
this.DF = new DominanceFrontiers(ir.getControlFlowGraph(), ir.getControlFlowGraph().entry()); this.DF = new DominanceFrontiers<IBasicBlock>(ir.getControlFlowGraph(), ir.getControlFlowGraph().entry());
this.dominatorTree = DF.dominatorTree(); this.dominatorTree = DF.dominatorTree();
this.flags = new int[2 * ir.getControlFlowGraph().getNumberOfNodes()]; this.flags = new int[2 * ir.getControlFlowGraph().getNumberOfNodes()];
this.instructions = ir.getInstructions(); this.instructions = ir.getInstructions();
@ -123,7 +124,6 @@ public abstract class AbstractSSAConversion {
this.defaultValues = options.getDefaultValues(); this.defaultValues = options.getDefaultValues();
} }
// //
// top-level control // top-level control
// //
@ -133,7 +133,6 @@ public abstract class AbstractSSAConversion {
renameVariables(); renameVariables();
} }
// //
// initialization // initialization
// //
@ -149,22 +148,22 @@ public abstract class AbstractSSAConversion {
for (Iterator BBs = CFG.iterateNodes(); BBs.hasNext();) { for (Iterator BBs = CFG.iterateNodes(); BBs.hasNext();) {
SSACFG.BasicBlock BB = (SSACFG.BasicBlock) BBs.next(); SSACFG.BasicBlock BB = (SSACFG.BasicBlock) BBs.next();
if (BB.getFirstInstructionIndex() >= 0) { if (BB.getFirstInstructionIndex() >= 0) {
for(Iterator IS = BB.iterateAllInstructions(); IS.hasNext(); ) { for (Iterator IS = BB.iterateAllInstructions(); IS.hasNext();) {
SSAInstruction inst = (SSAInstruction)IS.next(); SSAInstruction inst = (SSAInstruction) IS.next();
if (inst != null) { if (inst != null) {
for (int j = 0; j < getNumberOfDefs(inst); j++) { for (int j = 0; j < getNumberOfDefs(inst); j++) {
addDefiningBlock(assignmentMap, BB, getDef(inst, j)); addDefiningBlock(assignmentMap, BB, getDef(inst, j));
} }
} }
} }
} }
} }
} }
private void addDefiningBlock(Set[] A, SSACFG.BasicBlock BB, int i) { private void addDefiningBlock(Set<SSACFG.BasicBlock>[] A, SSACFG.BasicBlock BB, int i) {
if (! skip(i)) { if (!skip(i)) {
if (A[i] == null) { if (A[i] == null) {
A[i] = new LinkedHashSet(2); A[i] = new LinkedHashSet<SSACFG.BasicBlock>(2);
} }
A[i].add(BB); A[i].add(BB);
} }
@ -182,7 +181,7 @@ public abstract class AbstractSSAConversion {
setWork(X, 0); setWork(X, 0);
} }
Set W = new LinkedHashSet(); Set<BasicBlock> W = new LinkedHashSet<BasicBlock>();
for (int V = 0; V < assignmentMap.length; V++) { for (int V = 0; V < assignmentMap.length; V++) {
// some things (e.g. constants) have no defs at all // some things (e.g. constants) have no defs at all
@ -191,7 +190,7 @@ public abstract class AbstractSSAConversion {
// ignore values as requested // ignore values as requested
if (skip(V)) if (skip(V))
continue; continue;
IterCount++; IterCount++;
@ -202,15 +201,15 @@ public abstract class AbstractSSAConversion {
} }
while (!W.isEmpty()) { while (!W.isEmpty()) {
SSACFG.BasicBlock X = (SSACFG.BasicBlock) W.iterator().next(); SSACFG.BasicBlock X = W.iterator().next();
W.remove(X); W.remove(X);
for (Iterator YS = DF.getDominanceFrontier(X); YS.hasNext();) { for (Iterator YS = DF.getDominanceFrontier(X); YS.hasNext();) {
SSACFG.BasicBlock Y = (SSACFG.BasicBlock) YS.next(); SSACFG.BasicBlock Y = (SSACFG.BasicBlock) YS.next();
if (getHasAlready(Y) < IterCount) { if (getHasAlready(Y) < IterCount) {
if (isLive(Y, V)) { if (isLive(Y, V)) {
placeNewPhiAt(V, Y); placeNewPhiAt(V, Y);
phiCounts[Y.getGraphNodeId()]++; phiCounts[Y.getGraphNodeId()]++;
} }
setHasAlready(Y, IterCount); setHasAlready(Y, IterCount);
if (getWork(Y) < IterCount) { if (getWork(Y) < IterCount) {
setWork(Y, IterCount); setWork(Y, IterCount);
@ -238,15 +237,14 @@ public abstract class AbstractSSAConversion {
flags[BB.getGraphNodeId() * 2] = v; flags[BB.getGraphNodeId() * 2] = v;
} }
// //
// rename variables phase of traditional algorithm // rename variables phase of traditional algorithm
// //
private void renameVariables() { private void renameVariables() {
for (int V = 1; V <= getMaxValueNumber(); V++) { for (int V = 1; V <= getMaxValueNumber(); V++) {
if (! skip(V)) { if (!skip(V)) {
C[V] = 0; C[V] = 0;
S[V] = new IntStack(); S[V] = new IntStack();
} }
} }
@ -262,27 +260,27 @@ public abstract class AbstractSSAConversion {
// first loop // first loop
for (int i = 0; i < phiCounts[id]; i++) { for (int i = 0; i < phiCounts[id]; i++) {
SSAPhiInstruction phi = getPhi(X, i); SSAPhiInstruction phi = getPhi(X, i);
if (! skipRepair(phi, -1)) { if (!skipRepair(phi, -1)) {
setPhi(X, i, repairPhiDefs(phi, makeNewDefs(phi))); setPhi(X, i, repairPhiDefs(phi, makeNewDefs(phi)));
} }
} }
for (int i = Xf; i <= X.getLastInstructionIndex(); i++) { for (int i = Xf; i <= X.getLastInstructionIndex(); i++) {
SSAInstruction inst = instructions[i]; SSAInstruction inst = instructions[i];
if (isAssignInstruction(inst)) { if (isAssignInstruction(inst)) {
int lhs = getDef(inst, 0); int lhs = getDef(inst, 0);
int rhs = getUse(inst, 0); int rhs = getUse(inst, 0);
int newRhs = skip(rhs)? rhs: top(rhs); int newRhs = skip(rhs) ? rhs : top(rhs);
S[lhs].push( newRhs ); S[lhs].push(newRhs);
pushAssignment(inst, i, newRhs); pushAssignment(inst, i, newRhs);
} else { } else {
if (! skipRepair(inst, i)) { if (!skipRepair(inst, i)) {
int[] newUses = makeNewUses(inst); int[] newUses = makeNewUses(inst);
repairInstructionUses(inst, i, newUses); repairInstructionUses(inst, i, newUses);
int[] newDefs = makeNewDefs(inst); int[] newDefs = makeNewDefs(inst);
repairInstructionDefs(inst, i, newDefs, newUses); repairInstructionDefs(inst, i, newDefs, newUses);
} }
} }
} }
@ -295,10 +293,10 @@ public abstract class AbstractSSAConversion {
int Y_id = Y.getGraphNodeId(); int Y_id = Y.getGraphNodeId();
int j = com.ibm.wala.cast.ir.cfg.Util.whichPred(CFG, Y, X); int j = com.ibm.wala.cast.ir.cfg.Util.whichPred(CFG, Y, X);
for (int i = 0; i < phiCounts[Y_id]; i++) { for (int i = 0; i < phiCounts[Y_id]; i++) {
SSAPhiInstruction phi = getPhi(Y, i); SSAPhiInstruction phi = getPhi(Y, i);
int oldUse = getUse(phi, j); int oldUse = getUse(phi, j);
int newUse = skip(oldUse) ? oldUse: top(oldUse); int newUse = skip(oldUse) ? oldUse : top(oldUse);
repairPhiUse(Y, i, j, newUse); repairPhiUse(Y, i, j, newUse);
} }
} }
@ -309,31 +307,30 @@ public abstract class AbstractSSAConversion {
for (int i = 0; i < phiCounts[id]; i++) { for (int i = 0; i < phiCounts[id]; i++) {
SSAInstruction A = getPhi(X, i); SSAInstruction A = getPhi(X, i);
for (int j = 0; j < getNumberOfDefs(A); j++) { for (int j = 0; j < getNumberOfDefs(A); j++) {
if (! skip(getDef(A, j))) { if (!skip(getDef(A, j))) {
S[valueMap[getDef(A, j)]].pop(); S[valueMap[getDef(A, j)]].pop();
} }
} }
} }
for (int i = Xf; i <= X.getLastInstructionIndex(); i++) { for (int i = Xf; i <= X.getLastInstructionIndex(); i++) {
SSAInstruction A = instructions[i]; SSAInstruction A = instructions[i];
if (isAssignInstruction(A)) { if (isAssignInstruction(A)) {
S[ getDef(A, 0) ].pop(); S[getDef(A, 0)].pop();
popAssignment(A, i); popAssignment(A, i);
} else if (A != null) { } else if (A != null) {
for (int j = 0; j < getNumberOfDefs(A); j++) { for (int j = 0; j < getNumberOfDefs(A); j++) {
if (! skip(getDef(A, j))) { if (!skip(getDef(A, j))) {
S[valueMap[getDef(A, j)]].pop(); S[valueMap[getDef(A, j)]].pop();
} }
} }
} }
} }
} }
private int[] makeNewUses(SSAInstruction inst) { private int[] makeNewUses(SSAInstruction inst) {
int[] newUses = new int[getNumberOfUses(inst)]; int[] newUses = new int[getNumberOfUses(inst)];
for (int j = 0; j < getNumberOfUses(inst); j++) { for (int j = 0; j < getNumberOfUses(inst); j++) {
newUses[j] = newUses[j] = skip(getUse(inst, j)) ? getUse(inst, j) : top(getUse(inst, j));
skip(getUse(inst, j))? getUse(inst, j): top(getUse(inst, j));
} }
return newUses; return newUses;
@ -344,19 +341,19 @@ public abstract class AbstractSSAConversion {
for (int j = 0; j < getNumberOfDefs(inst); j++) { for (int j = 0; j < getNumberOfDefs(inst); j++) {
if (skip(getDef(inst, j))) { if (skip(getDef(inst, j))) {
newDefs[j] = getDef(inst, j); newDefs[j] = getDef(inst, j);
} else { } else {
int ii = getNextNewValueNumber(); int ii = getNextNewValueNumber();
if (valueMap.length <= ii) { if (valueMap.length <= ii) {
int[] nvm = new int[valueMap.length * 2 + ii + 1]; int[] nvm = new int[valueMap.length * 2 + ii + 1];
System.arraycopy(valueMap, 0, nvm, 0, valueMap.length); System.arraycopy(valueMap, 0, nvm, 0, valueMap.length);
valueMap = nvm; valueMap = nvm;
} }
valueMap[ii] = getDef(inst, j); valueMap[ii] = getDef(inst, j);
S[getDef(inst, j)].push(ii); S[getDef(inst, j)].push(ii);
newDefs[j] = ii; newDefs[j] = ii;
} }
} }
@ -366,24 +363,21 @@ public abstract class AbstractSSAConversion {
protected boolean skipRepair(SSAInstruction inst, int index) { protected boolean skipRepair(SSAInstruction inst, int index) {
if (inst == null) if (inst == null)
return true; return true;
for(int i = 0; i < getNumberOfDefs(inst); i++) for (int i = 0; i < getNumberOfDefs(inst); i++)
if (! skip(getDef(inst, i))) return false; if (!skip(getDef(inst, i)))
for(int i = 0; i < getNumberOfUses(inst); i++) return false;
if (! skip(getUse(inst, i))) return false; for (int i = 0; i < getNumberOfUses(inst); i++)
if (!skip(getUse(inst, i)))
return false;
return true; return true;
} }
protected void fail(int v) { protected void fail(int v) {
Assertions._assert( Assertions._assert(isConstant(v) || !S[v].isEmpty(), "bad stack for " + v + " while SSA converting");
isConstant(v) || !S[v].isEmpty(),
"bad stack for " + v + " while SSA converting");
} }
protected boolean hasDefaultValue(int valueNumber) { protected boolean hasDefaultValue(int valueNumber) {
return return (defaultValues != null) && (defaultValues.getDefaultValue(symbolTable, valueNumber) != -1);
(defaultValues != null)
&&
(defaultValues.getDefaultValue(symbolTable, valueNumber) != -1);
} }
protected int getDefaultValue(int valueNumber) { protected int getDefaultValue(int valueNumber) {
@ -391,11 +385,11 @@ public abstract class AbstractSSAConversion {
} }
protected int top(int v) { protected int top(int v) {
if (! (isConstant(v) || !S[v].isEmpty())) { if (!(isConstant(v) || !S[v].isEmpty())) {
if (hasDefaultValue(v)) { if (hasDefaultValue(v)) {
return getDefaultValue(v); return getDefaultValue(v);
} else { } else {
fail(v); fail(v);
} }
} }

View File

@ -15,52 +15,53 @@ import java.util.Collection;
import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SymbolTable; import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.ValueDecorator; import com.ibm.wala.ssa.ValueDecorator;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.Assertions;
public class AstAssertInstruction extends SSAInstruction { public class AstAssertInstruction extends SSAInstruction {
private final int value; private final int value;
private final boolean fromSpecification;
public AstAssertInstruction(int value, boolean fromSpecification) {
this.value = value;
this.fromSpecification = fromSpecification;
}
public int getNumberOfUses() {
return 1;
}
public int getUse(int i) {
Assertions._assert(i == 0);
return value;
}
public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return new AstAssertInstruction(uses==null? value: uses[0], fromSpecification);
}
public String toString(SymbolTable symbolTable, ValueDecorator d) { private final boolean fromSpecification;
return "assert " + getValueString(symbolTable, d, value) +
" (fromSpec: " + fromSpecification + ")";
}
public void visit(IVisitor v) { public AstAssertInstruction(int value, boolean fromSpecification) {
((AstInstructionVisitor)v).visitAssert(this); this.value = value;
} this.fromSpecification = fromSpecification;
}
public int hashCode() { public int getNumberOfUses() {
return 2177*value; return 1;
} }
public Collection getExceptionTypes() { public int getUse(int i) {
return null; Assertions._assert(i == 0);
} return value;
}
public boolean isFallThrough() { public SSAInstruction copyForSSA(int[] defs, int[] uses) {
return true; return new AstAssertInstruction(uses == null ? value : uses[0], fromSpecification);
} }
public boolean isFromSpecification() { public String toString(SymbolTable symbolTable, ValueDecorator d) {
return fromSpecification; return "assert " + getValueString(symbolTable, d, value) + " (fromSpec: " + fromSpecification + ")";
} }
public void visit(IVisitor v) {
((AstInstructionVisitor) v).visitAssert(this);
}
public int hashCode() {
return 2177 * value;
}
public Collection<TypeReference> getExceptionTypes() {
return null;
}
public boolean isFallThrough() {
return true;
}
public boolean isFromSpecification() {
return fromSpecification;
}
} }

View File

@ -12,8 +12,12 @@ package com.ibm.wala.cast.ir.ssa;
import java.util.Collection; import java.util.Collection;
import com.ibm.wala.ssa.*; import com.ibm.wala.ssa.SSAGetInstruction;
import com.ibm.wala.types.*; import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.ValueDecorator;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeReference;
public class AstGlobalRead extends SSAGetInstruction { public class AstGlobalRead extends SSAGetInstruction {
@ -38,7 +42,7 @@ public class AstGlobalRead extends SSAGetInstruction {
return true; return true;
} }
public Collection getExceptionTypes() { public Collection<TypeReference> getExceptionTypes() {
return null; return null;
} }

View File

@ -12,8 +12,12 @@ package com.ibm.wala.cast.ir.ssa;
import java.util.Collection; import java.util.Collection;
import com.ibm.wala.ssa.*; import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.*; import com.ibm.wala.ssa.SSAPutInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.ValueDecorator;
import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.TypeReference;
public class AstGlobalWrite extends SSAPutInstruction { public class AstGlobalWrite extends SSAPutInstruction {
@ -38,7 +42,7 @@ public class AstGlobalWrite extends SSAPutInstruction {
return true; return true;
} }
public Collection getExceptionTypes() { public Collection<TypeReference> getExceptionTypes() {
return null; return null;
} }

View File

@ -10,7 +10,6 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.ir.ssa; package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.cast.loader.*; import com.ibm.wala.cast.loader.*;
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
import com.ibm.wala.cfg.*; import com.ibm.wala.cfg.*;
@ -27,19 +26,16 @@ import java.util.*;
public class AstIRFactory implements IRFactory { public class AstIRFactory implements IRFactory {
private final boolean keepIR; private final boolean keepIR;
private final Map keptIRs;
private final Map<IMethod, IR> keptIRs;
AstIRFactory(boolean keepIR) { AstIRFactory(boolean keepIR) {
this.keepIR = keepIR; this.keepIR = keepIR;
this.keptIRs = (keepIR)? new HashMap(): null; this.keptIRs = (keepIR) ? new HashMap<IMethod, IR>() : null;
} }
public ControlFlowGraph makeCFG(final IMethod method, public ControlFlowGraph makeCFG(final IMethod method, final Context context, final ClassHierarchy cha, final WarningSet warnings) {
final Context context, return ((AstMethod) method).getControlFlowGraph();
final ClassHierarchy cha,
final WarningSet warnings)
{
return ((AstMethod)method).getControlFlowGraph();
} }
public class AstIR extends IR { public class AstIR extends IR {
@ -47,80 +43,63 @@ public class AstIRFactory implements IRFactory {
private void setCatchInstructions(SSACFG ssacfg, AbstractCFG oldcfg) { private void setCatchInstructions(SSACFG ssacfg, AbstractCFG oldcfg) {
for (int i = 0; i < oldcfg.getNumberOfNodes(); i++) for (int i = 0; i < oldcfg.getNumberOfNodes(); i++)
if (oldcfg.isCatchBlock(i)) { if (oldcfg.isCatchBlock(i)) {
ExceptionHandlerBasicBlock B = ExceptionHandlerBasicBlock B = (ExceptionHandlerBasicBlock) ssacfg.getNode(i);
(ExceptionHandlerBasicBlock) ssacfg.getNode(i); B.setCatchInstruction((SSAGetCaughtExceptionInstruction) getInstructions()[B.getFirstInstructionIndex()]);
B.setCatchInstruction((SSAGetCaughtExceptionInstruction) }
getInstructions()[B.getFirstInstructionIndex()]);
}
} }
private void setupCatchTypes(SSACFG cfg, TypeReference[][] catchTypes) { private void setupCatchTypes(SSACFG cfg, TypeReference[][] catchTypes) {
for (int i = 0; i < catchTypes.length; i++) { for (int i = 0; i < catchTypes.length; i++) {
if (catchTypes[i] != null) { if (catchTypes[i] != null) {
ExceptionHandlerBasicBlock bb = ExceptionHandlerBasicBlock bb = (ExceptionHandlerBasicBlock) cfg.getNode(i);
(ExceptionHandlerBasicBlock) cfg.getNode(i); for (int j = 0; j < catchTypes[i].length; j++) {
for (int j = 0; j < catchTypes[i].length; j++) { bb.addCaughtExceptionType(catchTypes[i][j]);
bb.addCaughtExceptionType(catchTypes[i][j]); }
} }
}
} }
} }
protected SSA2LocalMap getLocalMap() { protected SSA2LocalMap getLocalMap() {
return localMap; return localMap;
} }
protected String instructionPosition(int instructionIndex) { protected String instructionPosition(int instructionIndex) {
Position pos = Position pos = ((AstMethod) getMethod()).getSourcePosition(instructionIndex);
((AstMethod)getMethod()).getSourcePosition(instructionIndex);
if (pos == null) { if (pos == null) {
return ""; return "";
} else { } else {
return pos.toString(); return pos.toString();
} }
} }
private AstIR(AstMethod method, private AstIR(AstMethod method, SSAInstruction[] instructions, SymbolTable symbolTable, SSACFG cfg, SSAOptions options) {
SSAInstruction[] instructions,
SymbolTable symbolTable,
SSACFG cfg,
SSAOptions options)
{
super(method, instructions, symbolTable, cfg, options); super(method, instructions, symbolTable, cfg, options);
setCatchInstructions(getControlFlowGraph(), method.cfg); setCatchInstructions(getControlFlowGraph(), method.cfg);
localMap = SSAConversion.convert(method, this, options); localMap = SSAConversion.convert(method, this, options);
setupCatchTypes(getControlFlowGraph(), method.catchTypes); setupCatchTypes(getControlFlowGraph(), method.catchTypes);
setupLocationMap(); setupLocationMap();
} }
} }
public IR makeIR(final IMethod method, public IR makeIR(final IMethod method, final Context context, final ClassHierarchy cha, final SSAOptions options,
final Context context, final WarningSet warnings) {
final ClassHierarchy cha,
final SSAOptions options,
final WarningSet warnings)
{
Assertions._assert(method instanceof AstMethod, method.toString()); Assertions._assert(method instanceof AstMethod, method.toString());
if (keepIR) { if (keepIR) {
if (keptIRs.containsKey(method)) { if (keptIRs.containsKey(method)) {
return (IR) keptIRs.get(method); return keptIRs.get(method);
} }
} }
AbstractCFG oldCfg = ((AstMethod)method).cfg; AbstractCFG oldCfg = ((AstMethod) method).cfg;
SSAInstruction[] instrs = (SSAInstruction[])oldCfg.getInstructions(); SSAInstruction[] instrs = (SSAInstruction[]) oldCfg.getInstructions();
IR newIR = IR newIR = new AstIR((AstMethod) method, instrs, ((AstMethod) method).symtab, new SSACFG(method, oldCfg, instrs, warnings),
new AstIR((AstMethod)method, options);
instrs,
((AstMethod)method).symtab,
new SSACFG(method, oldCfg, instrs, warnings),
options);
if (keepIR) { if (keepIR) {
keptIRs.put(method, newIR); keptIRs.put(method, newIR);
@ -128,34 +107,25 @@ public class AstIRFactory implements IRFactory {
return newIR; return newIR;
} }
public static IRFactory makeDefaultFactory(final boolean keepAstIRs) { public static IRFactory makeDefaultFactory(final boolean keepAstIRs) {
return new DefaultIRFactory() { return new DefaultIRFactory() {
private final AstIRFactory astFactory = new AstIRFactory(keepAstIRs); private final AstIRFactory astFactory = new AstIRFactory(keepAstIRs);
public IR makeIR(IMethod method, public IR makeIR(IMethod method, Context context, ClassHierarchy cha, SSAOptions options, WarningSet warnings) {
Context context, if (method instanceof AstMethod) {
ClassHierarchy cha, return astFactory.makeIR(method, context, cha, options, warnings);
SSAOptions options, } else {
WarningSet warnings) return super.makeIR(method, context, cha, options, warnings);
{ }
if (method instanceof AstMethod) {
return astFactory.makeIR(method, context, cha, options, warnings);
} else {
return super.makeIR(method, context, cha, options, warnings);
}
} }
public ControlFlowGraph makeCFG(IMethod method, public ControlFlowGraph makeCFG(IMethod method, Context context, ClassHierarchy cha, WarningSet warnings) {
Context context, if (method instanceof AstMethod) {
ClassHierarchy cha, return astFactory.makeCFG(method, context, cha, warnings);
WarningSet warnings) } else {
{ return super.makeCFG(method, context, cha, warnings);
if (method instanceof AstMethod) { }
return astFactory.makeCFG(method, context, cha, warnings);
} else {
return super.makeCFG(method, context, cha, warnings);
}
} }
}; };
} }

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa;
import java.util.Collection; import java.util.Collection;
import com.ibm.wala.ssa.SSAInstruction; import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.TypeReference;
public abstract class AstLexicalAccess extends SSAInstruction { public abstract class AstLexicalAccess extends SSAInstruction {
@ -71,7 +72,7 @@ public abstract class AstLexicalAccess extends SSAInstruction {
return true; return true;
} }
public Collection getExceptionTypes() { public Collection<TypeReference> getExceptionTypes() {
return null; return null;
} }

View File

@ -10,9 +10,14 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.ir.ssa; package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.ssa.*; import java.util.Collection;
import java.util.Collections;
import java.util.*; import com.ibm.wala.ssa.SSAAbstractUnaryInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.ValueDecorator;
import com.ibm.wala.types.TypeReference;
public class EachElementGetInstruction extends SSAAbstractUnaryInstruction { public class EachElementGetInstruction extends SSAAbstractUnaryInstruction {
@ -34,7 +39,7 @@ public class EachElementGetInstruction extends SSAAbstractUnaryInstruction {
((AstInstructionVisitor) v).visitEachElementGet(this); ((AstInstructionVisitor) v).visitEachElementGet(this);
} }
public Collection getExceptionTypes() { public Collection<TypeReference> getExceptionTypes() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
} }

View File

@ -10,9 +10,14 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.ir.ssa; package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.ssa.*; import java.util.Collection;
import java.util.Collections;
import java.util.*; import com.ibm.wala.ssa.SSAAbstractUnaryInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.ssa.SymbolTable;
import com.ibm.wala.ssa.ValueDecorator;
import com.ibm.wala.types.TypeReference;
public class EachElementHasNextInstruction extends SSAAbstractUnaryInstruction { public class EachElementHasNextInstruction extends SSAAbstractUnaryInstruction {
@ -34,7 +39,7 @@ public class EachElementHasNextInstruction extends SSAAbstractUnaryInstruction {
((AstInstructionVisitor) v).visitEachElementHasNext(this); ((AstInstructionVisitor) v).visitEachElementHasNext(this);
} }
public Collection getExceptionTypes() { public Collection<TypeReference> getExceptionTypes() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
} }

View File

@ -10,9 +10,12 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.ir.ssa; package com.ibm.wala.cast.ir.ssa;
import com.ibm.wala.ssa.*; import java.util.Collection;
import java.util.Collections;
import java.util.*; import com.ibm.wala.ssa.SSAAbstractThrowInstruction;
import com.ibm.wala.ssa.SSAInstruction;
import com.ibm.wala.types.TypeReference;
public class NonExceptingThrowInstruction extends SSAAbstractThrowInstruction { public class NonExceptingThrowInstruction extends SSAAbstractThrowInstruction {
@ -31,8 +34,8 @@ public class NonExceptingThrowInstruction extends SSAAbstractThrowInstruction {
((AstInstructionVisitor)v).visitNonExceptingThrow(this); ((AstInstructionVisitor)v).visitNonExceptingThrow(this);
} }
public Collection getExceptionTypes() { public Collection<TypeReference> getExceptionTypes() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
} }

View File

@ -38,14 +38,17 @@ import com.ibm.wala.util.intset.MutableIntSet;
/** /**
* @author Julian Dolby * @author Julian Dolby
* *
* Standard SSA conversion for local value numbers. * Standard SSA conversion for local value numbers.
*/ */
public class SSAConversion extends AbstractSSAConversion { public class SSAConversion extends AbstractSSAConversion {
public static boolean DEBUG = false; public static boolean DEBUG = false;
public static boolean DEBUG_UNDO = true; public static boolean DEBUG_UNDO = true;
public static boolean DEBUG_NAMES = true; public static boolean DEBUG_NAMES = true;
public static boolean DUMP = false; public static boolean DUMP = false;
private final AstIR ir; private final AstIR ir;
@ -66,32 +69,35 @@ public class SSAConversion extends AbstractSSAConversion {
// Copy propagation history // Copy propagation history
// //
private final Map copyPropagationMap; private final Map<Object, CopyPropagationRecord> copyPropagationMap;
private final Stack R[];
private final Stack<CopyPropagationRecord> R[];
private static class UseRecord { private static class UseRecord {
final int instructionIndex; final int instructionIndex;
final int useNumber; final int useNumber;
private UseRecord(int instructionIndex, int useNumber) { private UseRecord(int instructionIndex, int useNumber) {
this.useNumber = useNumber; this.useNumber = useNumber;
this.instructionIndex = instructionIndex; this.instructionIndex = instructionIndex;
} }
public int hashCode() { public int hashCode() {
return useNumber*instructionIndex; return useNumber * instructionIndex;
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof UseRecord) && return (o instanceof UseRecord) && instructionIndex == ((UseRecord) o).instructionIndex
instructionIndex==((UseRecord)o).instructionIndex && && useNumber == ((UseRecord) o).useNumber;
useNumber==((UseRecord)o).useNumber;
} }
} }
private class PhiUseRecord { private class PhiUseRecord {
final int BBnumber; final int BBnumber;
final int phiNumber; final int phiNumber;
final int useNumber; final int useNumber;
private PhiUseRecord(int BBnumber, int phiNumber, int useNumber) { private PhiUseRecord(int BBnumber, int phiNumber, int useNumber) {
@ -99,68 +105,73 @@ public class SSAConversion extends AbstractSSAConversion {
this.phiNumber = phiNumber; this.phiNumber = phiNumber;
this.useNumber = useNumber; this.useNumber = useNumber;
} }
public int hashCode() { public int hashCode() {
return phiNumber*BBnumber*useNumber; return phiNumber * BBnumber * useNumber;
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof PhiUseRecord) && return (o instanceof PhiUseRecord) && BBnumber == ((PhiUseRecord) o).BBnumber && phiNumber == ((PhiUseRecord) o).phiNumber
BBnumber==((PhiUseRecord)o).BBnumber && && useNumber == ((PhiUseRecord) o).useNumber;
phiNumber==((PhiUseRecord)o).phiNumber &&
useNumber==((PhiUseRecord)o).useNumber;
} }
} }
private class CopyPropagationRecord { private class CopyPropagationRecord {
final int lhs; final int lhs;
final int rhs; final int rhs;
final int instructionIndex; final int instructionIndex;
final Set renamedUses = new HashSet(2);
private final Set childRecords = new HashSet(1); final Set<Object> renamedUses = new HashSet<Object>(2);
private final Set<CopyPropagationRecord> childRecords = new HashSet<CopyPropagationRecord>(1);
public int hashCode() { public int hashCode() {
return instructionIndex; return instructionIndex;
} }
public boolean equals(Object o) { public boolean equals(Object o) {
return (o instanceof CopyPropagationRecord) && return (o instanceof CopyPropagationRecord) && instructionIndex == ((CopyPropagationRecord) o).instructionIndex;
instructionIndex==((CopyPropagationRecord)o).instructionIndex;
} }
private CopyPropagationRecord(int instructionIndex, int lhs, int rhs) { private CopyPropagationRecord(int instructionIndex, int lhs, int rhs) {
if (DEBUG_UNDO) Trace.println("new copy record for instruction #" + instructionIndex + ", rhs value is " + rhs); if (DEBUG_UNDO)
Trace.println("new copy record for instruction #" + instructionIndex + ", rhs value is " + rhs);
this.lhs = lhs; this.lhs = lhs;
this.rhs = rhs; this.rhs = rhs;
this.instructionIndex = instructionIndex; this.instructionIndex = instructionIndex;
} }
private void addChild(CopyPropagationRecord rec) { private void addChild(CopyPropagationRecord rec) {
if (DEBUG_UNDO) Trace.println("("+rec.instructionIndex+","+rec.rhs+") is a child of ("+instructionIndex+","+rhs+")"); if (DEBUG_UNDO)
Trace.println("(" + rec.instructionIndex + "," + rec.rhs + ") is a child of (" + instructionIndex + "," + rhs + ")");
childRecords.add(rec); childRecords.add(rec);
} }
private void addUse(int instructionIndex, int use) { private void addUse(int instructionIndex, int use) {
if (DEBUG_UNDO) Trace.println("propagated use of (" + this.instructionIndex + "," + this.rhs + ") at use #" + use + " of instruction #" + instructionIndex); if (DEBUG_UNDO)
Trace.println("propagated use of (" + this.instructionIndex + "," + this.rhs + ") at use #" + use + " of instruction #"
+ instructionIndex);
UseRecord rec = new UseRecord(instructionIndex, use); UseRecord rec = new UseRecord(instructionIndex, use);
copyPropagationMap.put(rec, this); copyPropagationMap.put(rec, this);
renamedUses.add( rec ); renamedUses.add(rec);
} }
private void addUse(int BB, int phiNumber, int use) { private void addUse(int BB, int phiNumber, int use) {
PhiUseRecord rec = new PhiUseRecord(BB, phiNumber, use); PhiUseRecord rec = new PhiUseRecord(BB, phiNumber, use);
copyPropagationMap.put(rec, this); copyPropagationMap.put(rec, this);
renamedUses.add( rec ); renamedUses.add(rec);
} }
private SSAInstruction undo(SSAInstruction inst, int use, int val) { private SSAInstruction undo(SSAInstruction inst, int use, int val) {
int c = getNumberOfUses(inst); int c = getNumberOfUses(inst);
int[] newUses = new int[ c ]; int[] newUses = new int[c];
for(int i = 0; i < c; i++) { for (int i = 0; i < c; i++) {
if (i == use) if (i == use)
newUses[i] = val; newUses[i] = val;
else else
newUses[i] = getUse(inst, i); newUses[i] = getUse(inst, i);
} }
return inst.copyForSSA(null, newUses); return inst.copyForSSA(null, newUses);
@ -169,43 +180,45 @@ public class SSAConversion extends AbstractSSAConversion {
private void undo(int rhs) { private void undo(int rhs) {
int lhs = symtab.newSymbol(); int lhs = symtab.newSymbol();
instructions[ instructionIndex ] = new AssignInstruction(lhs, rhs); instructions[instructionIndex] = new AssignInstruction(lhs, rhs);
if (DEBUG_UNDO) Trace.println("recreating assignment at " + instructionIndex + " as " + lhs + " = " + rhs);
for(Iterator uses = renamedUses.iterator(); uses.hasNext(); ) { if (DEBUG_UNDO)
Object x = uses.next(); Trace.println("recreating assignment at " + instructionIndex + " as " + lhs + " = " + rhs);
if (x instanceof UseRecord) {
UseRecord use = (UseRecord)x;
int idx = use.instructionIndex;
SSAInstruction inst = instructions[ idx ];
if (DEBUG_UNDO) Trace.println("Changing use #" + use.useNumber + " of inst #" + idx + " to val " + lhs); for (Iterator<Object> uses = renamedUses.iterator(); uses.hasNext();) {
Object x = uses.next();
if (x instanceof UseRecord) {
UseRecord use = (UseRecord) x;
int idx = use.instructionIndex;
SSAInstruction inst = instructions[idx];
if (use.useNumber >= 0) { if (DEBUG_UNDO)
instructions[idx] = undo(inst, use.useNumber, lhs); Trace.println("Changing use #" + use.useNumber + " of inst #" + idx + " to val " + lhs);
} else {
lexicalInfo.getExposedUses(idx)[-use.useNumber - 1] = lhs; if (use.useNumber >= 0) {
} instructions[idx] = undo(inst, use.useNumber, lhs);
copyPropagationMap.remove( use ); } else {
} else { lexicalInfo.getExposedUses(idx)[-use.useNumber - 1] = lhs;
PhiUseRecord use = (PhiUseRecord)x; }
int bb = use.BBnumber; copyPropagationMap.remove(use);
int phi = use.phiNumber; } else {
SSACFG.BasicBlock BB = (SSACFG.BasicBlock)CFG.getNode(bb); PhiUseRecord use = (PhiUseRecord) x;
BB.addPhiForLocal(phi, (SSAPhiInstruction)undo(BB.getPhiForLocal(phi), use.useNumber, lhs)); int bb = use.BBnumber;
copyPropagationMap.remove( use ); int phi = use.phiNumber;
} SSACFG.BasicBlock BB = (SSACFG.BasicBlock) CFG.getNode(bb);
BB.addPhiForLocal(phi, (SSAPhiInstruction) undo(BB.getPhiForLocal(phi), use.useNumber, lhs));
copyPropagationMap.remove(use);
}
} }
for(Iterator cs = childRecords.iterator(); cs.hasNext(); ) { for (Iterator<CopyPropagationRecord> cs = childRecords.iterator(); cs.hasNext();) {
((CopyPropagationRecord)cs.next()).undo( lhs ); cs.next().undo(lhs);
} }
} }
public void undo() { public void undo() {
undo( this.rhs ); undo(this.rhs);
copyPropagationMap.remove( new UseRecord(instructionIndex, rhs) ); copyPropagationMap.remove(new UseRecord(instructionIndex, rhs));
} }
} }
@ -218,57 +231,55 @@ public class SSAConversion extends AbstractSSAConversion {
SSAInformation info = (SSAInformation) ir.getLocalMap(); SSAInformation info = (SSAInformation) ir.getLocalMap();
info.copyUse(fromInst, fromUse, toInst, toUse); info.copyUse(fromInst, fromUse, toInst, toUse);
} }
// //
// SSA2LocalMap implementation for SSAConversion // SSA2LocalMap implementation for SSAConversion
// //
private class SSAInformation implements com.ibm.wala.ssa.IR.SSA2LocalMap { private class SSAInformation implements com.ibm.wala.ssa.IR.SSA2LocalMap {
public String[] getLocalNames(int pc, int vn) { public String[] getLocalNames(int pc, int vn) {
int v = skip(vn)||vn>=valueMap.length? vn: valueMap[vn]; int v = skip(vn) || vn >= valueMap.length ? vn : valueMap[vn];
String[][] namesData = debugInfo.getSourceNamesForValues(); String[][] namesData = debugInfo.getSourceNamesForValues();
if (namesData == null || namesData.length <= v) if (namesData == null || namesData.length <= v)
return new String[0]; return new String[0];
else else
return namesData[v]; return namesData[v];
} }
private void undoCopyPropagation(int instructionIndex, int useNumber) { private void undoCopyPropagation(int instructionIndex, int useNumber) {
if (DEBUG_UNDO) if (DEBUG_UNDO)
Trace.println("undoing for use #" + useNumber + " of inst #" + instructionIndex); Trace.println("undoing for use #" + useNumber + " of inst #" + instructionIndex);
UseRecord use = new UseRecord(instructionIndex, useNumber); UseRecord use = new UseRecord(instructionIndex, useNumber);
if (copyPropagationMap.containsKey(use)) { if (copyPropagationMap.containsKey(use)) {
((CopyPropagationRecord)copyPropagationMap.get(use)).undo(); copyPropagationMap.get(use).undo();
} }
} }
private void copyUse(int fromInst, int fromUse, int toInst, int toUse) { private void copyUse(int fromInst, int fromUse, int toInst, int toUse) {
UseRecord use = new UseRecord(fromInst, fromUse); UseRecord use = new UseRecord(fromInst, fromUse);
if (copyPropagationMap.containsKey(use)) { if (copyPropagationMap.containsKey(use)) {
((CopyPropagationRecord)copyPropagationMap.get(use)).addUse(toInst, toUse); copyPropagationMap.get(use).addUse(toInst, toUse);
} }
} }
private Map getCopyHistory() { private Map<Object, CopyPropagationRecord> getCopyHistory() {
return copyPropagationMap; return copyPropagationMap;
} }
} }
private CopyPropagationRecord topR(int v) { private CopyPropagationRecord topR(int v) {
if (R[v] != null && !R[v].isEmpty()) { if (R[v] != null && !R[v].isEmpty()) {
CopyPropagationRecord rec = (CopyPropagationRecord)R[v].peek(); CopyPropagationRecord rec = (CopyPropagationRecord) R[v].peek();
if (top(v) == rec.rhs) { if (top(v) == rec.rhs) {
return rec; return rec;
} }
} }
return null; return null;
} }
// //
// implementation of AbstractSSAConversion hooks // implementation of AbstractSSAConversion hooks
// //
@ -331,7 +342,7 @@ public class SSAConversion extends AbstractSSAConversion {
} }
protected SSAPhiInstruction repairPhiDefs(SSAPhiInstruction phi, int[] newDefs) { protected SSAPhiInstruction repairPhiDefs(SSAPhiInstruction phi, int[] newDefs) {
return (SSAPhiInstruction)phi.copyForSSA(newDefs, null); return (SSAPhiInstruction) phi.copyForSSA(newDefs, null);
} }
protected void repairPhiUse(SSACFG.BasicBlock BB, int phiIndex, int rvalIndex, int newRval) { protected void repairPhiUse(SSACFG.BasicBlock BB, int phiIndex, int rvalIndex, int newRval) {
@ -340,11 +351,11 @@ public class SSAConversion extends AbstractSSAConversion {
int[] newUses = new int[getNumberOfUses(phi)]; int[] newUses = new int[getNumberOfUses(phi)];
for (int v = 0; v < newUses.length; v++) { for (int v = 0; v < newUses.length; v++) {
int oldUse = getUse(phi, v); int oldUse = getUse(phi, v);
int newUse = (v==rvalIndex)? newRval: oldUse; int newUse = (v == rvalIndex) ? newRval : oldUse;
newUses[v] = newUse; newUses[v] = newUse;
if (v==rvalIndex && topR(oldUse) != null) { if (v == rvalIndex && topR(oldUse) != null) {
topR(oldUse).addUse(BB.getGraphNodeId(), phiIndex, v); topR(oldUse).addUse(BB.getGraphNodeId(), phiIndex, v);
} }
} }
@ -358,36 +369,36 @@ public class SSAConversion extends AbstractSSAConversion {
copyNames(rhs, lhs); copyNames(rhs, lhs);
CopyPropagationRecord rec = new CopyPropagationRecord(index, lhs, newRhs); CopyPropagationRecord rec = new CopyPropagationRecord(index, lhs, newRhs);
R[lhs].push( rec ); R[lhs].push(rec);
if (topR(rhs) != null) { if (topR(rhs) != null) {
topR(rhs).addChild( rec ); topR(rhs).addChild(rec);
} }
} }
protected void repairInstructionUses(SSAInstruction inst, int index, int[] newUses){ protected void repairInstructionUses(SSAInstruction inst, int index, int[] newUses) {
for (int j = 0; j < getNumberOfUses(inst); j++) { for (int j = 0; j < getNumberOfUses(inst); j++) {
if (topR(getUse(inst, j)) != null) { if (topR(getUse(inst, j)) != null) {
topR(getUse(inst, j)).addUse(index, j); topR(getUse(inst, j)).addUse(index, j);
} }
} }
int[] lexicalUses = lexicalInfo.getExposedUses(index); int[] lexicalUses = lexicalInfo.getExposedUses(index);
if (lexicalUses != null) { if (lexicalUses != null) {
for(int j = 0; j < lexicalUses.length; j++) { for (int j = 0; j < lexicalUses.length; j++) {
int lexicalUse = lexicalUses[j]; int lexicalUse = lexicalUses[j];
if (lexicalUse != -1 && !skip(lexicalUse)) { if (lexicalUse != -1 && !skip(lexicalUse)) {
if (S[lexicalUse].isEmpty()) { if (S[lexicalUse].isEmpty()) {
lexicalUses[j] = -1; lexicalUses[j] = -1;
} else { } else {
int newUse = top(lexicalUse); int newUse = top(lexicalUse);
lexicalUses[j] = newUse;
if (topR(lexicalUse) != null) { lexicalUses[j] = newUse;
topR(lexicalUse).addUse(index, -j - 1);
} if (topR(lexicalUse) != null) {
} topR(lexicalUse).addUse(index, -j - 1);
} }
}
}
} }
} }
} }
@ -405,18 +416,19 @@ public class SSAConversion extends AbstractSSAConversion {
} }
protected boolean skipRepair(SSAInstruction inst, int index) { protected boolean skipRepair(SSAInstruction inst, int index) {
if (! super.skipRepair(inst, index)) { if (!super.skipRepair(inst, index)) {
return false; return false;
} }
if (index == -1) return true; if (index == -1)
return true;
int[] lexicalUses = lexicalInfo.getExposedUses(index); int[] lexicalUses = lexicalInfo.getExposedUses(index);
if (lexicalUses != null) { if (lexicalUses != null) {
for(int j = 0; j < lexicalUses.length; j++) { for (int j = 0; j < lexicalUses.length; j++) {
if (! skip(lexicalUses[j])) { if (!skip(lexicalUses[j])) {
return false; return false;
} }
} }
} }
@ -427,12 +439,11 @@ public class SSAConversion extends AbstractSSAConversion {
* @param ir * @param ir
* @param options * @param options
*/ */
@SuppressWarnings("unchecked")
private SSAConversion(AstMethod M, AstIR ir, SSAOptions options) { private SSAConversion(AstMethod M, AstIR ir, SSAOptions options) {
super(ir, options); super(ir, options);
this.copyPropagationMap = this.copyPropagationMap = (ir.getLocalMap() instanceof SSAInformation) ? ((SSAInformation) ir.getLocalMap()).getCopyHistory()
(ir.getLocalMap() instanceof SSAInformation)? : new HashMap<Object,CopyPropagationRecord>();
((SSAInformation)ir.getLocalMap()).getCopyHistory():
new HashMap();
this.ir = ir; this.ir = ir;
this.debugInfo = M.debugInfo; this.debugInfo = M.debugInfo;
@ -440,24 +451,25 @@ public class SSAConversion extends AbstractSSAConversion {
this.symtab = ir.getSymbolTable(); this.symtab = ir.getSymbolTable();
this.R = new Stack[ir.getSymbolTable().getMaxValueNumber() + 1]; this.R = new Stack[ir.getSymbolTable().getMaxValueNumber() + 1];
for(int i = 0; i < CFG.getNumberOfNodes(); i++) { for (int i = 0; i < CFG.getNumberOfNodes(); i++) {
SSACFG.BasicBlock bb = (SSACFG.BasicBlock) CFG.getNode(i); SSACFG.BasicBlock bb = (SSACFG.BasicBlock) CFG.getNode(i);
if (bb.hasPhi()) { if (bb.hasPhi()) {
int n = 0; int n = 0;
for(Iterator X = bb.iteratePhis(); X.hasNext(); n++) X.next(); for (Iterator X = bb.iteratePhis(); X.hasNext(); n++)
phiCounts[i] = n; X.next();
phiCounts[i] = n;
} }
} }
this.nextSSAValue = ir.getNumberOfParameters()+1; this.nextSSAValue = ir.getNumberOfParameters() + 1;
int[] exitLive = lexicalInfo.getExitExposedUses(); int[] exitLive = lexicalInfo.getExitExposedUses();
BitVector v = new BitVector(); BitVector v = new BitVector();
if (exitLive != null) if (exitLive != null)
for(int i = 0; i < exitLive.length; i++) for (int i = 0; i < exitLive.length; i++)
v.set( exitLive[i] ); v.set(exitLive[i]);
this.liveness = LiveAnalysis.perform(CFG, symtab, v); this.liveness = LiveAnalysis.perform(CFG, symtab, v);
if (DEBUG) { if (DEBUG) {
Trace.println(liveness); Trace.println(liveness);
} }
@ -466,39 +478,36 @@ public class SSAConversion extends AbstractSSAConversion {
protected int getNextNewValueNumber() { protected int getNextNewValueNumber() {
while (symtab.isConstant(nextSSAValue) || skip(nextSSAValue)) while (symtab.isConstant(nextSSAValue) || skip(nextSSAValue))
++nextSSAValue; ++nextSSAValue;
symtab.ensureSymbol( nextSSAValue ); symtab.ensureSymbol(nextSSAValue);
return nextSSAValue++; return nextSSAValue++;
} }
private void copyNames(int to, int from) { private void copyNames(int to, int from) {
String[][] namesData = debugInfo.getSourceNamesForValues(); String[][] namesData = debugInfo.getSourceNamesForValues();
if (namesData != null && if (namesData != null && namesData.length > from && namesData[from] != null) {
namesData.length > from &&
namesData[from] != null)
{
if (namesData[to] == null) { if (namesData[to] == null) {
namesData[to] = namesData[from]; namesData[to] = namesData[from];
} else { } else {
String[] newNames = new String[ namesData[from].length+namesData[to].length ]; String[] newNames = new String[namesData[from].length + namesData[to].length];
System.arraycopy(namesData[from], 0, newNames, 0, namesData[from].length); System.arraycopy(namesData[from], 0, newNames, 0, namesData[from].length);
System.arraycopy(namesData[to], 0, newNames, namesData[from].length, namesData[to].length); System.arraycopy(namesData[to], 0, newNames, namesData[from].length, namesData[to].length);
namesData[to] = newNames; namesData[to] = newNames;
} }
} }
} }
protected void initializeVariables() { protected void initializeVariables() {
for (int V = 1; V <= getMaxValueNumber(); V++) { for (int V = 1; V <= getMaxValueNumber(); V++) {
if (! skip(V)) { if (!skip(V)) {
R[V] = new Stack(); R[V] = new Stack();
} }
} }
int[] params = symtab.getParameterValueNumbers(); int[] params = symtab.getParameterValueNumbers();
for (int i = 0; i < params.length; i++) { for (int i = 0; i < params.length; i++) {
if (! skip( params[i] )) { if (!skip(params[i])) {
S[params[i]].push( params[i] ); S[params[i]].push(params[i]);
valueMap[ params[i] ] = params[i]; valueMap[params[i]] = params[i];
} }
} }
@ -507,11 +516,11 @@ public class SSAConversion extends AbstractSSAConversion {
protected void repairExit() { protected void repairExit() {
int[] exitLives = lexicalInfo.getExitExposedUses(); int[] exitLives = lexicalInfo.getExitExposedUses();
if (exitLives != null) { if (exitLives != null) {
for(int i = 0; i < exitLives.length; i++) { for (int i = 0; i < exitLives.length; i++) {
if (! skip(exitLives[i])) { if (!skip(exitLives[i])) {
Assertions._assert(! S[exitLives[i]].isEmpty()); Assertions._assert(!S[exitLives[i]].isEmpty());
exitLives[i] = top(exitLives[i]); exitLives[i] = top(exitLives[i]);
} }
} }
} }
} }
@ -521,8 +530,8 @@ public class SSAConversion extends AbstractSSAConversion {
// //
protected void fail(int v) { protected void fail(int v) {
System.err.println( "during SSA conversion of the following IR:" ); System.err.println("during SSA conversion of the following IR:");
System.err.println( ir ); System.err.println(ir);
super.fail(v); super.fail(v);
} }
@ -534,18 +543,18 @@ public class SSAConversion extends AbstractSSAConversion {
super.perform(); super.perform();
if (DUMP) { if (DUMP) {
Trace.println( ir ); Trace.println(ir);
if (lexicalInfo != null) { if (lexicalInfo != null) {
for(int i = 0; i < instructions.length; i++) { for (int i = 0; i < instructions.length; i++) {
int[] lexicalUses = lexicalInfo.getExposedUses(i); int[] lexicalUses = lexicalInfo.getExposedUses(i);
if (lexicalUses != null) { if (lexicalUses != null) {
Trace.print("extra uses for " + instructions[i] + ": "); Trace.print("extra uses for " + instructions[i] + ": ");
for(int j = 0; j < lexicalUses.length; j++) { for (int j = 0; j < lexicalUses.length; j++) {
Trace.print( new Integer(lexicalUses[j]).toString() + " " ); Trace.print(new Integer(lexicalUses[j]).toString() + " ");
} }
Trace.println(""); Trace.println("");
} }
} }
} }
} }
@ -556,23 +565,20 @@ public class SSAConversion extends AbstractSSAConversion {
IInstruction[] insts = ir.getInstructions(); IInstruction[] insts = ir.getInstructions();
MutableIntSet foundOne = new BitVectorIntSet(); MutableIntSet foundOne = new BitVectorIntSet();
MutableIntSet foundTwo = new BitVectorIntSet(); MutableIntSet foundTwo = new BitVectorIntSet();
for(int i = 0; i < insts.length; i++) { for (int i = 0; i < insts.length; i++) {
SSAInstruction inst = (SSAInstruction) insts[i]; SSAInstruction inst = (SSAInstruction) insts[i];
if (inst != null) { if (inst != null) {
for(int j = 0; j < inst.getNumberOfDefs(); j++) { for (int j = 0; j < inst.getNumberOfDefs(); j++) {
int def = inst.getDef(j); int def = inst.getDef(j);
if (def != -1) { if (def != -1) {
if (foundOne.contains(def) || if (foundOne.contains(def) || ir.getSymbolTable().isConstant(def) || def <= ir.getNumberOfParameters()
ir.getSymbolTable().isConstant(def) || || inst instanceof AssignInstruction) {
def <= ir.getNumberOfParameters() || foundTwo.add(def);
inst instanceof AssignInstruction) } else {
{ foundOne.add(def);
foundTwo.add(def); }
} else { }
foundOne.add(def); }
}
}
}
} }
} }
@ -583,25 +589,24 @@ public class SSAConversion extends AbstractSSAConversion {
return convert(M, ir, options, valuesToConvert(ir)); return convert(M, ir, options, valuesToConvert(ir));
} }
public static SSA2LocalMap convert(AstMethod M, public static SSA2LocalMap convert(AstMethod M, final AstIR ir, SSAOptions options, final IntSet values) {
final AstIR ir,
SSAOptions options,
final IntSet values)
{
try { try {
if (DEBUG) { if (DEBUG) {
Trace.println("starting conversion for " + values); Trace.println("starting conversion for " + values);
Trace.println( ir ); Trace.println(ir);
} }
if (DEBUG_UNDO) Trace.println(">>> starting " + ir.getMethod()); if (DEBUG_UNDO)
Trace.println(">>> starting " + ir.getMethod());
SSAConversion ssa = new SSAConversion(M, ir, options) { SSAConversion ssa = new SSAConversion(M, ir, options) {
final int limit = ir.getSymbolTable().getMaxValueNumber(); final int limit = ir.getSymbolTable().getMaxValueNumber();
protected boolean skip(int i) {
return (i >= 0) && (i <= limit) && (!values.contains(i)); protected boolean skip(int i) {
} return (i >= 0) && (i <= limit) && (!values.contains(i));
}
}; };
ssa.perform(); ssa.perform();
if (DEBUG_UNDO) Trace.println("<<< done " + ir.getMethod()); if (DEBUG_UNDO)
Trace.println("<<< done " + ir.getMethod());
return ssa.getComputedLocalMap(); return ssa.getComputedLocalMap();
} catch (RuntimeException e) { } catch (RuntimeException e) {
Trace.println("exception " + e + " while converting:"); Trace.println("exception " + e + " while converting:");

View File

@ -13,6 +13,7 @@ package com.ibm.wala.cast.ir.ssa.analysis;
import java.util.Iterator; import java.util.Iterator;
import com.ibm.wala.cfg.ControlFlowGraph; import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.cfg.IBasicBlock;
import com.ibm.wala.dataflow.graph.AbstractMeetOperator; import com.ibm.wala.dataflow.graph.AbstractMeetOperator;
import com.ibm.wala.dataflow.graph.BitVectorSolver; import com.ibm.wala.dataflow.graph.BitVectorSolver;
import com.ibm.wala.dataflow.graph.BitVectorUnion; import com.ibm.wala.dataflow.graph.BitVectorUnion;
@ -152,15 +153,15 @@ public class LiveAnalysis {
} }
} }
final BitVectorSolver S = new BitVectorSolver(new IKilldallFramework() { final BitVectorSolver<IBasicBlock> S = new BitVectorSolver<IBasicBlock>(new IKilldallFramework<IBasicBlock>() {
private final Graph G = GraphInverter.invert(cfg); private final Graph<IBasicBlock> G = GraphInverter.invert(cfg);
public Graph getFlowGraph() { public Graph<IBasicBlock> getFlowGraph() {
return G; return G;
} }
public ITransferFunctionProvider getTransferFunctionProvider() { public ITransferFunctionProvider<IBasicBlock> getTransferFunctionProvider() {
return new ITransferFunctionProvider() { return new ITransferFunctionProvider<IBasicBlock>() {
public boolean hasNodeTransferFunctions() { public boolean hasNodeTransferFunctions() {
return true; return true;
@ -170,7 +171,7 @@ public class LiveAnalysis {
return false; return false;
} }
public UnaryOperator getNodeTransferFunction(Object node) { public UnaryOperator getNodeTransferFunction(IBasicBlock node) {
if (((SSACFG.BasicBlock) node).isExitBlock()) { if (((SSACFG.BasicBlock) node).isExitBlock()) {
return new ExitBlockGenKillOperator(); return new ExitBlockGenKillOperator();
} else { } else {
@ -178,7 +179,7 @@ public class LiveAnalysis {
} }
} }
public UnaryOperator getEdgeTransferFunction(Object s, Object d) { public UnaryOperator getEdgeTransferFunction(IBasicBlock s, IBasicBlock d) {
Assertions.UNREACHABLE(); Assertions.UNREACHABLE();
return null; return null;
} }

View File

@ -50,6 +50,7 @@ import com.ibm.wala.cast.util.CAstPrinter;
import com.ibm.wala.cfg.AbstractCFG; import com.ibm.wala.cfg.AbstractCFG;
import com.ibm.wala.cfg.IBasicBlock; import com.ibm.wala.cfg.IBasicBlock;
import com.ibm.wala.classLoader.IClassLoader; import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.shrikeBT.BinaryOpInstruction; import com.ibm.wala.shrikeBT.BinaryOpInstruction;
import com.ibm.wala.shrikeBT.ConditionalBranchInstruction; import com.ibm.wala.shrikeBT.ConditionalBranchInstruction;
@ -331,7 +332,7 @@ public abstract class AstTranslator extends CAstVisitor {
private int lastIndex = -2; private int lastIndex = -2;
private final List instructions = new ArrayList(); private final List<SSAInstruction> instructions = new ArrayList<SSAInstruction>();
public int getNumber() { public int getNumber() {
return getGraphNodeId(); return getGraphNodeId();
@ -389,7 +390,7 @@ public abstract class AstTranslator extends CAstVisitor {
return "PreBB" + number + ":" + firstIndex + ".." + lastIndex; return "PreBB" + number + ":" + firstIndex + ".." + lastIndex;
} }
List instructions() { List<SSAInstruction> instructions() {
return instructions; return instructions;
} }
@ -401,7 +402,7 @@ public abstract class AstTranslator extends CAstVisitor {
return null; return null;
} }
public Iterator iterateAllInstructions() { public Iterator<SSAInstruction> iterateAllInstructions() {
return instructions.iterator(); return instructions.iterator();
} }
} }
@ -452,12 +453,12 @@ public abstract class AstTranslator extends CAstVisitor {
} }
} }
public final class IncipientCFG extends SparseNumberedGraph { public final class IncipientCFG extends SparseNumberedGraph<PreBasicBlock> {
protected class Unwind { protected class Unwind {
private final Map unwindData = new LinkedHashMap(); private final Map<PreBasicBlock, UnwindState> unwindData = new LinkedHashMap<PreBasicBlock, UnwindState>();
private final Map code = new LinkedHashMap(); private final Map<Pair<UnwindState, Pair<PreBasicBlock, Boolean>>, PreBasicBlock> code = new LinkedHashMap<Pair<UnwindState, Pair<PreBasicBlock, Boolean>>, PreBasicBlock>();
void setUnwindState(PreBasicBlock block, UnwindState context) { void setUnwindState(PreBasicBlock block, UnwindState context) {
unwindData.put(block, context); unwindData.put(block, context);
@ -468,7 +469,7 @@ public abstract class AstTranslator extends CAstVisitor {
} }
public PreBasicBlock findOrCreateCode(PreBasicBlock source, PreBasicBlock target, boolean exception) { public PreBasicBlock findOrCreateCode(PreBasicBlock source, PreBasicBlock target, boolean exception) {
UnwindState sourceContext = (UnwindState) unwindData.get(source); UnwindState sourceContext = unwindData.get(source);
// no unwinding is needed, so jump to target block directly // no unwinding is needed, so jump to target block directly
if (sourceContext == null) if (sourceContext == null)
@ -477,16 +478,17 @@ public abstract class AstTranslator extends CAstVisitor {
WalkContext astContext = sourceContext.astContext; WalkContext astContext = sourceContext.astContext;
UnwindState targetContext = null; UnwindState targetContext = null;
if (target != null) if (target != null)
targetContext = (UnwindState) unwindData.get(target); targetContext = unwindData.get(target);
// in unwind context, but catch in same (or inner) unwind context // in unwind context, but catch in same (or inner) unwind context
if (targetContext != null && targetContext.covers(sourceContext)) if (targetContext != null && targetContext.covers(sourceContext))
return target; return target;
Pair key = new Pair(sourceContext, new Pair(target, exception ? Boolean.TRUE : Boolean.FALSE)); Pair<UnwindState, Pair<PreBasicBlock, Boolean>> key = new Pair<UnwindState, Pair<PreBasicBlock, Boolean>>(sourceContext,
new Pair<PreBasicBlock, Boolean>(target, exception ? Boolean.TRUE : Boolean.FALSE));
if (code.containsKey(key)) { if (code.containsKey(key)) {
return (PreBasicBlock) code.get(key); return code.get(key);
} else { } else {
int e = -1; int e = -1;
@ -544,19 +546,19 @@ public abstract class AstTranslator extends CAstVisitor {
private Unwind unwind = null; private Unwind unwind = null;
private final List blocks = new ArrayList(); private final List<PreBasicBlock> blocks = new ArrayList<PreBasicBlock>();
private final Map nodeToBlock = new LinkedHashMap(); private final Map<CAstNode, PreBasicBlock> nodeToBlock = new LinkedHashMap<CAstNode, PreBasicBlock>();
private final Map delayedEdges = new LinkedHashMap(); private final Map<Object, Set<Pair<PreBasicBlock, Boolean>>> delayedEdges = new LinkedHashMap<Object, Set<Pair<PreBasicBlock, Boolean>>>();
private final Object exitMarker = new Object(); private final Object exitMarker = new Object();
private final Set deadBlocks = new LinkedHashSet(); private final Set<PreBasicBlock> deadBlocks = new LinkedHashSet<PreBasicBlock>();
private final Set normalToExit = new LinkedHashSet(); private final Set<PreBasicBlock> normalToExit = new LinkedHashSet<PreBasicBlock>();
private final Set exceptionalToExit = new LinkedHashSet(); private final Set<PreBasicBlock> exceptionalToExit = new LinkedHashSet<PreBasicBlock>();
private Position[] linePositions = new Position[10]; private Position[] linePositions = new Position[10];
@ -620,11 +622,11 @@ public abstract class AstTranslator extends CAstVisitor {
} }
private void addDelayedEdge(PreBasicBlock src, Object dst, boolean exception) { private void addDelayedEdge(PreBasicBlock src, Object dst, boolean exception) {
Pair v = new Pair(src, exception ? Boolean.TRUE : Boolean.FALSE); Pair<PreBasicBlock, Boolean> v = new Pair<PreBasicBlock, Boolean>(src, exception ? Boolean.TRUE : Boolean.FALSE);
if (delayedEdges.containsKey(dst)) if (delayedEdges.containsKey(dst))
((Set) delayedEdges.get(dst)).add(v); delayedEdges.get(dst).add(v);
else { else {
Set s = new LinkedHashSet(); Set<Pair<PreBasicBlock, Boolean>> s = new LinkedHashSet<Pair<PreBasicBlock, Boolean>>();
s.add(v); s.add(v);
delayedEdges.put(dst, s); delayedEdges.put(dst, s);
} }
@ -637,7 +639,7 @@ public abstract class AstTranslator extends CAstVisitor {
void makeExitBlock(PreBasicBlock bb) { void makeExitBlock(PreBasicBlock bb) {
bb.makeExitBlock(); bb.makeExitBlock();
for (Iterator ps = getPredNodes(bb); ps.hasNext();) for (Iterator<? extends PreBasicBlock> ps = getPredNodes(bb); ps.hasNext();)
normalToExit.add(ps.next()); normalToExit.add(ps.next());
checkForRealizedExitEdges(bb); checkForRealizedExitEdges(bb);
@ -649,14 +651,14 @@ public abstract class AstTranslator extends CAstVisitor {
private void checkForRealizedEdges(CAstNode n) { private void checkForRealizedEdges(CAstNode n) {
if (delayedEdges.containsKey(n)) { if (delayedEdges.containsKey(n)) {
for (Iterator ss = ((Set) delayedEdges.get(n)).iterator(); ss.hasNext();) { for (Iterator ss = delayedEdges.get(n).iterator(); ss.hasNext();) {
Pair s = (Pair) ss.next(); Pair s = (Pair) ss.next();
PreBasicBlock that = (PreBasicBlock) s.fst; PreBasicBlock that = (PreBasicBlock) s.fst;
boolean exception = ((Boolean) s.snd).booleanValue(); boolean exception = ((Boolean) s.snd).booleanValue();
if (unwind == null) { if (unwind == null) {
addEdge(that, nodeToBlock.get(n)); addEdge(that, nodeToBlock.get(n));
} else { } else {
PreBasicBlock target = (PreBasicBlock) nodeToBlock.get(n); PreBasicBlock target = nodeToBlock.get(n);
addEdge(that, unwind.findOrCreateCode(that, target, exception)); addEdge(that, unwind.findOrCreateCode(that, target, exception));
} }
} }
@ -667,7 +669,7 @@ public abstract class AstTranslator extends CAstVisitor {
private void checkForRealizedExitEdges(PreBasicBlock n) { private void checkForRealizedExitEdges(PreBasicBlock n) {
if (delayedEdges.containsKey(exitMarker)) { if (delayedEdges.containsKey(exitMarker)) {
for (Iterator ss = ((Set) delayedEdges.get(exitMarker)).iterator(); ss.hasNext();) { for (Iterator ss = delayedEdges.get(exitMarker).iterator(); ss.hasNext();) {
Pair s = (Pair) ss.next(); Pair s = (Pair) ss.next();
PreBasicBlock that = (PreBasicBlock) s.fst; PreBasicBlock that = (PreBasicBlock) s.fst;
boolean exception = ((Boolean) s.snd).booleanValue(); boolean exception = ((Boolean) s.snd).booleanValue();
@ -704,12 +706,12 @@ public abstract class AstTranslator extends CAstVisitor {
public void addPreEdge(CAstNode src, CAstNode dst, boolean exception) { public void addPreEdge(CAstNode src, CAstNode dst, boolean exception) {
Assertions._assert(nodeToBlock.containsKey(src)); Assertions._assert(nodeToBlock.containsKey(src));
addPreEdge((PreBasicBlock) nodeToBlock.get(src), dst, exception); addPreEdge(nodeToBlock.get(src), dst, exception);
} }
public void addPreEdge(PreBasicBlock src, CAstNode dst, boolean exception) { public void addPreEdge(PreBasicBlock src, CAstNode dst, boolean exception) {
if (nodeToBlock.containsKey(dst)) { if (nodeToBlock.containsKey(dst)) {
PreBasicBlock target = (PreBasicBlock) nodeToBlock.get(dst); PreBasicBlock target = nodeToBlock.get(dst);
if (DEBUG_CFG) if (DEBUG_CFG)
Trace.println("adding pre-edge " + src + " --> " + dst); Trace.println("adding pre-edge " + src + " --> " + dst);
if (unwind == null) { if (unwind == null) {
@ -726,7 +728,7 @@ public abstract class AstTranslator extends CAstVisitor {
public void addPreEdgeToExit(CAstNode src, boolean exception) { public void addPreEdgeToExit(CAstNode src, boolean exception) {
Assertions._assert(nodeToBlock.containsKey(src)); Assertions._assert(nodeToBlock.containsKey(src));
addPreEdgeToExit((PreBasicBlock) nodeToBlock.get(src), exception); addPreEdgeToExit(nodeToBlock.get(src), exception);
} }
public void addPreEdgeToExit(PreBasicBlock src, boolean exception) { public void addPreEdgeToExit(PreBasicBlock src, boolean exception) {
@ -741,7 +743,7 @@ public abstract class AstTranslator extends CAstVisitor {
addDelayedEdge(src, exitMarker, exception); addDelayedEdge(src, exitMarker, exception);
} }
public void addEdge(Object src, Object dst) { public void addEdge(PreBasicBlock src, PreBasicBlock dst) {
super.addEdge(src, dst); super.addEdge(src, dst);
deadBlocks.remove(dst); deadBlocks.remove(dst);
} }
@ -751,7 +753,7 @@ public abstract class AstTranslator extends CAstVisitor {
} }
public PreBasicBlock getBlock(CAstNode n) { public PreBasicBlock getBlock(CAstNode n) {
return (PreBasicBlock) nodeToBlock.get(n); return nodeToBlock.get(n);
} }
private void noteLinePosition(int instruction) { private void noteLinePosition(int instruction) {
@ -798,24 +800,24 @@ public abstract class AstTranslator extends CAstVisitor {
AstCFG(CAstEntity n, IncipientCFG icfg, SymbolTable symtab) { AstCFG(CAstEntity n, IncipientCFG icfg, SymbolTable symtab) {
super(null); super(null);
List blocks = icfg.blocks; List<PreBasicBlock> blocks = icfg.blocks;
this.symtab = symtab; this.symtab = symtab;
functionName = n.getName(); functionName = n.getName();
instructionToBlockMap = new int[blocks.size()]; instructionToBlockMap = new int[blocks.size()];
for (int i = 0; i < blocks.size(); i++) for (int i = 0; i < blocks.size(); i++)
instructionToBlockMap[i] = ((PreBasicBlock) blocks.get(i)).getLastInstructionIndex(); instructionToBlockMap[i] = blocks.get(i).getLastInstructionIndex();
for (int i = 0; i < blocks.size(); i++) { for (int i = 0; i < blocks.size(); i++) {
PreBasicBlock block = (PreBasicBlock) blocks.get(i); PreBasicBlock block = blocks.get(i);
this.addNode(block); this.addNode(block);
if (block.isCatchBlock()) { if (block.isCatchBlock()) {
setCatchBlock(i); setCatchBlock(i);
} }
if (DEBUG_CFG) if (DEBUG_CFG)
Trace.println("added " + blocks.get(i) + " to final CFG as " + getNumber((IBasicBlock) blocks.get(i))); Trace.println("added " + blocks.get(i) + " to final CFG as " + getNumber(blocks.get(i)));
} }
if (DEBUG_CFG) if (DEBUG_CFG)
Trace.println(getMaxNumber() + " blocks total"); Trace.println(getMaxNumber() + " blocks total");
@ -823,7 +825,7 @@ public abstract class AstTranslator extends CAstVisitor {
init(); init();
for (int i = 0; i < blocks.size(); i++) { for (int i = 0; i < blocks.size(); i++) {
PreBasicBlock src = (PreBasicBlock) blocks.get(i); PreBasicBlock src = blocks.get(i);
for (Iterator j = icfg.getSuccNodes(src); j.hasNext();) { for (Iterator j = icfg.getSuccNodes(src); j.hasNext();) {
PreBasicBlock dst = (PreBasicBlock) j.next(); PreBasicBlock dst = (PreBasicBlock) j.next();
if (isCatchBlock(dst.getNumber()) || (dst.isExitBlock() && icfg.exceptionalToExit.contains(src))) { if (isCatchBlock(dst.getNumber()) || (dst.isExitBlock() && icfg.exceptionalToExit.contains(src))) {
@ -843,9 +845,9 @@ public abstract class AstTranslator extends CAstVisitor {
int x = 0; int x = 0;
instructions = new SSAInstruction[icfg.currentInstruction]; instructions = new SSAInstruction[icfg.currentInstruction];
for (int i = 0; i < blocks.size(); i++) { for (int i = 0; i < blocks.size(); i++) {
List bi = ((PreBasicBlock) blocks.get(i)).instructions(); List<SSAInstruction> bi = blocks.get(i).instructions();
for (int j = 0; j < bi.size(); j++) { for (int j = 0; j < bi.size(); j++) {
instructions[x++] = (SSAInstruction) bi.get(j); instructions[x++] = bi.get(j);
} }
} }
} }
@ -944,7 +946,7 @@ public abstract class AstTranslator extends CAstVisitor {
Symbol lookup(String name); Symbol lookup(String name);
Iterator getAllNames(); Iterator<String> getAllNames();
int size(); int size();
@ -987,9 +989,9 @@ public abstract class AstTranslator extends CAstVisitor {
private abstract class AbstractScope implements Scope { private abstract class AbstractScope implements Scope {
private final Scope parent; private final Scope parent;
private final Map values = new LinkedHashMap(); private final Map<String, Symbol> values = new LinkedHashMap<String, Symbol>();
private final Map caseInsensitiveNames = new LinkedHashMap(); private final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
protected abstract SymbolTable getUnderlyingSymtab(); protected abstract SymbolTable getUnderlyingSymtab();
@ -997,7 +999,7 @@ public abstract class AstTranslator extends CAstVisitor {
return getUnderlyingSymtab().getMaxValueNumber() + 1; return getUnderlyingSymtab().getMaxValueNumber() + 1;
} }
public Iterator getAllNames() { public Iterator<String> getAllNames() {
return values.keySet().iterator(); return values.keySet().iterator();
} }
@ -1061,7 +1063,7 @@ public abstract class AstTranslator extends CAstVisitor {
} }
private final String mapName(String nm) { private final String mapName(String nm) {
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase()); String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
return (mappedName == null) ? nm : mappedName; return (mappedName == null) ? nm : mappedName;
} }
@ -1081,7 +1083,7 @@ public abstract class AstTranslator extends CAstVisitor {
public Symbol lookup(String nm) { public Symbol lookup(String nm) {
if (contains(nm)) { if (contains(nm)) {
return (Symbol) values.get(mapName(nm)); return values.get(mapName(nm));
} else { } else {
Symbol scoped = parent.lookup(nm); Symbol scoped = parent.lookup(nm);
if (scoped != null && getEntityScope() == this && (isGlobal(scoped) || isLexicallyScoped(scoped))) { if (scoped != null && getEntityScope() == this && (isGlobal(scoped) || isLexicallyScoped(scoped))) {
@ -1089,7 +1091,7 @@ public abstract class AstTranslator extends CAstVisitor {
if (scoped.getDefiningScope().isCaseInsensitive(nm)) { if (scoped.getDefiningScope().isCaseInsensitive(nm)) {
caseInsensitiveNames.put(nm.toLowerCase(), nm); caseInsensitiveNames.put(nm.toLowerCase(), nm);
} }
return (Symbol) values.get(nm); return values.get(nm);
} else { } else {
return scoped; return scoped;
} }
@ -1097,7 +1099,7 @@ public abstract class AstTranslator extends CAstVisitor {
} }
public boolean contains(String nm) { public boolean contains(String nm) {
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase()); String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
return values.containsKey(mappedName == null ? nm : mappedName); return values.containsKey(mappedName == null ? nm : mappedName);
} }
@ -1277,11 +1279,11 @@ public abstract class AstTranslator extends CAstVisitor {
} }
private Scope makeGlobalScope() { private Scope makeGlobalScope() {
final Map globalSymbols = new LinkedHashMap(); final Map<String, AbstractSymbol> globalSymbols = new LinkedHashMap<String, AbstractSymbol>();
final Map caseInsensitiveNames = new LinkedHashMap(); final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
return new Scope() { return new Scope() {
private final String mapName(String nm) { private final String mapName(String nm) {
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase()); String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
return (mappedName == null) ? nm : mappedName; return (mappedName == null) ? nm : mappedName;
} }
@ -1301,7 +1303,7 @@ public abstract class AstTranslator extends CAstVisitor {
return globalSymbols.size(); return globalSymbols.size();
} }
public Iterator getAllNames() { public Iterator<String> getAllNames() {
return globalSymbols.keySet().iterator(); return globalSymbols.keySet().iterator();
} }
@ -1343,7 +1345,7 @@ public abstract class AstTranslator extends CAstVisitor {
throw new Error("cannot find " + name); throw new Error("cannot find " + name);
} }
return (Symbol) globalSymbols.get(mapName(name)); return globalSymbols.get(mapName(name));
} }
public void declare(final String name, boolean isFinal, boolean isCaseInsensitive, int vn) { public void declare(final String name, boolean isFinal, boolean isCaseInsensitive, int vn) {
@ -1373,11 +1375,11 @@ public abstract class AstTranslator extends CAstVisitor {
} }
protected Scope makeTypeScope(final CAstEntity type, final Scope parent) { protected Scope makeTypeScope(final CAstEntity type, final Scope parent) {
final Map typeSymbols = new LinkedHashMap(); final Map<String, AbstractSymbol> typeSymbols = new LinkedHashMap<String, AbstractSymbol>();
final Map caseInsensitiveNames = new LinkedHashMap(); final Map<String, String> caseInsensitiveNames = new LinkedHashMap<String, String>();
return new Scope() { return new Scope() {
private final String mapName(String nm) { private final String mapName(String nm) {
String mappedName = (String) caseInsensitiveNames.get(nm.toLowerCase()); String mappedName = caseInsensitiveNames.get(nm.toLowerCase());
return (mappedName == null) ? nm : mappedName; return (mappedName == null) ? nm : mappedName;
} }
@ -1397,7 +1399,7 @@ public abstract class AstTranslator extends CAstVisitor {
return typeSymbols.size(); return typeSymbols.size();
} }
public Iterator getAllNames() { public Iterator<String> getAllNames() {
return typeSymbols.keySet().iterator(); return typeSymbols.keySet().iterator();
} }
@ -1431,7 +1433,7 @@ public abstract class AstTranslator extends CAstVisitor {
public Symbol lookup(String nm) { public Symbol lookup(String nm) {
if (typeSymbols.containsKey(mapName(nm))) if (typeSymbols.containsKey(mapName(nm)))
return (Symbol) typeSymbols.get(mapName(nm)); return typeSymbols.get(mapName(nm));
else { else {
return parent.lookup(nm); return parent.lookup(nm);
} }
@ -1475,7 +1477,7 @@ public abstract class AstTranslator extends CAstVisitor {
Scope currentScope(); Scope currentScope();
Set entityScopes(); Set<Scope> entityScopes();
IncipientCFG cfg(); IncipientCFG cfg();
@ -1520,7 +1522,7 @@ public abstract class AstTranslator extends CAstVisitor {
return parent.currentScope(); return parent.currentScope();
} }
public Set entityScopes() { public Set<Scope> entityScopes() {
return parent.entityScopes(); return parent.entityScopes();
} }
@ -1601,7 +1603,7 @@ public abstract class AstTranslator extends CAstVisitor {
private class CodeEntityContext extends EntityContext { private class CodeEntityContext extends EntityContext {
private final Scope topEntityScope; private final Scope topEntityScope;
private final Set allEntityScopes; private final Set<Scope> allEntityScopes;
private final IncipientCFG cfg; private final IncipientCFG cfg;
@ -1612,7 +1614,7 @@ public abstract class AstTranslator extends CAstVisitor {
this.topEntityScope = entityScope; this.topEntityScope = entityScope;
this.allEntityScopes = new HashSet(); this.allEntityScopes = new HashSet<Scope>();
this.allEntityScopes.add(entityScope); this.allEntityScopes.add(entityScope);
cfg = new IncipientCFG(); cfg = new IncipientCFG();
@ -1630,7 +1632,7 @@ public abstract class AstTranslator extends CAstVisitor {
return topEntityScope; return topEntityScope;
} }
public Set entityScopes() { public Set<Scope> entityScopes() {
return allEntityScopes; return allEntityScopes;
} }
@ -1762,14 +1764,14 @@ public abstract class AstTranslator extends CAstVisitor {
} }
if (accesses != null) { if (accesses != null) {
Set parents = new LinkedHashSet(); Set<String> parents = new LinkedHashSet<String>();
for (Iterator ACS = accesses.iterator(); ACS.hasNext();) { for (Iterator ACS = accesses.iterator(); ACS.hasNext();) {
Access AC = (Access) ACS.next(); Access AC = (Access) ACS.next();
if (AC.variableDefiner != null) { if (AC.variableDefiner != null) {
parents.add(AC.variableDefiner); parents.add(AC.variableDefiner);
} }
} }
scopingParents = (String[]) parents.toArray(new String[parents.size()]); scopingParents = parents.toArray(new String[parents.size()]);
if (DEBUG_LEXICAL) { if (DEBUG_LEXICAL) {
Trace.println("scoping parents of " + scope.getEntity()); Trace.println("scoping parents of " + scope.getEntity());
@ -1810,7 +1812,7 @@ public abstract class AstTranslator extends CAstVisitor {
} }
}; };
private final Map results = new LinkedHashMap(); private final Map<CAstNode, Integer> results = new LinkedHashMap<CAstNode, Integer>();
protected boolean hasValue(CAstNode n) { protected boolean hasValue(CAstNode n) {
return results.containsKey(n); return results.containsKey(n);
@ -1823,18 +1825,18 @@ public abstract class AstTranslator extends CAstVisitor {
public final int getValue(CAstNode n) { public final int getValue(CAstNode n) {
if (results.containsKey(n)) if (results.containsKey(n))
return ((Integer) results.get(n)).intValue(); return results.get(n).intValue();
else { else {
Trace.println("no value for " + n.getKind()); Trace.println("no value for " + n.getKind());
return -1; return -1;
} }
} }
private final Map entityNames = new LinkedHashMap(); private final Map<CAstEntity, String> entityNames = new LinkedHashMap<CAstEntity, String>();
private final Map exposedNames = new LinkedHashMap(); private final Map<CAstEntity, LinkedHashSet<Pair<Pair<String, String>, Integer>>> exposedNames = new LinkedHashMap<CAstEntity, LinkedHashSet<Pair<Pair<String, String>, Integer>>>();
private final Map accesses = new LinkedHashMap(); private final Map<CAstEntity, LinkedHashSet<Access>> accesses = new LinkedHashMap<CAstEntity, LinkedHashSet<Access>>();
private void addEntityName(CAstEntity e, String name) { private void addEntityName(CAstEntity e, String name) {
entityNames.put(e, name); entityNames.put(e, name);
@ -1842,15 +1844,17 @@ public abstract class AstTranslator extends CAstVisitor {
private void addAccess(CAstEntity e, Access access) { private void addAccess(CAstEntity e, Access access) {
if (!accesses.containsKey(e)) if (!accesses.containsKey(e))
accesses.put(e, new LinkedHashSet()); accesses.put(e, new LinkedHashSet<Access>());
((Set) accesses.get(e)).add(access); accesses.get(e).add(access);
} }
private void addExposedName(CAstEntity entity, CAstEntity declaration, String name, int valueNumber) { private void addExposedName(CAstEntity entity, CAstEntity declaration, String name, int valueNumber) {
if (!exposedNames.containsKey(entity)) if (!exposedNames.containsKey(entity))
exposedNames.put(entity, new LinkedHashSet()); exposedNames.put(entity, new LinkedHashSet<Pair<Pair<String, String>, Integer>>());
((Set) exposedNames.get(entity)).add(new Pair(new Pair(name, getEntityName(declaration)), new Integer(valueNumber))); exposedNames.get(entity).add(
new Pair<Pair<String, String>, Integer>(new Pair<String, String>(name, getEntityName(declaration)),
new Integer(valueNumber)));
} }
private String getEntityName(CAstEntity e) { private String getEntityName(CAstEntity e) {
@ -1938,19 +1942,19 @@ public abstract class AstTranslator extends CAstVisitor {
} }
} }
private String[] makeNameMap(Set scopes) { private String[] makeNameMap(Set<Scope> scopes) {
// all scopes share the same underlying symtab, which is what // all scopes share the same underlying symtab, which is what
// size really refers to. // size really refers to.
String[] map = new String[((Scope) scopes.iterator().next()).size() + 1]; String[] map = new String[scopes.iterator().next().size() + 1];
if (DEBUG_NAMES) { if (DEBUG_NAMES) {
Trace.println("names array of size " + map.length); Trace.println("names array of size " + map.length);
} }
for (Iterator S = scopes.iterator(); S.hasNext();) { for (Iterator<Scope> S = scopes.iterator(); S.hasNext();) {
Scope scope = (Scope) S.next(); Scope scope = S.next();
for (Iterator I = scope.getAllNames(); I.hasNext();) { for (Iterator<String> I = scope.getAllNames(); I.hasNext();) {
String nm = (String) I.next(); String nm = I.next();
Symbol v = (Symbol) scope.lookup(nm); Symbol v = (Symbol) scope.lookup(nm);
// hack for new expression idiom in the Java translator // hack for new expression idiom in the Java translator
@ -2088,20 +2092,19 @@ public abstract class AstTranslator extends CAstVisitor {
String[] nms = makeNameMap(functionContext.entityScopes()); String[] nms = makeNameMap(functionContext.entityScopes());
/* /*
Set reachableBlocks = * Set reachableBlocks = DFS.getReachableNodes(cfg,
DFS.getReachableNodes(cfg, Collections.singleton(cfg.entry())); * Collections.singleton(cfg.entry()));
Assertions._assert(reachableBlocks.size() == cfg.getNumberOfNodes(), * Assertions._assert(reachableBlocks.size() == cfg.getNumberOfNodes(),
cfg.toString()); * cfg.toString());
*/ */
// (put here to allow subclasses to handle stuff in scoped entities) // (put here to allow subclasses to handle stuff in scoped entities)
// assemble lexical information // assemble lexical information
patchLexicalAccesses(cfg.getInstructions(), (Set) accesses.get(n)); patchLexicalAccesses(cfg.getInstructions(), accesses.get(n));
LexicalInformation LI = LexicalInformation LI =
// TODO: Ask Julian if the below change is always correct // TODO: Ask Julian if the below change is always correct
new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(), (Set) exposedNames.get(n), new AstLexicalInformation((AbstractScope) functionContext.currentScope(), cfg.getInstructions(), exposedNames.get(n), accesses
(Set) accesses.get(n)); .get(n));
DebuggingInformation DBG = new AstDebuggingInformation(line, nms); DebuggingInformation DBG = new AstDebuggingInformation(line, nms);
@ -2109,7 +2112,7 @@ public abstract class AstTranslator extends CAstVisitor {
defineFunction(n, parentContext, cfg, symtab, katch, catchTypes, LI, DBG); defineFunction(n, parentContext, cfg, symtab, katch, catchTypes, LI, DBG);
} }
private final Stack positions = new Stack(); private final Stack<Position> positions = new Stack<Position>();
protected Context makeLocalContext(Context context, CAstNode n) { protected Context makeLocalContext(Context context, CAstNode n) {
return new LocalContext((WalkContext) context, makeLocalScope(n, ((WalkContext) context).currentScope())); return new LocalContext((WalkContext) context, makeLocalScope(n, ((WalkContext) context).currentScope()));
@ -2121,7 +2124,7 @@ public abstract class AstTranslator extends CAstVisitor {
// FIXME: should it be possible to override visit() instead to do the below // FIXME: should it be possible to override visit() instead to do the below
// and then call super.visit? // and then call super.visit?
private Map popPositionM = new LinkedHashMap(); private Map<CAstNode, Boolean> popPositionM = new LinkedHashMap<CAstNode, Boolean>();
protected boolean enterNode(CAstNode n, Context c, CAstVisitor visitor) { protected boolean enterNode(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext) c; WalkContext context = (WalkContext) c;
@ -2146,7 +2149,7 @@ public abstract class AstTranslator extends CAstVisitor {
protected void postProcessNode(CAstNode n, Context c, CAstVisitor visitor) { protected void postProcessNode(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext context = (WalkContext) c; WalkContext context = (WalkContext) c;
if (popPositionM.get(n) != null) { if (popPositionM.get(n) != null) {
context.cfg().setCurrentPosition((Position) positions.pop()); context.cfg().setCurrentPosition(positions.pop());
} }
} }
@ -2178,7 +2181,7 @@ public abstract class AstTranslator extends CAstVisitor {
int result = processFunctionExpr(n, c); int result = processFunctionExpr(n, c);
CAstEntity fn = (CAstEntity) n.getChild(0).getValue(); CAstEntity fn = (CAstEntity) n.getChild(0).getValue();
// FIXME: handle redefinitions of functions // FIXME: handle redefinitions of functions
if (! context.currentScope().contains(fn.getName())) { if (!context.currentScope().contains(fn.getName())) {
context.currentScope().declare(fn.getName(), true, false, result); context.currentScope().declare(fn.getName(), true, false, result);
} }
} }
@ -2667,7 +2670,7 @@ public abstract class AstTranslator extends CAstVisitor {
int[] dims = gatherArrayDims(n); int[] dims = gatherArrayDims(n);
doArrayRead(context, temp, getValue(n.getChild(0)), n, dims); doArrayRead(context, temp, getValue(n.getChild(0)), n, dims);
int rval = processAssignOp(n, v, a, temp, !pre, c); int rval = processAssignOp(n, v, a, temp, !pre, c);
setValue(n, pre? rval: temp); setValue(n, pre ? rval : temp);
doArrayWrite(context, getValue(n.getChild(0)), n, dims, rval); doArrayWrite(context, getValue(n.getChild(0)), n, dims, rval);
} }
@ -2694,7 +2697,7 @@ public abstract class AstTranslator extends CAstVisitor {
int temp = context.currentScope().allocateTempValue(); int temp = context.currentScope().allocateTempValue();
doFieldRead(context, temp, getValue(n.getChild(0)), n.getChild(1), n); doFieldRead(context, temp, getValue(n.getChild(0)), n.getChild(1), n);
int rval = processAssignOp(n, v, a, temp, !pre, c); int rval = processAssignOp(n, v, a, temp, !pre, c);
setValue(n, pre? rval: temp); setValue(n, pre ? rval : temp);
doFieldWrite(context, getValue(n.getChild(0)), n.getChild(1), n, rval); doFieldWrite(context, getValue(n.getChild(0)), n.getChild(1), n, rval);
} }
@ -2729,8 +2732,7 @@ public abstract class AstTranslator extends CAstVisitor {
else if (context.currentScope().isLexicallyScoped(ls)) { else if (context.currentScope().isLexicallyScoped(ls)) {
doLexicallyScopedWrite(context, nm, rval); doLexicallyScopedWrite(context, nm, rval);
} else { } else {
Assertions._assert(rval != -1, Assertions._assert(rval != -1, CAstPrinter.print(n, c.top().getSourceMap()));
CAstPrinter.print(n, c.top().getSourceMap()));
doLocalWrite(context, nm, rval); doLocalWrite(context, nm, rval);
} }
} }
@ -2776,8 +2778,8 @@ public abstract class AstTranslator extends CAstVisitor {
private boolean isSimpleSwitch(CAstNode n, WalkContext context, CAstVisitor visitor) { private boolean isSimpleSwitch(CAstNode n, WalkContext context, CAstVisitor visitor) {
CAstControlFlowMap ctrl = context.getControlFlow(); CAstControlFlowMap ctrl = context.getControlFlow();
Collection caseLabels = ctrl.getTargetLabels(n); Collection<IField> caseLabels = ctrl.getTargetLabels(n);
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) { for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
Object x = kases.next(); Object x = kases.next();
if (x == CAstControlFlowMap.SWITCH_DEFAULT) if (x == CAstControlFlowMap.SWITCH_DEFAULT)
@ -2816,7 +2818,7 @@ public abstract class AstTranslator extends CAstVisitor {
boolean hasExplicitDefault = ctrl.getTarget(n, CAstControlFlowMap.SWITCH_DEFAULT) != null; boolean hasExplicitDefault = ctrl.getTarget(n, CAstControlFlowMap.SWITCH_DEFAULT) != null;
Collection caseLabels = ctrl.getTargetLabels(n); Collection<IField> caseLabels = ctrl.getTargetLabels(n);
int cases = caseLabels.size(); int cases = caseLabels.size();
if (hasExplicitDefault) if (hasExplicitDefault)
cases--; cases--;
@ -2839,7 +2841,7 @@ public abstract class AstTranslator extends CAstVisitor {
context.cfg().newBlock(true); context.cfg().newBlock(true);
int cn = 0; int cn = 0;
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) { for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
Object x = kases.next(); Object x = kases.next();
CAstNode target = ctrl.getTarget(n, x); CAstNode target = ctrl.getTarget(n, x);
if (x == CAstControlFlowMap.SWITCH_DEFAULT) { if (x == CAstControlFlowMap.SWITCH_DEFAULT) {
@ -2863,9 +2865,9 @@ public abstract class AstTranslator extends CAstVisitor {
visitor.visit(switchValue, context, visitor); visitor.visit(switchValue, context, visitor);
int v = getValue(switchValue); int v = getValue(switchValue);
Collection caseLabels = ctrl.getTargetLabels(n); Collection<IField> caseLabels = ctrl.getTargetLabels(n);
Map labelToBlock = new LinkedHashMap(); Map<Object, PreBasicBlock> labelToBlock = new LinkedHashMap<Object, PreBasicBlock>();
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) { for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
Object x = kases.next(); Object x = kases.next();
if (x != CAstControlFlowMap.SWITCH_DEFAULT) { if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
walkNodes((CAstNode) x, context); walkNodes((CAstNode) x, context);
@ -2885,8 +2887,7 @@ public abstract class AstTranslator extends CAstVisitor {
visitor.visit(switchBody, context, visitor); visitor.visit(switchBody, context, visitor);
context.cfg().newBlock(true); context.cfg().newBlock(true);
PreBasicBlock nextBlock = context.cfg().getCurrentBlock(); for (Iterator<IField> kases = caseLabels.iterator(); kases.hasNext();) {
for (Iterator kases = caseLabels.iterator(); kases.hasNext();) {
Object x = kases.next(); Object x = kases.next();
if (x != CAstControlFlowMap.SWITCH_DEFAULT) { if (x != CAstControlFlowMap.SWITCH_DEFAULT) {
CAstNode target = ctrl.getTarget(n, x); CAstNode target = ctrl.getTarget(n, x);
@ -2930,8 +2931,8 @@ public abstract class AstTranslator extends CAstVisitor {
context.cfg().addPreNode(n, context.getUnwindState()); context.cfg().addPreNode(n, context.getUnwindState());
context.cfg().newBlock(false); context.cfg().newBlock(false);
Collection labels = context.getControlFlow().getTargetLabels(n); Collection<IField> labels = context.getControlFlow().getTargetLabels(n);
for (Iterator iter = labels.iterator(); iter.hasNext();) { for (Iterator<IField> iter = labels.iterator(); iter.hasNext();) {
Object label = iter.next(); Object label = iter.next();
CAstNode target = context.getControlFlow().getTarget(n, label); CAstNode target = context.getControlFlow().getTarget(n, label);
if (target == CAstControlFlowMap.EXCEPTION_TO_EXIT) if (target == CAstControlFlowMap.EXCEPTION_TO_EXIT)
@ -3080,17 +3081,16 @@ public abstract class AstTranslator extends CAstVisitor {
((WalkContext) c).cfg().addInstruction(new EachElementHasNextInstruction(result, getValue(n.getChild(0)))); ((WalkContext) c).cfg().addInstruction(new EachElementHasNextInstruction(result, getValue(n.getChild(0))));
} }
protected boolean visitTypeLiteralExpr(CAstNode n, Context c, CAstVisitor visitor) { protected boolean visitTypeLiteralExpr(CAstNode n, Context c, CAstVisitor visitor) {
return false; return false;
} }
protected void leaveTypeLiteralExpr(CAstNode n, Context c, CAstVisitor visitor) { protected void leaveTypeLiteralExpr(CAstNode n, Context c, CAstVisitor visitor) {
WalkContext wc = (WalkContext)c; WalkContext wc = (WalkContext) c;
Assertions._assert(n.getChild(0).getKind() == CAstNode.CONSTANT); Assertions._assert(n.getChild(0).getKind() == CAstNode.CONSTANT);
String typeNameStr = (String) n.getChild(0).getValue(); String typeNameStr = (String) n.getChild(0).getValue();
TypeName typeName = TypeName.string2TypeName(typeNameStr); TypeName typeName = TypeName.string2TypeName(typeNameStr);
TypeReference typeRef = TypeReference typeRef = TypeReference.findOrCreate(loader.getReference(), typeName);
TypeReference.findOrCreate(loader.getReference(), typeName);
int result = wc.currentScope().allocateTempValue(); int result = wc.currentScope().allocateTempValue();
setValue(n, result); setValue(n, result);
@ -3131,7 +3131,7 @@ public abstract class AstTranslator extends CAstVisitor {
return t.globalScope; return t.globalScope;
} }
public Set entityScopes() { public Set<Scope> entityScopes() {
return Collections.singleton(t.globalScope); return Collections.singleton(t.globalScope);
} }

View File

@ -11,31 +11,41 @@
package com.ibm.wala.cast.loader; package com.ibm.wala.cast.loader;
import com.ibm.wala.cast.tree.*; import java.net.URL;
import com.ibm.wala.classLoader.*; import java.util.Collection;
import com.ibm.wala.ipa.cha.*; import java.util.HashSet;
import com.ibm.wala.shrikeCT.*; import java.util.Iterator;
import com.ibm.wala.types.*; import java.util.Map;
import com.ibm.wala.util.*; import java.util.Set;
import com.ibm.wala.util.debug.Assertions;
import java.net.*; import com.ibm.wala.cast.tree.CAstSourcePositionMap;
import java.util.*; import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IField;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.shrikeCT.ClassConstants;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.Atom;
import com.ibm.wala.util.debug.Assertions;
abstract public class AstClass implements IClass, ClassConstants { abstract public class AstClass implements IClass, ClassConstants {
private final CAstSourcePositionMap.Position sourcePosition; private final CAstSourcePositionMap.Position sourcePosition;
private final TypeName typeName; private final TypeName typeName;
private final IClassLoader loader; private final IClassLoader loader;
private final short modifiers; private final short modifiers;
protected final Map declaredFields; protected final Map<Atom, IField> declaredFields;
protected final Map declaredMethods; protected final Map<Selector,IMethod> declaredMethods;
protected AstClass(CAstSourcePositionMap.Position sourcePosition, protected AstClass(CAstSourcePositionMap.Position sourcePosition,
TypeName typeName, TypeName typeName,
IClassLoader loader, IClassLoader loader,
short modifiers, short modifiers,
Map declaredFields, Map<Atom, IField> declaredFields,
Map declaredMethods) Map<Selector,IMethod> declaredMethods)
{ {
this.sourcePosition = sourcePosition; this.sourcePosition = sourcePosition;
this.typeName = typeName; this.typeName = typeName;
@ -95,22 +105,22 @@ abstract public class AstClass implements IClass, ClassConstants {
public abstract IClass getSuperclass() throws ClassHierarchyException; public abstract IClass getSuperclass() throws ClassHierarchyException;
private Collection gatherInterfaces() throws ClassHierarchyException { private Collection<IClass> gatherInterfaces() throws ClassHierarchyException {
Set result = new HashSet(); Set<IClass> result = new HashSet<IClass>();
result.addAll( getDirectInterfaces() ); result.addAll( getDirectInterfaces() );
if (getSuperclass() != null) if (getSuperclass() != null)
result.addAll( getSuperclass().getAllImplementedInterfaces() ); result.addAll( getSuperclass().getAllImplementedInterfaces() );
return result; return result;
} }
public abstract Collection getDirectInterfaces() throws ClassHierarchyException; public abstract Collection<IClass> getDirectInterfaces() throws ClassHierarchyException;
public Collection getAllImplementedInterfaces() throws ClassHierarchyException { public Collection<IClass> getAllImplementedInterfaces() throws ClassHierarchyException {
Assertions._assert(! isInterface()); Assertions._assert(! isInterface());
return gatherInterfaces(); return gatherInterfaces();
} }
public Collection getAllAncestorInterfaces() throws ClassHierarchyException { public Collection<IClass> getAllAncestorInterfaces() throws ClassHierarchyException {
Assertions._assert(isInterface()); Assertions._assert(isInterface());
return gatherInterfaces(); return gatherInterfaces();
} }
@ -122,7 +132,7 @@ abstract public class AstClass implements IClass, ClassConstants {
public IMethod getMethod(Selector selector) { public IMethod getMethod(Selector selector) {
try { try {
if (declaredMethods.containsKey(selector)) { if (declaredMethods.containsKey(selector)) {
return (IMethod)declaredMethods.get(selector); return declaredMethods.get(selector);
} else if (getSuperclass() != null) { } else if (getSuperclass() != null) {
return getSuperclass().getMethod(selector); return getSuperclass().getMethod(selector);
} else { } else {
@ -137,7 +147,7 @@ abstract public class AstClass implements IClass, ClassConstants {
public IField getField(Atom name) { public IField getField(Atom name) {
try { try {
if (declaredFields.containsKey(name)) { if (declaredFields.containsKey(name)) {
return (IField)declaredFields.get(name); return declaredFields.get(name);
} else if (getSuperclass() != null) { } else if (getSuperclass() != null) {
return getSuperclass().getField(name); return getSuperclass().getField(name);
} else { } else {
@ -153,10 +163,10 @@ abstract public class AstClass implements IClass, ClassConstants {
return declaredMethods.values(); return declaredMethods.values();
} }
public Collection getDeclaredInstanceFields() { public Collection<IField> getDeclaredInstanceFields() {
Set result = new HashSet(); Set<IField> result = new HashSet<IField>();
for(Iterator FS = declaredFields.values().iterator(); FS.hasNext();) { for(Iterator<IField> FS = declaredFields.values().iterator(); FS.hasNext();) {
IField F = (IField) FS.next(); IField F = FS.next();
if (! F.isStatic()) { if (! F.isStatic()) {
result.add( F ); result.add( F );
} }
@ -165,10 +175,10 @@ abstract public class AstClass implements IClass, ClassConstants {
return result; return result;
} }
public Collection getDeclaredStaticFields() { public Collection<IField> getDeclaredStaticFields() {
Set result = new HashSet(); Set<IField> result = new HashSet<IField>();
for(Iterator FS = declaredFields.values().iterator(); FS.hasNext();) { for(Iterator<IField> FS = declaredFields.values().iterator(); FS.hasNext();) {
IField F = (IField) FS.next(); IField F = FS.next();
if (F.isStatic()) { if (F.isStatic()) {
result.add( F ); result.add( F );
} }
@ -177,8 +187,8 @@ abstract public class AstClass implements IClass, ClassConstants {
return result; return result;
} }
public Collection getAllInstanceFields() throws ClassHierarchyException { public Collection<IField> getAllInstanceFields() throws ClassHierarchyException {
Collection result = new HashSet(); Collection<IField> result = new HashSet<IField>();
result.addAll( getDeclaredInstanceFields() ); result.addAll( getDeclaredInstanceFields() );
if (getSuperclass() != null) { if (getSuperclass() != null) {
result.addAll( getSuperclass().getAllInstanceFields() ); result.addAll( getSuperclass().getAllInstanceFields() );
@ -187,8 +197,8 @@ abstract public class AstClass implements IClass, ClassConstants {
return result; return result;
} }
public Collection getAllStaticFields() throws ClassHierarchyException { public Collection<IField> getAllStaticFields() throws ClassHierarchyException {
Collection result = new HashSet(); Collection<IField> result = new HashSet<IField>();
result.addAll( getDeclaredStaticFields() ); result.addAll( getDeclaredStaticFields() );
if (getSuperclass() != null) { if (getSuperclass() != null) {
result.addAll( getSuperclass().getAllStaticFields() ); result.addAll( getSuperclass().getAllStaticFields() );
@ -197,16 +207,16 @@ abstract public class AstClass implements IClass, ClassConstants {
return result; return result;
} }
public Collection getAllFields() throws ClassHierarchyException { public Collection<IField> getAllFields() throws ClassHierarchyException {
Collection result = new HashSet(); Collection<IField> result = new HashSet<IField>();
result.addAll( getAllInstanceFields() ); result.addAll( getAllInstanceFields() );
result.addAll( getAllStaticFields() ); result.addAll( getAllStaticFields() );
return result; return result;
} }
public Collection getAllMethods() throws ClassHierarchyException { public Collection<IMethod> getAllMethods() throws ClassHierarchyException {
Collection result = new HashSet(); Collection<IMethod> result = new HashSet<IMethod>();
for(Iterator ms = getDeclaredMethods().iterator(); ms.hasNext(); ) { for(Iterator<IMethod> ms = getDeclaredMethods().iterator(); ms.hasNext(); ) {
result.add( ms.next() ); result.add( ms.next() );
} }
if (getSuperclass() != null) { if (getSuperclass() != null) {

View File

@ -10,7 +10,6 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.loader; package com.ibm.wala.cast.loader;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -18,9 +17,11 @@ import com.ibm.wala.cast.tree.CAstSourcePositionMap;
import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IClassLoader; import com.ibm.wala.classLoader.IClassLoader;
import com.ibm.wala.classLoader.IField; import com.ibm.wala.classLoader.IField;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.cha.ClassHierarchy; import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ipa.cha.ClassHierarchyException; import com.ibm.wala.ipa.cha.ClassHierarchyException;
import com.ibm.wala.types.FieldReference; import com.ibm.wala.types.FieldReference;
import com.ibm.wala.types.Selector;
import com.ibm.wala.types.TypeName; import com.ibm.wala.types.TypeName;
import com.ibm.wala.types.TypeReference; import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.Atom; import com.ibm.wala.util.Atom;
@ -29,15 +30,16 @@ import com.ibm.wala.util.debug.Assertions;
public abstract class AstDynamicPropertyClass extends AstClass { public abstract class AstDynamicPropertyClass extends AstClass {
private final TypeReference defaultDescriptor; private final TypeReference defaultDescriptor;
protected AstDynamicPropertyClass(CAstSourcePositionMap.Position sourcePosition, TypeName typeName, IClassLoader loader, short modifiers, Map declaredMethods, TypeReference defaultDescriptor) { protected AstDynamicPropertyClass(CAstSourcePositionMap.Position sourcePosition, TypeName typeName, IClassLoader loader,
super(sourcePosition, typeName, loader, modifiers, new HashMap(), declaredMethods); short modifiers, Map<Selector, IMethod> declaredMethods, TypeReference defaultDescriptor) {
super(sourcePosition, typeName, loader, modifiers, new HashMap<Atom, IField>(), declaredMethods);
this.defaultDescriptor = defaultDescriptor; this.defaultDescriptor = defaultDescriptor;
} }
public IField getField(final Atom name) { public IField getField(final Atom name) {
try { try {
if (declaredFields.containsKey(name)) { if (declaredFields.containsKey(name)) {
return (IField) declaredFields.get(name); return declaredFields.get(name);
} else if (getSuperclass() != null) { } else if (getSuperclass() != null) {
return getSuperclass().getField(name); return getSuperclass().getField(name);
} else { } else {
@ -88,11 +90,11 @@ public abstract class AstDynamicPropertyClass extends AstClass {
} }
public ClassHierarchy getClassHierarchy() { public ClassHierarchy getClassHierarchy() {
return AstDynamicPropertyClass.this.getClassHierarchy(); return AstDynamicPropertyClass.this.getClassHierarchy();
} }
}); });
return (IField) declaredFields.get(name); return declaredFields.get(name);
} }
} catch (ClassHierarchyException e) { } catch (ClassHierarchyException e) {
Assertions.UNREACHABLE(); Assertions.UNREACHABLE();

View File

@ -81,16 +81,16 @@ abstract public class AstFunctionClass implements IClass, ClassConstants {
return loader.lookupClass(superReference.getName(), getClassHierarchy()); return loader.lookupClass(superReference.getName(), getClassHierarchy());
} }
public Collection getDirectInterfaces() { public Collection<IClass> getDirectInterfaces() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public Collection getAllImplementedInterfaces() { public Collection<IClass> getAllImplementedInterfaces() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public Collection getAllAncestorInterfaces() { public Collection<IClass> getAllAncestorInterfaces() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public IMethod getMethod(Selector selector) { public IMethod getMethod(Selector selector) {
@ -137,27 +137,27 @@ abstract public class AstFunctionClass implements IClass, ClassConstants {
} }
} }
public Collection getDeclaredInstanceFields() { public Collection<IField> getDeclaredInstanceFields() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public Collection getDeclaredStaticFields() { public Collection<IField> getDeclaredStaticFields() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public Collection getAllInstanceFields() { public Collection<IField> getAllInstanceFields() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public Collection getAllStaticFields() { public Collection<IField> getAllStaticFields() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public Collection getAllFields() { public Collection<IField> getAllFields() {
return Collections.EMPTY_SET; return Collections.emptySet();
} }
public Collection getAllMethods() { public Collection<IMethod> getAllMethods() {
return Collections.singleton(functionBody); return Collections.singleton(functionBody);
} }

View File

@ -72,5 +72,5 @@ public interface CAstControlFlowMap {
* Returns an iterator of all CAstNodes for which this map contains * Returns an iterator of all CAstNodes for which this map contains
* control flow mapping information. * control flow mapping information.
*/ */
Collection getMappedNodes(); Collection<CAstNode> getMappedNodes();
} }

View File

@ -16,7 +16,7 @@ package com.ibm.wala.cast.tree;
import java.util.*; import java.util.*;
public class CAstQualifier { public class CAstQualifier {
public static final Set/* <CAstQualifier> */sQualifiers = new HashSet(); public static final Set/* <CAstQualifier> */<CAstQualifier>sQualifiers = new HashSet<CAstQualifier>();
public static final CAstQualifier CONST = new CAstQualifier("const"); public static final CAstQualifier CONST = new CAstQualifier("const");
public static final CAstQualifier STRICTFP = new CAstQualifier("strictfp"); public static final CAstQualifier STRICTFP = new CAstQualifier("strictfp");

View File

@ -53,6 +53,6 @@ public interface CAstSourcePositionMap {
* Returns an iterator of all CAstNodes for which this map contains * Returns an iterator of all CAstNodes for which this map contains
* source mapping information. * source mapping information.
*/ */
Iterator getMappedNodes(); Iterator<CAstNode> getMappedNodes();
} }

View File

@ -11,6 +11,7 @@
package com.ibm.wala.cast.tree.impl; package com.ibm.wala.cast.tree.impl;
import com.ibm.wala.cast.tree.*; import com.ibm.wala.cast.tree.*;
import com.ibm.wala.classLoader.IField;
import java.util.*; import java.util.*;
@ -32,7 +33,7 @@ public class CAstCloner {
} }
private CAstNode copyNodes(CAstNode root, Map nodeMap) { private CAstNode copyNodes(CAstNode root, Map<CAstNode, CAstNode> nodeMap) {
if (root instanceof CAstOperator) { if (root instanceof CAstOperator) {
nodeMap.put(root, root); nodeMap.put(root, root);
return root; return root;
@ -53,12 +54,12 @@ public class CAstCloner {
} }
} }
private CAstControlFlowMap copyFlow(Map nodeMap, CAstControlFlowMap orig) { private CAstControlFlowMap copyFlow(Map<CAstNode, CAstNode> nodeMap, CAstControlFlowMap orig) {
Collection oldSources = orig.getMappedNodes(); Collection<CAstNode> oldSources = orig.getMappedNodes();
CAstControlFlowRecorder newMap = new CAstControlFlowRecorder(); CAstControlFlowRecorder newMap = new CAstControlFlowRecorder();
for(Iterator NS = nodeMap.keySet().iterator(); NS.hasNext(); ) { for(Iterator<CAstNode> NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
CAstNode old = (CAstNode) NS.next(); CAstNode old = NS.next();
CAstNode newNode = (CAstNode) nodeMap.get(old); CAstNode newNode = nodeMap.get(old);
newMap.map(newNode, newNode); newMap.map(newNode, newNode);
if (oldSources.contains(old)) { if (oldSources.contains(old)) {
if (orig.getTarget(old, null) != null) { if (orig.getTarget(old, null) != null) {
@ -70,7 +71,7 @@ public class CAstCloner {
} }
} }
for(Iterator LS = orig.getTargetLabels(old).iterator(); LS.hasNext(); ) { for(Iterator<IField> LS = orig.getTargetLabels(old).iterator(); LS.hasNext(); ) {
Object label = LS.next(); Object label = LS.next();
CAstNode oldTarget = orig.getTarget(old, label); CAstNode oldTarget = orig.getTarget(old, label);
if (nodeMap.containsKey(oldTarget)) { if (nodeMap.containsKey(oldTarget)) {
@ -86,15 +87,15 @@ public class CAstCloner {
} }
private CAstSourcePositionMap private CAstSourcePositionMap
copySource(Map nodeMap, CAstSourcePositionMap orig) copySource(Map<CAstNode, CAstNode> nodeMap, CAstSourcePositionMap orig)
{ {
if (orig == null) { if (orig == null) {
return null; return null;
} else { } else {
CAstSourcePositionRecorder newMap = new CAstSourcePositionRecorder(); CAstSourcePositionRecorder newMap = new CAstSourcePositionRecorder();
for(Iterator NS = nodeMap.keySet().iterator(); NS.hasNext(); ) { for(Iterator<CAstNode> NS = nodeMap.keySet().iterator(); NS.hasNext(); ) {
CAstNode old = (CAstNode) NS.next(); CAstNode old = NS.next();
CAstNode newNode = (CAstNode) nodeMap.get(old); CAstNode newNode = nodeMap.get(old);
if (orig.getPosition(old) != null) { if (orig.getPosition(old) != null) {
newMap.setPosition(newNode, orig.getPosition(old)); newMap.setPosition(newNode, orig.getPosition(old));
@ -109,7 +110,7 @@ public class CAstCloner {
final CAstControlFlowMap cfg, final CAstControlFlowMap cfg,
final CAstSourcePositionMap pos) final CAstSourcePositionMap pos)
{ {
final Map nodes = new HashMap(); final Map<CAstNode, CAstNode> nodes = new HashMap<CAstNode, CAstNode>();
final CAstNode newRoot = copyNodes(root, nodes); final CAstNode newRoot = copyNodes(root, nodes);
return new Clone() { return new Clone() {
private CAstControlFlowMap theCfg = null; private CAstControlFlowMap theCfg = null;

View File

@ -10,21 +10,25 @@
*****************************************************************************/ *****************************************************************************/
package com.ibm.wala.cast.tree.impl; package com.ibm.wala.cast.tree.impl;
import com.ibm.wala.cast.tree.*; import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.io.*; import com.ibm.wala.cast.tree.CAstNode;
import java.net.*; import com.ibm.wala.cast.tree.CAstSourcePositionMap;
import java.util.*;
public class CAstSourcePositionRecorder implements CAstSourcePositionMap { public class CAstSourcePositionRecorder implements CAstSourcePositionMap {
private final HashMap positions = new HashMap(); private final HashMap<CAstNode, Position> positions = new HashMap<CAstNode, Position>();
public Position getPosition(CAstNode n) { public Position getPosition(CAstNode n) {
return (Position) positions.get(n); return positions.get(n);
} }
public Iterator getMappedNodes() { public Iterator<CAstNode> getMappedNodes() {
return positions.keySet().iterator(); return positions.keySet().iterator();
} }
@ -79,8 +83,8 @@ public class CAstSourcePositionRecorder implements CAstSourcePositionMap {
} }
public void addAll(CAstSourcePositionMap other) { public void addAll(CAstSourcePositionMap other) {
for(Iterator nodes = other.getMappedNodes(); nodes.hasNext(); ) { for(Iterator<CAstNode> nodes = other.getMappedNodes(); nodes.hasNext(); ) {
CAstNode node = (CAstNode) nodes.next(); CAstNode node = nodes.next();
setPosition(node, other.getPosition(node)); setPosition(node, other.getPosition(node));
} }
} }

View File

@ -18,10 +18,10 @@ import com.ibm.wala.cast.tree.*;
import java.util.*; import java.util.*;
public class CAstTypeDictionaryImpl implements CAstTypeDictionary { public class CAstTypeDictionaryImpl implements CAstTypeDictionary {
private final Map/*<ASTType,CAstType>*/ fMap= new HashMap(); private final Map/*<ASTType,CAstType>*/<Object, CAstType> fMap= new HashMap<Object, CAstType>();
public CAstType getCAstTypeFor(Object/*ASTType*/ astType) { public CAstType getCAstTypeFor(Object/*ASTType*/ astType) {
return (CAstType) fMap.get(astType); return fMap.get(astType);
} }
public void map(Object/*ASTType*/ astType, CAstType castType) { public void map(Object/*ASTType*/ astType, CAstType castType) {

View File

@ -68,7 +68,7 @@ public abstract class CAstVisitor {
*/ */
protected Context makeUnwindContext(Context context, CAstNode n, CAstVisitor visitor) { return context; } protected Context makeUnwindContext(Context context, CAstNode n, CAstVisitor visitor) { return context; }
private final Map entityParents = new HashMap(); private final Map<CAstEntity, CAstEntity> entityParents = new HashMap<CAstEntity, CAstEntity>();
/** /**
* Get the parent entity for a given entity. * Get the parent entity for a given entity.
@ -76,7 +76,7 @@ public abstract class CAstVisitor {
* @return the parent entity for the given entity * @return the parent entity for the given entity
*/ */
protected CAstEntity getParent(CAstEntity entity) { protected CAstEntity getParent(CAstEntity entity) {
return (CAstEntity) entityParents.get(entity); return entityParents.get(entity);
} }
/** /**

View File

@ -22,11 +22,11 @@ public class CAstFunctions {
if (f.accepts(tree)) { if (f.accepts(tree)) {
return tree; return tree;
} else { } else {
for(int i = 0; i < tree.getChildCount(); i++) { for (int i = 0; i < tree.getChildCount(); i++) {
CAstNode result = findIf(tree.getChild(i), f); CAstNode result = findIf(tree.getChild(i), f);
if (result != null) { if (result != null) {
return result; return result;
} }
} }
} }
@ -36,36 +36,36 @@ public class CAstFunctions {
public static Iterator iterateNodes(final CAstNode tree) { public static Iterator iterateNodes(final CAstNode tree) {
return new DFSDiscoverTimeIterator() { return new DFSDiscoverTimeIterator() {
private final Map pendingChildren = new HashMap(); private final Map<Object, Iterator> pendingChildren = new HashMap<Object, Iterator>();
protected Iterator getPendingChildren(Object n) { protected Iterator getPendingChildren(Object n) {
return (Iterator) pendingChildren.get(n); return pendingChildren.get(n);
} }
protected void setPendingChildren(Object v, Iterator iterator) { protected void setPendingChildren(Object v, Iterator iterator) {
pendingChildren.put(v, iterator); pendingChildren.put(v, iterator);
} }
protected Iterator getConnected(final Object n) { protected Iterator getConnected(final Object n) {
return new Iterator() { return new Iterator() {
private int i = 0; private int i = 0;
public boolean hasNext() { public boolean hasNext() {
return i < ((CAstNode)n).getChildCount(); return i < ((CAstNode) n).getChildCount();
} }
public Object next() { public Object next() {
return ((CAstNode)n).getChild(i++); return ((CAstNode) n).getChild(i++);
} }
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
}; };
} }
{ {
init(tree); init(tree);
} }
}; };
} }
@ -73,5 +73,5 @@ public class CAstFunctions {
public static Iterator findAll(CAstNode tree, Filter f) { public static Iterator findAll(CAstNode tree, Filter f) {
return new FilterIterator(iterateNodes(tree), f); return new FilterIterator(iterateNodes(tree), f);
} }
} }

View File

@ -25,13 +25,19 @@ import com.ibm.wala.util.debug.Trace;
public class CAstPattern { public class CAstPattern {
private static boolean DEBUG_PARSER = false; private static boolean DEBUG_PARSER = false;
private static boolean DEBUG_MATCH = false; private static boolean DEBUG_MATCH = false;
private final static int CHILD_KIND = -1; private final static int CHILD_KIND = -1;
private final static int CHILDREN_KIND = -2; private final static int CHILDREN_KIND = -2;
private final static int REPEATED_PATTERN_KIND = -3; private final static int REPEATED_PATTERN_KIND = -3;
private final static int ALTERNATIVE_PATTERN_KIND = -4; private final static int ALTERNATIVE_PATTERN_KIND = -4;
private final static int OPTIONAL_PATTERN_KIND = -5; private final static int OPTIONAL_PATTERN_KIND = -5;
private final static int REFERENCE_PATTERN_KIND = -6; private final static int REFERENCE_PATTERN_KIND = -6;
private final static int IGNORE_KIND = -99; private final static int IGNORE_KIND = -99;
@ -39,61 +45,62 @@ public class CAstPattern {
private final String name; private final String name;
private final int kind; private final int kind;
private final String value;
private final CAstPattern[] children;
private final Map references;
public static class Segments extends TreeMap { private final String value;
private final CAstPattern[] children;
private final Map<String, CAstPattern> references;
public static class Segments extends TreeMap<String,Object> {
public CAstNode getSingle(String name) { public CAstNode getSingle(String name) {
Assertions._assert(containsKey(name), name); Assertions._assert(containsKey(name), name);
return (CAstNode) get(name); return (CAstNode) get(name);
} }
public List getMultiple(String name) { public List<Object> getMultiple(String name) {
if (! containsKey(name)) { if (!containsKey(name)) {
return Collections.EMPTY_LIST; return Collections.emptyList();
} else { } else {
Object o = get(name); Object o = get(name);
if (o instanceof CAstNode) { if (o instanceof CAstNode) {
return Collections.singletonList(o); return Collections.singletonList(o);
} else { } else {
Assertions._assert(o instanceof List); Assertions._assert(o instanceof List);
return (List)o; return (List<Object>) o;
} }
} }
} }
private void addAll(Segments other) { private void addAll(Segments other) {
for(Iterator xs = other.entrySet().iterator(); xs.hasNext(); ) { for (Iterator xs = other.entrySet().iterator(); xs.hasNext();) {
Map.Entry e = (Map.Entry) xs.next(); Map.Entry e = (Map.Entry) xs.next();
String name = (String)e.getKey(); String name = (String) e.getKey();
if (e.getValue() instanceof CAstNode) { if (e.getValue() instanceof CAstNode) {
add(name, (CAstNode) e.getValue()); add(name, (CAstNode) e.getValue());
} else { } else {
for(Iterator vs = ((List)e.getValue()).iterator(); for (Iterator vs = ((List) e.getValue()).iterator(); vs.hasNext();) {
vs.hasNext(); ) add(name, (CAstNode) vs.next());
{ }
add(name, (CAstNode) vs.next()); }
}
}
} }
} }
private void add(String name, CAstNode result) { private void add(String name, CAstNode result) {
if (containsKey(name)) { if (containsKey(name)) {
Object o = get(name); Object o = get(name);
if (o instanceof List) { if (o instanceof List) {
((List)o).add(result); ((List<CAstNode>) o).add(result);
} else { } else {
Assertions._assert(o instanceof CAstNode); Assertions._assert(o instanceof CAstNode);
List x = new ArrayList(); List<Object> x = new ArrayList<Object>();
x.add(o); x.add(o);
x.add(result); x.add(result);
put(name, x); put(name, x);
} }
} else { } else {
put(name, result); put(name, result);
} }
} }
} }
@ -114,7 +121,7 @@ public class CAstPattern {
this.references = null; this.references = null;
} }
public CAstPattern(String patternName, Map references) { public CAstPattern(String patternName, Map<String, CAstPattern> references) {
this.name = null; this.name = null;
this.kind = REFERENCE_PATTERN_KIND; this.kind = REFERENCE_PATTERN_KIND;
this.value = patternName; this.value = patternName;
@ -133,7 +140,7 @@ public class CAstPattern {
if (kind == REFERENCE_PATTERN_KIND) { if (kind == REFERENCE_PATTERN_KIND) {
sb.append("ref:").append(value); sb.append("ref:").append(value);
} else { } else {
sb.append("literal:").append(value); sb.append("literal:").append(value);
} }
} else if (kind == CHILD_KIND) { } else if (kind == CHILD_KIND) {
sb.append("*"); sb.append("*");
@ -151,22 +158,20 @@ public class CAstPattern {
if (children != null) { if (children != null) {
sb.append("("); sb.append("(");
for(int i = 0; i < children.length; i++) { for (int i = 0; i < children.length; i++) {
sb.append( children[i].toString() ); sb.append(children[i].toString());
if (i == children.length-1) { if (i == children.length - 1) {
sb.append(")"); sb.append(")");
} else { } else {
sb.append(","); sb.append(",");
} }
} }
} }
return sb.toString(); return sb.toString();
} }
private static boolean private static boolean matchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s) {
matchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s)
{
if (i >= tree.getChildCount() && j >= cs.length) { if (i >= tree.getChildCount() && j >= cs.length) {
return true; return true;
} else if (i < tree.getChildCount() && j >= cs.length) { } else if (i < tree.getChildCount() && j >= cs.length) {
@ -176,160 +181,151 @@ public class CAstPattern {
case CHILDREN_KIND: case CHILDREN_KIND:
case OPTIONAL_PATTERN_KIND: case OPTIONAL_PATTERN_KIND:
case REPEATED_PATTERN_KIND: case REPEATED_PATTERN_KIND:
return matchChildren(tree, i, cs, j+1, s); return matchChildren(tree, i, cs, j + 1, s);
default: default:
return false; return false;
} }
} else { } else {
if (cs[j].kind == CHILD_KIND) { if (cs[j].kind == CHILD_KIND) {
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println("* matches "+CAstPrinter.print(tree.getChild(i))); Trace.println("* matches " + CAstPrinter.print(tree.getChild(i)));
} }
if (s != null && cs[j].name != null) { if (s != null && cs[j].name != null) {
s.add(cs[j].name, tree.getChild(i)); s.add(cs[j].name, tree.getChild(i));
} }
return matchChildren(tree, i+1, cs, j+1, s); return matchChildren(tree, i + 1, cs, j + 1, s);
} else if (cs[j].kind == CHILDREN_KIND) { } else if (cs[j].kind == CHILDREN_KIND) {
if (tryMatchChildren(tree, i, cs, j+1, s)) { if (tryMatchChildren(tree, i, cs, j + 1, s)) {
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println("** matches nothing"); Trace.println("** matches nothing");
} }
return true; return true;
} else { } else {
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println( Trace.println("** matches " + CAstPrinter.print(tree.getChild(i)));
"** matches " + CAstPrinter.print(tree.getChild(i))); }
}
if (s != null && cs[j].name != null) { if (s != null && cs[j].name != null) {
s.add(cs[j].name, tree.getChild(i) ); s.add(cs[j].name, tree.getChild(i));
} }
return matchChildren(tree, i+1, cs, j, s); return matchChildren(tree, i + 1, cs, j, s);
} }
} else if (cs[j].kind == REPEATED_PATTERN_KIND) { } else if (cs[j].kind == REPEATED_PATTERN_KIND) {
CAstPattern repeatedPattern = cs[j].children[0]; CAstPattern repeatedPattern = cs[j].children[0];
if (repeatedPattern.tryMatch(tree.getChild(i), s)) { if (repeatedPattern.tryMatch(tree.getChild(i), s)) {
if (s != null && cs[j].name != null) { if (s != null && cs[j].name != null) {
s.add(cs[j].name, tree.getChild(i) ); s.add(cs[j].name, tree.getChild(i));
} }
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println( Trace.println(cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
cs[j] + " matches " + CAstPrinter.print(tree.getChild(i))); }
}
return matchChildren(tree, i+1, cs, j, s); return matchChildren(tree, i + 1, cs, j, s);
} else { } else {
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println(cs[j] + " matches nothing"); Trace.println(cs[j] + " matches nothing");
} }
return matchChildren(tree, i, cs, j+1, s); return matchChildren(tree, i, cs, j + 1, s);
} }
} else if (cs[j].kind == OPTIONAL_PATTERN_KIND) { } else if (cs[j].kind == OPTIONAL_PATTERN_KIND) {
if (tryMatchChildren(tree, i, cs, j+1, s)) { if (tryMatchChildren(tree, i, cs, j + 1, s)) {
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println(cs[j] + " matches nothing"); Trace.println(cs[j] + " matches nothing");
} }
return true; return true;
} else { } else {
CAstPattern optionalPattern = cs[j].children[0]; CAstPattern optionalPattern = cs[j].children[0];
if (optionalPattern.tryMatch(tree.getChild(i), s)) { if (optionalPattern.tryMatch(tree.getChild(i), s)) {
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println( Trace.println(cs[j] + " matches " + CAstPrinter.print(tree.getChild(i)));
cs[j] + " matches " + CAstPrinter.print(tree.getChild(i))); }
}
return matchChildren(tree, i+1, cs, j+1, s); return matchChildren(tree, i + 1, cs, j + 1, s);
} else { } else {
return false; return false;
} }
} }
} else { } else {
return return cs[j].match(tree.getChild(i), s) && matchChildren(tree, i + 1, cs, j + 1, s);
cs[j].match(tree.getChild(i), s)
&&
matchChildren(tree, i+1, cs, j+1, s);
} }
} }
} }
public boolean match(CAstNode tree, Segments s) { public boolean match(CAstNode tree, Segments s) {
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println("matching "+this+" against "+CAstPrinter.print(tree)); Trace.println("matching " + this + " against " + CAstPrinter.print(tree));
} }
if (kind == REFERENCE_PATTERN_KIND) { if (kind == REFERENCE_PATTERN_KIND) {
return ((CAstPattern)references.get(value)).match(tree, s); return references.get(value).match(tree, s);
} else if (kind == ALTERNATIVE_PATTERN_KIND) { } else if (kind == ALTERNATIVE_PATTERN_KIND) {
for(int i = 0; i < children.length; i++) { for (int i = 0; i < children.length; i++) {
if (children[i].tryMatch(tree, s)) { if (children[i].tryMatch(tree, s)) {
if (s != null && name != null) s.add(name, tree); if (s != null && name != null)
s.add(name, tree);
return true;
} return true;
}
} }
if (DEBUG_MATCH) { if (DEBUG_MATCH) {
Trace.println("match failed (a)"); Trace.println("match failed (a)");
} }
return false; return false;
} else { } else {
if ( (value == null)? if ((value == null) ? tree.getKind() != kind : (tree.getKind() != CAstNode.CONSTANT || !value.equals(tree.getValue()
tree.getKind() != kind: .toString()))) {
( tree.getKind()!=CAstNode.CONSTANT if (DEBUG_MATCH) {
|| Trace.println("match failed (b)");
!value.equals(tree.getValue().toString()) ) ) }
{
if (DEBUG_MATCH) {
Trace.println("match failed (b)");
}
return false; return false;
} }
if (s != null && name != null) s.add(name, tree); if (s != null && name != null)
s.add(name, tree);
if (children == null || children.length == 0) { if (children == null || children.length == 0) {
if (DEBUG_MATCH && tree.getChildCount() != 0) { if (DEBUG_MATCH && tree.getChildCount() != 0) {
Trace.println("match failed (c)"); Trace.println("match failed (c)");
} }
return tree.getChildCount() == 0; return tree.getChildCount() == 0;
} else { } else {
return matchChildren(tree, 0, children, 0, s); return matchChildren(tree, 0, children, 0, s);
} }
} }
} }
private static boolean private static boolean tryMatchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s) {
tryMatchChildren(CAstNode tree, int i, CAstPattern[] cs, int j, Segments s)
{
if (s == null) { if (s == null) {
return matchChildren(tree, i, cs, j, s); return matchChildren(tree, i, cs, j, s);
} else { } else {
Segments ss = new Segments(); Segments ss = new Segments();
boolean result = matchChildren(tree, i, cs, j, ss); boolean result = matchChildren(tree, i, cs, j, ss);
if (result) s.addAll(ss); if (result)
s.addAll(ss);
return result; return result;
} }
} }
@ -340,7 +336,8 @@ public class CAstPattern {
} else { } else {
Segments ss = new Segments(); Segments ss = new Segments();
boolean result = match(tree, ss); boolean result = match(tree, ss);
if (result) s.addAll(ss); if (result)
s.addAll(ss);
return result; return result;
} }
} }
@ -367,36 +364,37 @@ public class CAstPattern {
} }
private static class Parser { private static class Parser {
private final Map namedPatterns = new HashMap(); private final Map<String, CAstPattern> namedPatterns = new HashMap<String, CAstPattern>();
private final String patternString; private final String patternString;
private int start; private int start;
private int end; private int end;
private Parser(String patternString) { private Parser(String patternString) {
this.patternString = patternString; this.patternString = patternString;
} }
// private Parser(String patternString, int start) { // private Parser(String patternString, int start) {
// this(patternString); // this(patternString);
// this.start = start; // this.start = start;
// } // }
private String parseName(boolean internal) { private String parseName(boolean internal) {
if (patternString.charAt(start) == (internal?'{':'<')) { if (patternString.charAt(start) == (internal ? '{' : '<')) {
int nameStart = start+1; int nameStart = start + 1;
int nameEnd = patternString.indexOf(internal?'}':'>', nameStart); int nameEnd = patternString.indexOf(internal ? '}' : '>', nameStart);
start = nameEnd + 1; start = nameEnd + 1;
return patternString.substring(nameStart, nameEnd); return patternString.substring(nameStart, nameEnd);
} else { } else {
return null; return null;
} }
} }
public CAstPattern parse() public CAstPattern parse() throws NoSuchFieldException, IllegalAccessException {
throws NoSuchFieldException, IllegalAccessException
{
if (DEBUG_PARSER) { if (DEBUG_PARSER) {
Trace.println("parsing " + patternString.substring(start)); Trace.println("parsing " + patternString.substring(start));
} }
String internalName = parseName(true); String internalName = parseName(true);
@ -404,103 +402,92 @@ public class CAstPattern {
CAstPattern result; CAstPattern result;
if (patternString.charAt(start) == '`') { if (patternString.charAt(start) == '`') {
int strEnd = patternString.indexOf('`', start+1); int strEnd = patternString.indexOf('`', start + 1);
end = strEnd+1; end = strEnd + 1;
String patternName = patternString.substring(start+1, strEnd); String patternName = patternString.substring(start + 1, strEnd);
Assertions._assert(internalName == null); Assertions._assert(internalName == null);
result = new CAstPattern(patternName, namedPatterns); result = new CAstPattern(patternName, namedPatterns);
} else if (patternString.charAt(start) == '"') { } else if (patternString.charAt(start) == '"') {
int strEnd = patternString.indexOf('"', start+1); int strEnd = patternString.indexOf('"', start + 1);
end = strEnd+1; end = strEnd + 1;
result = result = new CAstPattern(name, patternString.substring(start + 1, strEnd));
new CAstPattern(
name,
patternString.substring(start+1, strEnd));
} else if (patternString.startsWith("**", start)) { } else if (patternString.startsWith("**", start)) {
end = start+2; end = start + 2;
result = new CAstPattern(name, CHILDREN_KIND, null); result = new CAstPattern(name, CHILDREN_KIND, null);
} else if (patternString.startsWith("*", start)) { } else if (patternString.startsWith("*", start)) {
end = start+1; end = start + 1;
result = new CAstPattern(name, CHILD_KIND, null); result = new CAstPattern(name, CHILD_KIND, null);
} else if (patternString.startsWith("|(", start)) { } else if (patternString.startsWith("|(", start)) {
List alternatives = new ArrayList(); List<CAstPattern> alternatives = new ArrayList<CAstPattern>();
start += 2; start += 2;
do { do {
alternatives.add( parse() ); alternatives.add(parse());
start = end+2; start = end + 2;
} while (patternString.startsWith("||", end)); } while (patternString.startsWith("||", end));
Assertions._assert(patternString.startsWith(")|", end), patternString); Assertions._assert(patternString.startsWith(")|", end), patternString);
end += 2; end += 2;
result = new CAstPattern(name, result = new CAstPattern(name, ALTERNATIVE_PATTERN_KIND, alternatives.toArray(new CAstPattern[alternatives.size()]));
ALTERNATIVE_PATTERN_KIND,
(CAstPattern[])
alternatives.toArray(new CAstPattern[alternatives.size()]));
} else if (patternString.startsWith("@(", start)) { } else if (patternString.startsWith("@(", start)) {
start += 2; start += 2;
CAstPattern children[] = new CAstPattern[]{ parse() }; CAstPattern children[] = new CAstPattern[] { parse() };
Assertions._assert( patternString.startsWith(")@", end) ); Assertions._assert(patternString.startsWith(")@", end));
end += 2; end += 2;
if (DEBUG_PARSER) { if (DEBUG_PARSER) {
Trace.println("repeated pattern: " + children[0]); Trace.println("repeated pattern: " + children[0]);
} }
result = new CAstPattern(name, REPEATED_PATTERN_KIND, children);
result = new CAstPattern(name, REPEATED_PATTERN_KIND, children);
} else if (patternString.startsWith("?(", start)) { } else if (patternString.startsWith("?(", start)) {
start += 2; start += 2;
CAstPattern children[] = new CAstPattern[]{ parse() }; CAstPattern children[] = new CAstPattern[] { parse() };
Assertions._assert( patternString.startsWith(")?", end) ); Assertions._assert(patternString.startsWith(")?", end));
end += 2; end += 2;
if (DEBUG_PARSER) { if (DEBUG_PARSER) {
Trace.println("optional pattern: " + children[0]); Trace.println("optional pattern: " + children[0]);
} }
result = new CAstPattern(name, OPTIONAL_PATTERN_KIND, children);
result = new CAstPattern(name, OPTIONAL_PATTERN_KIND, children);
} else { } else {
int kindEnd = patternString.indexOf('(', start); int kindEnd = patternString.indexOf('(', start);
String kindStr = patternString.substring(start, kindEnd); String kindStr = patternString.substring(start, kindEnd);
Field kindField = CAstNode.class.getField(kindStr); Field kindField = CAstNode.class.getField(kindStr);
int kind = kindField.getInt(null); int kind = kindField.getInt(null);
if (patternString.charAt(kindEnd+1) == ')') { if (patternString.charAt(kindEnd + 1) == ')') {
end = kindEnd+2; end = kindEnd + 2;
result = new CAstPattern(name, kind, null); result = new CAstPattern(name, kind, null);
} else {
List children = new ArrayList();
start = patternString.indexOf('(', start) + 1;
do {
children.add( parse() );
start = end+1;
if (DEBUG_PARSER) {
Trace.println(
"parsing children: " + patternString.substring(end));
}
} while (patternString.charAt(end) == ',');
Assertions._assert(patternString.charAt(end) == ')');
end++;
result = new CAstPattern( } else {
name, List<CAstPattern> children = new ArrayList<CAstPattern>();
kind, start = patternString.indexOf('(', start) + 1;
(CAstPattern[]) do {
children.toArray(new CAstPattern[children.size()])); children.add(parse());
} start = end + 1;
if (DEBUG_PARSER) {
Trace.println("parsing children: " + patternString.substring(end));
}
} while (patternString.charAt(end) == ',');
Assertions._assert(patternString.charAt(end) == ')');
end++;
result = new CAstPattern(name, kind, children.toArray(new CAstPattern[children.size()]));
}
} }
if (internalName != null) { if (internalName != null) {
namedPatterns.put(internalName, result); namedPatterns.put(internalName, result);
} }
return result; return result;