21 * questions. |
21 * questions. |
22 * |
22 * |
23 */ |
23 */ |
24 |
24 |
25 #include "precompiled.hpp" |
25 #include "precompiled.hpp" |
|
26 #include "classfile/defaultMethods.hpp" |
26 #include "classfile/systemDictionary.hpp" |
27 #include "classfile/systemDictionary.hpp" |
27 #include "classfile/vmSymbols.hpp" |
28 #include "classfile/vmSymbols.hpp" |
28 #include "compiler/compileBroker.hpp" |
29 #include "compiler/compileBroker.hpp" |
29 #include "gc_interface/collectedHeap.inline.hpp" |
30 #include "gc_interface/collectedHeap.inline.hpp" |
30 #include "interpreter/bytecode.hpp" |
31 #include "interpreter/bytecode.hpp" |
402 |
403 |
403 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
404 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
404 Symbol* method_name, Symbol* method_signature, |
405 Symbol* method_name, Symbol* method_signature, |
405 KlassHandle current_klass, bool check_access, TRAPS) { |
406 KlassHandle current_klass, bool check_access, TRAPS) { |
406 |
407 |
407 // 1. check if klass is not interface |
|
408 if (resolved_klass->is_interface()) { |
|
409 ResourceMark rm(THREAD); |
|
410 char buf[200]; |
|
411 jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", Klass::cast(resolved_klass())->external_name()); |
|
412 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
|
413 } |
|
414 |
|
415 Handle nested_exception; |
408 Handle nested_exception; |
416 |
409 |
417 // 2. lookup method in resolved klass and its super klasses |
410 // 1. lookup method in resolved klass and its super klasses |
418 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
411 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
419 |
412 |
420 if (resolved_method.is_null()) { // not found in the class hierarchy |
413 if (resolved_method.is_null()) { // not found in the class hierarchy |
421 // 3. lookup method in all the interfaces implemented by the resolved klass |
414 // 2. lookup method in all the interfaces implemented by the resolved klass |
422 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
415 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
423 |
416 |
424 if (resolved_method.is_null()) { |
417 if (resolved_method.is_null()) { |
425 // JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc |
418 // JSR 292: see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc |
426 lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature, |
419 lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature, |
430 CLEAR_PENDING_EXCEPTION; |
423 CLEAR_PENDING_EXCEPTION; |
431 } |
424 } |
432 } |
425 } |
433 |
426 |
434 if (resolved_method.is_null()) { |
427 if (resolved_method.is_null()) { |
435 // 4. method lookup failed |
428 // 3. method lookup failed |
436 ResourceMark rm(THREAD); |
429 ResourceMark rm(THREAD); |
437 THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), |
430 THROW_MSG_CAUSE(vmSymbols::java_lang_NoSuchMethodError(), |
438 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
431 Method::name_and_sig_as_C_string(Klass::cast(resolved_klass()), |
439 method_name, |
432 method_name, |
440 method_signature), |
433 method_signature), |
441 nested_exception); |
434 nested_exception); |
442 } |
435 } |
|
436 } |
|
437 |
|
438 // 4. check if klass is not interface |
|
439 if (resolved_klass->is_interface() && resolved_method->is_abstract()) { |
|
440 ResourceMark rm(THREAD); |
|
441 char buf[200]; |
|
442 jio_snprintf(buf, sizeof(buf), "Found interface %s, but class was expected", |
|
443 resolved_klass()->external_name()); |
|
444 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
443 } |
445 } |
444 |
446 |
445 // 5. check if method is concrete |
447 // 5. check if method is concrete |
446 if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { |
448 if (resolved_method->is_abstract() && !resolved_klass->is_abstract()) { |
447 ResourceMark rm(THREAD); |
449 ResourceMark rm(THREAD); |
741 // throws linktime exceptions |
743 // throws linktime exceptions |
742 void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
744 void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
743 Symbol* method_name, Symbol* method_signature, |
745 Symbol* method_name, Symbol* method_signature, |
744 KlassHandle current_klass, bool check_access, TRAPS) { |
746 KlassHandle current_klass, bool check_access, TRAPS) { |
745 |
747 |
|
748 if (resolved_klass->is_interface() && current_klass() != NULL) { |
|
749 // If the target class is a direct interface, treat this as a "super" |
|
750 // default call. |
|
751 // |
|
752 // If the current method is an overpass that happens to call a direct |
|
753 // super-interface's method, then we'll end up rerunning the default method |
|
754 // analysis even though we don't need to, but that's ok since it will end |
|
755 // up with the same answer. |
|
756 InstanceKlass* ik = InstanceKlass::cast(current_klass()); |
|
757 Array<Klass*>* interfaces = ik->local_interfaces(); |
|
758 int num_interfaces = interfaces->length(); |
|
759 for (int index = 0; index < num_interfaces; index++) { |
|
760 if (interfaces->at(index) == resolved_klass()) { |
|
761 Method* method = DefaultMethods::find_super_default(current_klass(), |
|
762 resolved_klass(), method_name, method_signature, CHECK); |
|
763 resolved_method = methodHandle(THREAD, method); |
|
764 return; |
|
765 } |
|
766 } |
|
767 } |
|
768 |
746 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
769 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
747 |
770 |
748 // check if method name is <init>, that it is found in same klass as static type |
771 // check if method name is <init>, that it is found in same klass as static type |
749 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
772 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
750 resolved_method->method_holder() != resolved_klass()) { |
773 resolved_method->method_holder() != resolved_klass()) { |
782 |
805 |
783 // check if this is an old-style super call and do a new lookup if so |
806 // check if this is an old-style super call and do a new lookup if so |
784 { KlassHandle method_klass = KlassHandle(THREAD, |
807 { KlassHandle method_klass = KlassHandle(THREAD, |
785 resolved_method->method_holder()); |
808 resolved_method->method_holder()); |
786 |
809 |
787 if (check_access && |
810 const bool direct_calling_default_method = |
|
811 resolved_klass() != NULL && resolved_method() != NULL && |
|
812 resolved_klass->is_interface() && !resolved_method->is_abstract(); |
|
813 |
|
814 if (!direct_calling_default_method && |
|
815 check_access && |
788 // a) check if ACC_SUPER flag is set for the current class |
816 // a) check if ACC_SUPER flag is set for the current class |
789 current_klass->is_super() && |
817 current_klass->is_super() && |
790 // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!) |
818 // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!) |
791 current_klass->is_subtype_of(method_klass()) && current_klass() != method_klass() && |
819 current_klass->is_subtype_of(method_klass()) && |
|
820 current_klass() != method_klass() && |
792 // c) check if the method is not <init> |
821 // c) check if the method is not <init> |
793 resolved_method->name() != vmSymbols::object_initializer_name()) { |
822 resolved_method->name() != vmSymbols::object_initializer_name()) { |
794 // Lookup super method |
823 // Lookup super method |
795 KlassHandle super_klass(THREAD, current_klass->super()); |
824 KlassHandle super_klass(THREAD, current_klass->super()); |
796 lookup_instance_method_in_klasses(sel_method, super_klass, |
825 lookup_instance_method_in_klasses(sel_method, super_klass, |