src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMethodHandleAccessProvider.java
changeset 54669 ad45b3802d4e
parent 50858 2d3e99a72541
equal deleted inserted replaced
54668:0bda2308eded 54669:ad45b3802d4e
     1 /*
     1 /*
     2  * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
    24 
    24 
    25 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
    25 import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM;
    26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
    26 import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;
    27 
    27 
    28 import java.lang.invoke.MethodHandle;
    28 import java.lang.invoke.MethodHandle;
    29 import java.util.Objects;
       
    30 
    29 
    31 import jdk.vm.ci.common.JVMCIError;
    30 import jdk.vm.ci.common.JVMCIError;
       
    31 import jdk.vm.ci.common.NativeImageReinitialize;
       
    32 import jdk.vm.ci.hotspot.HotSpotMethodData.VMState;
    32 import jdk.vm.ci.meta.ConstantReflectionProvider;
    33 import jdk.vm.ci.meta.ConstantReflectionProvider;
    33 import jdk.vm.ci.meta.JavaConstant;
    34 import jdk.vm.ci.meta.JavaConstant;
    34 import jdk.vm.ci.meta.MethodHandleAccessProvider;
    35 import jdk.vm.ci.meta.MethodHandleAccessProvider;
    35 import jdk.vm.ci.meta.ResolvedJavaField;
    36 import jdk.vm.ci.meta.ResolvedJavaField;
    36 import jdk.vm.ci.meta.ResolvedJavaMethod;
    37 import jdk.vm.ci.meta.ResolvedJavaMethod;
    43     public HotSpotMethodHandleAccessProvider(ConstantReflectionProvider constantReflection) {
    44     public HotSpotMethodHandleAccessProvider(ConstantReflectionProvider constantReflection) {
    44         this.constantReflection = constantReflection;
    45         this.constantReflection = constantReflection;
    45     }
    46     }
    46 
    47 
    47     /**
    48     /**
    48      * Lazy initialization to break class initialization cycle. Field and method lookup is only
    49      * Lazy initialized reflection on {@link MethodHandle} internals. Field and method lookup is
    49      * possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
    50      * only possible after the {@link HotSpotJVMCIRuntime} is fully initialized.
    50      */
    51      */
    51     static class LazyInitialization {
    52     static final class Internals {
    52         static final ResolvedJavaType lambdaFormType;
    53         final ResolvedJavaType lambdaFormType;
    53         static final ResolvedJavaField methodHandleFormField;
    54         final ResolvedJavaField methodHandleFormField;
    54         static final ResolvedJavaField lambdaFormVmentryField;
    55         final ResolvedJavaField lambdaFormVmentryField;
    55         static final ResolvedJavaField methodField;
    56         final HotSpotResolvedJavaField callSiteTargetField;
    56         static final HotSpotResolvedJavaField vmtargetField;
    57         final ResolvedJavaField methodField;
       
    58         final HotSpotResolvedJavaField vmtargetField;
    57 
    59 
    58         /**
    60         /**
    59          * Search for an instance field with the given name in a class.
    61          * Search for an instance field with the given name in a class.
    60          *
    62          *
    61          * @param declaringType the type declaring the field
    63          * @param declaringType the type declaring the field
    69             for (ResolvedJavaField field : fields) {
    71             for (ResolvedJavaField field : fields) {
    70                 if (field.getName().equals(fieldName) && field.getType().equals(fieldType)) {
    72                 if (field.getName().equals(fieldName) && field.getType().equals(fieldType)) {
    71                     return field;
    73                     return field;
    72                 }
    74                 }
    73             }
    75             }
    74             throw new NoSuchFieldError(fieldType.getName() + " " + declaringType + "." + fieldName);
    76             throw new NoSuchFieldError(declaringType + "." + fieldName);
    75         }
    77         }
    76 
    78 
    77         private static ResolvedJavaType resolveType(Class<?> c) {
    79         private static ResolvedJavaType resolveType(String className) {
    78             return runtime().fromClass(c);
    80             return (ResolvedJavaType) runtime().lookupTypeInternal(className, null, true);
    79         }
    81         }
    80 
    82 
    81         private static ResolvedJavaType resolveType(String className) throws ClassNotFoundException {
    83         private Internals() {
    82             return resolveType(Class.forName(className));
       
    83         }
       
    84 
       
    85         static {
       
    86             try {
    84             try {
    87                 ResolvedJavaType methodHandleType = resolveType(MethodHandle.class);
    85                 ResolvedJavaType methodHandleType = resolveType("Ljava/lang/invoke/MethodHandle;");
    88                 ResolvedJavaType memberNameType = resolveType("java.lang.invoke.MemberName");
    86                 ResolvedJavaType memberNameType = resolveType("Ljava/lang/invoke/MemberName;");
    89                 lambdaFormType = resolveType("java.lang.invoke.LambdaForm");
    87                 lambdaFormType = resolveType("Ljava/lang/invoke/LambdaForm;");
    90                 methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
    88                 methodHandleFormField = findFieldInClass(methodHandleType, "form", lambdaFormType);
    91                 lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);
    89                 lambdaFormVmentryField = findFieldInClass(lambdaFormType, "vmentry", memberNameType);
    92                 ResolvedJavaType methodType = resolveType("java.lang.invoke.ResolvedMethodName");
    90 
       
    91                 ResolvedJavaType methodType = resolveType("Ljava/lang/invoke/ResolvedMethodName;");
    93                 methodField = findFieldInClass(memberNameType, "method", methodType);
    92                 methodField = findFieldInClass(memberNameType, "method", methodType);
    94                 vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(HotSpotJVMCIRuntime.getHostWordKind().toJavaClass()));
    93                 vmtargetField = (HotSpotResolvedJavaField) findFieldInClass(methodType, "vmtarget", resolveType(Character.toString(HotSpotJVMCIRuntime.getHostWordKind().getTypeChar())));
    95 
    94 
       
    95                 ResolvedJavaType callSiteType = resolveType("Ljava/lang/invoke/CallSite;");
       
    96                 callSiteTargetField = (HotSpotResolvedJavaField) findFieldInClass(callSiteType, "target", methodHandleType);
    96             } catch (Throwable ex) {
    97             } catch (Throwable ex) {
    97                 throw new JVMCIError(ex);
    98                 throw new JVMCIError(ex);
    98             }
    99             }
    99         }
   100         }
       
   101 
       
   102         /**
       
   103          * Singleton instance lazily initialized via double-checked locking.
       
   104          */
       
   105         @NativeImageReinitialize private static volatile Internals instance;
       
   106 
       
   107         static Internals instance() {
       
   108             Internals result = instance;
       
   109             if (result == null) {
       
   110                 synchronized (VMState.class) {
       
   111                     result = instance;
       
   112                     if (result == null) {
       
   113                         instance = result = new Internals();
       
   114                     }
       
   115                 }
       
   116             }
       
   117             return result;
       
   118         }
       
   119 
   100     }
   120     }
       
   121 
   101 
   122 
   102     @Override
   123     @Override
   103     public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
   124     public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) {
   104         int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
   125         int intrinsicId = ((HotSpotResolvedJavaMethodImpl) method).intrinsicId();
   105         if (intrinsicId != 0) {
   126         if (intrinsicId != 0) {
   129         if (methodHandle.isNull()) {
   150         if (methodHandle.isNull()) {
   130             return null;
   151             return null;
   131         }
   152         }
   132 
   153 
   133         /* Load non-public field: LambdaForm MethodHandle.form */
   154         /* Load non-public field: LambdaForm MethodHandle.form */
   134         JavaConstant lambdaForm = constantReflection.readFieldValue(LazyInitialization.methodHandleFormField, methodHandle);
   155         Internals internals = Internals.instance();
       
   156         JavaConstant lambdaForm = constantReflection.readFieldValue(internals.methodHandleFormField, methodHandle);
   135         if (lambdaForm == null || lambdaForm.isNull()) {
   157         if (lambdaForm == null || lambdaForm.isNull()) {
   136             return null;
   158             return null;
   137         }
   159         }
   138 
   160 
   139         JavaConstant memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
   161         JavaConstant memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
   140         if (memberName.isNull() && forceBytecodeGeneration) {
   162         if (memberName.isNull() && forceBytecodeGeneration) {
   141             Object lf = ((HotSpotObjectConstant) lambdaForm).asObject(LazyInitialization.lambdaFormType);
   163             compilerToVM().compileToBytecode((HotSpotObjectConstantImpl) lambdaForm);
   142             compilerToVM().compileToBytecode(Objects.requireNonNull(lf));
   164             memberName = constantReflection.readFieldValue(internals.lambdaFormVmentryField, lambdaForm);
   143             memberName = constantReflection.readFieldValue(LazyInitialization.lambdaFormVmentryField, lambdaForm);
       
   144             assert memberName.isNonNull();
   165             assert memberName.isNonNull();
   145         }
   166         }
   146         JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
   167         JavaConstant method = constantReflection.readFieldValue(internals.methodField, memberName);
   147         return getTargetMethod(method);
   168         return getTargetMethod(method);
   148     }
   169     }
   149 
   170 
   150     @Override
   171     @Override
   151     public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) {
   172     public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) {
   152         if (memberName.isNull()) {
   173         if (memberName.isNull()) {
   153             return null;
   174             return null;
   154         }
   175         }
   155         JavaConstant method = constantReflection.readFieldValue(LazyInitialization.methodField, memberName);
   176         JavaConstant method = constantReflection.readFieldValue(Internals.instance().methodField, memberName);
   156         return getTargetMethod(method);
   177         return getTargetMethod(method);
   157     }
   178     }
   158 
   179 
   159     /**
   180     /**
   160      * Returns the {@link ResolvedJavaMethod} for the method of a java.lang.invoke.MemberName.
   181      * Returns the {@link ResolvedJavaMethod} for the method of a java.lang.invoke.MemberName.
   163         if (method == null) {
   184         if (method == null) {
   164             // If readFieldValue returns NULL the type was wrong
   185             // If readFieldValue returns NULL the type was wrong
   165             throw new IllegalArgumentException("unexpected type for memberName");
   186             throw new IllegalArgumentException("unexpected type for memberName");
   166         }
   187         }
   167 
   188 
   168         Object object = ((HotSpotObjectConstantImpl) method).object();
       
   169         /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */
   189         /* Read the ResolvedJavaMethod from the injected field MemberName.method.vmtarget */
   170         return compilerToVM().getResolvedJavaMethod(object, LazyInitialization.vmtargetField.getOffset());
   190         return compilerToVM().getResolvedJavaMethod((HotSpotObjectConstantImpl) method, Internals.instance().vmtargetField.getOffset());
   171     }
   191     }
   172 }
   192 }