53 |
53 |
54 //------------------------------------------------------------------------------------------------------------------------ |
54 //------------------------------------------------------------------------------------------------------------------------ |
55 // Implementation of CallInfo |
55 // Implementation of CallInfo |
56 |
56 |
57 |
57 |
58 void CallInfo::set_static(KlassHandle resolved_klass, const methodHandle& resolved_method, TRAPS) { |
58 void CallInfo::set_static(Klass* resolved_klass, const methodHandle& resolved_method, TRAPS) { |
59 int vtable_index = Method::nonvirtual_vtable_index; |
59 int vtable_index = Method::nonvirtual_vtable_index; |
60 set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK); |
60 set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK); |
61 } |
61 } |
62 |
62 |
63 |
63 |
64 void CallInfo::set_interface(KlassHandle resolved_klass, |
64 void CallInfo::set_interface(Klass* resolved_klass, |
65 KlassHandle selected_klass, |
65 Klass* selected_klass, |
66 const methodHandle& resolved_method, |
66 const methodHandle& resolved_method, |
67 const methodHandle& selected_method, |
67 const methodHandle& selected_method, |
68 int itable_index, TRAPS) { |
68 int itable_index, TRAPS) { |
69 // This is only called for interface methods. If the resolved_method |
69 // This is only called for interface methods. If the resolved_method |
70 // comes from java/lang/Object, it can be the subject of a virtual call, so |
70 // comes from java/lang/Object, it can be the subject of a virtual call, so |
73 assert(resolved_method->method_holder()->is_interface(), ""); |
73 assert(resolved_method->method_holder()->is_interface(), ""); |
74 assert(itable_index == resolved_method()->itable_index(), ""); |
74 assert(itable_index == resolved_method()->itable_index(), ""); |
75 set_common(resolved_klass, selected_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK); |
75 set_common(resolved_klass, selected_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK); |
76 } |
76 } |
77 |
77 |
78 void CallInfo::set_virtual(KlassHandle resolved_klass, |
78 void CallInfo::set_virtual(Klass* resolved_klass, |
79 KlassHandle selected_klass, |
79 Klass* selected_klass, |
80 const methodHandle& resolved_method, |
80 const methodHandle& resolved_method, |
81 const methodHandle& selected_method, |
81 const methodHandle& selected_method, |
82 int vtable_index, TRAPS) { |
82 int vtable_index, TRAPS) { |
83 assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "valid index"); |
83 assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "valid index"); |
84 assert(vtable_index < 0 || !resolved_method->has_vtable_index() || vtable_index == resolved_method->vtable_index(), ""); |
84 assert(vtable_index < 0 || !resolved_method->has_vtable_index() || vtable_index == resolved_method->vtable_index(), ""); |
91 Handle resolved_appendix, |
91 Handle resolved_appendix, |
92 Handle resolved_method_type, TRAPS) { |
92 Handle resolved_method_type, TRAPS) { |
93 set_handle(SystemDictionary::MethodHandle_klass(), resolved_method, resolved_appendix, resolved_method_type, CHECK); |
93 set_handle(SystemDictionary::MethodHandle_klass(), resolved_method, resolved_appendix, resolved_method_type, CHECK); |
94 } |
94 } |
95 |
95 |
96 void CallInfo::set_handle(KlassHandle resolved_klass, |
96 void CallInfo::set_handle(Klass* resolved_klass, |
97 const methodHandle& resolved_method, |
97 const methodHandle& resolved_method, |
98 Handle resolved_appendix, |
98 Handle resolved_appendix, |
99 Handle resolved_method_type, TRAPS) { |
99 Handle resolved_method_type, TRAPS) { |
100 if (resolved_method.is_null()) { |
100 if (resolved_method.is_null()) { |
101 THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null"); |
101 THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null"); |
160 } else if (resolved_method->has_vtable_index()) { |
160 } else if (resolved_method->has_vtable_index()) { |
161 // Can occur if an interface redeclares a method of Object. |
161 // Can occur if an interface redeclares a method of Object. |
162 |
162 |
163 #ifdef ASSERT |
163 #ifdef ASSERT |
164 // Ensure that this is really the case. |
164 // Ensure that this is really the case. |
165 KlassHandle object_klass = SystemDictionary::Object_klass(); |
165 Klass* object_klass = SystemDictionary::Object_klass(); |
166 Method * object_resolved_method = object_klass()->vtable()->method_at(index); |
166 Method * object_resolved_method = object_klass->vtable()->method_at(index); |
167 assert(object_resolved_method->name() == resolved_method->name(), |
167 assert(object_resolved_method->name() == resolved_method->name(), |
168 "Object and interface method names should match at vtable index %d, %s != %s", |
168 "Object and interface method names should match at vtable index %d, %s != %s", |
169 index, object_resolved_method->name()->as_C_string(), resolved_method->name()->as_C_string()); |
169 index, object_resolved_method->name()->as_C_string(), resolved_method->name()->as_C_string()); |
170 assert(object_resolved_method->signature() == resolved_method->signature(), |
170 assert(object_resolved_method->signature() == resolved_method->signature(), |
171 "Object and interface method signatures should match at vtable index %d, %s != %s", |
171 "Object and interface method signatures should match at vtable index %d, %s != %s", |
223 //------------------------------------------------------------------------------------------------------------------------ |
223 //------------------------------------------------------------------------------------------------------------------------ |
224 // Implementation of LinkInfo |
224 // Implementation of LinkInfo |
225 |
225 |
226 LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, methodHandle current_method, TRAPS) { |
226 LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, methodHandle current_method, TRAPS) { |
227 // resolve klass |
227 // resolve klass |
228 Klass* result = pool->klass_ref_at(index, CHECK); |
228 _resolved_klass = pool->klass_ref_at(index, CHECK); |
229 _resolved_klass = KlassHandle(THREAD, result); |
|
230 |
229 |
231 // Get name, signature, and static klass |
230 // Get name, signature, and static klass |
232 _name = pool->name_ref_at(index); |
231 _name = pool->name_ref_at(index); |
233 _signature = pool->signature_ref_at(index); |
232 _signature = pool->signature_ref_at(index); |
234 _tag = pool->tag_ref_at(index); |
233 _tag = pool->tag_ref_at(index); |
235 _current_klass = KlassHandle(THREAD, pool->pool_holder()); |
234 _current_klass = pool->pool_holder(); |
236 _current_method = current_method; |
235 _current_method = current_method; |
237 |
236 |
238 // Coming from the constant pool always checks access |
237 // Coming from the constant pool always checks access |
239 _check_access = true; |
238 _check_access = true; |
240 } |
239 } |
241 |
240 |
242 LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { |
241 LinkInfo::LinkInfo(const constantPoolHandle& pool, int index, TRAPS) { |
243 // resolve klass |
242 // resolve klass |
244 Klass* result = pool->klass_ref_at(index, CHECK); |
243 _resolved_klass = pool->klass_ref_at(index, CHECK); |
245 _resolved_klass = KlassHandle(THREAD, result); |
|
246 |
244 |
247 // Get name, signature, and static klass |
245 // Get name, signature, and static klass |
248 _name = pool->name_ref_at(index); |
246 _name = pool->name_ref_at(index); |
249 _signature = pool->signature_ref_at(index); |
247 _signature = pool->signature_ref_at(index); |
250 _tag = pool->tag_ref_at(index); |
248 _tag = pool->tag_ref_at(index); |
251 _current_klass = KlassHandle(THREAD, pool->pool_holder()); |
249 _current_klass = pool->pool_holder(); |
252 _current_method = methodHandle(); |
250 _current_method = methodHandle(); |
253 |
251 |
254 // Coming from the constant pool always checks access |
252 // Coming from the constant pool always checks access |
255 _check_access = true; |
253 _check_access = true; |
256 } |
254 } |
257 |
255 |
258 char* LinkInfo::method_string() const { |
256 char* LinkInfo::method_string() const { |
259 return Method::name_and_sig_as_C_string(_resolved_klass(), _name, _signature); |
257 return Method::name_and_sig_as_C_string(_resolved_klass, _name, _signature); |
260 } |
258 } |
261 |
259 |
262 #ifndef PRODUCT |
260 #ifndef PRODUCT |
263 void LinkInfo::print() { |
261 void LinkInfo::print() { |
264 ResourceMark rm; |
262 ResourceMark rm; |
265 tty->print_cr("Link resolved_klass=%s name=%s signature=%s current_klass=%s check_access=%s", |
263 tty->print_cr("Link resolved_klass=%s name=%s signature=%s current_klass=%s check_access=%s", |
266 _resolved_klass->name()->as_C_string(), |
264 _resolved_klass->name()->as_C_string(), |
267 _name->as_C_string(), |
265 _name->as_C_string(), |
268 _signature->as_C_string(), |
266 _signature->as_C_string(), |
269 _current_klass.is_null() ? "(none)" : _current_klass->name()->as_C_string(), |
267 _current_klass == NULL ? "(none)" : _current_klass->name()->as_C_string(), |
270 _check_access ? "true" : "false"); |
268 _check_access ? "true" : "false"); |
271 } |
269 } |
272 #endif // PRODUCT |
270 #endif // PRODUCT |
273 //------------------------------------------------------------------------------------------------------------------------ |
271 //------------------------------------------------------------------------------------------------------------------------ |
274 // Klass resolution |
272 // Klass resolution |
275 |
273 |
276 void LinkResolver::check_klass_accessability(KlassHandle ref_klass, KlassHandle sel_klass, TRAPS) { |
274 void LinkResolver::check_klass_accessability(Klass* ref_klass, Klass* sel_klass, TRAPS) { |
277 Reflection::VerifyClassAccessResults vca_result = |
275 Reflection::VerifyClassAccessResults vca_result = |
278 Reflection::verify_class_access(ref_klass(), InstanceKlass::cast(sel_klass()), true); |
276 Reflection::verify_class_access(ref_klass, InstanceKlass::cast(sel_klass), true); |
279 if (vca_result != Reflection::ACCESS_OK) { |
277 if (vca_result != Reflection::ACCESS_OK) { |
280 ResourceMark rm(THREAD); |
278 ResourceMark rm(THREAD); |
281 char* msg = Reflection::verify_class_access_msg(ref_klass(), |
279 char* msg = Reflection::verify_class_access_msg(ref_klass, |
282 InstanceKlass::cast(sel_klass()), |
280 InstanceKlass::cast(sel_klass), |
283 vca_result); |
281 vca_result); |
284 if (msg == NULL) { |
282 if (msg == NULL) { |
285 Exceptions::fthrow( |
283 Exceptions::fthrow( |
286 THREAD_AND_LOCATION, |
284 THREAD_AND_LOCATION, |
287 vmSymbols::java_lang_IllegalAccessError(), |
285 vmSymbols::java_lang_IllegalAccessError(), |
306 // Look up method in klasses, including static methods |
304 // Look up method in klasses, including static methods |
307 // Then look up local default methods |
305 // Then look up local default methods |
308 methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, |
306 methodHandle LinkResolver::lookup_method_in_klasses(const LinkInfo& link_info, |
309 bool checkpolymorphism, |
307 bool checkpolymorphism, |
310 bool in_imethod_resolve, TRAPS) { |
308 bool in_imethod_resolve, TRAPS) { |
311 KlassHandle klass = link_info.resolved_klass(); |
309 Klass* klass = link_info.resolved_klass(); |
312 Symbol* name = link_info.name(); |
310 Symbol* name = link_info.name(); |
313 Symbol* signature = link_info.signature(); |
311 Symbol* signature = link_info.signature(); |
314 |
312 |
315 // Ignore overpasses so statics can be found during resolution |
313 // Ignore overpasses so statics can be found during resolution |
316 Method* result = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); |
314 Method* result = klass->uncached_lookup_method(name, signature, Klass::skip_overpass); |
372 // Only consider klass and super klass for arrays |
370 // Only consider klass and super klass for arrays |
373 return methodHandle(THREAD, result); |
371 return methodHandle(THREAD, result); |
374 } |
372 } |
375 |
373 |
376 if (result == NULL) { |
374 if (result == NULL) { |
377 Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); |
375 Array<Method*>* default_methods = InstanceKlass::cast(klass)->default_methods(); |
378 if (default_methods != NULL) { |
376 if (default_methods != NULL) { |
379 result = InstanceKlass::find_method(default_methods, name, signature); |
377 result = InstanceKlass::find_method(default_methods, name, signature); |
380 assert(result == NULL || !result->is_static(), "static defaults not allowed"); |
378 assert(result == NULL || !result->is_static(), "static defaults not allowed"); |
381 } |
379 } |
382 } |
380 } |
383 return methodHandle(THREAD, result); |
381 return methodHandle(THREAD, result); |
384 } |
382 } |
385 |
383 |
386 int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, |
384 int LinkResolver::vtable_index_of_interface_method(Klass* klass, |
387 const methodHandle& resolved_method) { |
385 const methodHandle& resolved_method) { |
388 |
386 |
389 int vtable_index = Method::invalid_vtable_index; |
387 int vtable_index = Method::invalid_vtable_index; |
390 Symbol* name = resolved_method->name(); |
388 Symbol* name = resolved_method->name(); |
391 Symbol* signature = resolved_method->signature(); |
389 Symbol* signature = resolved_method->signature(); |
392 InstanceKlass* ik = InstanceKlass::cast(klass()); |
390 InstanceKlass* ik = InstanceKlass::cast(klass); |
393 |
391 |
394 // First check in default method array |
392 // First check in default method array |
395 if (!resolved_method->is_abstract() && ik->default_methods() != NULL) { |
393 if (!resolved_method->is_abstract() && ik->default_methods() != NULL) { |
396 int index = InstanceKlass::find_method_index(ik->default_methods(), |
394 int index = InstanceKlass::find_method_index(ik->default_methods(), |
397 name, signature, Klass::find_overpass, |
395 name, signature, Klass::find_overpass, |
423 methodHandle LinkResolver::lookup_polymorphic_method( |
421 methodHandle LinkResolver::lookup_polymorphic_method( |
424 const LinkInfo& link_info, |
422 const LinkInfo& link_info, |
425 Handle *appendix_result_or_null, |
423 Handle *appendix_result_or_null, |
426 Handle *method_type_result, |
424 Handle *method_type_result, |
427 TRAPS) { |
425 TRAPS) { |
428 KlassHandle klass = link_info.resolved_klass(); |
426 Klass* klass = link_info.resolved_klass(); |
429 Symbol* name = link_info.name(); |
427 Symbol* name = link_info.name(); |
430 Symbol* full_signature = link_info.signature(); |
428 Symbol* full_signature = link_info.signature(); |
431 |
429 |
432 vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); |
430 vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name); |
433 if (TraceMethodHandles) { |
431 if (TraceMethodHandles) { |
434 ResourceMark rm(THREAD); |
432 ResourceMark rm(THREAD); |
435 tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s", |
433 tty->print_cr("lookup_polymorphic_method iid=%s %s.%s%s", |
436 vmIntrinsics::name_at(iid), klass->external_name(), |
434 vmIntrinsics::name_at(iid), klass->external_name(), |
437 name->as_C_string(), full_signature->as_C_string()); |
435 name->as_C_string(), full_signature->as_C_string()); |
438 } |
436 } |
439 if ((klass() == SystemDictionary::MethodHandle_klass() || |
437 if ((klass == SystemDictionary::MethodHandle_klass() || |
440 klass() == SystemDictionary::VarHandle_klass()) && |
438 klass == SystemDictionary::VarHandle_klass()) && |
441 iid != vmIntrinsics::_none) { |
439 iid != vmIntrinsics::_none) { |
442 if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) { |
440 if (MethodHandles::is_signature_polymorphic_intrinsic(iid)) { |
443 // Most of these do not need an up-call to Java to resolve, so can be done anywhere. |
441 // Most of these do not need an up-call to Java to resolve, so can be done anywhere. |
444 // Do not erase last argument type (MemberName) if it is a static linkTo method. |
442 // Do not erase last argument type (MemberName) if it is a static linkTo method. |
445 bool keep_last_arg = MethodHandles::is_signature_polymorphic_static(iid); |
443 bool keep_last_arg = MethodHandles::is_signature_polymorphic_static(iid); |
545 // to public. |
543 // to public. |
546 // |
544 // |
547 // We'll check for the method name first, as that's most likely |
545 // We'll check for the method name first, as that's most likely |
548 // to be false (so we'll short-circuit out of these tests). |
546 // to be false (so we'll short-circuit out of these tests). |
549 if (sel_method->name() == vmSymbols::clone_name() && |
547 if (sel_method->name() == vmSymbols::clone_name() && |
550 sel_klass() == SystemDictionary::Object_klass() && |
548 sel_klass == SystemDictionary::Object_klass() && |
551 resolved_klass->is_array_klass()) { |
549 resolved_klass->is_array_klass()) { |
552 // We need to change "protected" to "public". |
550 // We need to change "protected" to "public". |
553 assert(flags.is_protected(), "clone not protected?"); |
551 assert(flags.is_protected(), "clone not protected?"); |
554 jint new_flags = flags.as_int(); |
552 jint new_flags = flags.as_int(); |
555 new_flags = new_flags & (~JVM_ACC_PROTECTED); |
553 new_flags = new_flags & (~JVM_ACC_PROTECTED); |
556 new_flags = new_flags | JVM_ACC_PUBLIC; |
554 new_flags = new_flags | JVM_ACC_PUBLIC; |
557 flags.set_flags(new_flags); |
555 flags.set_flags(new_flags); |
558 } |
556 } |
559 // assert(extra_arg_result_or_null != NULL, "must be able to return extra argument"); |
557 // assert(extra_arg_result_or_null != NULL, "must be able to return extra argument"); |
560 |
558 |
561 if (!Reflection::verify_field_access(ref_klass(), |
559 if (!Reflection::verify_field_access(ref_klass, |
562 resolved_klass(), |
560 resolved_klass, |
563 sel_klass(), |
561 sel_klass, |
564 flags, |
562 flags, |
565 true)) { |
563 true)) { |
566 ResourceMark rm(THREAD); |
564 ResourceMark rm(THREAD); |
567 Exceptions::fthrow( |
565 Exceptions::fthrow( |
568 THREAD_AND_LOCATION, |
566 THREAD_AND_LOCATION, |
584 // and |
582 // and |
585 // (2) in Bytecode_invoke::static_target |
583 // (2) in Bytecode_invoke::static_target |
586 // It appears to fail when applied to an invokeinterface call site. |
584 // It appears to fail when applied to an invokeinterface call site. |
587 // FIXME: Remove this method and ciMethod::check_call; refactor to use the other LinkResolver entry points. |
585 // FIXME: Remove this method and ciMethod::check_call; refactor to use the other LinkResolver entry points. |
588 // resolve klass |
586 // resolve klass |
589 KlassHandle resolved_klass; |
|
590 if (code == Bytecodes::_invokedynamic) { |
587 if (code == Bytecodes::_invokedynamic) { |
591 resolved_klass = SystemDictionary::MethodHandle_klass(); |
588 Klass* resolved_klass = SystemDictionary::MethodHandle_klass(); |
592 Symbol* method_name = vmSymbols::invoke_name(); |
589 Symbol* method_name = vmSymbols::invoke_name(); |
593 Symbol* method_signature = pool->signature_ref_at(index); |
590 Symbol* method_signature = pool->signature_ref_at(index); |
594 KlassHandle current_klass(THREAD, pool->pool_holder()); |
591 Klass* current_klass = pool->pool_holder(); |
595 LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass); |
592 LinkInfo link_info(resolved_klass, method_name, method_signature, current_klass); |
596 return resolve_method(link_info, code, THREAD); |
593 return resolve_method(link_info, code, THREAD); |
597 } |
594 } |
598 |
595 |
599 LinkInfo link_info(pool, index, methodHandle(), CHECK_NULL); |
596 LinkInfo link_info(pool, index, methodHandle(), CHECK_NULL); |
600 resolved_klass = link_info.resolved_klass(); |
597 Klass* resolved_klass = link_info.resolved_klass(); |
601 |
598 |
602 if (pool->has_preresolution() |
599 if (pool->has_preresolution() |
603 || (resolved_klass() == SystemDictionary::MethodHandle_klass() && |
600 || (resolved_klass == SystemDictionary::MethodHandle_klass() && |
604 MethodHandles::is_signature_polymorphic_name(resolved_klass(), link_info.name()))) { |
601 MethodHandles::is_signature_polymorphic_name(resolved_klass, link_info.name()))) { |
605 Method* result = ConstantPool::method_at_if_loaded(pool, index); |
602 Method* result = ConstantPool::method_at_if_loaded(pool, index); |
606 if (result != NULL) { |
603 if (result != NULL) { |
607 return methodHandle(THREAD, result); |
604 return methodHandle(THREAD, result); |
608 } |
605 } |
609 } |
606 } |
684 |
681 |
685 methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, |
682 methodHandle LinkResolver::resolve_method(const LinkInfo& link_info, |
686 Bytecodes::Code code, TRAPS) { |
683 Bytecodes::Code code, TRAPS) { |
687 |
684 |
688 Handle nested_exception; |
685 Handle nested_exception; |
689 KlassHandle resolved_klass = link_info.resolved_klass(); |
686 Klass* resolved_klass = link_info.resolved_klass(); |
690 |
687 |
691 // 1. For invokevirtual, cannot call an interface method |
688 // 1. For invokevirtual, cannot call an interface method |
692 if (code == Bytecodes::_invokevirtual && resolved_klass->is_interface()) { |
689 if (code == Bytecodes::_invokevirtual && resolved_klass->is_interface()) { |
693 ResourceMark rm(THREAD); |
690 ResourceMark rm(THREAD); |
694 char buf[200]; |
691 char buf[200]; |
695 jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", |
692 jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", |
696 resolved_klass()->external_name()); |
693 resolved_klass->external_name()); |
697 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
694 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
698 } |
695 } |
699 |
696 |
700 // 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref |
697 // 2. check constant pool tag for called method - must be JVM_CONSTANT_Methodref |
701 if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) { |
698 if (!link_info.tag().is_invalid() && !link_info.tag().is_method()) { |
725 |
722 |
726 // 5. method lookup failed |
723 // 5. method lookup failed |
727 if (resolved_method.is_null()) { |
724 if (resolved_method.is_null()) { |
728 ResourceMark rm(THREAD); |
725 ResourceMark rm(THREAD); |
729 THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(), |
726 THROW_MSG_CAUSE_(vmSymbols::java_lang_NoSuchMethodError(), |
730 Method::name_and_sig_as_C_string(resolved_klass(), |
727 Method::name_and_sig_as_C_string(resolved_klass, |
731 link_info.name(), |
728 link_info.name(), |
732 link_info.signature()), |
729 link_info.signature()), |
733 nested_exception, NULL); |
730 nested_exception, NULL); |
734 } |
731 } |
735 |
732 |
736 // 6. access checks, access checking may be turned off when calling from within the VM. |
733 // 5. access checks, access checking may be turned off when calling from within the VM. |
737 KlassHandle current_klass = link_info.current_klass(); |
734 Klass* current_klass = link_info.current_klass(); |
738 if (link_info.check_access()) { |
735 if (link_info.check_access()) { |
739 assert(current_klass.not_null() , "current_klass should not be null"); |
736 assert(current_klass != NULL , "current_klass should not be null"); |
740 |
737 |
741 // check if method can be accessed by the referring class |
738 // check if method can be accessed by the referring class |
742 check_method_accessability(current_klass, |
739 check_method_accessability(current_klass, |
743 resolved_klass, |
740 resolved_klass, |
744 KlassHandle(THREAD, resolved_method->method_holder()), |
741 resolved_method->method_holder(), |
745 resolved_method, |
742 resolved_method, |
746 CHECK_NULL); |
743 CHECK_NULL); |
747 |
744 |
748 // check loader constraints |
745 // check loader constraints |
749 check_method_loader_constraints(link_info, resolved_method, "method", CHECK_NULL); |
746 check_method_loader_constraints(link_info, resolved_method, "method", CHECK_NULL); |
766 } else { |
763 } else { |
767 st = Log(vtables)::trace_stream(); |
764 st = Log(vtables)::trace_stream(); |
768 } |
765 } |
769 st->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", |
766 st->print("%s%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", |
770 prefix, |
767 prefix, |
771 (klass.is_null() ? "<NULL>" : klass->internal_name()), |
768 (klass == NULL ? "<NULL>" : klass->internal_name()), |
772 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), |
769 (resolved_klass == NULL ? "<NULL>" : resolved_klass->internal_name()), |
773 Method::name_and_sig_as_C_string(resolved_klass(), |
770 Method::name_and_sig_as_C_string(resolved_klass, |
774 method->name(), |
771 method->name(), |
775 method->signature()), |
772 method->signature()), |
776 method->method_holder()->internal_name()); |
773 method->method_holder()->internal_name()); |
777 method->print_linkage_flags(st); |
774 method->print_linkage_flags(st); |
778 if (index != -1) { |
775 if (index != -1) { |
783 } |
780 } |
784 |
781 |
785 // Do linktime resolution of a method in the interface within the context of the specied bytecode. |
782 // Do linktime resolution of a method in the interface within the context of the specied bytecode. |
786 methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS) { |
783 methodHandle LinkResolver::resolve_interface_method(const LinkInfo& link_info, Bytecodes::Code code, TRAPS) { |
787 |
784 |
788 KlassHandle resolved_klass = link_info.resolved_klass(); |
785 Klass* resolved_klass = link_info.resolved_klass(); |
789 |
786 |
790 // check if klass is interface |
787 // check if klass is interface |
791 if (!resolved_klass->is_interface()) { |
788 if (!resolved_klass->is_interface()) { |
792 ResourceMark rm(THREAD); |
789 ResourceMark rm(THREAD); |
793 char buf[200]; |
790 char buf[200]; |
794 jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name()); |
791 jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass->external_name()); |
795 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
792 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
796 } |
793 } |
797 |
794 |
798 // check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref |
795 // check constant pool tag for called method - must be JVM_CONSTANT_InterfaceMethodref |
799 if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) { |
796 if (!link_info.tag().is_invalid() && !link_info.tag().is_interface_method()) { |
814 |
811 |
815 if (resolved_method.is_null()) { |
812 if (resolved_method.is_null()) { |
816 // no method found |
813 // no method found |
817 ResourceMark rm(THREAD); |
814 ResourceMark rm(THREAD); |
818 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), |
815 THROW_MSG_NULL(vmSymbols::java_lang_NoSuchMethodError(), |
819 Method::name_and_sig_as_C_string(resolved_klass(), |
816 Method::name_and_sig_as_C_string(resolved_klass, |
820 link_info.name(), |
817 link_info.name(), |
821 link_info.signature())); |
818 link_info.signature())); |
822 } |
819 } |
823 |
820 |
824 if (link_info.check_access()) { |
821 if (link_info.check_access()) { |
825 // JDK8 adds non-public interface methods, and accessability check requirement |
822 // JDK8 adds non-public interface methods, and accessability check requirement |
826 KlassHandle current_klass = link_info.current_klass(); |
823 Klass* current_klass = link_info.current_klass(); |
827 |
824 |
828 assert(current_klass.not_null() , "current_klass should not be null"); |
825 assert(current_klass != NULL , "current_klass should not be null"); |
829 |
826 |
830 // check if method can be accessed by the referring class |
827 // check if method can be accessed by the referring class |
831 check_method_accessability(current_klass, |
828 check_method_accessability(current_klass, |
832 resolved_klass, |
829 resolved_klass, |
833 KlassHandle(THREAD, resolved_method->method_holder()), |
830 resolved_method->method_holder(), |
834 resolved_method, |
831 resolved_method, |
835 CHECK_NULL); |
832 CHECK_NULL); |
836 |
833 |
837 check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL); |
834 check_method_loader_constraints(link_info, resolved_method, "interface method", CHECK_NULL); |
838 } |
835 } |
839 |
836 |
840 if (code != Bytecodes::_invokestatic && resolved_method->is_static()) { |
837 if (code != Bytecodes::_invokestatic && resolved_method->is_static()) { |
841 ResourceMark rm(THREAD); |
838 ResourceMark rm(THREAD); |
842 char buf[200]; |
839 char buf[200]; |
843 jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", |
840 jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", |
844 Method::name_and_sig_as_C_string(resolved_klass(), |
841 Method::name_and_sig_as_C_string(resolved_klass, |
845 resolved_method->name(), resolved_method->signature())); |
842 resolved_method->name(), resolved_method->signature())); |
846 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
843 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
847 } |
844 } |
848 |
845 |
849 if (code == Bytecodes::_invokeinterface && resolved_method->is_private()) { |
846 if (code == Bytecodes::_invokeinterface && resolved_method->is_private()) { |
850 ResourceMark rm(THREAD); |
847 ResourceMark rm(THREAD); |
851 char buf[200]; |
848 char buf[200]; |
852 |
849 |
853 KlassHandle current_klass = link_info.current_klass(); |
850 Klass* current_klass = link_info.current_klass(); |
854 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s, caller-class:%s", |
851 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s, caller-class:%s", |
855 Method::name_and_sig_as_C_string(resolved_klass(), |
852 Method::name_and_sig_as_C_string(resolved_klass, |
856 resolved_method->name(), |
853 resolved_method->name(), |
857 resolved_method->signature()), |
854 resolved_method->signature()), |
858 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name())); |
855 (current_klass == NULL ? "<NULL>" : current_klass->internal_name())); |
859 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
856 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
860 } |
857 } |
861 |
858 |
862 if (log_develop_is_enabled(Trace, itables)) { |
859 if (log_develop_is_enabled(Trace, itables)) { |
863 char buf[200]; |
860 char buf[200]; |
911 (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode"); |
908 (byte == Bytecodes::_nop && !link_info.check_access()), "bad field access bytecode"); |
912 |
909 |
913 bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic); |
910 bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic); |
914 bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield); |
911 bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield); |
915 // Check if there's a resolved klass containing the field |
912 // Check if there's a resolved klass containing the field |
916 KlassHandle resolved_klass = link_info.resolved_klass(); |
913 Klass* resolved_klass = link_info.resolved_klass(); |
917 Symbol* field = link_info.name(); |
914 Symbol* field = link_info.name(); |
918 Symbol* sig = link_info.signature(); |
915 Symbol* sig = link_info.signature(); |
919 |
916 |
920 if (resolved_klass.is_null()) { |
917 if (resolved_klass == NULL) { |
921 ResourceMark rm(THREAD); |
918 ResourceMark rm(THREAD); |
922 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); |
919 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); |
923 } |
920 } |
924 |
921 |
925 // Resolve instance field |
922 // Resolve instance field |
926 KlassHandle sel_klass(THREAD, resolved_klass->find_field(field, sig, &fd)); |
923 Klass* sel_klass = resolved_klass->find_field(field, sig, &fd); |
927 // check if field exists; i.e., if a klass containing the field def has been selected |
924 // check if field exists; i.e., if a klass containing the field def has been selected |
928 if (sel_klass.is_null()) { |
925 if (sel_klass == NULL) { |
929 ResourceMark rm(THREAD); |
926 ResourceMark rm(THREAD); |
930 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); |
927 THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); |
931 } |
928 } |
932 |
929 |
933 if (!link_info.check_access()) |
930 if (!link_info.check_access()) |
934 // Access checking may be turned off when calling from within the VM. |
931 // Access checking may be turned off when calling from within the VM. |
935 return; |
932 return; |
936 |
933 |
937 // check access |
934 // check access |
938 KlassHandle current_klass = link_info.current_klass(); |
935 Klass* current_klass = link_info.current_klass(); |
939 check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK); |
936 check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK); |
940 |
937 |
941 // check for errors |
938 // check for errors |
942 if (is_static != fd.is_static()) { |
939 if (is_static != fd.is_static()) { |
943 ResourceMark rm(THREAD); |
940 ResourceMark rm(THREAD); |
944 char msg[200]; |
941 char msg[200]; |
945 jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string()); |
942 jio_snprintf(msg, sizeof(msg), "Expected %s field %s.%s", is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string()); |
946 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); |
943 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), msg); |
947 } |
944 } |
948 |
945 |
949 // A final field can be modified only |
946 // A final field can be modified only |
950 // (1) by methods declared in the class declaring the field and |
947 // (1) by methods declared in the class declaring the field and |
952 // or by the <init> method (in case of an instance field). |
949 // or by the <init> method (in case of an instance field). |
953 if (is_put && fd.access_flags().is_final()) { |
950 if (is_put && fd.access_flags().is_final()) { |
954 ResourceMark rm(THREAD); |
951 ResourceMark rm(THREAD); |
955 stringStream ss; |
952 stringStream ss; |
956 |
953 |
957 if (sel_klass() != current_klass()) { |
954 if (sel_klass != current_klass) { |
958 ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", |
955 ss.print("Update to %s final field %s.%s attempted from a different class (%s) than the field's declaring class", |
959 is_static ? "static" : "non-static", resolved_klass()->external_name(), fd.name()->as_C_string(), |
956 is_static ? "static" : "non-static", resolved_klass->external_name(), fd.name()->as_C_string(), |
960 current_klass()->external_name()); |
957 current_klass->external_name()); |
961 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string()); |
958 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), ss.as_string()); |
962 } |
959 } |
963 |
960 |
964 if (fd.constants()->pool_holder()->major_version() >= 53) { |
961 if (fd.constants()->pool_holder()->major_version() >= 53) { |
965 methodHandle m = link_info.current_method(); |
962 methodHandle m = link_info.current_method(); |
1076 // <init> |
1073 // <init> |
1077 // local private method invocation, for classes and interfaces |
1074 // local private method invocation, for classes and interfaces |
1078 // superclass.method, which can also resolve to a default method |
1075 // superclass.method, which can also resolve to a default method |
1079 // and the selected method is recalculated relative to the direct superclass |
1076 // and the selected method is recalculated relative to the direct superclass |
1080 // superinterface.method, which explicitly does not check shadowing |
1077 // superinterface.method, which explicitly does not check shadowing |
1081 KlassHandle resolved_klass = link_info.resolved_klass(); |
1078 Klass* resolved_klass = link_info.resolved_klass(); |
1082 methodHandle resolved_method; |
1079 methodHandle resolved_method; |
1083 |
1080 |
1084 if (!resolved_klass->is_interface()) { |
1081 if (!resolved_klass->is_interface()) { |
1085 resolved_method = resolve_method(link_info, Bytecodes::_invokespecial, CHECK_NULL); |
1082 resolved_method = resolve_method(link_info, Bytecodes::_invokespecial, CHECK_NULL); |
1086 } else { |
1083 } else { |
1087 resolved_method = resolve_interface_method(link_info, Bytecodes::_invokespecial, CHECK_NULL); |
1084 resolved_method = resolve_interface_method(link_info, Bytecodes::_invokespecial, CHECK_NULL); |
1088 } |
1085 } |
1089 |
1086 |
1090 // check if method name is <init>, that it is found in same klass as static type |
1087 // check if method name is <init>, that it is found in same klass as static type |
1091 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
1088 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
1092 resolved_method->method_holder() != resolved_klass()) { |
1089 resolved_method->method_holder() != resolved_klass) { |
1093 ResourceMark rm(THREAD); |
1090 ResourceMark rm(THREAD); |
1094 Exceptions::fthrow( |
1091 Exceptions::fthrow( |
1095 THREAD_AND_LOCATION, |
1092 THREAD_AND_LOCATION, |
1096 vmSymbols::java_lang_NoSuchMethodError(), |
1093 vmSymbols::java_lang_NoSuchMethodError(), |
1097 "%s: method %s%s not found", |
1094 "%s: method %s%s not found", |
1101 ); |
1098 ); |
1102 return NULL; |
1099 return NULL; |
1103 } |
1100 } |
1104 |
1101 |
1105 // check if invokespecial's interface method reference is in an indirect superinterface |
1102 // check if invokespecial's interface method reference is in an indirect superinterface |
1106 KlassHandle current_klass = link_info.current_klass(); |
1103 Klass* current_klass = link_info.current_klass(); |
1107 if (!current_klass.is_null() && resolved_klass->is_interface()) { |
1104 if (current_klass != NULL && resolved_klass->is_interface()) { |
1108 Klass *klass_to_check = !InstanceKlass::cast(current_klass())->is_anonymous() ? |
1105 InstanceKlass* ck = InstanceKlass::cast(current_klass); |
1109 current_klass() : |
1106 InstanceKlass *klass_to_check = !ck->is_anonymous() ? |
1110 InstanceKlass::cast(current_klass())->host_klass(); |
1107 ck : |
|
1108 InstanceKlass::cast(ck->host_klass()); |
1111 // Disable verification for the dynamically-generated reflection bytecodes. |
1109 // Disable verification for the dynamically-generated reflection bytecodes. |
1112 bool is_reflect = klass_to_check->is_subclass_of( |
1110 bool is_reflect = klass_to_check->is_subclass_of( |
1113 SystemDictionary::reflect_MagicAccessorImpl_klass()); |
1111 SystemDictionary::reflect_MagicAccessorImpl_klass()); |
1114 |
1112 |
1115 if (!is_reflect && |
1113 if (!is_reflect && |
1116 !InstanceKlass::cast(klass_to_check)->is_same_or_direct_interface(resolved_klass())) { |
1114 !klass_to_check->is_same_or_direct_interface(resolved_klass)) { |
1117 ResourceMark rm(THREAD); |
1115 ResourceMark rm(THREAD); |
1118 char buf[200]; |
1116 char buf[200]; |
1119 jio_snprintf(buf, sizeof(buf), |
1117 jio_snprintf(buf, sizeof(buf), |
1120 "Interface method reference: %s, is in an indirect superinterface of %s", |
1118 "Interface method reference: %s, is in an indirect superinterface of %s", |
1121 Method::name_and_sig_as_C_string(resolved_klass(), |
1119 Method::name_and_sig_as_C_string(resolved_klass, |
1122 resolved_method->name(), |
1120 resolved_method->name(), |
1123 resolved_method->signature()), |
1121 resolved_method->signature()), |
1124 current_klass->external_name()); |
1122 current_klass->external_name()); |
1125 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1123 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1126 } |
1124 } |
1127 } |
1125 } |
1128 |
1126 |
1147 } |
1145 } |
1148 |
1146 |
1149 // throws runtime exceptions |
1147 // throws runtime exceptions |
1150 void LinkResolver::runtime_resolve_special_method(CallInfo& result, |
1148 void LinkResolver::runtime_resolve_special_method(CallInfo& result, |
1151 const methodHandle& resolved_method, |
1149 const methodHandle& resolved_method, |
1152 KlassHandle resolved_klass, |
1150 Klass* resolved_klass, |
1153 KlassHandle current_klass, |
1151 Klass* current_klass, |
1154 bool check_access, TRAPS) { |
1152 bool check_access, TRAPS) { |
1155 |
1153 |
1156 // resolved method is selected method unless we have an old-style lookup |
1154 // resolved method is selected method unless we have an old-style lookup |
1157 // for a superclass method |
1155 // for a superclass method |
1158 // Invokespecial for a superinterface, resolved method is selected method, |
1156 // Invokespecial for a superinterface, resolved method is selected method, |
1159 // no checks for shadowing |
1157 // no checks for shadowing |
1160 methodHandle sel_method(THREAD, resolved_method()); |
1158 methodHandle sel_method(THREAD, resolved_method()); |
1161 |
1159 |
1162 // check if this is an old-style super call and do a new lookup if so |
1160 // check if this is an old-style super call and do a new lookup if so |
1163 { KlassHandle method_klass = KlassHandle(THREAD, |
1161 if (check_access && |
1164 resolved_method->method_holder()); |
1162 // a) check if ACC_SUPER flag is set for the current class |
1165 |
1163 (current_klass->is_super() || !AllowNonVirtualCalls) && |
1166 if (check_access && |
1164 // b) check if the class of the resolved_klass is a superclass |
1167 // a) check if ACC_SUPER flag is set for the current class |
1165 // (not supertype in order to exclude interface classes) of the current class. |
1168 (current_klass->is_super() || !AllowNonVirtualCalls) && |
1166 // This check is not performed for super.invoke for interface methods |
1169 // b) check if the class of the resolved_klass is a superclass |
1167 // in super interfaces. |
1170 // (not supertype in order to exclude interface classes) of the current class. |
1168 current_klass->is_subclass_of(resolved_klass) && |
1171 // This check is not performed for super.invoke for interface methods |
1169 current_klass != resolved_klass && |
1172 // in super interfaces. |
1170 // c) check if the method is not <init> |
1173 current_klass->is_subclass_of(resolved_klass()) && |
1171 resolved_method->name() != vmSymbols::object_initializer_name()) { |
1174 current_klass() != resolved_klass() && |
1172 // Lookup super method |
1175 // c) check if the method is not <init> |
1173 Klass* super_klass = current_klass->super(); |
1176 resolved_method->name() != vmSymbols::object_initializer_name()) { |
1174 sel_method = lookup_instance_method_in_klasses(super_klass, |
1177 // Lookup super method |
1175 resolved_method->name(), |
1178 KlassHandle super_klass(THREAD, current_klass->super()); |
1176 resolved_method->signature(), CHECK); |
1179 sel_method = lookup_instance_method_in_klasses(super_klass, |
1177 // check if found |
1180 resolved_method->name(), |
1178 if (sel_method.is_null()) { |
1181 resolved_method->signature(), CHECK); |
1179 ResourceMark rm(THREAD); |
1182 // check if found |
1180 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1183 if (sel_method.is_null()) { |
1181 Method::name_and_sig_as_C_string(resolved_klass, |
1184 ResourceMark rm(THREAD); |
1182 resolved_method->name(), |
1185 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1183 resolved_method->signature())); |
1186 Method::name_and_sig_as_C_string(resolved_klass(), |
|
1187 resolved_method->name(), |
|
1188 resolved_method->signature())); |
|
1189 } |
|
1190 } |
1184 } |
1191 } |
1185 } |
1192 |
1186 |
1193 // check if not static |
1187 // check if not static |
1194 if (sel_method->is_static()) { |
1188 if (sel_method->is_static()) { |
1195 ResourceMark rm(THREAD); |
1189 ResourceMark rm(THREAD); |
1196 char buf[200]; |
1190 char buf[200]; |
1197 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), |
1191 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass, |
1198 resolved_method->name(), |
1192 resolved_method->name(), |
1199 resolved_method->signature())); |
1193 resolved_method->signature())); |
1200 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1194 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1201 } |
1195 } |
1202 |
1196 |
1203 // check if abstract |
1197 // check if abstract |
1204 if (sel_method->is_abstract()) { |
1198 if (sel_method->is_abstract()) { |
1205 ResourceMark rm(THREAD); |
1199 ResourceMark rm(THREAD); |
1206 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1200 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1207 Method::name_and_sig_as_C_string(resolved_klass(), |
1201 Method::name_and_sig_as_C_string(resolved_klass, |
1208 sel_method->name(), |
1202 sel_method->name(), |
1209 sel_method->signature())); |
1203 sel_method->signature())); |
1210 } |
1204 } |
1211 |
1205 |
1212 if (log_develop_is_enabled(Trace, itables)) { |
1206 if (log_develop_is_enabled(Trace, itables)) { |
1216 |
1210 |
1217 // setup result |
1211 // setup result |
1218 result.set_static(resolved_klass, sel_method, CHECK); |
1212 result.set_static(resolved_klass, sel_method, CHECK); |
1219 } |
1213 } |
1220 |
1214 |
1221 void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, |
1215 void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, Klass* receiver_klass, |
1222 const LinkInfo& link_info, |
1216 const LinkInfo& link_info, |
1223 bool check_null_and_abstract, TRAPS) { |
1217 bool check_null_and_abstract, TRAPS) { |
1224 methodHandle resolved_method = linktime_resolve_virtual_method(link_info, CHECK); |
1218 methodHandle resolved_method = linktime_resolve_virtual_method(link_info, CHECK); |
1225 runtime_resolve_virtual_method(result, resolved_method, |
1219 runtime_resolve_virtual_method(result, resolved_method, |
1226 link_info.resolved_klass(), |
1220 link_info.resolved_klass(), |
1236 |
1230 |
1237 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); |
1231 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); |
1238 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); |
1232 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); |
1239 |
1233 |
1240 // check if private interface method |
1234 // check if private interface method |
1241 KlassHandle resolved_klass = link_info.resolved_klass(); |
1235 Klass* resolved_klass = link_info.resolved_klass(); |
1242 KlassHandle current_klass = link_info.current_klass(); |
1236 Klass* current_klass = link_info.current_klass(); |
1243 |
1237 |
1244 // This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method |
1238 // This is impossible, if resolve_klass is an interface, we've thrown icce in resolve_method |
1245 if (resolved_klass->is_interface() && resolved_method->is_private()) { |
1239 if (resolved_klass->is_interface() && resolved_method->is_private()) { |
1246 ResourceMark rm(THREAD); |
1240 ResourceMark rm(THREAD); |
1247 char buf[200]; |
1241 char buf[200]; |
1248 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s", |
1242 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s", |
1249 Method::name_and_sig_as_C_string(resolved_klass(), |
1243 Method::name_and_sig_as_C_string(resolved_klass, |
1250 resolved_method->name(), |
1244 resolved_method->name(), |
1251 resolved_method->signature()), |
1245 resolved_method->signature()), |
1252 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name())); |
1246 (current_klass == NULL ? "<NULL>" : current_klass->internal_name())); |
1253 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1247 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1254 } |
1248 } |
1255 |
1249 |
1256 // check if not static |
1250 // check if not static |
1257 if (resolved_method->is_static()) { |
1251 if (resolved_method->is_static()) { |
1258 ResourceMark rm(THREAD); |
1252 ResourceMark rm(THREAD); |
1259 char buf[200]; |
1253 char buf[200]; |
1260 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), |
1254 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass, |
1261 resolved_method->name(), |
1255 resolved_method->name(), |
1262 resolved_method->signature())); |
1256 resolved_method->signature())); |
1263 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1257 THROW_MSG_NULL(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1264 } |
1258 } |
1265 |
1259 |
1266 if (log_develop_is_enabled(Trace, vtables)) { |
1260 if (log_develop_is_enabled(Trace, vtables)) { |
1267 trace_method_resolution("invokevirtual resolved method: caller-class:", |
1261 trace_method_resolution("invokevirtual resolved method: caller-class:", |
1323 |
1317 |
1324 // check if method exists |
1318 // check if method exists |
1325 if (selected_method.is_null()) { |
1319 if (selected_method.is_null()) { |
1326 ResourceMark rm(THREAD); |
1320 ResourceMark rm(THREAD); |
1327 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1321 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1328 Method::name_and_sig_as_C_string(resolved_klass(), |
1322 Method::name_and_sig_as_C_string(resolved_klass, |
1329 resolved_method->name(), |
1323 resolved_method->name(), |
1330 resolved_method->signature())); |
1324 resolved_method->signature())); |
1331 } |
1325 } |
1332 |
1326 |
1333 // check if abstract |
1327 // check if abstract |
1334 if (check_null_and_abstract && selected_method->is_abstract()) { |
1328 if (check_null_and_abstract && selected_method->is_abstract()) { |
1335 ResourceMark rm(THREAD); |
1329 ResourceMark rm(THREAD); |
1336 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1330 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1337 Method::name_and_sig_as_C_string(resolved_klass(), |
1331 Method::name_and_sig_as_C_string(resolved_klass, |
1338 selected_method->name(), |
1332 selected_method->name(), |
1339 selected_method->signature())); |
1333 selected_method->signature())); |
1340 } |
1334 } |
1341 |
1335 |
1342 if (log_develop_is_enabled(Trace, vtables)) { |
1336 if (log_develop_is_enabled(Trace, vtables)) { |
1343 trace_method_resolution("invokevirtual selected method: receiver-class:", |
1337 trace_method_resolution("invokevirtual selected method: receiver-class:", |
1344 recv_klass, resolved_klass, selected_method, |
1338 recv_klass, resolved_klass, selected_method, |
1346 } |
1340 } |
1347 // setup result |
1341 // setup result |
1348 result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); |
1342 result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); |
1349 } |
1343 } |
1350 |
1344 |
1351 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, |
1345 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, Klass* recv_klass, |
1352 const LinkInfo& link_info, |
1346 const LinkInfo& link_info, |
1353 bool check_null_and_abstract, TRAPS) { |
1347 bool check_null_and_abstract, TRAPS) { |
1354 // throws linktime exceptions |
1348 // throws linktime exceptions |
1355 methodHandle resolved_method = linktime_resolve_interface_method(link_info, CHECK); |
1349 methodHandle resolved_method = linktime_resolve_interface_method(link_info, CHECK); |
1356 runtime_resolve_interface_method(result, resolved_method,link_info.resolved_klass(), |
1350 runtime_resolve_interface_method(result, resolved_method,link_info.resolved_klass(), |
1368 } |
1362 } |
1369 |
1363 |
1370 // throws runtime exceptions |
1364 // throws runtime exceptions |
1371 void LinkResolver::runtime_resolve_interface_method(CallInfo& result, |
1365 void LinkResolver::runtime_resolve_interface_method(CallInfo& result, |
1372 const methodHandle& resolved_method, |
1366 const methodHandle& resolved_method, |
1373 KlassHandle resolved_klass, |
1367 Klass* resolved_klass, |
1374 Handle recv, |
1368 Handle recv, |
1375 KlassHandle recv_klass, |
1369 Klass* recv_klass, |
1376 bool check_null_and_abstract, TRAPS) { |
1370 bool check_null_and_abstract, TRAPS) { |
1377 // check if receiver exists |
1371 // check if receiver exists |
1378 if (check_null_and_abstract && recv.is_null()) { |
1372 if (check_null_and_abstract && recv.is_null()) { |
1379 THROW(vmSymbols::java_lang_NullPointerException()); |
1373 THROW(vmSymbols::java_lang_NullPointerException()); |
1380 } |
1374 } |
1381 |
1375 |
1382 // check if receiver klass implements the resolved interface |
1376 // check if receiver klass implements the resolved interface |
1383 if (!recv_klass->is_subtype_of(resolved_klass())) { |
1377 if (!recv_klass->is_subtype_of(resolved_klass)) { |
1384 ResourceMark rm(THREAD); |
1378 ResourceMark rm(THREAD); |
1385 char buf[200]; |
1379 char buf[200]; |
1386 jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s", |
1380 jio_snprintf(buf, sizeof(buf), "Class %s does not implement the requested interface %s", |
1387 recv_klass()->external_name(), |
1381 recv_klass->external_name(), |
1388 resolved_klass()->external_name()); |
1382 resolved_klass->external_name()); |
1389 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1383 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
1390 } |
1384 } |
1391 |
1385 |
1392 // do lookup based on receiver klass |
1386 // do lookup based on receiver klass |
1393 // This search must match the linktime preparation search for itable initialization |
1387 // This search must match the linktime preparation search for itable initialization |
1403 } |
1397 } |
1404 // check if method exists |
1398 // check if method exists |
1405 if (sel_method.is_null()) { |
1399 if (sel_method.is_null()) { |
1406 ResourceMark rm(THREAD); |
1400 ResourceMark rm(THREAD); |
1407 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1401 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1408 Method::name_and_sig_as_C_string(recv_klass(), |
1402 Method::name_and_sig_as_C_string(recv_klass, |
1409 resolved_method->name(), |
1403 resolved_method->name(), |
1410 resolved_method->signature())); |
1404 resolved_method->signature())); |
1411 } |
1405 } |
1412 // check access |
1406 // check access |
1413 // Throw Illegal Access Error if sel_method is not public. |
1407 // Throw Illegal Access Error if sel_method is not public. |
1414 if (!sel_method->is_public()) { |
1408 if (!sel_method->is_public()) { |
1415 ResourceMark rm(THREAD); |
1409 ResourceMark rm(THREAD); |
1416 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1410 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1417 Method::name_and_sig_as_C_string(recv_klass(), |
1411 Method::name_and_sig_as_C_string(recv_klass, |
1418 sel_method->name(), |
1412 sel_method->name(), |
1419 sel_method->signature())); |
1413 sel_method->signature())); |
1420 } |
1414 } |
1421 // check if abstract |
1415 // check if abstract |
1422 if (check_null_and_abstract && sel_method->is_abstract()) { |
1416 if (check_null_and_abstract && sel_method->is_abstract()) { |
1423 ResourceMark rm(THREAD); |
1417 ResourceMark rm(THREAD); |
1424 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1418 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1425 Method::name_and_sig_as_C_string(recv_klass(), |
1419 Method::name_and_sig_as_C_string(recv_klass, |
1426 sel_method->name(), |
1420 sel_method->name(), |
1427 sel_method->signature())); |
1421 sel_method->signature())); |
1428 } |
1422 } |
1429 |
1423 |
1430 if (log_develop_is_enabled(Trace, itables)) { |
1424 if (log_develop_is_enabled(Trace, itables)) { |
1431 trace_method_resolution("invokeinterface selected method: receiver-class:", |
1425 trace_method_resolution("invokeinterface selected method: receiver-class:", |
1432 recv_klass, resolved_klass, sel_method, true); |
1426 recv_klass, resolved_klass, sel_method, true); |
1587 void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, |
1581 void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, |
1588 const constantPoolHandle& pool, int index, |
1582 const constantPoolHandle& pool, int index, |
1589 TRAPS) { |
1583 TRAPS) { |
1590 |
1584 |
1591 LinkInfo link_info(pool, index, CHECK); |
1585 LinkInfo link_info(pool, index, CHECK); |
1592 KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); |
1586 Klass* recvrKlass = recv.is_null() ? (Klass*)NULL : recv->klass(); |
1593 resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); |
1587 resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); |
1594 } |
1588 } |
1595 |
1589 |
1596 |
1590 |
1597 void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) { |
1591 void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) { |
1598 LinkInfo link_info(pool, index, CHECK); |
1592 LinkInfo link_info(pool, index, CHECK); |
1599 KlassHandle recvrKlass (THREAD, recv.is_null() ? (Klass*)NULL : recv->klass()); |
1593 Klass* recvrKlass = recv.is_null() ? (Klass*)NULL : recv->klass(); |
1600 resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); |
1594 resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); |
1601 } |
1595 } |
1602 |
1596 |
1603 |
1597 |
1604 void LinkResolver::resolve_invokehandle(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { |
1598 void LinkResolver::resolve_invokehandle(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { |
1614 |
1608 |
1615 void LinkResolver::resolve_handle_call(CallInfo& result, |
1609 void LinkResolver::resolve_handle_call(CallInfo& result, |
1616 const LinkInfo& link_info, |
1610 const LinkInfo& link_info, |
1617 TRAPS) { |
1611 TRAPS) { |
1618 // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar |
1612 // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...) or similar |
1619 KlassHandle resolved_klass = link_info.resolved_klass(); |
1613 Klass* resolved_klass = link_info.resolved_klass(); |
1620 assert(resolved_klass() == SystemDictionary::MethodHandle_klass() || |
1614 assert(resolved_klass == SystemDictionary::MethodHandle_klass() || |
1621 resolved_klass() == SystemDictionary::VarHandle_klass(), ""); |
1615 resolved_klass == SystemDictionary::VarHandle_klass(), ""); |
1622 assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), ""); |
1616 assert(MethodHandles::is_signature_polymorphic_name(link_info.name()), ""); |
1623 Handle resolved_appendix; |
1617 Handle resolved_appendix; |
1624 Handle resolved_method_type; |
1618 Handle resolved_method_type; |
1625 methodHandle resolved_method = lookup_polymorphic_method(link_info, |
1619 methodHandle resolved_method = lookup_polymorphic_method(link_info, |
1626 &resolved_appendix, &resolved_method_type, CHECK); |
1620 &resolved_appendix, &resolved_method_type, CHECK); |