173 lines
5.2 KiB
Java
173 lines
5.2 KiB
Java
/******************************************************************************
|
|
* Copyright (c) 2002 - 2006 IBM Corporation.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*****************************************************************************/
|
|
package com.ibm.wala.cast.ipa.callgraph;
|
|
|
|
|
|
import com.ibm.wala.cast.ir.translator.*;
|
|
import com.ibm.wala.cast.loader.AstMethod.*;
|
|
import com.ibm.wala.classLoader.*;
|
|
import com.ibm.wala.ipa.callgraph.*;
|
|
import com.ibm.wala.ipa.callgraph.propagation.*;
|
|
import com.ibm.wala.types.*;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
import com.ibm.wala.util.debug.Trace;
|
|
|
|
import java.util.*;
|
|
|
|
abstract public class ScopeMappingInstanceKeys implements InstanceKeyFactory {
|
|
|
|
protected abstract LexicalParent[] getParents(InstanceKey base);
|
|
|
|
protected abstract boolean needsScopeMappingKey(InstanceKey base);
|
|
|
|
private final PropagationCallGraphBuilder builder;
|
|
private final InstanceKeyFactory basic;
|
|
|
|
public class ScopeMappingInstanceKey implements InstanceKey {
|
|
private final InstanceKey base;
|
|
private final CGNode creator;
|
|
private final ScopeMap map;
|
|
|
|
private class ScopeMap extends HashMap {
|
|
|
|
private static final long serialVersionUID = 3645910671551712906L;
|
|
|
|
private void scan(int level, int toDo, LexicalParent parents[], CGNode node, Set parentNodes) {
|
|
if (toDo > 0) {
|
|
int restoreIndex = -1;
|
|
LexicalParent restoreParent = null;
|
|
|
|
if (AstTranslator.DEBUG_LEXICAL)
|
|
Trace.println(level + ": searching " + node + " for parents");
|
|
|
|
for(int i = 0; i < parents.length; i++) {
|
|
|
|
if (parents[i] == null) continue;
|
|
|
|
if (AstTranslator.DEBUG_LEXICAL)
|
|
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--;
|
|
restoreIndex = i;
|
|
restoreParent = parents[i];
|
|
parents[i] = null;
|
|
}
|
|
}
|
|
|
|
CallGraph CG = builder.getCallGraph();
|
|
|
|
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() {
|
|
LexicalParent[] parents = getParents(base);
|
|
|
|
if (AstTranslator.DEBUG_LEXICAL)
|
|
Trace.println("starting search for parents at " + creator);
|
|
|
|
scan( 0, parents.length, parents, creator, new HashSet(5));
|
|
}
|
|
|
|
CGNode getDefiningNode(String definer) {
|
|
return (CGNode) get(definer);
|
|
}
|
|
}
|
|
|
|
private ScopeMappingInstanceKey(CGNode creator, InstanceKey base) {
|
|
this.creator = creator;
|
|
this.base = base;
|
|
this.map = new ScopeMap();
|
|
}
|
|
|
|
public IClass getConcreteType() {
|
|
return base.getConcreteType();
|
|
}
|
|
|
|
CGNode getDefiningNode(String definer) {
|
|
return map.getDefiningNode( definer );
|
|
}
|
|
|
|
public int hashCode() {
|
|
return base.hashCode()*creator.hashCode();
|
|
}
|
|
|
|
public boolean equals(Object o) {
|
|
return (o instanceof ScopeMappingInstanceKey) &&
|
|
((ScopeMappingInstanceKey)o).base.equals(base) &&
|
|
((ScopeMappingInstanceKey)o).creator.equals(creator);
|
|
}
|
|
|
|
public String toString() {
|
|
return "SMIK:"+base+"@"+creator;
|
|
}
|
|
}
|
|
|
|
public InstanceKey getInstanceKeyForAllocation(CGNode node, NewSiteReference allocation) {
|
|
InstanceKey base = basic.getInstanceKeyForAllocation(node, allocation);
|
|
if (base != null && needsScopeMappingKey(base)) {
|
|
return new ScopeMappingInstanceKey(node, base);
|
|
} else {
|
|
return base;
|
|
}
|
|
}
|
|
|
|
public InstanceKey getInstanceKeyForMultiNewArray(CGNode node, NewSiteReference allocation, int dim) {
|
|
return basic.getInstanceKeyForMultiNewArray(node, allocation, dim);
|
|
}
|
|
|
|
public InstanceKey getInstanceKeyForConstant(Object S) {
|
|
return basic.getInstanceKeyForConstant(S);
|
|
}
|
|
|
|
public String getStringConstantForInstanceKey(InstanceKey I) {
|
|
return basic.getStringConstantForInstanceKey(I);
|
|
}
|
|
|
|
public InstanceKey getInstanceKeyForPEI(CGNode node, ProgramCounter instr, TypeReference type) {
|
|
return basic.getInstanceKeyForPEI(node, instr, type);
|
|
}
|
|
|
|
public InstanceKey getInstanceKeyForClassObject(TypeReference type) {
|
|
return basic.getInstanceKeyForClassObject(type);
|
|
}
|
|
|
|
public ScopeMappingInstanceKeys(
|
|
PropagationCallGraphBuilder builder,
|
|
InstanceKeyFactory basic)
|
|
{
|
|
this.basic = basic;
|
|
this.builder = builder;
|
|
}
|
|
}
|