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 } |