56 private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) { |
56 private DirectMethodHandle(MethodType mtype, LambdaForm form, MemberName member) { |
57 super(mtype, form); |
57 super(mtype, form); |
58 if (!member.isResolved()) throw new InternalError(); |
58 if (!member.isResolved()) throw new InternalError(); |
59 |
59 |
60 if (member.getDeclaringClass().isInterface() && |
60 if (member.getDeclaringClass().isInterface() && |
61 member.isMethod() && !member.isAbstract()) { |
61 member.getReferenceKind() == REF_invokeInterface && |
|
62 member.isMethod() && !member.isAbstract()) { |
62 // Check for corner case: invokeinterface of Object method |
63 // Check for corner case: invokeinterface of Object method |
63 MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); |
64 MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); |
64 m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); |
65 m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); |
65 if (m != null && m.isPublic()) { |
66 if (m != null && m.isPublic()) { |
66 assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong |
67 assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong |
78 if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor()) |
79 if (!member.getDeclaringClass().isAssignableFrom(refc) || member.isConstructor()) |
79 throw new InternalError(member.toString()); |
80 throw new InternalError(member.toString()); |
80 mtype = mtype.insertParameterTypes(0, refc); |
81 mtype = mtype.insertParameterTypes(0, refc); |
81 } |
82 } |
82 if (!member.isField()) { |
83 if (!member.isField()) { |
|
84 // refKind reflects the original type of lookup via findSpecial or |
|
85 // findVirtual etc. |
83 switch (refKind) { |
86 switch (refKind) { |
84 case REF_invokeSpecial: { |
87 case REF_invokeSpecial: { |
85 member = member.asSpecial(); |
88 member = member.asSpecial(); |
86 LambdaForm lform = preparedLambdaForm(member, callerClass); |
89 // if caller is an interface we need to adapt to get the |
87 Class<?> checkClass = refc; // Class to use for receiver type check |
90 // receiver check inserted |
88 if (callerClass != null) { |
91 if (callerClass == null) { |
89 checkClass = callerClass; // potentially strengthen to caller class |
92 throw new InternalError("callerClass must not be null for REF_invokeSpecial"); |
90 } |
93 } |
91 return new Special(mtype, lform, member, checkClass); |
94 LambdaForm lform = preparedLambdaForm(member, callerClass.isInterface()); |
|
95 return new Special(mtype, lform, member, callerClass); |
92 } |
96 } |
93 case REF_invokeInterface: { |
97 case REF_invokeInterface: { |
94 LambdaForm lform = preparedLambdaForm(member, callerClass); |
98 // for interfaces we always need the receiver typecheck, |
|
99 // so we always pass 'true' to ensure we adapt if needed |
|
100 // to include the REF_invokeSpecial case |
|
101 LambdaForm lform = preparedLambdaForm(member, true); |
95 return new Interface(mtype, lform, member, refc); |
102 return new Interface(mtype, lform, member, refc); |
96 } |
103 } |
97 default: { |
104 default: { |
98 LambdaForm lform = preparedLambdaForm(member, callerClass); |
105 LambdaForm lform = preparedLambdaForm(member); |
99 return new DirectMethodHandle(mtype, lform, member); |
106 return new DirectMethodHandle(mtype, lform, member); |
100 } |
107 } |
101 } |
108 } |
102 } else { |
109 } else { |
103 LambdaForm lform = preparedFieldLambdaForm(member); |
110 LambdaForm lform = preparedFieldLambdaForm(member); |
163 /** |
170 /** |
164 * Create a LF which can invoke the given method. |
171 * Create a LF which can invoke the given method. |
165 * Cache and share this structure among all methods with |
172 * Cache and share this structure among all methods with |
166 * the same basicType and refKind. |
173 * the same basicType and refKind. |
167 */ |
174 */ |
168 private static LambdaForm preparedLambdaForm(MemberName m, Class<?> callerClass) { |
175 private static LambdaForm preparedLambdaForm(MemberName m, boolean adaptToSpecialIfc) { |
169 assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead |
176 assert(m.isInvocable()) : m; // call preparedFieldLambdaForm instead |
170 MethodType mtype = m.getInvocationType().basicType(); |
177 MethodType mtype = m.getInvocationType().basicType(); |
171 assert(!m.isMethodHandleInvoke()) : m; |
178 assert(!m.isMethodHandleInvoke()) : m; |
172 int which; |
179 int which; |
|
180 // MemberName.getReferenceKind represents the JVM optimized form of the call |
|
181 // as distinct from the "kind" passed to DMH.make which represents the original |
|
182 // bytecode-equivalent request. Specifically private/final methods that use a direct |
|
183 // call have getReferenceKind adapted to REF_invokeSpecial, even though the actual |
|
184 // invocation mode may be invokevirtual or invokeinterface. |
173 switch (m.getReferenceKind()) { |
185 switch (m.getReferenceKind()) { |
174 case REF_invokeVirtual: which = LF_INVVIRTUAL; break; |
186 case REF_invokeVirtual: which = LF_INVVIRTUAL; break; |
175 case REF_invokeStatic: which = LF_INVSTATIC; break; |
187 case REF_invokeStatic: which = LF_INVSTATIC; break; |
176 case REF_invokeSpecial: which = LF_INVSPECIAL; break; |
188 case REF_invokeSpecial: which = LF_INVSPECIAL; break; |
177 case REF_invokeInterface: which = LF_INVINTERFACE; break; |
189 case REF_invokeInterface: which = LF_INVINTERFACE; break; |
181 if (which == LF_INVSTATIC && shouldBeInitialized(m)) { |
193 if (which == LF_INVSTATIC && shouldBeInitialized(m)) { |
182 // precompute the barrier-free version: |
194 // precompute the barrier-free version: |
183 preparedLambdaForm(mtype, which); |
195 preparedLambdaForm(mtype, which); |
184 which = LF_INVSTATIC_INIT; |
196 which = LF_INVSTATIC_INIT; |
185 } |
197 } |
186 if (which == LF_INVSPECIAL && callerClass != null && callerClass.isInterface()) { |
198 if (which == LF_INVSPECIAL && adaptToSpecialIfc) { |
187 which = LF_INVSPECIAL_IFC; |
199 which = LF_INVSPECIAL_IFC; |
188 } |
200 } |
189 LambdaForm lform = preparedLambdaForm(mtype, which); |
201 LambdaForm lform = preparedLambdaForm(mtype, which); |
190 maybeCompile(lform, m); |
202 maybeCompile(lform, m); |
191 assert(lform.methodType().dropParameterTypes(0, 1) |
203 assert(lform.methodType().dropParameterTypes(0, 1) |
193 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType()); |
205 : Arrays.asList(m, m.getInvocationType().basicType(), lform, lform.methodType()); |
194 return lform; |
206 return lform; |
195 } |
207 } |
196 |
208 |
197 private static LambdaForm preparedLambdaForm(MemberName m) { |
209 private static LambdaForm preparedLambdaForm(MemberName m) { |
198 return preparedLambdaForm(m, null); |
210 return preparedLambdaForm(m, false); |
199 } |
211 } |
200 |
212 |
201 private static LambdaForm preparedLambdaForm(MethodType mtype, int which) { |
213 private static LambdaForm preparedLambdaForm(MethodType mtype, int which) { |
202 LambdaForm lform = mtype.form().cachedLambdaForm(which); |
214 LambdaForm lform = mtype.form().cachedLambdaForm(which); |
203 if (lform != null) return lform; |
215 if (lform != null) return lform; |