Mercurial > hg > graal-compiler
comparison src/share/vm/interpreter/linkResolver.cpp @ 6266:1d7922586cf6
7023639: JSR 292 method handle invocation needs a fast path for compiled code
6984705: JSR 292 method handle creation should not go through JNI
Summary: remove assembly code for JDK 7 chained method handles
Reviewed-by: jrose, twisti, kvn, mhaupt
Contributed-by: John Rose <john.r.rose@oracle.com>, Christian Thalinger <christian.thalinger@oracle.com>, Michael Haupt <michael.haupt@oracle.com>
author | twisti |
---|---|
date | Tue, 24 Jul 2012 10:51:00 -0700 |
parents | f08d439fab8c |
children | 93c71eb28866 |
comparison
equal
deleted
inserted
replaced
6241:aba91a731143 | 6266:1d7922586cf6 |
---|---|
94 } | 94 } |
95 | 95 |
96 void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { | 96 void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { |
97 assert(vtable_index >= 0 || vtable_index == methodOopDesc::nonvirtual_vtable_index, "valid index"); | 97 assert(vtable_index >= 0 || vtable_index == methodOopDesc::nonvirtual_vtable_index, "valid index"); |
98 set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK); | 98 set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK); |
99 } | 99 assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call"); |
100 | 100 } |
101 void CallInfo::set_dynamic(methodHandle resolved_method, TRAPS) { | 101 |
102 assert(resolved_method->is_method_handle_invoke(), ""); | 102 void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, TRAPS) { |
103 if (resolved_method.is_null()) { | |
104 THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null"); | |
105 } | |
103 KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); | 106 KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); |
104 assert(resolved_klass == resolved_method->method_holder(), ""); | 107 assert(resolved_method->intrinsic_id() == vmIntrinsics::_invokeBasic || |
108 resolved_method->is_compiled_lambda_form(), | |
109 "linkMethod must return one of these"); | |
105 int vtable_index = methodOopDesc::nonvirtual_vtable_index; | 110 int vtable_index = methodOopDesc::nonvirtual_vtable_index; |
106 assert(resolved_method->vtable_index() == vtable_index, ""); | 111 assert(resolved_method->vtable_index() == vtable_index, ""); |
107 set_common(resolved_klass, KlassHandle(), resolved_method, resolved_method, vtable_index, CHECK); | 112 set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK); |
113 _resolved_appendix = resolved_appendix; | |
108 } | 114 } |
109 | 115 |
110 void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { | 116 void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { |
111 assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond"); | 117 assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond"); |
112 _resolved_klass = resolved_klass; | 118 _resolved_klass = resolved_klass; |
113 _selected_klass = selected_klass; | 119 _selected_klass = selected_klass; |
114 _resolved_method = resolved_method; | 120 _resolved_method = resolved_method; |
115 _selected_method = selected_method; | 121 _selected_method = selected_method; |
116 _vtable_index = vtable_index; | 122 _vtable_index = vtable_index; |
123 _resolved_appendix = Handle(); | |
117 if (CompilationPolicy::must_be_compiled(selected_method)) { | 124 if (CompilationPolicy::must_be_compiled(selected_method)) { |
118 // This path is unusual, mostly used by the '-Xcomp' stress test mode. | 125 // This path is unusual, mostly used by the '-Xcomp' stress test mode. |
119 | 126 |
120 // Note: with several active threads, the must_be_compiled may be true | 127 // Note: with several active threads, the must_be_compiled may be true |
121 // while can_be_compiled is false; remove assert | 128 // while can_be_compiled is false; remove assert |
178 // According to JVM spec. $5.4.3c & $5.4.3d | 185 // According to JVM spec. $5.4.3c & $5.4.3d |
179 | 186 |
180 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { | 187 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { |
181 methodOop result_oop = klass->uncached_lookup_method(name, signature); | 188 methodOop result_oop = klass->uncached_lookup_method(name, signature); |
182 if (EnableInvokeDynamic && result_oop != NULL) { | 189 if (EnableInvokeDynamic && result_oop != NULL) { |
183 switch (result_oop->intrinsic_id()) { | 190 vmIntrinsics::ID iid = result_oop->intrinsic_id(); |
184 case vmIntrinsics::_invokeExact: | 191 if (MethodHandles::is_signature_polymorphic(iid)) { |
185 case vmIntrinsics::_invokeGeneric: | 192 // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method. |
186 case vmIntrinsics::_invokeDynamic: | |
187 // Do not link directly to these. The VM must produce a synthetic one using lookup_implicit_method. | |
188 return; | 193 return; |
189 } | 194 } |
190 } | 195 } |
191 result = methodHandle(THREAD, result_oop); | 196 result = methodHandle(THREAD, result_oop); |
192 } | 197 } |
211 void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { | 216 void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { |
212 instanceKlass *ik = instanceKlass::cast(klass()); | 217 instanceKlass *ik = instanceKlass::cast(klass()); |
213 result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature)); | 218 result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature)); |
214 } | 219 } |
215 | 220 |
216 void LinkResolver::lookup_implicit_method(methodHandle& result, | 221 void LinkResolver::lookup_polymorphic_method(methodHandle& result, |
217 KlassHandle klass, Symbol* name, Symbol* signature, | 222 KlassHandle klass, Symbol* name, Symbol* full_signature, |
218 KlassHandle current_klass, | 223 KlassHandle current_klass, |
219 TRAPS) { | 224 Handle* appendix_result_or_null, |
225 TRAPS) { | |
226 vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); | |
227 if (TraceMethodHandles) { | |
228 tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s", | |
229 vmIntrinsics::name_at(iid), klass->external_name(), | |
230 name->as_C_string(), full_signature->as_C_string()); | |
231 } | |
220 if (EnableInvokeDynamic && | 232 if (EnableInvokeDynamic && |
221 klass() == SystemDictionary::MethodHandle_klass() && | 233 klass() == SystemDictionary::MethodHandle_klass() && |
222 methodOopDesc::is_method_handle_invoke_name(name)) { | 234 iid != vmIntrinsics::_none) { |
223 if (!THREAD->is_Compiler_thread() && !MethodHandles::enabled()) { | 235 if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) { |
224 // Make sure the Java part of the runtime has been booted up. | 236 // Most of these do not need an up-call to Java to resolve, so can be done anywhere. |
225 klassOop natives = SystemDictionary::MethodHandleNatives_klass(); | 237 // Do not erase last argument type (MemberName) if it is a static linkTo method. |
226 if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) { | 238 bool keep_last_arg = MethodHandles::is_signature_polymorphic_static(iid); |
227 SystemDictionary::resolve_or_fail(vmSymbols::java_lang_invoke_MethodHandleNatives(), | 239 TempNewSymbol basic_signature = |
228 Handle(), | 240 MethodHandles::lookup_basic_type_signature(full_signature, keep_last_arg, CHECK); |
229 Handle(), | 241 if (TraceMethodHandles) { |
230 true, | 242 tty->print_cr("lookup_polymorphic_method %s %s => basic %s", |
231 CHECK); | 243 name->as_C_string(), |
244 full_signature->as_C_string(), | |
245 basic_signature->as_C_string()); | |
232 } | 246 } |
233 } | 247 result = SystemDictionary::find_method_handle_intrinsic(iid, |
234 methodOop result_oop = SystemDictionary::find_method_handle_invoke(name, | 248 basic_signature, |
235 signature, | 249 CHECK); |
236 current_klass, | 250 if (result.not_null()) { |
237 CHECK); | 251 assert(result->is_method_handle_intrinsic(), "MH.invokeBasic or MH.linkTo* intrinsic"); |
238 if (result_oop != NULL) { | 252 assert(result->intrinsic_id() != vmIntrinsics::_invokeGeneric, "wrong place to find this"); |
239 assert(result_oop->is_method_handle_invoke() && result_oop->signature() == signature, "consistent"); | 253 assert(basic_signature == result->signature(), "predict the result signature"); |
240 result = methodHandle(THREAD, result_oop); | 254 if (TraceMethodHandles) { |
255 tty->print("lookup_polymorphic_method => intrinsic "); | |
256 result->print_on(tty); | |
257 } | |
258 return; | |
259 } | |
260 } else if (iid == vmIntrinsics::_invokeGeneric | |
261 && !THREAD->is_Compiler_thread() | |
262 && appendix_result_or_null != NULL) { | |
263 // This is a method with type-checking semantics. | |
264 // We will ask Java code to spin an adapter method for it. | |
265 if (!MethodHandles::enabled()) { | |
266 // Make sure the Java part of the runtime has been booted up. | |
267 klassOop natives = SystemDictionary::MethodHandleNatives_klass(); | |
268 if (natives == NULL || instanceKlass::cast(natives)->is_not_initialized()) { | |
269 SystemDictionary::resolve_or_fail(vmSymbols::java_lang_invoke_MethodHandleNatives(), | |
270 Handle(), | |
271 Handle(), | |
272 true, | |
273 CHECK); | |
274 } | |
275 } | |
276 | |
277 Handle appendix; | |
278 result = SystemDictionary::find_method_handle_invoker(name, | |
279 full_signature, | |
280 current_klass, | |
281 &appendix, | |
282 CHECK); | |
283 if (TraceMethodHandles) { | |
284 tty->print("lookup_polymorphic_method => (via Java) "); | |
285 result->print_on(tty); | |
286 tty->print(" lookup_polymorphic_method => appendix = "); | |
287 if (appendix.is_null()) tty->print_cr("(none)"); | |
288 else appendix->print_on(tty); | |
289 } | |
290 if (result.not_null()) { | |
291 #ifdef ASSERT | |
292 TempNewSymbol basic_signature = | |
293 MethodHandles::lookup_basic_type_signature(full_signature, CHECK); | |
294 int actual_size_of_params = result->size_of_parameters(); | |
295 int expected_size_of_params = ArgumentSizeComputer(basic_signature).size(); | |
296 // +1 for MethodHandle.this, +1 for trailing MethodType | |
297 if (!MethodHandles::is_signature_polymorphic_static(iid)) expected_size_of_params += 1; | |
298 if (appendix.not_null()) expected_size_of_params += 1; | |
299 if (actual_size_of_params != expected_size_of_params) { | |
300 tty->print_cr("*** basic_signature=%s", basic_signature->as_C_string()); | |
301 tty->print_cr("*** result for %s: ", vmIntrinsics::name_at(iid)); | |
302 result->print(); | |
303 } | |
304 assert(actual_size_of_params == expected_size_of_params, | |
305 err_msg("%d != %d", actual_size_of_params, expected_size_of_params)); | |
306 #endif //ASSERT | |
307 | |
308 assert(appendix_result_or_null != NULL, ""); | |
309 (*appendix_result_or_null) = appendix; | |
310 return; | |
311 } | |
241 } | 312 } |
242 } | 313 } |
243 } | 314 } |
244 | 315 |
245 void LinkResolver::check_method_accessability(KlassHandle ref_klass, | 316 void LinkResolver::check_method_accessability(KlassHandle ref_klass, |
265 jint new_flags = flags.as_int(); | 336 jint new_flags = flags.as_int(); |
266 new_flags = new_flags & (~JVM_ACC_PROTECTED); | 337 new_flags = new_flags & (~JVM_ACC_PROTECTED); |
267 new_flags = new_flags | JVM_ACC_PUBLIC; | 338 new_flags = new_flags | JVM_ACC_PUBLIC; |
268 flags.set_flags(new_flags); | 339 flags.set_flags(new_flags); |
269 } | 340 } |
341 // assert(extra_arg_result_or_null != NULL, "must be able to return extra argument"); | |
270 | 342 |
271 if (!Reflection::verify_field_access(ref_klass->as_klassOop(), | 343 if (!Reflection::verify_field_access(ref_klass->as_klassOop(), |
272 resolved_klass->as_klassOop(), | 344 resolved_klass->as_klassOop(), |
273 sel_klass->as_klassOop(), | 345 sel_klass->as_klassOop(), |
274 flags, | 346 flags, |
285 ); | 357 ); |
286 return; | 358 return; |
287 } | 359 } |
288 } | 360 } |
289 | 361 |
290 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle& resolved_klass, | 362 void LinkResolver::resolve_method_statically(methodHandle& resolved_method, KlassHandle& resolved_klass, |
291 constantPoolHandle pool, int index, TRAPS) { | 363 Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS) { |
292 | 364 |
293 // resolve klass | 365 // resolve klass |
366 if (code == Bytecodes::_invokedynamic) { | |
367 resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); | |
368 Symbol* method_name = vmSymbols::invoke_name(); | |
369 Symbol* method_signature = pool->signature_ref_at(index); | |
370 KlassHandle current_klass(THREAD, pool->pool_holder()); | |
371 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); | |
372 return; | |
373 } | |
374 | |
294 resolve_klass(resolved_klass, pool, index, CHECK); | 375 resolve_klass(resolved_klass, pool, index, CHECK); |
295 | 376 |
296 Symbol* method_name = pool->name_ref_at(index); | 377 Symbol* method_name = pool->name_ref_at(index); |
297 Symbol* method_signature = pool->signature_ref_at(index); | 378 Symbol* method_signature = pool->signature_ref_at(index); |
298 KlassHandle current_klass(THREAD, pool->pool_holder()); | 379 KlassHandle current_klass(THREAD, pool->pool_holder()); |
299 | 380 |
300 if (pool->has_preresolution() | 381 if (pool->has_preresolution() |
301 || (resolved_klass() == SystemDictionary::MethodHandle_klass() && | 382 || (resolved_klass() == SystemDictionary::MethodHandle_klass() && |
302 methodOopDesc::is_method_handle_invoke_name(method_name))) { | 383 MethodHandles::is_signature_polymorphic_name(resolved_klass(), method_name))) { |
303 methodOop result_oop = constantPoolOopDesc::method_at_if_loaded(pool, index); | 384 methodOop result_oop = constantPoolOopDesc::method_at_if_loaded(pool, index); |
304 if (result_oop != NULL) { | 385 if (result_oop != NULL) { |
305 resolved_method = methodHandle(THREAD, result_oop); | 386 resolved_method = methodHandle(THREAD, result_oop); |
306 return; | 387 return; |
307 } | 388 } |
308 } | 389 } |
309 | 390 |
310 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); | 391 if (code == Bytecodes::_invokeinterface) { |
311 } | 392 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); |
312 | 393 } else { |
313 void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { | 394 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); |
314 // The class is java.lang.invoke.MethodHandle | 395 } |
315 resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); | 396 } |
316 | |
317 Symbol* method_name = vmSymbols::invokeExact_name(); | |
318 | |
319 Symbol* method_signature = pool->signature_ref_at(index); | |
320 KlassHandle current_klass (THREAD, pool->pool_holder()); | |
321 | |
322 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); | |
323 } | |
324 | |
325 void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) { | |
326 | |
327 // resolve klass | |
328 resolve_klass(resolved_klass, pool, index, CHECK); | |
329 Symbol* method_name = pool->name_ref_at(index); | |
330 Symbol* method_signature = pool->signature_ref_at(index); | |
331 KlassHandle current_klass(THREAD, pool->pool_holder()); | |
332 | |
333 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); | |
334 } | |
335 | |
336 | 397 |
337 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, | 398 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
338 Symbol* method_name, Symbol* method_signature, | 399 Symbol* method_name, Symbol* method_signature, |
339 KlassHandle current_klass, bool check_access, TRAPS) { | 400 KlassHandle current_klass, bool check_access, TRAPS) { |
340 | 401 |
344 char buf[200]; | 405 char buf[200]; |
345 jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name()); | 406 jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name()); |
346 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | 407 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
347 } | 408 } |
348 | 409 |
410 Handle nested_exception; | |
411 | |
349 // 2. lookup method in resolved klass and its super klasses | 412 // 2. lookup method in resolved klass and its super klasses |
350 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); | 413 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
351 | 414 |
352 if (resolved_method.is_null()) { // not found in the class hierarchy | 415 if (resolved_method.is_null()) { // not found in the class hierarchy |
353 // 3. lookup method in all the interfaces implemented by the resolved klass | 416 // 3. lookup method in all the interfaces implemented by the resolved klass |
354 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); | 417 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
355 | 418 |
356 if (resolved_method.is_null()) { | 419 if (resolved_method.is_null()) { |
357 // JSR 292: see if this is an implicitly generated method MethodHandle.invoke(*...) | 420 // JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc |
358 lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, CHECK); | 421 lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature, |
422 current_klass, (Handle*)NULL, THREAD); | |
423 if (HAS_PENDING_EXCEPTION) { | |
424 nested_exception = Handle(THREAD, PENDING_EXCEPTION); | |
425 CLEAR_PENDING_EXCEPTION; | |
426 } | |
359 } | 427 } |
360 | 428 |
361 if (resolved_method.is_null()) { | 429 if (resolved_method.is_null()) { |
362 // 4. method lookup failed | 430 // 4. method lookup failed |
363 ResourceMark rm(THREAD); | 431 ResourceMark rm(THREAD); |
364 THROW_MSG(vmSymbols::java_lang_NoSuchMethodError(), | 432 THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), |
365 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), | 433 methodOopDesc::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
366 method_name, | 434 method_name, |
367 method_signature)); | 435 method_signature), |
436 nested_exception); | |
368 } | 437 } |
369 } | 438 } |
370 | 439 |
371 // 5. check if method is concrete | 440 // 5. check if method is concrete |
372 if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { | 441 if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { |
1051 void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { | 1120 void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { |
1052 switch (byte) { | 1121 switch (byte) { |
1053 case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; | 1122 case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; |
1054 case Bytecodes::_invokespecial : resolve_invokespecial (result, pool, index, CHECK); break; | 1123 case Bytecodes::_invokespecial : resolve_invokespecial (result, pool, index, CHECK); break; |
1055 case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break; | 1124 case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break; |
1125 case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; | |
1056 case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; | 1126 case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; |
1057 case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; | 1127 case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; |
1058 } | 1128 } |
1059 return; | 1129 return; |
1060 } | 1130 } |
1114 KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass()); | 1184 KlassHandle recvrKlass (THREAD, recv.is_null() ? (klassOop)NULL : recv->klass()); |
1115 resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); | 1185 resolve_interface_call(result, recv, recvrKlass, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); |
1116 } | 1186 } |
1117 | 1187 |
1118 | 1188 |
1119 void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int raw_index, TRAPS) { | 1189 void LinkResolver::resolve_invokehandle(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { |
1120 assert(EnableInvokeDynamic, ""); | 1190 assert(EnableInvokeDynamic, ""); |
1121 | 1191 // This guy is reached from InterpreterRuntime::resolve_invokehandle. |
1122 // This guy is reached from InterpreterRuntime::resolve_invokedynamic. | 1192 KlassHandle resolved_klass; |
1123 | 1193 Symbol* method_name = NULL; |
1124 // At this point, we only need the signature, and can ignore the name. | 1194 Symbol* method_signature = NULL; |
1125 Symbol* method_signature = pool->signature_ref_at(raw_index); // raw_index works directly | 1195 KlassHandle current_klass; |
1126 Symbol* method_name = vmSymbols::invokeExact_name(); | 1196 resolve_pool(resolved_klass, method_name, method_signature, current_klass, pool, index, CHECK); |
1127 KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); | 1197 if (TraceMethodHandles) |
1128 | 1198 tty->print_cr("resolve_invokehandle %s %s", method_name->as_C_string(), method_signature->as_C_string()); |
1129 // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) | 1199 resolve_handle_call(result, resolved_klass, method_name, method_signature, current_klass, CHECK); |
1130 // The extra MH receiver will be inserted into the stack on every call. | 1200 } |
1201 | |
1202 void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_klass, | |
1203 Symbol* method_name, Symbol* method_signature, | |
1204 KlassHandle current_klass, | |
1205 TRAPS) { | |
1206 // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar | |
1207 assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), ""); | |
1208 assert(MethodHandles::is_signature_polymorphic_name(method_name), ""); | |
1131 methodHandle resolved_method; | 1209 methodHandle resolved_method; |
1132 KlassHandle current_klass(THREAD, pool->pool_holder()); | 1210 Handle resolved_appendix; |
1133 lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, THREAD); | 1211 lookup_polymorphic_method(resolved_method, resolved_klass, |
1212 method_name, method_signature, | |
1213 current_klass, &resolved_appendix, CHECK); | |
1214 result.set_handle(resolved_method, resolved_appendix, CHECK); | |
1215 } | |
1216 | |
1217 | |
1218 void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) { | |
1219 assert(EnableInvokeDynamic, ""); | |
1220 pool->set_invokedynamic(); // mark header to flag active call sites | |
1221 | |
1222 //resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK); | |
1223 Symbol* method_name = pool->name_ref_at(index); | |
1224 Symbol* method_signature = pool->signature_ref_at(index); | |
1225 KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder()); | |
1226 | |
1227 // Resolve the bootstrap specifier (BSM + optional arguments). | |
1228 Handle bootstrap_specifier; | |
1229 // Check if CallSite has been bound already: | |
1230 ConstantPoolCacheEntry* cpce = pool->cache()->secondary_entry_at(index); | |
1231 if (cpce->is_f1_null()) { | |
1232 int pool_index = pool->cache()->main_entry_at(index)->constant_pool_index(); | |
1233 oop bsm_info = pool->resolve_bootstrap_specifier_at(pool_index, CHECK); | |
1234 assert(bsm_info != NULL, ""); | |
1235 // FIXME: Cache this once per BootstrapMethods entry, not once per CONSTANT_InvokeDynamic. | |
1236 bootstrap_specifier = Handle(THREAD, bsm_info); | |
1237 } | |
1238 if (!cpce->is_f1_null()) { | |
1239 methodHandle method(THREAD, cpce->f2_as_vfinal_method()); | |
1240 Handle appendix(THREAD, cpce->has_appendix() ? cpce->f1_appendix() : (oop)NULL); | |
1241 result.set_handle(method, appendix, CHECK); | |
1242 return; | |
1243 } | |
1244 | |
1245 if (TraceMethodHandles) { | |
1246 tty->print_cr("resolve_invokedynamic #%d %s %s", | |
1247 constantPoolCacheOopDesc::decode_secondary_index(index), | |
1248 method_name->as_C_string(), method_signature->as_C_string()); | |
1249 tty->print(" BSM info: "); bootstrap_specifier->print(); | |
1250 } | |
1251 | |
1252 resolve_dynamic_call(result, bootstrap_specifier, method_name, method_signature, current_klass, CHECK); | |
1253 } | |
1254 | |
1255 void LinkResolver::resolve_dynamic_call(CallInfo& result, | |
1256 Handle bootstrap_specifier, | |
1257 Symbol* method_name, Symbol* method_signature, | |
1258 KlassHandle current_klass, | |
1259 TRAPS) { | |
1260 // JSR 292: this must resolve to an implicitly generated method MH.linkToCallSite(*...) | |
1261 // The appendix argument is likely to be a freshly-created CallSite. | |
1262 Handle resolved_appendix; | |
1263 methodHandle resolved_method = | |
1264 SystemDictionary::find_dynamic_call_site_invoker(current_klass, | |
1265 bootstrap_specifier, | |
1266 method_name, method_signature, | |
1267 &resolved_appendix, | |
1268 CHECK); | |
1134 if (HAS_PENDING_EXCEPTION) { | 1269 if (HAS_PENDING_EXCEPTION) { |
1270 if (TraceMethodHandles) { | |
1271 tty->print_cr("invokedynamic throws BSME for "INTPTR_FORMAT, PENDING_EXCEPTION); | |
1272 PENDING_EXCEPTION->print(); | |
1273 } | |
1135 if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) { | 1274 if (PENDING_EXCEPTION->is_a(SystemDictionary::BootstrapMethodError_klass())) { |
1136 // throw these guys, since they are already wrapped | 1275 // throw these guys, since they are already wrapped |
1137 return; | 1276 return; |
1138 } | 1277 } |
1139 if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { | 1278 if (!PENDING_EXCEPTION->is_a(SystemDictionary::LinkageError_klass())) { |
1140 // intercept only LinkageErrors which might have failed to wrap | 1279 // intercept only LinkageErrors which might have failed to wrap |
1141 return; | 1280 return; |
1142 } | 1281 } |
1143 // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS. | 1282 // See the "Linking Exceptions" section for the invokedynamic instruction in the JVMS. |
1144 Handle ex(THREAD, PENDING_EXCEPTION); | 1283 Handle nested_exception(THREAD, PENDING_EXCEPTION); |
1145 CLEAR_PENDING_EXCEPTION; | 1284 CLEAR_PENDING_EXCEPTION; |
1146 oop bsme = Klass::cast(SystemDictionary::BootstrapMethodError_klass())->java_mirror(); | 1285 THROW_MSG_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), |
1147 MethodHandles::raise_exception(Bytecodes::_athrow, ex(), bsme, CHECK); | 1286 "BootstrapMethodError", nested_exception) |
1148 // java code should not return, but if it does throw out anyway | 1287 } |
1149 THROW(vmSymbols::java_lang_InternalError()); | 1288 result.set_handle(resolved_method, resolved_appendix, CHECK); |
1150 } | |
1151 if (resolved_method.is_null()) { | |
1152 THROW(vmSymbols::java_lang_InternalError()); | |
1153 } | |
1154 result.set_dynamic(resolved_method, CHECK); | |
1155 } | 1289 } |
1156 | 1290 |
1157 //------------------------------------------------------------------------------------------------------------------------ | 1291 //------------------------------------------------------------------------------------------------------------------------ |
1158 #ifndef PRODUCT | 1292 #ifndef PRODUCT |
1159 | 1293 |