This is an automated email from the ASF dual-hosted git repository.

blackdrag pushed a commit to branch feature/GROOVY-8299/default_methods
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to 
refs/heads/feature/GROOVY-8299/default_methods by this push:
     new 0817795573 GRPPVY-8299: implement dynamic path for default interface 
methods
0817795573 is described below

commit 08177955736e9ed0952be3f2343b87e370dec346
Author: Jochen Theodorou <blackd...@gmx.org>
AuthorDate: Fri Sep 29 21:51:08 2023 +0200

    GRPPVY-8299: implement dynamic path for default interface methods
---
 .../classgen/asm/indy/InvokeDynamicWriter.java     | 22 ++++++-
 .../codehaus/groovy/vmplugin/v7/IndyInterface.java |  6 +-
 .../groovy/vmplugin/v8/CacheableCallSite.java      |  9 ++-
 .../codehaus/groovy/vmplugin/v8/IndyInterface.java | 41 +++++++-----
 .../org/codehaus/groovy/vmplugin/v8/Selector.java  | 74 +++++++++++++---------
 5 files changed, 103 insertions(+), 49 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
index 74aee3209d..041b177c3a 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/indy/InvokeDynamicWriter.java
@@ -25,6 +25,7 @@ import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
 import org.codehaus.groovy.ast.expr.EmptyExpression;
 import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.PropertyExpression;
 import org.codehaus.groovy.ast.tools.WideningCategories;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
 import org.codehaus.groovy.classgen.asm.CompileStack;
@@ -35,6 +36,7 @@ import org.codehaus.groovy.classgen.asm.WriterController;
 import org.codehaus.groovy.runtime.wrappers.Wrapper;
 import org.codehaus.groovy.vmplugin.v8.IndyInterface;
 import org.objectweb.asm.Handle;
+import org.objectweb.asm.Opcodes;
 
 import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandles.Lookup;
@@ -47,6 +49,7 @@ import static 
org.codehaus.groovy.ast.ClassHelper.boolean_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.getWrapper;
 import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveBoolean;
 import static org.codehaus.groovy.ast.ClassHelper.isWrapperBoolean;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.bytecodeX;
 import static org.codehaus.groovy.classgen.asm.BytecodeHelper.doCast;
 import static 
org.codehaus.groovy.classgen.asm.BytecodeHelper.getTypeDescription;
 import static org.codehaus.groovy.vmplugin.v8.IndyInterface.GROOVY_OBJECT;
@@ -57,6 +60,7 @@ import static 
org.codehaus.groovy.vmplugin.v8.IndyInterface.THIS_CALL;
 import static org.codehaus.groovy.vmplugin.v8.IndyInterface.CallType.CAST;
 import static org.codehaus.groovy.vmplugin.v8.IndyInterface.CallType.GET;
 import static org.codehaus.groovy.vmplugin.v8.IndyInterface.CallType.INIT;
+import static org.codehaus.groovy.vmplugin.v8.IndyInterface.CallType.INTERFACE;
 import static org.codehaus.groovy.vmplugin.v8.IndyInterface.CallType.METHOD;
 import static org.objectweb.asm.Opcodes.H_INVOKESTATIC;
 
@@ -122,9 +126,10 @@ public class InvokeDynamicWriter extends InvocationWriter {
         compileStack.popLHS();
     }
 
