Skip to content

Commit

Permalink
Different attempt to fix #93 and to remove extra entries
Browse files Browse the repository at this point in the history
  • Loading branch information
circlespainter committed Jun 15, 2015
1 parent c52ba8e commit 117011b
Showing 1 changed file with 41 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -511,34 +511,13 @@ private void walkGraph() {

while (!q.isEmpty()) {
final MethodNode m = q.poll();
if (m.inProject) {
followBridges(q, getClassNode(m), m);
if (m.inProject)
followSupers(q, getClassNode(m), m);
}
followNonOverriddenSubs(q, getClassNode(m), m);
followCallers(q, m);
}
}

private void followBridges(Queue<MethodNode> q, ClassNode cls, MethodNode method) {
log("followBridges " + method + " " + cls, Project.MSG_DEBUG);
if (cls == null)
return;

if (method.suspendType == SuspendableType.NON_SUSPENDABLE)
return;
final List<String> bridges = cls.getMethodWithDifferentReturn(method.name);
for (String m1 : bridges) {
if (!method.name.equals(m1)) {
MethodNode m = getOrCreateMethodNode(cls.name + '.' + m1);
if (m.suspendType != SuspendableType.SUSPENDABLE && m.suspendType != SuspendableType.SUSPENDABLE_SUPER) {
m.setSuspendType(SuspendableType.SUSPENDABLE_SUPER);
q.add(m);
}
}
}
}

