263 lines
7.2 KiB
Java
263 lines
7.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.ipa.callgraph.propagation;
|
|
|
|
import java.util.Comparator;
|
|
|
|
import com.ibm.wala.classLoader.ArrayClass;
|
|
import com.ibm.wala.classLoader.IClass;
|
|
import com.ibm.wala.classLoader.IField;
|
|
import com.ibm.wala.ipa.callgraph.propagation.cfa.ExceptionReturnValueKey;
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.util.debug.Assertions;
|
|
|
|
public class PointerKeyComparator implements Comparator {
|
|
|
|
private final IClassHierarchy cha;
|
|
|
|
public PointerKeyComparator(IClassHierarchy cha) {
|
|
if (cha == null) {
|
|
throw new IllegalArgumentException("null cha");
|
|
}
|
|
this.cha = cha;
|
|
}
|
|
|
|
protected int comparePrimitives(TypeReference r1, TypeReference r2) {
|
|
int h1 = r1.hashCode();
|
|
int h2 = r2.hashCode();
|
|
if (h1 != h2)
|
|
return h1-h2;
|
|
else {
|
|
assert r1 == r2;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
protected int compareConcreteTypes(IClass k1, IClass k2) {
|
|
int n1 = cha.getNumber( k1 );
|
|
int n2 = cha.getNumber( k2 );
|
|
if (n1 != n2)
|
|
return n1-n2;
|
|
else {
|
|
int s1 = k1.hashCode();
|
|
int s2 = k2.hashCode();
|
|
assert k1 == k2 || s1 != s2;
|
|
return s1-s2;
|
|
}
|
|
}
|
|
|
|
protected int compareInstanceKeys(InstanceKey k1, InstanceKey k2) {
|
|
return compareConcreteTypes( k1.getConcreteType(), k2.getConcreteType() );
|
|
}
|
|
|
|
protected int compareFields(IField if1, IField if2) {
|
|
int f1 = if1.hashCode();
|
|
int f2 = if2.hashCode();
|
|
if (f1 != f2)
|
|
return f1-f2;
|
|
else {
|
|
assert if1 == if2;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
private int compareLocalKey(LocalPointerKey key1, Object key2) {
|
|
if (key2 instanceof LocalPointerKey) {
|
|
int l1 = key1.getValueNumber();
|
|
int l2 = ((LocalPointerKey)key2).getValueNumber();
|
|
if (l1 != l2)
|
|
return l1-l2;
|
|
else {
|
|
int n1 = key1.getNode().getGraphNodeId();
|
|
int n2 = ((LocalPointerKey)key2).getNode().getGraphNodeId();
|
|
if (n1 != n2)
|
|
return n1-n2;
|
|
else {
|
|
assert key1.equals(key2);
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
else return -1;
|
|
}
|
|
|
|
private int compareReturnValueKey(ReturnValueKey key1, Object key2) {
|
|
if (key2 instanceof ReturnValueKey) {
|
|
int n1 = key1.getNode().getGraphNodeId();
|
|
int n2 = ((ReturnValueKey)key2).getNode().getGraphNodeId();
|
|
if (n1 != n2)
|
|
return n1-n2;
|
|
else {
|
|
assert key1.equals(key2);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
else return -1;
|
|
}
|
|
|
|
private int compareExceptionKey(ExceptionReturnValueKey key1, Object key2) {
|
|
if (key2 instanceof ExceptionReturnValueKey) {
|
|
int n1 = key1.getNode().getGraphNodeId();
|
|
int n2 = ((ExceptionReturnValueKey)key2).getNode().getGraphNodeId();
|
|
if (n1 != n2)
|
|
return n1-n2;
|
|
else {
|
|
assert key1.equals(key2);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
else return -1;
|
|
}
|
|
|
|
private int compareFieldKey(InstanceFieldKey key1, Object key2) {
|
|
if (key2 instanceof InstanceFieldKey) {
|
|
int r1 = compareInstanceKeys(key1.getInstanceKey(), ((InstanceFieldKey)key2).getInstanceKey());
|
|
if (r1 != 0)
|
|
return r1;
|
|
else {
|
|
return compareFields(key1.getField(), ((InstanceFieldKey)key2).getField());
|
|
}
|
|
}
|
|
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
private int compareStaticKey(StaticFieldKey key1, Object key2) {
|
|
if (key2 instanceof StaticFieldKey) {
|
|
int n1 = cha.getNumber( key1.getField().getDeclaringClass() );
|
|
int n2 = cha.getNumber( ((StaticFieldKey)key2).getField().getDeclaringClass() );
|
|
if (n1 != n2)
|
|
return n1-n2;
|
|
else {
|
|
return compareFields(key1.getField(), ((StaticFieldKey)key2).getField());
|
|
}
|
|
}
|
|
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
private int compareArrayKey(ArrayContentsKey key1, Object key2) {
|
|
if (key2 instanceof ArrayContentsKey) {
|
|
ArrayClass k1 = (ArrayClass)key1.getInstanceKey().getConcreteType();
|
|
ArrayClass k2 = (ArrayClass)((ArrayContentsKey)key2).getInstanceKey().getConcreteType();
|
|
int d1 = k1.getDimensionality();
|
|
int d2 = k2.getDimensionality();
|
|
if (d1 != d2) {
|
|
return d1-d2;
|
|
} else if (k1.getInnermostElementClass() == null) {
|
|
if (k2.getInnermostElementClass() == null)
|
|
return
|
|
comparePrimitives(
|
|
k1.getReference().getInnermostElementType(),
|
|
k2.getReference().getInnermostElementType());
|
|
else
|
|
return -1;
|
|
} else if (k2.getInnermostElementClass() == null) {
|
|
return 1;
|
|
} else {
|
|
return
|
|
compareConcreteTypes(
|
|
k1.getInnermostElementClass(),
|
|
k2.getInnermostElementClass());
|
|
}
|
|
}
|
|
|
|
else
|
|
return -1;
|
|
}
|
|
|
|
@Override
|
|
public int compare(Object key1, Object key2) {
|
|
if (key1 == key2) return 0;
|
|
|
|
else if (key1 instanceof LocalPointerKey) {
|
|
return compareLocalKey((LocalPointerKey) key1, key2);
|
|
}
|
|
|
|
else if (key2 instanceof LocalPointerKey) {
|
|
return -1*compareLocalKey((LocalPointerKey) key2, key1);
|
|
}
|
|
|
|
// at this point, neither key is local
|
|
else if (key1 instanceof ReturnValueKey) {
|
|
return compareReturnValueKey((ReturnValueKey)key1, key2);
|
|
}
|
|
|
|
else if (key2 instanceof ReturnValueKey) {
|
|
return -1*compareReturnValueKey((ReturnValueKey)key2, key1);
|
|
}
|
|
|
|
// at this point, neither key is local or retval
|
|
else if (key1 instanceof ExceptionReturnValueKey) {
|
|
return compareExceptionKey((ExceptionReturnValueKey)key1, key2);
|
|
}
|
|
|
|
else if (key2 instanceof ExceptionReturnValueKey) {
|
|
return -1*compareExceptionKey((ExceptionReturnValueKey)key2, key1);
|
|
}
|
|
|
|
// at this point, neither key is local or retval, expretval
|
|
else if (key1 instanceof InstanceFieldKey) {
|
|
return compareFieldKey((InstanceFieldKey)key1, key2);
|
|
}
|
|
|
|
else if (key2 instanceof InstanceFieldKey) {
|
|
return -1*compareFieldKey((InstanceFieldKey)key2, key1);
|
|
}
|
|
|
|
// at this point, neither key is local or retval, expretval, field
|
|
else if (key1 instanceof StaticFieldKey) {
|
|
return compareStaticKey((StaticFieldKey)key1, key2);
|
|
}
|
|
|
|
else if (key2 instanceof StaticFieldKey) {
|
|
return -1*compareStaticKey((StaticFieldKey)key2, key1);
|
|
}
|
|
|
|
// at this point, neither key is local or retval, expretval, field, static
|
|
else if (key1 instanceof ArrayContentsKey) {
|
|
return compareArrayKey((ArrayContentsKey)key1, key2);
|
|
}
|
|
|
|
else if (key2 instanceof ArrayContentsKey) {
|
|
return -1*compareArrayKey((ArrayContentsKey)key2, key1);
|
|
}
|
|
|
|
else {
|
|
return compareOtherKeys(key1, key2);
|
|
}
|
|
}
|
|
|
|
protected int compareOtherKeys(Object key1, Object key2) {
|
|
System.err.println("Cannot compare " + key1 + " and " + key2);
|
|
Assertions.UNREACHABLE();
|
|
return 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
return (o instanceof PointerKeyComparator) &&
|
|
((PointerKeyComparator)o).cha.equals(cha);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return cha.hashCode();
|
|
}
|
|
|
|
}
|