Skip to content

Commit

Permalink
Added linkage sort order to predictably handle ambiguous linkage case…
Browse files Browse the repository at this point in the history
…s introduced by automatic proxying.
  • Loading branch information
danielperano committed Apr 17, 2024
1 parent c38aac5 commit ca9eb00
Showing 1 changed file with 39 additions and 1 deletion.
40 changes: 39 additions & 1 deletion Lang/src/main/java/chipmunk/vm/invoke/ChipmunkLinker.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,42 @@ public GuardedInvocation resolveCallTarget(MethodHandles.Lookup lookup, Object r
return null;
}

public static void linkOrder(Method[] methods){
Arrays.sort(methods, (m1, m2) -> {
// Favor shorter parameter lists first
if(m1.getParameterCount() < m2.getParameterCount()){
return -1;
}

// Favor simple types over interfaces (which will be proxied to). This
// ensures that interface linkage only happens if a more appropriate linkage
// is not found first. This is important because without type information,
// interface receiver types will match with any parameter, resulting in some
// cases where interface proxying happens when a different method is available
// with an identical type match. Worse, these scenarios are unpredictable since
// the order of methods returned by Object.getMethods() is not specified.
if(m1.getParameterCount() == m2.getParameterCount()){
var p1Types = m1.getParameterTypes();
var p2Types = m2.getParameterTypes();
int m1Weight = 0;
for(int i = 0; i < p1Types.length; i++){
var p1IsInterface = p1Types[i].isInterface();
var p2IsInterface = p2Types[i].isInterface();

if(p1IsInterface && !p2IsInterface){
m1Weight++;
}else if(!p1IsInterface && p2IsInterface){
m1Weight--;
}
}
return m1Weight;
}

// At this point we know m2 has a shorter parameter list
return 1;
});
}

public MethodHandle getMethod(Object receiver, Class<?> expectedReturnType, String methodName, Object[] params, Class<?>[] pTypes, boolean enforceLinkagePolicy) throws IllegalAccessException, NoSuchMethodException {

Class<?> receiverType;
Expand All @@ -230,7 +266,9 @@ public MethodHandle getMethod(Object receiver, Class<?> expectedReturnType, Stri
receiverType = receiver.getClass();
}

for (Method m : receiverType.getMethods()) {
var methods = receiverType.getMethods();
linkOrder(methods);
for (Method m : methods) {
Class<?>[] candidatePTypes = m.getParameterTypes();

if (candidatePTypes.length != pTypes.length - 1 && !m.isVarArgs()) {
Expand Down

0 comments on commit ca9eb00

Please sign in to comment.