-    private void makeIndyCall(final MethodCallerMultiAdapter adapter, final 
Expression receiver, final boolean implicitThis, final boolean safe, final 
String methodName, final Expression arguments) {
+    private void makeIndyCall(final MethodCallerMultiAdapter adapter, final 
Expression origReceiver, final boolean implicitThis, final boolean safe, final 
String methodName, final Expression arguments) {
         OperandStack operandStack = controller.getOperandStack();
 
+        Expression receiver = correctReceiverForInterfaceCall(origReceiver, 
operandStack);
         StringBuilder sig = new StringBuilder(prepareIndyCall(receiver, 
implicitThis));
 
         // load arguments
@@ -150,12 +155,27 @@ public class InvokeDynamicWriter extends InvocationWriter 
{
         }
 
         sig.append(")Ljava/lang/Object;");
+
         String callSiteName = METHOD.getCallSiteName();
         if (adapter == null) callSiteName = INIT.getCallSiteName();
+        // receiver != origReceiver interface default method call
+        if (receiver != origReceiver) callSiteName = 
INTERFACE.getCallSiteName();
+
         int flags = getMethodCallFlags(adapter, safe, 
containsSpreadExpression);
+
         finishIndyCall(BSM, callSiteName, sig.toString(), numberOfArguments, 
methodName, flags);
     }
 
+    private Expression correctReceiverForInterfaceCall(Expression exp, 
OperandStack operandStack) {
+        if (exp instanceof PropertyExpression) {
+            PropertyExpression pexp = (PropertyExpression) exp;
+            if (pexp.getObjectExpression() instanceof ClassExpression && 
"super".equals(pexp.getPropertyAsString())) {
+                return bytecodeX(pexp.getObjectExpression().getType(), mv -> 
mv.visitIntInsn(Opcodes.ALOAD, 0));
+            }
+        }
+        return exp;
+    }
+
     private static int getMethodCallFlags(final MethodCallerMultiAdapter 
adapter, final boolean safe, final boolean spread) {
         int flags = 0;
         if (safe)                           flags |= SAFE_NAVIGATION;
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyInterface.java 
b/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyInterface.java
index 2583aeaf68..57e8da6e18 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyInterface.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v7/IndyInterface.java
@@ -18,6 +18,8 @@
  */
 package org.codehaus.groovy.vmplugin.v7;
 
+import org.codehaus.groovy.vmplugin.v8.CacheableCallSite;
+
 import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
@@ -121,14 +123,14 @@ public class IndyInterface {
      * Get the cached methodhandle. if the related methodhandle is not found 
in the inline cache, cache and return it.
      */
     public static Object fromCache(MutableCallSite callSite, Class<?> sender, 
String methodName, int callID, Boolean safeNavigation, Boolean thisCall, 
Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws Throwable {
-        return 
org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache(callSite, sender, 
methodName, callID, safeNavigation, thisCall, spreadCall, dummyReceiver, 
arguments);
+        return 
org.codehaus.groovy.vmplugin.v8.IndyInterface.fromCache((CacheableCallSite)callSite,
 sender, methodName, callID, safeNavigation, thisCall, spreadCall, 
dummyReceiver, arguments);
     }
 
     /**
      * Core method for indy method selection using runtime types.
      */
     public static Object selectMethod(MutableCallSite callSite, Class<?> 
sender, String methodName, int callID, Boolean safeNavigation, Boolean 
thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws 
Throwable {
-        return 
org.codehaus.groovy.vmplugin.v8.IndyInterface.selectMethod(callSite, sender, 
methodName, callID, safeNavigation, thisCall, spreadCall, dummyReceiver, 
arguments);
+        return 
org.codehaus.groovy.vmplugin.v8.IndyInterface.selectMethod((CacheableCallSite)callSite,
 sender, methodName, callID, safeNavigation, thisCall, spreadCall, 
dummyReceiver, arguments);
     }
 
     /**
diff --git 
a/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java 
b/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
index a356f0a20c..9e00ccfa8e 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/CacheableCallSite.java
@@ -22,6 +22,7 @@ import org.apache.groovy.util.SystemUtil;
 import org.codehaus.groovy.runtime.memoize.MemoizeCache;
 
 import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import java.lang.invoke.MutableCallSite;
 import java.lang.ref.SoftReference;
@@ -38,6 +39,7 @@ public class CacheableCallSite extends MutableCallSite {
     private static final int CACHE_SIZE = 
SystemUtil.getIntegerSafe("groovy.indy.callsite.cache.size", 4);
     private static final float LOAD_FACTOR = 0.75f;
     private static final int INITIAL_CAPACITY = (int) Math.ceil(CACHE_SIZE / 
LOAD_FACTOR) + 1;
+    private final MethodHandles.Lookup lookup;
     private volatile SoftReference<MethodHandleWrapper> 
latestHitMethodHandleWrapperSoftReference = null;
     private final AtomicLong fallbackCount = new AtomicLong();
     private MethodHandle defaultTarget;
@@ -52,8 +54,9 @@ public class CacheableCallSite extends MutableCallSite {
                 }
             };
 
-    public CacheableCallSite(MethodType type) {
+    public CacheableCallSite(MethodType type, MethodHandles.Lookup lookup) {
         super(type);
+        this.lookup = lookup;
     }
 
     public MethodHandleWrapper getAndPut(String className, 
MemoizeCache.ValueProvider<? super String, ? extends MethodHandleWrapper> 
valueProvider) {
@@ -124,4 +127,8 @@ public class CacheableCallSite extends MutableCallSite {
     public void setFallbackTarget(MethodHandle fallbackTarget) {
         this.fallbackTarget = fallbackTarget;
     }
+
+    public MethodHandles.Lookup getLookup() {
+        return lookup;
+    }
 }
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java 
b/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java
index 04a2d2d94a..b719d5e641 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/IndyInterface.java
@@ -67,23 +67,28 @@ public class IndyInterface {
         /**
          * Method invocation type
          */
-        METHOD("invoke"),
+        METHOD("invoke", 0),
         /**
          * Constructor invocation type
          */
-        INIT("init"),
+        INIT("init", 1),
         /**
          * Get property invocation type
          */
-        GET("getProperty"),
+        GET("getProperty", 2),
         /**
          * Set property invocation type
          */
-        SET("setProperty"),
+        SET("setProperty", 3),
         /**
          * Cast invocation type
          */
-        CAST("cast");
+        CAST("cast", 4),
+
+        /**
+         * call to interface method
+         */
+        INTERFACE("interface", 5);
 
         private static final Map<String, CallType> NAME_CALLTYPE_MAP =
                 
Stream.of(CallType.values()).collect(Collectors.toMap(CallType::getCallSiteName,
 Function.identity()));
@@ -92,8 +97,10 @@ public class IndyInterface {
          * The name of the call site type
          */
         private final String name;
+        private final int orderNumber;
 
-        CallType(String callSiteName) {
+        CallType(String callSiteName, int orderNumber) {
+            this.orderNumber = orderNumber;
             this.name = callSiteName;
         }
 
@@ -107,6 +114,10 @@ public class IndyInterface {
         public static CallType fromCallSiteName(String callSiteName) {
             return NAME_CALLTYPE_MAP.get(callSiteName);
         }
+
+        public int getOrderNumber() {
+            return this.orderNumber;
+        }
     }
 
     /**
@@ -153,14 +164,14 @@ public class IndyInterface {
     static {
 
         try {
-            MethodType mt = MethodType.methodType(Object.class, 
MutableCallSite.class, Class.class, String.class, int.class, Boolean.class, 
Boolean.class, Boolean.class, Object.class, Object[].class);
+            MethodType mt = MethodType.methodType(Object.class, 
CacheableCallSite.class, Class.class, String.class, int.class, Boolean.class, 
Boolean.class, Boolean.class, Object.class, Object[].class);
             FROM_CACHE_METHOD = LOOKUP.findStatic(IndyInterface.class, 
"fromCache", mt);
         } catch (Exception e) {
             throw new GroovyBugError(e);
         }
 
         try {
-            MethodType mt = MethodType.methodType(Object.class, 
MutableCallSite.class, Class.class, String.class, int.class, Boolean.class, 
Boolean.class, Boolean.class, Object.class, Object[].class);
+            MethodType mt = MethodType.methodType(Object.class, 
CacheableCallSite.class, Class.class, String.class, int.class, Boolean.class, 
Boolean.class, Boolean.class, Object.class, Object[].class);
             SELECT_METHOD = LOOKUP.findStatic(IndyInterface.class, 
"selectMethod", mt);
         } catch (Exception e) {
             throw new GroovyBugError(e);
@@ -208,7 +219,7 @@ public class IndyInterface {
         CallType ct = CallType.fromCallSiteName(callType);
         if (null == ct) throw new GroovyBugError("Unknown call type: " + 
callType);
 
-        int callID = ct.ordinal();
+        int callID = ct.getOrderNumber();
         boolean safe = (flags & SAFE_NAVIGATION) != 0;
         boolean thisCall = (flags & THIS_CALL) != 0;
         boolean spreadCall = (flags & SPREAD_CALL) != 0;
@@ -223,7 +234,7 @@ public class IndyInterface {
         // first produce a dummy call site, since indy doesn't give the 
runtime types;
         // the site then changes to the target when INDY_OPTIMIZE_THRESHOLD is 
reached
         // that does the method selection including the direct call to the 
real method
-        CacheableCallSite mc = new CacheableCallSite(type);
+        CacheableCallSite mc = new CacheableCallSite(type, caller);
         Class<?> sender = caller.lookupClass();
         if (thisCall) {
             while (GeneratedClosure.class.isAssignableFrom(sender)) {
@@ -258,7 +269,7 @@ public class IndyInterface {
     }
 
     private static class FallbackSupplier {
-        private final MutableCallSite callSite;
+        private final CacheableCallSite callSite;
         private final Class<?> sender;
         private final String methodName;
         private final int callID;
@@ -269,7 +280,7 @@ public class IndyInterface {
         private final Object[] arguments;
         private MethodHandleWrapper result;
 
-        FallbackSupplier(MutableCallSite callSite, Class<?> sender, String 
methodName, int callID, Boolean safeNavigation, Boolean thisCall, Boolean 
spreadCall, Object dummyReceiver, Object[] arguments) {
+        FallbackSupplier(CacheableCallSite callSite, Class<?> sender, String 
methodName, int callID, Boolean safeNavigation, Boolean thisCall, Boolean 
spreadCall, Object dummyReceiver, Object[] arguments) {
             this.callSite = callSite;
             this.sender = sender;
             this.methodName = methodName;
@@ -293,7 +304,7 @@ public class IndyInterface {
     /**
      * Get the cached methodhandle. if the related methodhandle is not found 
in the inline cache, cache and return it.
      */
-    public static Object fromCache(MutableCallSite callSite, Class<?> sender, 
String methodName, int callID, Boolean safeNavigation, Boolean thisCall, 
Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws Throwable {
+    public static Object fromCache(CacheableCallSite callSite, Class<?> 
sender, String methodName, int callID, Boolean safeNavigation, Boolean 
thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws 
Throwable {
         FallbackSupplier fallbackSupplier = new FallbackSupplier(callSite, 
sender, methodName, callID, safeNavigation, thisCall, spreadCall, 
dummyReceiver, arguments);
 
         MethodHandleWrapper mhw =
@@ -334,7 +345,7 @@ public class IndyInterface {
     /**
      * Core method for indy method selection using runtime types.
      */
-    public static Object selectMethod(MutableCallSite callSite, Class<?> 
sender, String methodName, int callID, Boolean safeNavigation, Boolean 
thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws 
Throwable {
+    public static Object selectMethod(CacheableCallSite callSite, Class<?> 
sender, String methodName, int callID, Boolean safeNavigation, Boolean 
thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) throws 
Throwable {
         final MethodHandleWrapper mhw = fallback(callSite, sender, methodName, 
callID, safeNavigation, thisCall, spreadCall, dummyReceiver, arguments);
 
         if (callSite instanceof CacheableCallSite) {
@@ -359,7 +370,7 @@ public class IndyInterface {
         return mhw.getCachedMethodHandle().invokeExact(arguments);
     }
 
-    private static MethodHandleWrapper fallback(MutableCallSite callSite, 
Class<?> sender, String methodName, int callID, Boolean safeNavigation, Boolean 
thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) {
+    private static MethodHandleWrapper fallback(CacheableCallSite callSite, 
Class<?> sender, String methodName, int callID, Boolean safeNavigation, Boolean 
thisCall, Boolean spreadCall, Object dummyReceiver, Object[] arguments) {
         Selector selector = Selector.getSelector(callSite, sender, methodName, 
callID, safeNavigation, thisCall, spreadCall, arguments);
         selector.setCallSiteTarget();
 
diff --git a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java 
b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
index 7585f70c8d..b7cbbff9c8 100644
--- a/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
+++ b/src/main/java/org/codehaus/groovy/vmplugin/v8/Selector.java
@@ -18,7 +18,6 @@
  */
 package org.codehaus.groovy.vmplugin.v8;
 
-import groovy.lang.AdaptingMetaClass;
 import groovy.lang.Closure;
 import groovy.lang.ExpandoMetaClass;
 import groovy.lang.GroovyInterceptable;
@@ -57,7 +56,6 @@ import org.codehaus.groovy.vmplugin.VMPluginFactory;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-import java.lang.invoke.MutableCallSite;
 import java.lang.reflect.Array;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
@@ -108,7 +106,7 @@ public abstract class Selector {
     public String name;
     public MethodHandle handle;
     public boolean useMetaClass = false, cache = true;
-    public MutableCallSite callSite;
+    public CacheableCallSite callSite;
     public Class<?> sender;
     public boolean isVargs;
     public boolean safeNavigation, safeNavigationOrig, spread;
@@ -126,7 +124,7 @@ public abstract class Selector {
     /**
      * Returns the Selector
      */
-    public static Selector getSelector(MutableCallSite callSite, Class<?> 
sender, String methodName, int callID, boolean safeNavigation, boolean 
thisCall, boolean spreadCall, Object[] arguments) {
+    public static Selector getSelector(CacheableCallSite callSite, Class<?> 
sender, String methodName, int callID, boolean safeNavigation, boolean 
thisCall, boolean spreadCall, Object[] arguments) {
         CallType callType = CALL_TYPE_VALUES[callID];
         switch (callType) {
             case INIT:
@@ -139,6 +137,8 @@ public abstract class Selector {
                 throw new GroovyBugError("your call tried to do a property 
set, which is not supported.");
             case CAST:
                 return new CastSelector(callSite, arguments);
+            case INTERFACE:
+                return new InterfaceSelector(callSite, sender, methodName, 
callType, safeNavigation, thisCall, spreadCall, arguments);
             default:
                 throw new GroovyBugError("unexpected call type");
         }
@@ -165,7 +165,7 @@ public abstract class Selector {
     private static class CastSelector extends MethodSelector {
         private final Class<?> staticSourceType, staticTargetType;
 
-        public CastSelector(MutableCallSite callSite, Object[] arguments) {
+        public CastSelector(CacheableCallSite callSite, Object[] arguments) {
             super(callSite, Selector.class, "", CallType.CAST, Boolean.FALSE, 
Boolean.FALSE, Boolean.FALSE, arguments);
             this.staticSourceType = callSite.type().parameterType(0);
             this.staticTargetType = callSite.type().returnType();
@@ -284,7 +284,7 @@ public abstract class Selector {
     private static class PropertySelector extends MethodSelector {
         private boolean insertName;
 
-        public PropertySelector(MutableCallSite callSite, Class<?> sender, 
String methodName, CallType callType, boolean safeNavigation, boolean thisCall, 
boolean spreadCall, Object[] arguments) {
+        public PropertySelector(CacheableCallSite callSite, Class<?> sender, 
String methodName, CallType callType, boolean safeNavigation, boolean thisCall, 
boolean spreadCall, Object[] arguments) {
             super(callSite, sender, methodName, callType, safeNavigation, 
thisCall, spreadCall, arguments);
         }
 
@@ -384,7 +384,7 @@ public abstract class Selector {
         private static final MethodType MT_OBJECT = 
MethodType.methodType(Object.class);
         private boolean beanConstructor;
 
-        public InitSelector(MutableCallSite callSite, Class<?> sender, String 
methodName, CallType callType, boolean safeNavigation, boolean thisCall, 
boolean spreadCall, Object[] arguments) {
+        public InitSelector(CacheableCallSite callSite, Class<?> sender, 
String methodName, CallType callType, boolean safeNavigation, boolean thisCall, 
boolean spreadCall, Object[] arguments) {
             super(callSite, sender, methodName, callType, safeNavigation, 
thisCall, spreadCall, arguments);
         }
 
@@ -434,7 +434,7 @@ public abstract class Selector {
                 if (LOG_ENABLED) LOG.info("meta method is MetaConstructor 
instance");
                 MetaConstructor mc = (MetaConstructor) method;
                 isVargs = mc.isVargsMethod();
-                Constructor con = 
mc.getCachedConstrcutor().getCachedConstructor();
+                Constructor<?> con = 
mc.getCachedConstrcutor().getCachedConstructor();
                 try {
                     handle = LOOKUP.unreflectConstructor(con);
                     if (LOG_ENABLED) LOG.info("successfully unreflected 
constructor");
@@ -466,7 +466,7 @@ public abstract class Selector {
 
         /**
          * In case of a bean constructor we don't do any varags or implicit 
null argument
-         * transformations. Otherwise we do the same as for {@link 
MethodSelector#correctParameterLength()}
+         * transformations. Otherwise, we do the same as for {@link 
MethodSelector#correctParameterLength()}
          */
         @Override
         public void correctParameterLength() {
@@ -499,6 +499,31 @@ public abstract class Selector {
         }
     }
 
+    private static class InterfaceSelector extends MethodSelector {
+        public InterfaceSelector(CacheableCallSite callSite, Class<?> sender, 
String methodName, CallType callType, boolean safeNavigation, boolean thisCall, 
boolean spreadCall, Object[] arguments) {
+            super(callSite, sender, methodName, callType, safeNavigation, 
thisCall, spreadCall, arguments);
+        }
+
+        @Override
+        public MetaClass getMetaClass() {
+            mc = 
GroovySystem.getMetaClassRegistry().getMetaClass(targetType.parameterType(0));
+            mc.initialize();
+            if (LOG_ENABLED) LOG.info("meta class is " + mc);
+            return mc;
+        }
+
+        @Override
+        public void setSelectionBase() {
+            selectionBase = mc.getTheClass();
+            if (LOG_ENABLED) LOG.info("selectionBase set to " + selectionBase);
+        }
+
+        @Override
+        public MethodHandle unreflect(Method cachedMethod) throws 
IllegalAccessException {
+            return this.callSite.getLookup().unreflectSpecial(cachedMethod, 
this.sender); // throws if sender cannot invoke method
+        }
+    }
+
     /**
      * Method invocation based {@link Selector}.
      * This Selector is called for method invocations and is base for 
constructor
@@ -509,7 +534,7 @@ public abstract class Selector {
         private boolean isCategoryMethod;
         protected MetaClass mc;
 
-        public MethodSelector(MutableCallSite callSite, Class<?> sender, 
String methodName, CallType callType, Boolean safeNavigation, Boolean thisCall, 
Boolean spreadCall, Object[] arguments) {
+        public MethodSelector(CacheableCallSite callSite, Class<?> sender, 
String methodName, CallType callType, Boolean safeNavigation, Boolean thisCall, 
Boolean spreadCall, Object[] arguments) {
             this.callType = callType;
             this.targetType = callSite.type();
             this.name = methodName;
@@ -654,8 +679,7 @@ public abstract class Selector {
                     } else if (parameterCount == 1 && name.equals("forName") 
&& declaringClass == Class.class) {
                         handle = MethodHandles.insertArguments(CLASS_FOR_NAME, 
1, Boolean.TRUE, sender.getClassLoader());
                     } else {
-                        MethodHandles.Lookup lookup = cm.isPublic() ? LOOKUP : 
((Java8)vmplugin).newLookup(sender); // GROOVY-10070, et al.
-                        handle = lookup.unreflect(cm.getCachedMethod()); // 
throws if sender cannot invoke method
+                        handle = unreflect(cm.getCachedMethod());
                     }
                 } catch (ReflectiveOperationException e) {
                     throw new GroovyBugError(e);
@@ -686,6 +710,10 @@ public abstract class Selector {
             }
         }
 
+        protected MethodHandle unreflect(Method cachedMethod) throws 
IllegalAccessException {
+            return this.callSite.getLookup().unreflect(cachedMethod); // 
throws if sender cannot invoke method
+        }
+
         /**
          * Helper method to manipulate the given type to replace Wrapper with 
Object.
          */
@@ -834,10 +862,10 @@ public abstract class Selector {
 
                 // equal in terms of an assignment in Java. That means 
according to Java widening rules, or
                 // a subclass, interface, superclass relation, this case then 
handles also
-                // primitive to primitive conversion. Those case are also 
solved by explicitCastArguments.
+                // primitive to primitive conversion. Those cases are also 
solved by explicitCastArguments.
                 if (parameterType.isAssignableFrom(got)) continue;
 
-                // to aid explicitCastArguments we convert to the wrapper type 
to let is only unbox
+                // to aid explicitCastArguments we convert to the wrapper type 
to let it only unbox
                 handle = TypeTransformers.addTransformer(handle, i, arg, 
wrappedPara);
                 if (LOG_ENABLED)
                     LOG.info("added transformer at pos " + i + " for type " + 
got + " to type " + wrappedPara);
@@ -885,12 +913,7 @@ public abstract class Selector {
             if (handle == null) return;
             if (!cache) return;
 
-            MethodHandle fallback;
-            if (callSite instanceof CacheableCallSite) {
-                fallback = ((CacheableCallSite) callSite).getFallbackTarget();
-            } else {
-                throw new GroovyBugError("CacheableCallSite is expected, but 
the actual callsite is: " + callSite);
-            }
+            MethodHandle fallback = callSite.getFallbackTarget();
 
             // special guards for receiver
             if (receiver instanceof GroovyObject) {
@@ -970,14 +993,6 @@ public abstract class Selector {
          */
         public void doCallSiteTargetSet() {
             if (LOG_ENABLED) LOG.info("call site stays uncached");
-            /*
-            if (!cache) {
-                if (LOG_ENABLED) LOG.info("call site stays uncached");
-            } else {
-                callSite.setTarget(handle);
-                if (LOG_ENABLED) LOG.info("call site target set, preparing 
outside invocation");
-            }
-            */
         }
 
         /**
@@ -1049,11 +1064,10 @@ public abstract class Selector {
     private static MetaClassImpl getMetaClassImpl(final MetaClass mc, final 
boolean includeEMC) {
         Class<?> mcc = mc.getClass();
         boolean valid = mcc == MetaClassImpl.class
-                || mcc == AdaptingMetaClass.class
                 || mcc == ClosureMetaClass.class
                 || (includeEMC && mcc == ExpandoMetaClass.class);
         if (!valid) {
-            if (LOG_ENABLED) LOG.info("meta class is neither MetaClassImpl, 
nor AdoptingMetaClass, nor ClosureMetaClass, normal method selection path 
disabled.");
+            if (LOG_ENABLED) LOG.info("meta class is neither MetaClassImpl, 
nor ClosureMetaClass, normal method selection path disabled.");
             return null;
         }
         if (LOG_ENABLED) LOG.info("meta class is a recognized MetaClassImpl");

Reply via email to