changeset 22013:3904e33db5b3

Make sure HotSpotConstantPool.loadReferencedType resolves invokehandle call sites properly. Fixes eager resolution problems at those call sites.
author Gilles Duboscq <gilles.m.duboscq@oracle.com>
date Thu, 18 Jun 2015 18:09:19 +0200
parents 53b4acee50f1
children 35b153c26783
files graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MethodHandleEagerResolution.java jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/CompilerToVM.java jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/CompilerToVMImpl.java jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotConstantPool.java src/share/vm/jvmci/jvmciCompilerToVM.cpp
diffstat 5 files changed, 92 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.compiler.test/src/com/oracle/graal/compiler/test/MethodHandleEagerResolution.java	Thu Jun 18 18:09:19 2015 +0200
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.graal.compiler.test;
+
+import java.lang.invoke.*;
+import java.lang.reflect.*;
+
+import org.junit.*;
+
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.StructuredGraph.*;
+
+public final class MethodHandleEagerResolution extends GraalCompilerTest {
+    private static final MethodHandle FIELD_HANDLE;
+
+    static {
+        Field field;
+        try {
+            field = String.class.getDeclaredField("value");
+        } catch (NoSuchFieldException ex) {
+            throw new RuntimeException(ex.getMessage(), ex);
+        }
+        field.setAccessible(true);
+
+        try {
+            FIELD_HANDLE = MethodHandles.lookup().unreflectGetter(field);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException("unable to initialize field handle", e);
+        }
+    }
+
+    public static char[] getBackingCharArray(String str) {
+        try {
+            return (char[]) FIELD_HANDLE.invokeExact(str);
+        } catch (Throwable e) {
+            throw new IllegalStateException();
+        }
+    }
+
+    @Test
+    public void testFieldInvokeExact() {
+        StructuredGraph graph = parseEager("getBackingCharArray", AllowAssumptions.NO);
+        assertTrue(graph.getNodes().filter(DeoptimizeNode.class).isEmpty());
+    }
+
+}
--- a/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/CompilerToVM.java	Thu Jun 18 17:44:47 2015 +0200
+++ b/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/CompilerToVM.java	Thu Jun 18 18:09:19 2015 +0200
@@ -332,6 +332,8 @@
 
     void resolveInvokeDynamic(long metaspaceConstantPool, int index);
 
+    void resolveInvokeHandle(long metaspaceConstantPool, int index);
+
     int getVtableIndexForInterface(long metaspaceKlass, long metaspaceMethod);
 
     boolean shouldDebugNonSafepoints();
--- a/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/CompilerToVMImpl.java	Thu Jun 18 17:44:47 2015 +0200
+++ b/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/CompilerToVMImpl.java	Thu Jun 18 18:09:19 2015 +0200
@@ -196,6 +196,8 @@
 
     public native void resolveInvokeDynamic(long metaspaceConstantPool, int index);
 
+    public native void resolveInvokeHandle(long metaspaceConstantPool, int index);
+
     public native int getVtableIndexForInterface(long metaspaceKlass, long metaspaceMethod);
 
     public native boolean shouldDebugNonSafepoints();
