changeset 14057:0ce7c64463e2

Interpreter: Special-case dispatch for array clone operations; all tests pass.
author briangoetz
date Fri, 10 Jun 2016 19:09:50 -0400
parents 6821244a6e2c
children c6766c447aac
files interpreter/src/valhalla/interpreter/Interpreter.java
diffstat 1 files changed, 20 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/interpreter/src/valhalla/interpreter/Interpreter.java	Fri Jun 10 15:29:52 2016 -0400
+++ b/interpreter/src/valhalla/interpreter/Interpreter.java	Fri Jun 10 19:09:50 2016 -0400
@@ -36,10 +36,13 @@
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
@@ -343,6 +346,23 @@
     protected HandlerAction invokeOp(Frame f) throws InterpreterError {
         ClassModel.MemberDesc ref = f.readMemberRef(1);
         MethodType methodType = MethodType.fromMethodDescriptorString(ref.desc, f.curClassLoader());
+        if (f.curOpcode() == INVOKEVIRTUAL && ref.owner.startsWith("[")
+                && ref.name.equals("clone") && ref.desc.equals("()Ljava/lang/Object;")) {
+            try {
+                trace(f, "special array clone handling for " + ref.owner);
+                Object[] args = f.popArgs(ref.desc);
+                Object receiver = f.apop();
+                Method m = Object.class.getDeclaredMethod("clone");
+                m.setAccessible(true);
+                f.apush(m.invoke(receiver, args));
+                return next();
+            }
+            catch (ReflectiveOperationException e) {
+                if (TRACING)
+                    System.out.printf("Exception in field lookup: " + e);
+                // fall through to standard processing
+            }
+        }
         return memberOp(f, toClass(f, ref.owner), ref.name, methodType);
     }