209 lines
4.7 KiB
Java
209 lines
4.7 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.summaries;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.Map;
|
|
|
|
import com.ibm.wala.ssa.ConstantValue;
|
|
import com.ibm.wala.ssa.SSAInstruction;
|
|
import com.ibm.wala.types.MemberReference;
|
|
import com.ibm.wala.types.MethodReference;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.util.collections.HashMapFactory;
|
|
import com.ibm.wala.util.warnings.Warning;
|
|
|
|
/**
|
|
* Summary information for a method.
|
|
*/
|
|
public class MethodSummary {
|
|
|
|
protected final static SSAInstruction[] NO_STATEMENTS = new SSAInstruction[0];
|
|
|
|
/**
|
|
* The method summarized
|
|
*/
|
|
final private MethodReference method;
|
|
|
|
/**
|
|
* List of statements that define this method summary
|
|
*/
|
|
private ArrayList<SSAInstruction> statements;
|
|
|
|
/**
|
|
* Map: value number -> constant
|
|
*/
|
|
private Map<Integer, ConstantValue> constantValues;
|
|
|
|
/**
|
|
* The next available program counter value.
|
|
*/
|
|
private int nextProgramCounter = 0;
|
|
|
|
/**
|
|
* Some reason this method summary indicates a problem.
|
|
*/
|
|
private String poison;
|
|
|
|
/**
|
|
* An indication of how severe the poison problem is.
|
|
*/
|
|
private byte poisonLevel;
|
|
|
|
/**
|
|
* Is this a static method?
|
|
*/
|
|
private boolean isStatic = false;
|
|
|
|
/**
|
|
* Is this a "factory" method?
|
|
*/
|
|
private boolean isFactory = false;
|
|
|
|
public MethodSummary(MethodReference method) {
|
|
if (method == null) {
|
|
throw new IllegalArgumentException("null method");
|
|
}
|
|
this.method = method;
|
|
}
|
|
|
|
public int getNumberOfStatements() {
|
|
return (statements == null ? 0 : statements.size());
|
|
}
|
|
|
|
public void addStatement(SSAInstruction statement) {
|
|
if (statements == null) {
|
|
statements = new ArrayList<>();
|
|
}
|
|
statements.add(statement);
|
|
}
|
|
|
|
public void addConstant(Integer vn, ConstantValue value) {
|
|
if (constantValues == null)
|
|
constantValues = HashMapFactory.make(5);
|
|
constantValues.put(vn, value);
|
|
}
|
|
|
|
/**
|
|
* Returns the method.
|
|
*
|
|
* @return MethodReference
|
|
*/
|
|
public MemberReference getMethod() {
|
|
return method;
|
|
}
|
|
|
|
public boolean isNative() {
|
|
// TODO implement this.
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param reason
|
|
*/
|
|
public void addPoison(String reason) {
|
|
this.poison = reason;
|
|
}
|
|
|
|
public boolean hasPoison() {
|
|
return poison != null;
|
|
}
|
|
|
|
public String getPoison() {
|
|
return poison;
|
|
}
|
|
|
|
public void setPoisonLevel(byte b) {
|
|
poisonLevel = b;
|
|
assert b == Warning.MILD || b == Warning.MODERATE || b == Warning.SEVERE;
|
|
}
|
|
|
|
public byte getPoisonLevel() {
|
|
return poisonLevel;
|
|
}
|
|
|
|
public SSAInstruction[] getStatements() {
|
|
if (statements == null) {
|
|
return NO_STATEMENTS;
|
|
} else {
|
|
SSAInstruction[] result = new SSAInstruction[statements.size()];
|
|
Iterator<SSAInstruction> it = statements.iterator();
|
|
for (int i = 0; i < result.length; i++) {
|
|
result[i] = it.next();
|
|
}
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public Map<Integer, ConstantValue> getConstants() {
|
|
return constantValues;
|
|
}
|
|
|
|
/**
|
|
* @return the number of parameters, including the implicit 'this'
|
|
*/
|
|
public int getNumberOfParameters() {
|
|
return (isStatic()) ? method.getNumberOfParameters() : method.getNumberOfParameters() + 1;
|
|
}
|
|
|
|
public boolean isStatic() {
|
|
return isStatic;
|
|
}
|
|
|
|
public void setStatic(boolean b) {
|
|
isStatic = b;
|
|
}
|
|
|
|
public TypeReference getReturnType() {
|
|
return method.getReturnType();
|
|
}
|
|
|
|
@Override
|
|
public String toString() {
|
|
return "[Summary: " + method + "]";
|
|
}
|
|
|
|
/**
|
|
* Note that by convention, getParameterType(0) == this for non-static methods.
|
|
*/
|
|
public TypeReference getParameterType(int i) {
|
|
if (isStatic()) {
|
|
return method.getParameterType(i);
|
|
} else {
|
|
if (i == 0) {
|
|
return method.getDeclaringClass();
|
|
} else {
|
|
return method.getParameterType(i - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
public int getNextProgramCounter() {
|
|
return nextProgramCounter++;
|
|
}
|
|
|
|
/**
|
|
* Record if this is a "factory" method; meaning it returns some object which we know little about ... usually we'll resolve this
|
|
* based on downstream uses of the object
|
|
*
|
|
* @param b
|
|
*/
|
|
public void setFactory(boolean b) {
|
|
this.isFactory = b;
|
|
}
|
|
|
|
public boolean isFactory() {
|
|
return isFactory;
|
|
}
|
|
|
|
}
|