src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java
changeset 54669 ad45b3802d4e
parent 50858 2d3e99a72541
--- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Wed May 01 12:41:26 2019 -0400
+++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java	Wed May 01 12:31:29 2019 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2019, 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
@@ -26,9 +26,10 @@
 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
 
 import java.lang.invoke.MethodHandle;
-import java.util.Objects;
 
 import jdk.vm.ci.common.JVMCIError;
+import jdk.vm.ci.common.NativeImageReinitialize;
+import jdk.vm.ci.hotspot.HotSpotMethodData.VMState;
 import jdk.vm.ci.meta.ConstantReflectionProvider;
 import jdk.vm.ci.meta.JavaConstant;
 import jdk.vm.ci.meta.MethodHandleAccessProvider;
@@ -45,15 +46,16 @@
     }
 
     /**
-     * Lazy initialization to break class initialization cycle. Field and method lookup is only
-     * possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
+     * Lazy initialized reflection on {@link MethodHandle} internals. Field and method lookup is
+     * only possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
      */
-    static class LazyInitialization {
-        static final ResolvedJavaType lambdaFormType;
-        static final ResolvedJavaField methodHandleFormField;
-        static final ResolvedJavaField lambdaFormVmentryField;
-        static final ResolvedJavaField methodField;
-        static final HotSpotResolvedJavaField vmtargetField;
+    static final class Internals {
+        final ResolvedJavaType lambdaFormType;
+        final ResolvedJavaField methodHandleFormField;
+        final ResolvedJavaField lambdaFormVmentryField;
+        final HotSpotResolvedJavaField callSiteTargetField;
+        final ResolvedJavaField methodField;
+        final HotSpotResolvedJavaField vmtargetField;
 
         /**
          * Search for an instance field with the given name in a class.
@@ -71,34 +73,53 @@
                     return field;
                 }
             }
-            throw new NoSuchFieldError(fieldType.getName() + " " + declaringType + "." + fieldName);
+            throw new NoSuchFieldError(declaringType + "." + fieldName);
         }
 
-        private static ResolvedJavaType resolveType(Class<?> c) {
-            return runtime().fromClass(c);
-        }
-
-        private static ResolvedJavaType resolveType(String className) throws ClassNotFoundException {
-            return resolveType(Class.forName(className));
+        private static ResolvedJavaType resolveType(String className) {
+            return (ResolvedJavaType) runtime().lookupTypeInternal(className, null, true);
         }
 
-        static {
+        private Internals() {
             try {
-                ResolvedJavaType methodHandleType = resolveType(MethodHandle.class);
-                ResolvedJavaType memberNameType = resolveType("java.lang.invoke.MemberName");
-                lambdaFormType = resolveType("java.lang.invoke.LambdaForm");
+                ResolvedJavaType methodHandleType = resolveType("Ljava/lang/invoke/MethodHandle;");
+                ResolvedJavaType memberNameType = resolveType("Ljava/lang/invoke/MemberName;");
+                lambdaFormType = resolveType("Ljava/lang/invoke/LambdaForm;");
                 methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
                 lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);
-                ResolvedJavaType methodType = resolveType("java.lang.invoke.ResolvedMethodName");
+
+                ResolvedJavaType methodType = resolveType("Ljava/lang/invoke/ResolvedMethodName;");
                 methodField = findFieldInClass(memberNameType, "method", methodType);
-                vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(HotSpotJVMCIRuntime.getHostWordKind().toJavaClass()));
+                vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(Character.toString(HotSpotJVMCIRuntime.getHostWordKind().getTypeChar())));
 
+                ResolvedJavaType callSiteType = resolveType("Ljava/lang/invoke/CallSite;");
+                callSiteTargetField = (HotSpotResolvedJavaField) findFieldInClass(callSiteType, "target", methodHandleType);
             } catch (Throwable ex) {
                 throw new JVMCIError(ex);
             }
         }
+
+        /**
+         * Singleton instance lazily initialized via double-checked locking.
+         */
+        @NativeImageReinitialize private static volatile Internals instance;
+
+        static Internals instance() {
+            Internals result = instance;
+            if (result == null) {
+                synchronized (VMState.class) {
+                    result = instance;
+                    if (result == null) {
+                        instance = result = new Internals();
+                    }
+                }
+            }
+            return result;
+        }
+
     }
 
+
     @Override
     public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
         int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
@@ -131,19 +152,19 @@
         }
 
         /* Load non-public field: LambdaForm MethodHandle.form */
-        JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
+        Internals internals = Internals.instance();
+        JavaConstant lambdaForm = constantReflection.readFieldValue(internals.methodHandleFormField, methodHandle);
         if (lambdaForm == null || lambdaForm.isNull()) {
             return null;
         }
 
-        JavaConstant memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+        JavaConstant memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
         if (memberName.isNull() && forceBytecodeGeneration) {
-            Object lf = ((HotSpotObjectConstant) lambdaForm).asObject(LazyInitialization.lambdaFormType);
-            compilerToVM().compileToBytecode(Objects.requireNonNull(lf));
-            memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
+            compilerToVM().compileToBytecode((HotSpotObjectConstantImpl) lambdaForm);
+            memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
             assert memberName.isNonNull();
         }
-        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        JavaConstant method = constantReflection.readFieldValue(internals.methodField, memberName);
         return getTargetMethod(method);
     }
 
@@ -152,7 +173,7 @@
         if (memberName.isNull()) {
             return null;
         }
-        JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
+        JavaConstant method = constantReflection.readFieldValue(Internals.instance().methodField, memberName);
         return getTargetMethod(method);
     }
 
@@ -165,8 +186,7 @@
             throw new IllegalArgumentException("unexpected type for memberName");
         }
 
-        Object object = ((HotSpotObjectConstantImpl) method).object();
         /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */
-        return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.vmtargetField.getOffset());
+        return compilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) method, Internals.instance().vmtargetField.getOffset());
     }
 }