356 lines
9.2 KiB
Java
356 lines
9.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.loader;
|
|
|
|
import java.util.Collection;
|
|
import java.util.Map;
|
|
|
|
import com.ibm.wala.cast.ir.translator.AstTranslator;
|
|
import com.ibm.wala.cast.ir.translator.AstTranslator.AstLexicalInformation;
|
|
import com.ibm.wala.cast.tree.CAstEntity;
|
|
import com.ibm.wala.cast.tree.CAstQualifier;
|
|
import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position;
|
|
import com.ibm.wala.cfg.AbstractCFG;
|
|
import com.ibm.wala.cfg.ControlFlowGraph;
|
|
import com.ibm.wala.cfg.IBasicBlock;
|
|
import com.ibm.wala.classLoader.IClass;
|
|
import com.ibm.wala.classLoader.IMethod;
|
|
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
|
import com.ibm.wala.ssa.SSAInstruction;
|
|
import com.ibm.wala.ssa.SymbolTable;
|
|
import com.ibm.wala.types.Descriptor;
|
|
import com.ibm.wala.types.MethodReference;
|
|
import com.ibm.wala.types.Selector;
|
|
import com.ibm.wala.types.TypeReference;
|
|
import com.ibm.wala.types.annotations.Annotation;
|
|
import com.ibm.wala.util.collections.Pair;
|
|
import com.ibm.wala.util.intset.IntSet;
|
|
import com.ibm.wala.util.strings.Atom;
|
|
|
|
public abstract class AstMethod implements IMethod {
|
|
|
|
public interface Retranslatable {
|
|
void retranslate(AstTranslator xlator);
|
|
CAstEntity getEntity();
|
|
}
|
|
|
|
public interface DebuggingInformation {
|
|
|
|
Position getCodeBodyPosition();
|
|
|
|
Position getInstructionPosition(int instructionOffset);
|
|
|
|
String[][] getSourceNamesForValues();
|
|
|
|
Position getOperandPosition(int instructionOffset, int operand);
|
|
|
|
Position getParameterPosition(int param);
|
|
|
|
}
|
|
|
|
/**
|
|
* lexical access information for some entity scope. used during call graph
|
|
* construction to handle lexical accesses.
|
|
*/
|
|
public interface LexicalInformation {
|
|
|
|
/**
|
|
* names possibly accessed in a nested lexical scope, represented as pairs
|
|
* (name,nameOfDefiningEntity)
|
|
*/
|
|
public Pair<String, String>[] getExposedNames();
|
|
|
|
/**
|
|
* maps each exposed name (via its index in {@link #getExposedNames()}) to
|
|
* its value number at method exit.
|
|
*/
|
|
public int[] getExitExposedUses();
|
|
|
|
/**
|
|
* get a map from exposed name (via its index in {@link #getExposedNames()})
|
|
* to its value number at the instruction at offset instructionOffset.
|
|
*/
|
|
public int[] getExposedUses(int instructionOffset);
|
|
|
|
/**
|
|
* return all value numbers appearing as entries in either
|
|
* {@link #getExposedUses(int)} or {@link #getExitExposedUses()}
|
|
*/
|
|
public IntSet getAllExposedUses();
|
|
|
|
/**
|
|
* return the names of the enclosing methods declaring names that are
|
|
* lexically accessed by the entity
|
|
*/
|
|
public String[] getScopingParents();
|
|
|
|
/**
|
|
* returns true if name may be read in nested lexical scopes but cannot be
|
|
* written
|
|
*/
|
|
public boolean isReadOnly(String name);
|
|
|
|
/**
|
|
* get the name of this entity, as it appears in the definer portion of a
|
|
* lexical name
|
|
*/
|
|
public String getScopingName();
|
|
|
|
}
|
|
|
|
protected final IClass cls;
|
|
private final Collection<CAstQualifier> qualifiers;
|
|
private final AbstractCFG<?, ?> cfg;
|
|
private final SymbolTable symtab;
|
|
private final MethodReference ref;
|
|
private final boolean hasCatchBlock;
|
|
private final boolean hasMonitorOp;
|
|
private final Map<IBasicBlock<SSAInstruction>, TypeReference[]> catchTypes;
|
|
private final AstLexicalInformation lexicalInfo;
|
|
private final DebuggingInformation debugInfo;
|
|
private final Collection<Annotation> annotations;
|
|
|
|
protected AstMethod(IClass cls, Collection<CAstQualifier> qualifiers, AbstractCFG<?, ?> cfg, SymbolTable symtab, MethodReference ref,
|
|
boolean hasCatchBlock, Map<IBasicBlock<SSAInstruction>, TypeReference[]> caughtTypes, boolean hasMonitorOp, AstLexicalInformation lexicalInfo,
|
|
DebuggingInformation debugInfo, Collection<Annotation> annotations) {
|
|
this.cls = cls;
|
|
this.cfg = cfg;
|
|
this.ref = ref;
|
|
this.symtab = symtab;
|
|
this.qualifiers = qualifiers;
|
|
this.catchTypes = caughtTypes;
|
|
this.hasCatchBlock = hasCatchBlock;
|
|
this.hasMonitorOp = hasMonitorOp;
|
|
this.lexicalInfo = lexicalInfo;
|
|
this.debugInfo = debugInfo;
|
|
this.annotations = annotations;
|
|
}
|
|
|
|
protected AstMethod(IClass cls, Collection<CAstQualifier> qualifiers, MethodReference ref, Collection<Annotation> annotations) {
|
|
this.cls = cls;
|
|
this.qualifiers = qualifiers;
|
|
this.ref = ref;
|
|
this.annotations = annotations;
|
|
|
|
this.cfg = null;
|
|
this.symtab = null;
|
|
this.catchTypes = null;
|
|
this.hasCatchBlock = false;
|
|
this.hasMonitorOp = false;
|
|
this.lexicalInfo = null;
|
|
this.debugInfo = null;
|
|
|
|
assert isAbstract();
|
|
}
|
|
|
|
public AbstractCFG<?, ?> cfg() {
|
|
return cfg;
|
|
}
|
|
|
|
public boolean hasCatchBlock() {
|
|
return hasCatchBlock();
|
|
}
|
|
|
|
public SymbolTable symbolTable() {
|
|
return symtab;
|
|
}
|
|
|
|
public Map<IBasicBlock<SSAInstruction>, TypeReference[]> catchTypes() {
|
|
return catchTypes;
|
|
}
|
|
|
|
public LexicalInformation cloneLexicalInfo() {
|
|
return new AstLexicalInformation(lexicalInfo);
|
|
}
|
|
|
|
public LexicalInformation lexicalInfo() {
|
|
return lexicalInfo;
|
|
}
|
|
|
|
public DebuggingInformation debugInfo() {
|
|
return debugInfo;
|
|
}
|
|
|
|
@Override
|
|
public Collection<Annotation> getAnnotations() {
|
|
return annotations;
|
|
}
|
|
|
|
/**
|
|
* Parents of this method with respect to lexical scoping, that is, methods
|
|
* containing state possibly referenced lexically in this method
|
|
*/
|
|
public static abstract class LexicalParent {
|
|
public abstract String getName();
|
|
|
|
public abstract AstMethod getMethod();
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return getName().hashCode() * getMethod().hashCode();
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
return (o instanceof LexicalParent) && getName().equals(((LexicalParent) o).getName())
|
|
&& getMethod().equals(((LexicalParent) o).getMethod());
|
|
}
|
|
}
|
|
|
|
public abstract LexicalParent[] getParents();
|
|
|
|
@Override
|
|
public IClass getDeclaringClass() {
|
|
return cls;
|
|
}
|
|
|
|
@Override
|
|
public String getSignature() {
|
|
return ref.getSignature();
|
|
}
|
|
|
|
@Override
|
|
public Selector getSelector() {
|
|
return ref.getSelector();
|
|
}
|
|
|
|
@Override
|
|
public boolean isClinit() {
|
|
return getSelector().equals(MethodReference.clinitSelector);
|
|
}
|
|
|
|
@Override
|
|
public boolean isInit() {
|
|
return getSelector().getName().equals(MethodReference.initAtom);
|
|
}
|
|
|
|
@Override
|
|
public Atom getName() {
|
|
return ref.getName();
|
|
}
|
|
|
|
@Override
|
|
public Descriptor getDescriptor() {
|
|
return ref.getDescriptor();
|
|
}
|
|
|
|
@Override
|
|
public MethodReference getReference() {
|
|
return ref;
|
|
}
|
|
|
|
@Override
|
|
public TypeReference getReturnType() {
|
|
return ref.getReturnType();
|
|
}
|
|
|
|
@Override
|
|
public boolean isStatic() {
|
|
return qualifiers.contains(CAstQualifier.STATIC);
|
|
}
|
|
|
|
@Override
|
|
public boolean isSynchronized() {
|
|
return qualifiers.contains(CAstQualifier.SYNCHRONIZED);
|
|
}
|
|
|
|
@Override
|
|
public boolean isNative() {
|
|
return qualifiers.contains(CAstQualifier.NATIVE);
|
|
}
|
|
|
|
@Override
|
|
public boolean isSynthetic() {
|
|
return false;
|
|
}
|
|
|
|
@Override
|
|
public boolean isAbstract() {
|
|
return qualifiers.contains(CAstQualifier.ABSTRACT);
|
|
}
|
|
|
|
@Override
|
|
public boolean isPrivate() {
|
|
return qualifiers.contains(CAstQualifier.PRIVATE);
|
|
}
|
|
|
|
@Override
|
|
public boolean isProtected() {
|
|
return qualifiers.contains(CAstQualifier.PROTECTED);
|
|
}
|
|
|
|
@Override
|
|
public boolean isPublic() {
|
|
return qualifiers.contains(CAstQualifier.PUBLIC);
|
|
}
|
|
|
|
@Override
|
|
public boolean isFinal() {
|
|
return qualifiers.contains(CAstQualifier.FINAL);
|
|
}
|
|
|
|
@Override
|
|
public boolean isBridge() {
|
|
return qualifiers.contains(CAstQualifier.VOLATILE);
|
|
}
|
|
|
|
public ControlFlowGraph<?, ?> getControlFlowGraph() {
|
|
return cfg;
|
|
}
|
|
|
|
@Override
|
|
public boolean hasExceptionHandler() {
|
|
return hasCatchBlock;
|
|
}
|
|
|
|
public boolean hasMonitorOp() {
|
|
return hasMonitorOp;
|
|
}
|
|
|
|
@Override
|
|
public int getNumberOfParameters() {
|
|
return symtab.getParameterValueNumbers().length;
|
|
}
|
|
/** BEGIN Custom change: precise bytecode positions */
|
|
|
|
/*
|
|
* @see com.ibm.wala.classLoader.IMethod#getParameterSourcePosition(int)
|
|
*/
|
|
@Override
|
|
public SourcePosition getParameterSourcePosition(int paramNum) throws InvalidClassFileException {
|
|
return null;
|
|
}
|
|
/** END Custom change: precise bytecode positions */
|
|
|
|
@Override
|
|
public int getLineNumber(int instructionIndex) {
|
|
Position pos = debugInfo.getInstructionPosition(instructionIndex);
|
|
if (pos == null) {
|
|
return -1;
|
|
} else {
|
|
return pos.getFirstLine();
|
|
}
|
|
}
|
|
|
|
public Position getSourcePosition() {
|
|
return debugInfo.getCodeBodyPosition();
|
|
}
|
|
|
|
public Position getParameterPosition(int paramIndex) {
|
|
return debugInfo.getParameterPosition(paramIndex);
|
|
}
|
|
|
|
@Override
|
|
public Position getSourcePosition(int instructionIndex) {
|
|
return debugInfo.getInstructionPosition(instructionIndex);
|
|
}
|
|
}
|