Mercurial > hg > truffle
comparison src/share/vm/interpreter/linkResolver.cpp @ 6934:4735d2c84362
7200776: Implement default methods in interfaces
Summary: Add generic type analysis and default method selection algorithms
Reviewed-by: coleenp, acorn
author | kamg |
---|---|
date | Thu, 11 Oct 2012 12:25:42 -0400 |
parents | f6b0eb4e44cf |
children | 18fb7da42534 |
comparison
equal
deleted
inserted
replaced
6921:a1b8cf9cf970 | 6934:4735d2c84362 |
---|---|
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, |