private boolean followSupers(Queue<MethodNode> q, ClassNode cls, MethodNode method) {
log("followSupers " + method + " " + cls, Project.MSG_DEBUG);
if (cls == null)
Expand All @@ -549,14 +528,20 @@ private boolean followSupers(Queue<MethodNode> q, ClassNode cls, MethodNode meth

boolean foundMethod = false;

if (cls.hasMethod(method.name) && method.classNode != cls) {
final MethodNode m1 = methods.get((cls.name + '.' + method.name).intern());
if (m1 != null && m1.suspendType == SuspendableType.NON_SUSPENDABLE)
String clsMethodDesc = cls.findMethodBySignature(method.nameAndSignature);
if (clsMethodDesc != null && method.classNode != cls) {
final MethodNode m1 = methods.get((cls.name + '.' + method.nameAndSignature).intern());
if (m1 != null && m1.suspendType == SuspendableType.NON_SUSPENDABLE) // Already explored, not suspendable
return false;
if (m1 == null || m1.suspendType == null) {
log("Found parent of suspendable method: " + method.owner + '.' + method.name + " in " + cls.name
if (m1 == null || m1.suspendType == null) { // Not explored before, found first here
log("Found parent " + clsMethodDesc + " of suspendable method: " + method.owner + '.' + method.nameAndDesc + " in " + cls.name
+ (cls.inProject ? "" : " NOT IN PROJECT"), cls.inProject ? Project.MSG_VERBOSE : Project.MSG_WARN);

foundMethod = true;

MethodNode m = getOrCreateMethodNode(cls.name + '.' + clsMethodDesc);
m.setSuspendType(SuspendableType.SUSPENDABLE_SUPER);
q.add(m);
}
}

Expand All @@ -566,18 +551,10 @@ private boolean followSupers(Queue<MethodNode> q, ClassNode cls, MethodNode meth
methodInParent |= followSupers(q, fill(s), method);

if (!foundMethod && methodInParent)
log("Found parent of suspendable method in a parent of: " + method.owner + '.' + method.name + " in " + cls.name
log("Found parent of suspendable method in a parent of: " + method.owner + '.' + method.nameAndDesc + " in " + cls.name
+ (cls.inProject ? "" : " NOT IN PROJECT"), cls.inProject ? Project.MSG_VERBOSE : Project.MSG_WARN);

final boolean res = foundMethod | methodInParent;
if (res) {
MethodNode m = getOrCreateMethodNode(cls.name + '.' + method.name);
if (m.suspendType != SuspendableType.SUSPENDABLE && m.suspendType != SuspendableType.SUSPENDABLE_SUPER) {
m.setSuspendType(SuspendableType.SUSPENDABLE_SUPER);
q.add(m);
}
}
return res;
return foundMethod | methodInParent;
}

private void followNonOverriddenSubs(Queue<MethodNode> q, ClassNode cls, MethodNode method) {
Expand All @@ -590,8 +567,8 @@ private void followNonOverriddenSubs(Queue<MethodNode> q, ClassNode cls, MethodN

if (cls.subs != null) {
for (ClassNode s : cls.subs) {
if (s != null && !s.hasMethod(method.name) && s.inProject) {
MethodNode sm = getOrCreateMethodNode(s.name + '.' + method.name);
if (s != null && s.findMethodBySignature(method.nameAndSignature) == null && s.inProject) {
MethodNode sm = getOrCreateMethodNode(s.name + '.' + method.nameAndDesc);
sm.inProject = true;
sm.refersToSuper = true;
if (sm.inProject && sm.suspendType == null) {
Expand Down Expand Up @@ -629,7 +606,7 @@ else if (method.suspendType == SuspendableType.SUSPENDABLE_SUPER && !method.refe
}

private static String output(MethodNode method) {
return method.owner.replace('/', '.') + '.' + method.name;
return method.owner.replace('/', '.') + '.' + method.nameAndDesc;
}

private static void outputResults(String outputFile, boolean append, Collection<String> results) throws Exception {
Expand All @@ -639,16 +616,21 @@ private static void outputResults(String outputFile, boolean append, Collection<
}
}

private MethodNode getOrCreateMethodNode(String methodName) {
methodName = methodName.intern();
MethodNode entry = methods.get(methodName);
private MethodNode getOrCreateMethodNode(String fullMethodDesc) {
fullMethodDesc = fullMethodDesc.intern();
final String fullMethodSignature = getSignature(fullMethodDesc);
MethodNode entry = methods.get(fullMethodSignature);
if (entry == null) {
entry = new MethodNode(getClassName(methodName), getMethodWithDesc(methodName));
methods.put(methodName, entry);
entry = new MethodNode(getClassName(fullMethodSignature), getMethod(fullMethodSignature), getMethod(fullMethodDesc));
methods.put(fullMethodSignature, entry);
}
return entry;
}

private static String getSignature(String methodName) {
return methodName.substring(0, methodName.lastIndexOf(')') + 1).intern();
}

private ClassNode getOrCreateClassNode(String className) {
className = className.intern();
ClassNode node = classes.get(className);
Expand Down Expand Up @@ -722,22 +704,12 @@ void setMethods(Collection<String> ms) {
methods[i] = methods[i].intern();
}

boolean hasMethod(String method) {
String findMethodBySignature(String nameAndSignature) {
for (String m : methods) {
if (method.equals(m))
return true;
if (m.startsWith(nameAndSignature))
return m;
}
return false;
}

List<String> getMethodWithDifferentReturn(String method) {
method = getMethodWithoutReturn(method);
List<String> ms = new ArrayList<>();
for (String m : methods) {
if (m.startsWith(method))
ms.add(m);
}
return ms;
return null;
}

@Override
Expand All @@ -758,7 +730,7 @@ private void addSub(ClassNode cn) {
private static class MethodNode {
String owner;
ClassNode classNode;
final String name; // methodname+desc
final String nameAndSignature; // methodname+signature
//int acc;
boolean inProject;
boolean known;
Expand All @@ -767,10 +739,12 @@ private static class MethodNode {
boolean setBySuper;
private MethodNode[] callers;
private int numCallers;
private final String nameAndDesc;

public MethodNode(String owner, String nameAndDesc) {
public MethodNode(String owner, String nameAndSignature, String nameAndDesc) {
this.owner = owner.intern();
this.name = nameAndDesc.intern();
this.nameAndSignature = nameAndSignature.intern();
this.nameAndDesc = nameAndDesc.intern();
}

public void addCaller(MethodNode caller) {
Expand Down Expand Up @@ -813,7 +787,7 @@ public void remove() {

@Override
public String toString() {
return "MethodNode{" + owner + '.' + name + " inProject: " + inProject + " suspendType: " + suspendType + '}';
return "MethodNode{" + owner + '.' + nameAndDesc + " inProject: " + inProject + " suspendType: " + suspendType + '}';
}

public void setSuspendType(SuspendableType suspendType) {
Expand All @@ -826,17 +800,12 @@ public void setSuspendType(SuspendableType suspendType) {
}
}

private static String getClassName(String fullMethodWithDesc) {
return fullMethodWithDesc.substring(0, fullMethodWithDesc.lastIndexOf('.'));
}

private static String getMethodWithDesc(String fullMethodWithDesc) {
return fullMethodWithDesc.substring(fullMethodWithDesc.lastIndexOf('.') + 1);
private static String getClassName(String fullMethod) {
return fullMethod.substring(0, fullMethod.lastIndexOf('.'));
}

private static String getMethodWithoutReturn(String fullMethodWithDesc) {
String m = getMethodWithDesc(fullMethodWithDesc);
return m.substring(0, m.lastIndexOf(')') + 1);
private static String getMethod(String fullMethod) {
return fullMethod.substring(fullMethod.lastIndexOf('.') + 1);
}

private static boolean isReflectInvocation(String className, String methodName) {
Expand Down

0 comments on commit 117011b

Please sign in to comment.