--- a/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotConstantPool.java	Thu Jun 18 17:44:47 2015 +0200
+++ b/jvmci/com.oracle.jvmci.hotspot/src/com/oracle/jvmci/hotspot/HotSpotConstantPool.java	Thu Jun 18 18:09:19 2015 +0200
@@ -118,6 +118,7 @@
          */
         static class TagValueMap {
             private static final JVM_CONSTANT[] table = new JVM_CONSTANT[ExternalMax + 1 + (InternalMax - InternalMin) + 1];
+
             static {
                 assert InternalMin > ExternalMax;
                 for (JVM_CONSTANT e : values()) {
@@ -616,9 +617,12 @@
             assert getTagAt(index - 1) == JVM_CONSTANT.Double || getTagAt(index - 1) == JVM_CONSTANT.Long;
             return;
         }
+        int methodRefCacheIndex = -1;
         switch (tag) {
+            case MethodRef:
+                methodRefCacheIndex = toConstantPoolIndex(cpi, opcode);
+                // fall through
             case Fieldref:
-            case MethodRef:
             case InterfaceMethodref:
                 index = getUncachedKlassRefIndexAt(index);
                 tag = getTagAt(index);
@@ -633,6 +637,9 @@
                 if (!klass.isPrimitive() && !klass.isArray()) {
                     unsafe.ensureClassInitialized(klass);
                 }
+                if (methodRefCacheIndex != -1 && isInvokeHandle(methodRefCacheIndex, type)) {
+                    runtime().getCompilerToVM().resolveInvokeHandle(metaspaceConstantPool, methodRefCacheIndex);
+                }
                 break;
             case InvokeDynamic:
                 if (isInvokedynamicIndex(cpi)) {
@@ -645,6 +652,11 @@
         }
     }
 
+    private boolean isInvokeHandle(int methodRefCpi, HotSpotResolvedObjectTypeImpl klass) {
+        assert getTagAt(runtime().getCompilerToVM().constantPoolRemapInstructionOperandFromCache(metaspaceConstantPool, methodRefCpi)) == JVM_CONSTANT.MethodRef;
+        return ResolvedJavaMethod.isSignaturePolymorphic(klass, getNameRefAt(methodRefCpi), runtime().getHostJVMCIBackend().getMetaAccess());
+    }
+
     @Override
     public String toString() {
         HotSpotResolvedObjectType holder = getHolder();
--- a/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Thu Jun 18 17:44:47 2015 +0200
+++ b/src/share/vm/jvmci/jvmciCompilerToVM.cpp	Thu Jun 18 18:09:19 2015 +0200
@@ -916,6 +916,14 @@
   cp_cache_entry->set_dynamic_call(cp, callInfo);
 C2V_END
 
+C2V_VMENTRY(void, resolveInvokeHandle, (JNIEnv*, jobject, jlong metaspace_constant_pool, jint index))
+  ConstantPool* cp = (ConstantPool*)metaspace_constant_pool;
+  CallInfo callInfo;
+  LinkResolver::resolve_invokehandle(callInfo, cp, index, CHECK);
+  ConstantPoolCacheEntry* cp_cache_entry = cp_cache_entry = cp->cache()->entry_at(cp->decode_cpcache_index(index));
+  cp_cache_entry->set_method_handle(cp, callInfo);
+C2V_END
+
 C2V_VMENTRY(jboolean, shouldDebugNonSafepoints, (JNIEnv*, jobject))
   //see compute_recording_non_safepoints in debugInfroRec.cpp
   if (JvmtiExport::should_post_compiled_method_load() && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
@@ -1076,6 +1084,7 @@
   {CC"constantPoolRemapInstructionOperandFromCache", CC"("METASPACE_CONSTANT_POOL"I)I",                                        FN_PTR(constantPoolRemapInstructionOperandFromCache)},
   {CC"resolveField",                                 CC"("METASPACE_CONSTANT_POOL"IB[J)"METASPACE_KLASS,                       FN_PTR(resolveField)},
   {CC"resolveInvokeDynamic",                         CC"("METASPACE_CONSTANT_POOL"I)V",                                        FN_PTR(resolveInvokeDynamic)},
+  {CC"resolveInvokeHandle",                          CC"("METASPACE_CONSTANT_POOL"I)V",                                        FN_PTR(resolveInvokeHandle)},
   {CC"resolveMethod",                                CC"("METASPACE_KLASS METASPACE_METHOD METASPACE_KLASS")"METASPACE_METHOD, FN_PTR(resolveMethod)},
   {CC"getVtableIndexForInterface",                   CC"("METASPACE_KLASS METASPACE_METHOD")I",                                FN_PTR(getVtableIndexForInterface)},
   {CC"getClassInitializer",                          CC"("METASPACE_KLASS")"METASPACE_METHOD,                                  FN_PTR(getClassInitializer)},