You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/06/16 10:47:10 UTC

[groovy] branch danielsun/tweak-build updated: Support clone array

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

sunlan pushed a commit to branch danielsun/tweak-build
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/danielsun/tweak-build by this push:
     new 92ab4dc  Support clone array
92ab4dc is described below

commit 92ab4dc283219f952ae2730f36eb110c9e80bb9b
Author: Daniel Sun <su...@apache.org>
AuthorDate: Wed Jun 16 18:46:49 2021 +0800

    Support clone array
---
 src/main/java/groovy/lang/MetaClassImpl.java       | 44 ++++++++++++++++++++--
 .../org/codehaus/groovy/runtime/ArrayUtil.java     |  7 +++-
 2 files changed, 46 insertions(+), 5 deletions(-)

diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java
index 533045d..04f7ff5 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -39,6 +39,7 @@ import org.codehaus.groovy.reflection.ReflectionCache;
 import org.codehaus.groovy.reflection.ReflectionUtils;
 import org.codehaus.groovy.reflection.android.AndroidSupport;
 import org.codehaus.groovy.runtime.ArrayTypeUtils;
+import org.codehaus.groovy.runtime.ArrayUtil;
 import org.codehaus.groovy.runtime.ConvertedClosure;
 import org.codehaus.groovy.runtime.CurriedClosure;
 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
@@ -1139,6 +1140,18 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
         }
     }
 
+    private static class MethodHolder {
+        private static final Method CLONE_ARRAY_METHOD;
+        static {
+            Optional<Method> methodOptional = Arrays.stream(ArrayUtil.class.getDeclaredMethods()).filter(m -> "cloneArray".equals(m.getName())).findFirst();
+            if (!methodOptional.isPresent()) {
+                throw new GroovyBugError("Failed to find `cloneArray` method in class `" + ArrayUtil.class.getName() + "`");
+            }
+            CLONE_ARRAY_METHOD = methodOptional.get();
+        }
+        private MethodHolder() {}
+    }
+
     private Object doInvokeMethodFallback(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, MissingMethodException mme) {
         MethodHandles.Lookup lookup = null;
         if (object instanceof GroovyObject) {
@@ -1147,13 +1160,14 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
             lookup = lookupOptional.get();
         }
 
+        final Class<?> receiverClass = object.getClass();
         if (isCallToSuper) {
             if (null == lookup) throw mme;
             Method superMethod = findMethod(sender, methodName, originalArguments);
             if (null == superMethod) throw mme;
             MethodHandle superMethodHandle;
             try {
-                superMethodHandle = lookup.unreflectSpecial(superMethod, object.getClass());
+                superMethodHandle = lookup.unreflectSpecial(superMethod, receiverClass);
             } catch (IllegalAccessException e) {
                 throw mme;
             }
@@ -1163,8 +1177,32 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
                 throw new GroovyRuntimeException(t);
             }
         } else {
-            if (null == lookup) lookup = MethodHandles.lookup().in(object.getClass());
-            Method thisMethod = findMethod(object.getClass(), methodName, originalArguments);
+            if (receiverClass.isArray()) {
+                if ("clone".equals(methodName) && 0 == originalArguments.length) {
+                    MethodHandle cloneArrayMethodHandle;
+                    try {
+                        cloneArrayMethodHandle = MethodHandles.lookup().in(ArrayUtil.class).unreflect(MethodHolder.CLONE_ARRAY_METHOD);
+                    } catch (IllegalAccessException e) {
+                        throw mme;
+                    }
+                    try {
+                        Object[] array = (Object[]) object;
+                        Object[] result = (Object[]) cloneArrayMethodHandle.invokeExact(array);
+                        return result;
+                    } catch (Throwable t) {
+                        throw new GroovyRuntimeException(t);
+                    }
+                }
+            }
+
+            if (null == lookup) {
+                try {
+                    lookup = MethodHandles.lookup().in(receiverClass);
+                } catch (IllegalArgumentException e) {
+                    throw mme;
+                }
+            }
+            Method thisMethod = findMethod(receiverClass, methodName, originalArguments);
             if (null == thisMethod) throw mme;
             MethodHandle thisMethodHandle;
             try {
diff --git a/src/main/java/org/codehaus/groovy/runtime/ArrayUtil.java b/src/main/java/org/codehaus/groovy/runtime/ArrayUtil.java
index aa8096f..d0697de 100644
--- a/src/main/java/org/codehaus/groovy/runtime/ArrayUtil.java
+++ b/src/main/java/org/codehaus/groovy/runtime/ArrayUtil.java
@@ -53,8 +53,11 @@ package org.codehaus.groovy.runtime;
 * absolutely no sense in normal Java. But it is not used in normal Java, but from the bytecode. 
 */ 
 public class ArrayUtil {
-    private static final Object[] EMPTY = new Object[0]
-            ;
+    private static final Object[] EMPTY = new Object[0];
+
+    public static <T> T[] cloneArray(T[] array) {
+        return array.clone();
+    }
 
     public static Object[] createArray() {
         return EMPTY;