use of com.jopdesign.common.type.MethodRef in project jop by jop-devel.
the class CallGraph method findImplementationContexts.
/**
* For a given non-empty callstring, find all implementations which might get called by the last
* invocation in the callstring, i.e. find all methods which might appear in the next entry of the
* callstring.
* <p>
* This is only a lookup in the callgraph, and does not check if the invocation is a special invoke,
* so if callstring length of the callgraph is zero, the results are not correct. Instead use
* {@link AppInfo#findImplementations(CallString)} which handles all special cases and falls back
* to the default callgraph.
* </p>
*
* @param cs callstring of the invocation, must contain at least one invokesite.
* @return a list of all methods which might get invoked by the top invocation of the callstring,
* with their callstrings.
*/
public Set<ExecutionContext> findImplementationContexts(CallString cs) {
if (cs.length() == 0) {
throw new AssertionError("findImplementationContexts: callstring must not be empty!");
}
InvokeSite invoke = cs.top();
Set<ExecutionContext> methods = new LinkedHashSet<ExecutionContext>();
MethodRef invokeeRef = invoke.getInvokeeRef();
// if the invoke is not virtual, should we look it up in the graph anyway?
// We could just return new ExecutionContext(invokee, cs);
// But that's what AppInfo#findImplementations() is for, here we only lookup the callgraph,
// but then we cannot have different callgraphs and perform precise lookups on all of them,
// since that method only looks into the default callgraph (but why would we want multiple
// graphs anyway?)
// find all instances of possible invokers
Set<ExecutionContext> invoker = getNodes(invoke.getInvoker());
for (ExecutionContext invokeNode : invoker) {
for (ContextEdge outEdge : callGraph.outgoingEdgesOf(invokeNode)) {
CallString cgString = outEdge.getTarget().getCallString();
// check if the target callstring matches the given callstring
if (cgString.isEmpty()) {
// target has no callstring, must at least override the invoked method
if (invokeeRef.isInterfaceMethod() == Ternary.TRUE) {
// check if the receiver implements the interface..
if (outEdge.getTarget().getMethodInfo().implementsMethod(invokeeRef)) {
methods.add(outEdge.getTarget());
}
} else {
if (outEdge.getTarget().getMethodInfo().overrides(invokeeRef, true)) {
methods.add(outEdge.getTarget());
}
}
} else {
// if one of the callstrings is a suffix of the other, this context is a possible invocation
if (cs.matches(cgString)) {
methods.add(outEdge.getTarget());
}
}
}
}
return methods;
}
use of com.jopdesign.common.type.MethodRef in project jop by jop-devel.
the class InvokeSite method canInvoke.
/**
* @param methodInfo a possible invokee
* @return true if this invokeSite may invoke the method. Does not use the callgraph to check.
* For interface invoke sites this can return UNKNOWN if the class of the given method implementation
* does not implement the referenced interface.
*/
public Ternary canInvoke(MethodInfo methodInfo) {
assert methodInfo != null;
MethodRef invokeeRef = getInvokeeRef();
MethodInfo method = invokeeRef.getMethodInfo();
if (methodInfo.equals(method)) {
return Ternary.TRUE;
}
if (!isVirtual()) {
// and therefore cannot be invoked
return Ternary.FALSE;
}
if (method == null) {
return Ternary.UNKNOWN;
}
if (!methodInfo.getClassInfo().isSubclassOf(invokeeRef.getClassInfo())) {
if (isInvokeInterface() && !methodInfo.getClassInfo().isInterface()) {
// check the signature..
if (!invokeeRef.getMethodSignature().equals(methodInfo.getMethodSignature())) {
return Ternary.FALSE;
}
return Ternary.UNKNOWN;
}
return Ternary.FALSE;
}
return Ternary.valueOf(methodInfo.overrides(method, true));
}
use of com.jopdesign.common.type.MethodRef in project jop by jop-devel.
the class UsedCodeFinder method visitReferences.
private void visitReferences(Set<String> refs) {
for (String id : refs) {
// The member IDs returned by the reference finder use a syntax which is
// always unique, so if in doubt, we need to interpret it as a classname, not a fieldname
MemberID sig = MemberID.parse(id, false);
// find/load the corresponding classInfo
ClassInfo cls = getClassInfo(sig);
// class has been excluded from loading, skip this class
if (cls == null) {
continue;
}
// referenced class is used, visit it if it has not yet been visited, but skip its class members
// Note that this class might be different than the class containing the class member
markUsedMembers(cls, false);
// check if this id specifies a class member (or just a class, in this case we are done)
if (sig.hasMethodSignature()) {
// It's a method! mark the method as used (implementations are marked later)
MethodRef ref = appInfo.getMethodRef(sig);
MethodInfo method = ref.getMethodInfo();
// we keep the declarations. We mark it without following it and make it abstract later.
if (method != null) {
setMark(method, false);
}
} else if (sig.hasMemberName()) {
// It's a field! No need to look in subclasses, fields are not virtual
FieldRef ref = appInfo.getFieldRef(sig);
FieldInfo field = ref.getFieldInfo();
if (field != null) {
markUsedMembers(field);
}
}
}
}
use of com.jopdesign.common.type.MethodRef in project jop by jop-devel.
the class RelinkInvokesuper method relinkInvokeSuper.
private void relinkInvokeSuper(InvokeSite is) {
// this already resolves to the correct method..
MethodRef invokee = is.getInvokeeRef();
MethodInfo target = invokee.getMethodInfo();
if (target == null) {
// .. or not (class or method excluded or unknown)
logger.warn("Cannot try to relink invokespecial to unknown super method " + invokee);
return;
}
// now simply relink instruction (no need to check if it changes)
int index = is.getInvoker().getClassInfo().addConstantInfo(new ConstantMethodInfo(invokee));
if (!(is.getInvokeInstruction() instanceof INVOKESPECIAL)) {
throw new JavaClassFormatError("Invokesuper is not an invokespecial instruction!");
}
is.getInvokeInstruction().setIndex(index);
}
Aggregations