Mercurial > hg > truffle
comparison src/share/vm/interpreter/linkResolver.cpp @ 13413:7a58803b5069
8026066: ICCE for invokeinterface static
Reviewed-by: coleenp, lfoltan, hseigel
author | acorn |
---|---|
date | Tue, 03 Dec 2013 08:36:15 -0800 |
parents | 22eaa15b7960 |
children | 379f11bc04fc |
comparison
equal
deleted
inserted
replaced
13412:6ce6a0d23467 | 13413:7a58803b5069 |
---|---|
240 // | 240 // |
241 // According to JVM spec. $5.4.3c & $5.4.3d | 241 // According to JVM spec. $5.4.3c & $5.4.3d |
242 | 242 |
243 // Look up method in klasses, including static methods | 243 // Look up method in klasses, including static methods |
244 // Then look up local default methods | 244 // Then look up local default methods |
245 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { | 245 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, bool checkpolymorphism, TRAPS) { |
246 Method* result_oop = klass->uncached_lookup_method(name, signature); | 246 Method* result_oop = klass->uncached_lookup_method(name, signature); |
247 if (result_oop == NULL) { | 247 if (result_oop == NULL) { |
248 Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); | 248 Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); |
249 if (default_methods != NULL) { | 249 if (default_methods != NULL) { |
250 result_oop = InstanceKlass::find_method(default_methods, name, signature); | 250 result_oop = InstanceKlass::find_method(default_methods, name, signature); |
251 } | 251 } |
252 } | 252 } |
253 | 253 |
254 if (EnableInvokeDynamic && result_oop != NULL) { | 254 if (checkpolymorphism && EnableInvokeDynamic && result_oop != NULL) { |
255 vmIntrinsics::ID iid = result_oop->intrinsic_id(); | 255 vmIntrinsics::ID iid = result_oop->intrinsic_id(); |
256 if (MethodHandles::is_signature_polymorphic(iid)) { | 256 if (MethodHandles::is_signature_polymorphic(iid)) { |
257 // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method. | 257 // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method. |
258 return; | 258 return; |
259 } | 259 } |
501 return; | 501 return; |
502 } | 502 } |
503 } | 503 } |
504 | 504 |
505 if (code == Bytecodes::_invokeinterface) { | 505 if (code == Bytecodes::_invokeinterface) { |
506 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); | 506 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); |
507 } else if (code == Bytecodes::_invokevirtual) { | 507 } else if (code == Bytecodes::_invokevirtual) { |
508 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); | 508 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, true, CHECK); |
509 } else if (!resolved_klass->is_interface()) { | |
510 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); | |
509 } else { | 511 } else { |
510 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, false, CHECK); | 512 bool nostatics = (code == Bytecodes::_invokestatic) ? false : true; |
513 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, nostatics, CHECK); | |
511 } | 514 } |
512 } | 515 } |
513 | 516 |
514 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, | 517 void LinkResolver::resolve_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
515 Symbol* method_name, Symbol* method_signature, | 518 Symbol* method_name, Symbol* method_signature, |
526 resolved_klass()->external_name()); | 529 resolved_klass()->external_name()); |
527 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | 530 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
528 } | 531 } |
529 | 532 |
530 // 2. lookup method in resolved klass and its super klasses | 533 // 2. lookup method in resolved klass and its super klasses |
531 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); | 534 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, true, CHECK); |
532 | 535 |
533 if (resolved_method.is_null()) { // not found in the class hierarchy | 536 if (resolved_method.is_null()) { // not found in the class hierarchy |
534 // 3. lookup method in all the interfaces implemented by the resolved klass | 537 // 3. lookup method in all the interfaces implemented by the resolved klass |
535 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); | 538 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
536 | 539 |
610 void LinkResolver::resolve_interface_method(methodHandle& resolved_method, | 613 void LinkResolver::resolve_interface_method(methodHandle& resolved_method, |
611 KlassHandle resolved_klass, | 614 KlassHandle resolved_klass, |
612 Symbol* method_name, | 615 Symbol* method_name, |
613 Symbol* method_signature, | 616 Symbol* method_signature, |
614 KlassHandle current_klass, | 617 KlassHandle current_klass, |
615 bool check_access, TRAPS) { | 618 bool check_access, |
619 bool nostatics, TRAPS) { | |
616 | 620 |
617 // check if klass is interface | 621 // check if klass is interface |
618 if (!resolved_klass->is_interface()) { | 622 if (!resolved_klass->is_interface()) { |
619 ResourceMark rm(THREAD); | 623 ResourceMark rm(THREAD); |
620 char buf[200]; | 624 char buf[200]; |
621 jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name()); | 625 jio_snprintf(buf, sizeof(buf), "Found class %s, but interface was expected", resolved_klass()->external_name()); |
622 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | 626 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
623 } | 627 } |
624 | 628 |
625 // lookup method in this interface or its super, java.lang.Object | 629 // lookup method in this interface or its super, java.lang.Object |
626 lookup_instance_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, CHECK); | 630 // JDK8: also look for static methods |
631 lookup_method_in_klasses(resolved_method, resolved_klass, method_name, method_signature, false, CHECK); | |
627 | 632 |
628 if (resolved_method.is_null()) { | 633 if (resolved_method.is_null()) { |
629 // lookup method in all the super-interfaces | 634 // lookup method in all the super-interfaces |
630 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); | 635 lookup_method_in_interfaces(resolved_method, resolved_klass, method_name, method_signature, CHECK); |
631 if (resolved_method.is_null()) { | 636 if (resolved_method.is_null()) { |
635 Method::name_and_sig_as_C_string(resolved_klass(), | 640 Method::name_and_sig_as_C_string(resolved_klass(), |
636 method_name, | 641 method_name, |
637 method_signature)); | 642 method_signature)); |
638 } | 643 } |
639 } | 644 } |
645 | |
646 if (nostatics && resolved_method->is_static()) { | |
647 ResourceMark rm(THREAD); | |
648 char buf[200]; | |
649 jio_snprintf(buf, sizeof(buf), "Expected instance not static method %s", Method::name_and_sig_as_C_string(resolved_klass(), | |
650 resolved_method->name(), | |
651 resolved_method->signature())); | |
652 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | |
653 } | |
654 | |
640 | 655 |
641 if (check_access) { | 656 if (check_access) { |
642 // JDK8 adds non-public interface methods, and accessability check requirement | 657 // JDK8 adds non-public interface methods, and accessability check requirement |
643 assert(current_klass.not_null() , "current_klass should not be null"); | 658 assert(current_klass.not_null() , "current_klass should not be null"); |
644 | 659 |
862 // throws linktime exceptions | 877 // throws linktime exceptions |
863 void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass, | 878 void LinkResolver::linktime_resolve_static_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
864 Symbol* method_name, Symbol* method_signature, | 879 Symbol* method_name, Symbol* method_signature, |
865 KlassHandle current_klass, bool check_access, TRAPS) { | 880 KlassHandle current_klass, bool check_access, TRAPS) { |
866 | 881 |
867 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); | 882 if (!resolved_klass->is_interface()) { |
883 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); | |
884 } else { | |
885 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); | |
886 } | |
868 assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); | 887 assert(resolved_method->name() != vmSymbols::class_initializer_name(), "should have been checked in verifier"); |
869 | 888 |
870 // check if static | 889 // check if static |
871 if (!resolved_method->is_static()) { | 890 if (!resolved_method->is_static()) { |
872 ResourceMark rm(THREAD); | 891 ResourceMark rm(THREAD); |
896 // local private method invocation, for classes and interfaces | 915 // local private method invocation, for classes and interfaces |
897 // superclass.method, which can also resolve to a default method | 916 // superclass.method, which can also resolve to a default method |
898 // and the selected method is recalculated relative to the direct superclass | 917 // and the selected method is recalculated relative to the direct superclass |
899 // superinterface.method, which explicitly does not check shadowing | 918 // superinterface.method, which explicitly does not check shadowing |
900 | 919 |
901 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); | 920 if (!resolved_klass->is_interface()) { |
921 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, false, CHECK); | |
922 } else { | |
923 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); | |
924 } | |
902 | 925 |
903 // check if method name is <init>, that it is found in same klass as static type | 926 // check if method name is <init>, that it is found in same klass as static type |
904 if (resolved_method->name() == vmSymbols::object_initializer_name() && | 927 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
905 resolved_method->method_holder() != resolved_klass()) { | 928 resolved_method->method_holder() != resolved_klass()) { |
906 ResourceMark rm(THREAD); | 929 ResourceMark rm(THREAD); |
1217 | 1240 |
1218 // throws linktime exceptions | 1241 // throws linktime exceptions |
1219 void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, | 1242 void LinkResolver::linktime_resolve_interface_method(methodHandle& resolved_method, KlassHandle resolved_klass, Symbol* method_name, |
1220 Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { | 1243 Symbol* method_signature, KlassHandle current_klass, bool check_access, TRAPS) { |
1221 // normal interface method resolution | 1244 // normal interface method resolution |
1222 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); | 1245 resolve_interface_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, true, CHECK); |
1223 | 1246 |
1224 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); | 1247 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); |
1225 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); | 1248 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); |
1226 } | 1249 } |
1227 | 1250 |