Mercurial > hg > truffle
comparison src/share/vm/classfile/defaultMethods.cpp @ 12318:36b97be47bde
8011311: Private interface methods. Default conflicts:ICCE. no erased_super_default.
Reviewed-by: coleenp, bharadwaj, minqi
author | acorn |
---|---|
date | Tue, 01 Oct 2013 08:10:42 -0400 |
parents | 42863137168c |
children | 268e7a2178d7 |
comparison
equal
deleted
inserted
replaced
12317:a5ac0873476c | 12318:36b97be47bde |
---|---|
323 GrowableArray<Pair<Method*,QualifiedState> > _members; | 323 GrowableArray<Pair<Method*,QualifiedState> > _members; |
324 ResourceHashtable<Method*, int> _member_index; | 324 ResourceHashtable<Method*, int> _member_index; |
325 | 325 |
326 Method* _selected_target; // Filled in later, if a unique target exists | 326 Method* _selected_target; // Filled in later, if a unique target exists |
327 Symbol* _exception_message; // If no unique target is found | 327 Symbol* _exception_message; // If no unique target is found |
328 Symbol* _exception_name; // If no unique target is found | |
328 | 329 |
329 bool contains_method(Method* method) { | 330 bool contains_method(Method* method) { |
330 int* lookup = _member_index.get(method); | 331 int* lookup = _member_index.get(method); |
331 return lookup != NULL; | 332 return lookup != NULL; |
332 } | 333 } |
348 Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const; | 349 Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const; |
349 | 350 |
350 public: | 351 public: |
351 | 352 |
352 MethodFamily() | 353 MethodFamily() |
353 : _selected_target(NULL), _exception_message(NULL) {} | 354 : _selected_target(NULL), _exception_message(NULL), _exception_name(NULL) {} |
354 | 355 |
355 void set_target_if_empty(Method* m) { | 356 void set_target_if_empty(Method* m) { |
356 if (_selected_target == NULL && !m->is_overpass()) { | 357 if (_selected_target == NULL && !m->is_overpass()) { |
357 _selected_target = m; | 358 _selected_target = m; |
358 } | 359 } |
381 bool has_target() const { return _selected_target != NULL; } | 382 bool has_target() const { return _selected_target != NULL; } |
382 bool throws_exception() { return _exception_message != NULL; } | 383 bool throws_exception() { return _exception_message != NULL; } |
383 | 384 |
384 Method* get_selected_target() { return _selected_target; } | 385 Method* get_selected_target() { return _selected_target; } |
385 Symbol* get_exception_message() { return _exception_message; } | 386 Symbol* get_exception_message() { return _exception_message; } |
387 Symbol* get_exception_name() { return _exception_name; } | |
386 | 388 |
387 // Either sets the target or the exception error message | 389 // Either sets the target or the exception error message |
388 void determine_target(InstanceKlass* root, TRAPS) { | 390 void determine_target(InstanceKlass* root, TRAPS) { |
389 if (has_target() || throws_exception()) { | 391 if (has_target() || throws_exception()) { |
390 return; | 392 return; |
398 } | 400 } |
399 } | 401 } |
400 | 402 |
401 if (qualified_methods.length() == 0) { | 403 if (qualified_methods.length() == 0) { |
402 _exception_message = generate_no_defaults_message(CHECK); | 404 _exception_message = generate_no_defaults_message(CHECK); |
405 _exception_name = vmSymbols::java_lang_AbstractMethodError(); | |
403 } else if (qualified_methods.length() == 1) { | 406 } else if (qualified_methods.length() == 1) { |
404 Method* method = qualified_methods.at(0); | 407 Method* method = qualified_methods.at(0); |
405 if (method->is_abstract()) { | 408 if (method->is_abstract()) { |
406 _exception_message = generate_abstract_method_message(method, CHECK); | 409 _exception_message = generate_abstract_method_message(method, CHECK); |
410 _exception_name = vmSymbols::java_lang_AbstractMethodError(); | |
407 } else { | 411 } else { |
408 _selected_target = qualified_methods.at(0); | 412 _selected_target = qualified_methods.at(0); |
409 } | 413 } |
410 } else { | 414 } else { |
411 _exception_message = generate_conflicts_message(&qualified_methods,CHECK); | 415 _exception_message = generate_conflicts_message(&qualified_methods,CHECK); |
416 _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError(); | |
412 } | 417 } |
413 | 418 |
414 assert((has_target() ^ throws_exception()) == 1, | 419 assert((has_target() ^ throws_exception()) == 1, |
415 "One and only one must be true"); | 420 "One and only one must be true"); |
416 } | 421 } |
457 str->print_cr(""); | 462 str->print_cr(""); |
458 } | 463 } |
459 | 464 |
460 void print_exception(outputStream* str, int indent) { | 465 void print_exception(outputStream* str, int indent) { |
461 assert(throws_exception(), "Should be called otherwise"); | 466 assert(throws_exception(), "Should be called otherwise"); |
467 assert(_exception_name != NULL, "exception_name should be set"); | |
462 streamIndentor si(str, indent * 2); | 468 streamIndentor si(str, indent * 2); |
463 str->indent().print_cr("%s", _exception_message->as_C_string()); | 469 str->indent().print_cr("%s: %s", _exception_name->as_C_string(), _exception_message->as_C_string()); |
464 } | 470 } |
465 #endif // ndef PRODUCT | 471 #endif // ndef PRODUCT |
466 }; | 472 }; |
467 | 473 |
468 Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const { | 474 Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const { |
668 bool visit() { | 674 bool visit() { |
669 PseudoScope* scope = PseudoScope::cast(current_data()); | 675 PseudoScope* scope = PseudoScope::cast(current_data()); |
670 InstanceKlass* iklass = current_class(); | 676 InstanceKlass* iklass = current_class(); |
671 | 677 |
672 Method* m = iklass->find_method(_method_name, _method_signature); | 678 Method* m = iklass->find_method(_method_name, _method_signature); |
673 if (m != NULL) { | 679 // private interface methods are not candidates for default methods |
680 // invokespecial to private interface methods doesn't use default method logic | |
681 // future: take access controls into account for superclass methods | |
682 if (m != NULL && (!iklass->is_interface() || m->is_public())) { | |
674 if (_family == NULL) { | 683 if (_family == NULL) { |
675 _family = new StatefulMethodFamily(); | 684 _family = new StatefulMethodFamily(); |
676 } | 685 } |
677 | 686 |
678 if (iklass->is_interface()) { | 687 if (iklass->is_interface()) { |
780 tty->print_cr("Default method processing complete"); | 789 tty->print_cr("Default method processing complete"); |
781 } | 790 } |
782 #endif // ndef PRODUCT | 791 #endif // ndef PRODUCT |
783 } | 792 } |
784 | 793 |
785 /** | 794 |
786 * Interface inheritance rules were used to find a unique default method | |
787 * candidate for the resolved class. This | |
788 * method is only viable if it would also be in the set of default method | |
789 * candidates if we ran a full analysis on the current class. | |
790 * | |
791 * The only reason that the method would not be in the set of candidates for | |
792 * the current class is if that there's another matching method | |
793 * which is "more specific" than the found method -- i.e., one could find a | |
794 * path in the interface hierarchy in which the matching method appears | |
795 * before we get to '_target'. | |
796 * | |
797 * In order to determine this, we examine all of the implemented | |
798 * interfaces. If we find path that leads to the '_target' interface, then | |
799 * we examine that path to see if there are any methods that would shadow | |
800 * the selected method along that path. | |
801 */ | |
802 class ShadowChecker : public HierarchyVisitor<ShadowChecker> { | |
803 protected: | |
804 Thread* THREAD; | |
805 | |
806 InstanceKlass* _target; | |
807 | |
808 Symbol* _method_name; | |
809 InstanceKlass* _method_holder; | |
810 bool _found_shadow; | |
811 | |
812 | |
813 public: | |
814 | |
815 ShadowChecker(Thread* thread, Symbol* name, InstanceKlass* holder, | |
816 InstanceKlass* target) | |
817 : THREAD(thread), _method_name(name), _method_holder(holder), | |
818 _target(target), _found_shadow(false) {} | |
819 | |
820 void* new_node_data(InstanceKlass* cls) { return NULL; } | |
821 void free_node_data(void* data) { return; } | |
822 | |
823 bool visit() { | |
824 InstanceKlass* ik = current_class(); | |
825 if (ik == _target && current_depth() == 1) { | |
826 return false; // This was the specified super -- no need to search it | |
827 } | |
828 if (ik == _method_holder || ik == _target) { | |
829 // We found a path that should be examined to see if it shadows _method | |
830 if (path_has_shadow()) { | |
831 _found_shadow = true; | |
832 cancel_iteration(); | |
833 } | |
834 return false; // no need to continue up hierarchy | |
835 } | |
836 return true; | |
837 } | |
838 | |
839 virtual bool path_has_shadow() = 0; | |
840 bool found_shadow() { return _found_shadow; } | |
841 }; | |
842 | |
843 // Used for Invokespecial. | |
844 // Invokespecial is allowed to invoke a concrete interface method | |
845 // and can be used to disambuiguate among qualified candidates, | |
846 // which are methods in immediate superinterfaces, | |
847 // but may not be used to invoke a candidate that would be shadowed | |
848 // from the perspective of the caller. | |
849 // Invokespecial is also used in the overpass generation today | |
850 // We re-run the shadowchecker because we can't distinguish this case, | |
851 // but it should return the same answer, since the overpass target | |
852 // is now the invokespecial caller. | |
853 class ErasedShadowChecker : public ShadowChecker { | |
854 private: | |
855 bool path_has_shadow() { | |
856 | |
857 for (int i = current_depth() - 1; i > 0; --i) { | |
858 InstanceKlass* ik = class_at_depth(i); | |
859 | |
860 if (ik->is_interface()) { | |
861 int end; | |
862 int start = ik->find_method_by_name(_method_name, &end); | |
863 if (start != -1) { | |
864 return true; | |
865 } | |
866 } | |
867 } | |
868 return false; | |
869 } | |
870 public: | |
871 | |
872 ErasedShadowChecker(Thread* thread, Symbol* name, InstanceKlass* holder, | |
873 InstanceKlass* target) | |
874 : ShadowChecker(thread, name, holder, target) {} | |
875 }; | |
876 | |
877 // Find the unique qualified candidate from the perspective of the super_class | |
878 // which is the resolved_klass, which must be an immediate superinterface | |
879 // of klass | |
880 Method* find_erased_super_default(InstanceKlass* current_class, InstanceKlass* super_class, Symbol* method_name, Symbol* sig, TRAPS) { | |
881 | |
882 FindMethodsByErasedSig visitor(method_name, sig); | |
883 visitor.run(super_class); // find candidates from resolved_klass | |
884 | |
885 MethodFamily* family; | |
886 visitor.get_discovered_family(&family); | |
887 | |
888 if (family != NULL) { | |
889 family->determine_target(current_class, CHECK_NULL); // get target from current_class | |
890 | |
891 if (family->has_target()) { | |
892 Method* target = family->get_selected_target(); | |
893 InstanceKlass* holder = InstanceKlass::cast(target->method_holder()); | |
894 | |
895 // Verify that the identified method is valid from the context of | |
896 // the current class, which is the caller class for invokespecial | |
897 // link resolution, i.e. ensure there it is not shadowed. | |
898 // You can use invokespecial to disambiguate interface methods, but | |
899 // you can not use it to skip over an interface method that would shadow it. | |
900 ErasedShadowChecker checker(THREAD, target->name(), holder, super_class); | |
901 checker.run(current_class); | |
902 | |
903 if (checker.found_shadow()) { | |
904 #ifndef PRODUCT | |
905 if (TraceDefaultMethods) { | |
906 tty->print_cr(" Only candidate found was shadowed."); | |
907 } | |
908 #endif // ndef PRODUCT | |
909 THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), | |
910 "Accessible default method not found", NULL); | |
911 } else { | |
912 #ifndef PRODUCT | |
913 if (TraceDefaultMethods) { | |
914 family->print_sig_on(tty, target->signature(), 1); | |
915 } | |
916 #endif // ndef PRODUCT | |
917 return target; | |
918 } | |
919 } else { | |
920 assert(family->throws_exception(), "must have target or throw"); | |
921 THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), | |
922 family->get_exception_message()->as_C_string(), NULL); | |
923 } | |
924 } else { | |
925 // no method found | |
926 ResourceMark rm(THREAD); | |
927 THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), | |
928 Method::name_and_sig_as_C_string(current_class, | |
929 method_name, sig), NULL); | |
930 } | |
931 } | |
932 // This is called during linktime when we find an invokespecial call that | |
933 // refers to a direct superinterface. It indicates that we should find the | |
934 // default method in the hierarchy of that superinterface, and if that method | |
935 // would have been a candidate from the point of view of 'this' class, then we | |
936 // return that method. | |
937 // This logic assumes that the super is a direct superclass of the caller | |
938 Method* DefaultMethods::find_super_default( | |
939 Klass* cls, Klass* super, Symbol* method_name, Symbol* sig, TRAPS) { | |
940 | |
941 ResourceMark rm(THREAD); | |
942 | |
943 assert(cls != NULL && super != NULL, "Need real classes"); | |
944 | |
945 InstanceKlass* current_class = InstanceKlass::cast(cls); | |
946 InstanceKlass* super_class = InstanceKlass::cast(super); | |
947 | |
948 // Keep entire hierarchy alive for the duration of the computation | |
949 KeepAliveRegistrar keepAlive(THREAD); | |
950 KeepAliveVisitor loadKeepAlive(&keepAlive); | |
951 loadKeepAlive.run(current_class); // get hierarchy from current class | |
952 | |
953 #ifndef PRODUCT | |
954 if (TraceDefaultMethods) { | |
955 tty->print_cr("Finding super default method %s.%s%s from %s", | |
956 super_class->name()->as_C_string(), | |
957 method_name->as_C_string(), sig->as_C_string(), | |
958 current_class->name()->as_C_string()); | |
959 } | |
960 #endif // ndef PRODUCT | |
961 | |
962 assert(super_class->is_interface(), "only call for default methods"); | |
963 | |
964 Method* target = NULL; | |
965 target = find_erased_super_default(current_class, super_class, | |
966 method_name, sig, CHECK_NULL); | |
967 | |
968 #ifndef PRODUCT | |
969 if (target != NULL) { | |
970 if (TraceDefaultMethods) { | |
971 tty->print(" Returning "); | |
972 print_method(tty, target, true); | |
973 tty->print_cr(""); | |
974 } | |
975 } | |
976 #endif // ndef PRODUCT | |
977 return target; | |
978 } | |
979 | 795 |
980 #ifndef PRODUCT | 796 #ifndef PRODUCT |
981 // Return true is broad type is a covariant return of narrow type | 797 // Return true is broad type is a covariant return of narrow type |
982 static bool covariant_return_type(BasicType narrow, BasicType broad) { | 798 static bool covariant_return_type(BasicType narrow, BasicType broad) { |
983 if (narrow == broad) { | 799 if (narrow == broad) { |
1033 } | 849 } |
1034 assem._return(in.type()); | 850 assem._return(in.type()); |
1035 return parameter_count; | 851 return parameter_count; |
1036 } | 852 } |
1037 | 853 |
1038 static int assemble_abstract_method_error( | 854 static int assemble_method_error( |
1039 BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* message, TRAPS) { | 855 BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message, TRAPS) { |
1040 | 856 |
1041 Symbol* errorName = vmSymbols::java_lang_AbstractMethodError(); | |
1042 Symbol* init = vmSymbols::object_initializer_name(); | 857 Symbol* init = vmSymbols::object_initializer_name(); |
1043 Symbol* sig = vmSymbols::string_void_signature(); | 858 Symbol* sig = vmSymbols::string_void_signature(); |
1044 | 859 |
1045 BytecodeAssembler assem(buffer, cp); | 860 BytecodeAssembler assem(buffer, cp); |
1046 | 861 |
1148 if (selected->method_holder()->is_interface()) { | 963 if (selected->method_holder()->is_interface()) { |
1149 max_stack = assemble_redirect( | 964 max_stack = assemble_redirect( |
1150 &bpool, &buffer, slot->signature(), selected, CHECK); | 965 &bpool, &buffer, slot->signature(), selected, CHECK); |
1151 } | 966 } |
1152 } else if (method->throws_exception()) { | 967 } else if (method->throws_exception()) { |
1153 max_stack = assemble_abstract_method_error( | 968 max_stack = assemble_method_error(&bpool, &buffer, method->get_exception_name(), method->get_exception_message(), CHECK); |
1154 &bpool, &buffer, method->get_exception_message(), CHECK); | |
1155 } | 969 } |
1156 if (max_stack != 0) { | 970 if (max_stack != 0) { |
1157 AccessFlags flags = accessFlags_from( | 971 AccessFlags flags = accessFlags_from( |
1158 JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE); | 972 JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE); |
1159 Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(), | 973 Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(), |