Mercurial > hg > graal-jvmci-8
comparison src/share/vm/interpreter/linkResolver.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 | 190899198332 |
children | 359f7e70ae7f ac9cb1d5a202 |
comparison
equal
deleted
inserted
replaced
12317:a5ac0873476c | 12318:36b97be47bde |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. | |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 3 * |
5 * This code is free software; you can redistribute it and/or modify it | 4 * This code is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License version 2 only, as | 5 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 6 * published by the Free Software Foundation. |
571 method_signature)); | 570 method_signature)); |
572 } | 571 } |
573 } | 572 } |
574 | 573 |
575 if (check_access) { | 574 if (check_access) { |
575 // JDK8 adds non-public interface methods, and accessability check requirement | |
576 assert(current_klass.not_null() , "current_klass should not be null"); | |
577 | |
578 // check if method can be accessed by the referring class | |
579 check_method_accessability(current_klass, | |
580 resolved_klass, | |
581 KlassHandle(THREAD, resolved_method->method_holder()), | |
582 resolved_method, | |
583 CHECK); | |
584 | |
576 HandleMark hm(THREAD); | 585 HandleMark hm(THREAD); |
577 Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader()); | 586 Handle loader (THREAD, InstanceKlass::cast(current_klass())->class_loader()); |
578 Handle class_loader (THREAD, resolved_method->method_holder()->class_loader()); | 587 Handle class_loader (THREAD, resolved_method->method_holder()->class_loader()); |
579 { | 588 { |
580 ResourceMark rm(THREAD); | 589 ResourceMark rm(THREAD); |
602 target, failed_type_name); | 611 target, failed_type_name); |
603 THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); | 612 THROW_MSG(vmSymbols::java_lang_LinkageError(), buf); |
604 } | 613 } |
605 } | 614 } |
606 } | 615 } |
616 | |
617 if (TraceItables && Verbose) { | |
618 ResourceMark rm(THREAD); | |
619 tty->print("invokeinterface resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", | |
620 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()), | |
621 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | |
622 Method::name_and_sig_as_C_string(resolved_klass(), | |
623 resolved_method->name(), | |
624 resolved_method->signature()), | |
625 resolved_method->method_holder()->internal_name() | |
626 ); | |
627 resolved_method->access_flags().print_on(tty); | |
628 tty->cr(); | |
629 } | |
607 } | 630 } |
608 | 631 |
609 //------------------------------------------------------------------------------------------------------------------------ | 632 //------------------------------------------------------------------------------------------------------------------------ |
610 // Field resolution | 633 // Field resolution |
611 | 634 |
793 // throws linktime exceptions | 816 // throws linktime exceptions |
794 void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass, | 817 void LinkResolver::linktime_resolve_special_method(methodHandle& resolved_method, KlassHandle resolved_klass, |
795 Symbol* method_name, Symbol* method_signature, | 818 Symbol* method_name, Symbol* method_signature, |
796 KlassHandle current_klass, bool check_access, TRAPS) { | 819 KlassHandle current_klass, bool check_access, TRAPS) { |
797 | 820 |
798 if (resolved_klass->is_interface() && current_klass() != NULL) { | 821 // Invokespecial is called for multiple special reasons: |
799 // If the target class is a direct interface, treat this as a "super" | 822 // <init> |
800 // default call. | 823 // local private method invocation, for classes and interfaces |
801 // | 824 // superclass.method, which can also resolve to a default method |
802 // If the current method is an overpass that happens to call a direct | 825 // and the selected method is recalculated relative to the direct superclass |
803 // super-interface's method, then we'll end up rerunning the default method | 826 // superinterface.method, which explicitly does not check shadowing |
804 // analysis even though we don't need to, but that's ok since it will end | |
805 // up with the same answer. | |
806 InstanceKlass* ik = InstanceKlass::cast(current_klass()); | |
807 Array<Klass*>* interfaces = ik->local_interfaces(); | |
808 int num_interfaces = interfaces->length(); | |
809 for (int index = 0; index < num_interfaces; index++) { | |
810 if (interfaces->at(index) == resolved_klass()) { | |
811 Method* method = DefaultMethods::find_super_default(current_klass(), | |
812 resolved_klass(), method_name, method_signature, CHECK); | |
813 resolved_method = methodHandle(THREAD, method); | |
814 return; | |
815 } | |
816 } | |
817 } | |
818 | 827 |
819 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); | 828 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
820 | 829 |
821 // check if method name is <init>, that it is found in same klass as static type | 830 // check if method name is <init>, that it is found in same klass as static type |
822 if (resolved_method->name() == vmSymbols::object_initializer_name() && | 831 if (resolved_method->name() == vmSymbols::object_initializer_name() && |
842 Method::name_and_sig_as_C_string(resolved_klass(), | 851 Method::name_and_sig_as_C_string(resolved_klass(), |
843 resolved_method->name(), | 852 resolved_method->name(), |
844 resolved_method->signature())); | 853 resolved_method->signature())); |
845 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | 854 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
846 } | 855 } |
856 if (TraceItables && Verbose) { | |
857 ResourceMark rm(THREAD); | |
858 tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", | |
859 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()), | |
860 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | |
861 Method::name_and_sig_as_C_string(resolved_klass(), | |
862 resolved_method->name(), | |
863 resolved_method->signature()), | |
864 resolved_method->method_holder()->internal_name() | |
865 ); | |
866 resolved_method->access_flags().print_on(tty); | |
867 if (resolved_method->method_holder()->is_interface() && | |
868 !resolved_method->is_abstract()) { | |
869 tty->print("default"); | |
870 } | |
871 if (resolved_method->is_overpass()) { | |
872 tty->print("overpass"); | |
873 } | |
874 tty->cr(); | |
875 } | |
847 } | 876 } |
848 | 877 |
849 // throws runtime exceptions | 878 // throws runtime exceptions |
850 void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, | 879 void LinkResolver::runtime_resolve_special_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, |
851 KlassHandle current_klass, bool check_access, TRAPS) { | 880 KlassHandle current_klass, bool check_access, TRAPS) { |
852 | 881 |
853 // resolved method is selected method unless we have an old-style lookup | 882 // resolved method is selected method unless we have an old-style lookup |
883 // for a superclass method | |
884 // Invokespecial for a superinterface, resolved method is selected method, | |
885 // no checks for shadowing | |
854 methodHandle sel_method(THREAD, resolved_method()); | 886 methodHandle sel_method(THREAD, resolved_method()); |
855 | 887 |
856 // check if this is an old-style super call and do a new lookup if so | 888 // check if this is an old-style super call and do a new lookup if so |
857 { KlassHandle method_klass = KlassHandle(THREAD, | 889 { KlassHandle method_klass = KlassHandle(THREAD, |
858 resolved_method->method_holder()); | 890 resolved_method->method_holder()); |
859 | 891 |
860 const bool direct_calling_default_method = | 892 if (check_access && |
861 resolved_klass() != NULL && resolved_method() != NULL && | |
862 resolved_klass->is_interface() && !resolved_method->is_abstract(); | |
863 | |
864 if (!direct_calling_default_method && | |
865 check_access && | |
866 // a) check if ACC_SUPER flag is set for the current class | 893 // a) check if ACC_SUPER flag is set for the current class |
867 (current_klass->is_super() || !AllowNonVirtualCalls) && | 894 (current_klass->is_super() || !AllowNonVirtualCalls) && |
868 // b) check if the method class is a superclass of the current class (superclass relation is not reflexive!) | 895 // b) check if the class of the resolved_klass is a superclass |
869 current_klass->is_subtype_of(method_klass()) && | 896 // (not supertype in order to exclude interface classes) of the current class. |
870 current_klass() != method_klass() && | 897 // This check is not performed for super.invoke for interface methods |
898 // in super interfaces. | |
899 current_klass->is_subclass_of(resolved_klass()) && | |
900 current_klass() != resolved_klass() && | |
871 // c) check if the method is not <init> | 901 // c) check if the method is not <init> |
872 resolved_method->name() != vmSymbols::object_initializer_name()) { | 902 resolved_method->name() != vmSymbols::object_initializer_name()) { |
873 // Lookup super method | 903 // Lookup super method |
874 KlassHandle super_klass(THREAD, current_klass->super()); | 904 KlassHandle super_klass(THREAD, current_klass->super()); |
875 lookup_instance_method_in_klasses(sel_method, super_klass, | 905 lookup_instance_method_in_klasses(sel_method, super_klass, |
903 Method::name_and_sig_as_C_string(resolved_klass(), | 933 Method::name_and_sig_as_C_string(resolved_klass(), |
904 sel_method->name(), | 934 sel_method->name(), |
905 sel_method->signature())); | 935 sel_method->signature())); |
906 } | 936 } |
907 | 937 |
938 if (TraceItables && Verbose) { | |
939 ResourceMark rm(THREAD); | |
940 tty->print("invokespecial selected method: resolved-class:%s, method:%s, method_holder:%s, access_flags: ", | |
941 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | |
942 Method::name_and_sig_as_C_string(resolved_klass(), | |
943 sel_method->name(), | |
944 sel_method->signature()), | |
945 sel_method->method_holder()->internal_name() | |
946 ); | |
947 sel_method->access_flags().print_on(tty); | |
948 if (sel_method->method_holder()->is_interface() && | |
949 !sel_method->is_abstract()) { | |
950 tty->print("default"); | |
951 } | |
952 tty->cr(); | |
953 } | |
954 | |
908 // setup result | 955 // setup result |
909 result.set_static(resolved_klass, sel_method, CHECK); | 956 result.set_static(resolved_klass, sel_method, CHECK); |
910 } | 957 } |
911 | 958 |
912 void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass, | 959 void LinkResolver::resolve_virtual_call(CallInfo& result, Handle recv, KlassHandle receiver_klass, KlassHandle resolved_klass, |
925 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); | 972 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, check_access, CHECK); |
926 | 973 |
927 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); | 974 assert(resolved_method->name() != vmSymbols::object_initializer_name(), "should have been checked in verifier"); |
928 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); | 975 assert(resolved_method->name() != vmSymbols::class_initializer_name (), "should have been checked in verifier"); |
929 | 976 |
977 // check if private interface method | |
978 if (resolved_klass->is_interface() && resolved_method->is_private()) { | |
979 ResourceMark rm(THREAD); | |
980 char buf[200]; | |
981 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokevirtual: method %s, caller-class:%s", | |
982 Method::name_and_sig_as_C_string(resolved_klass(), | |
983 resolved_method->name(), | |
984 resolved_method->signature()), | |
985 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name())); | |
986 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | |
987 } | |
988 | |
930 // check if not static | 989 // check if not static |
931 if (resolved_method->is_static()) { | 990 if (resolved_method->is_static()) { |
932 ResourceMark rm(THREAD); | 991 ResourceMark rm(THREAD); |
933 char buf[200]; | 992 char buf[200]; |
934 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), | 993 jio_snprintf(buf, sizeof(buf), "Expecting non-static method %s", Method::name_and_sig_as_C_string(resolved_klass(), |
935 resolved_method->name(), | 994 resolved_method->name(), |
936 resolved_method->signature())); | 995 resolved_method->signature())); |
937 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | 996 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
938 } | 997 } |
998 | |
999 if (PrintVtables && Verbose) { | |
1000 ResourceMark rm(THREAD); | |
1001 tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", | |
1002 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()), | |
1003 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | |
1004 Method::name_and_sig_as_C_string(resolved_klass(), | |
1005 resolved_method->name(), | |
1006 resolved_method->signature()), | |
1007 resolved_method->method_holder()->internal_name() | |
1008 ); | |
1009 resolved_method->access_flags().print_on(tty); | |
1010 if (resolved_method->method_holder()->is_interface() && | |
1011 !resolved_method->is_abstract()) { | |
1012 tty->print("default"); | |
1013 } | |
1014 if (resolved_method->is_overpass()) { | |
1015 tty->print("overpass"); | |
1016 } | |
1017 tty->cr(); | |
1018 } | |
939 } | 1019 } |
940 | 1020 |
941 // throws runtime exceptions | 1021 // throws runtime exceptions |
942 void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, | 1022 void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, |
943 methodHandle resolved_method, | 1023 methodHandle resolved_method, |
1010 Method::name_and_sig_as_C_string(resolved_klass(), | 1090 Method::name_and_sig_as_C_string(resolved_klass(), |
1011 selected_method->name(), | 1091 selected_method->name(), |
1012 selected_method->signature())); | 1092 selected_method->signature())); |
1013 } | 1093 } |
1014 | 1094 |
1095 if (PrintVtables && Verbose) { | |
1096 ResourceMark rm(THREAD); | |
1097 tty->print("invokevirtual selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, vtable_index:%d, access_flags: ", | |
1098 (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()), | |
1099 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | |
1100 Method::name_and_sig_as_C_string(resolved_klass(), | |
1101 resolved_method->name(), | |
1102 resolved_method->signature()), | |
1103 selected_method->method_holder()->internal_name(), | |
1104 vtable_index | |
1105 ); | |
1106 selected_method->access_flags().print_on(tty); | |
1107 if (selected_method->method_holder()->is_interface() && | |
1108 !selected_method->is_abstract()) { | |
1109 tty->print("default"); | |
1110 } | |
1111 if (resolved_method->is_overpass()) { | |
1112 tty->print("overpass"); | |
1113 } | |
1114 tty->cr(); | |
1115 } | |
1015 // setup result | 1116 // setup result |
1016 result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); | 1117 result.set_virtual(resolved_klass, recv_klass, resolved_method, selected_method, vtable_index, CHECK); |
1017 } | 1118 } |
1018 | 1119 |
1019 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, | 1120 void LinkResolver::resolve_interface_call(CallInfo& result, Handle recv, KlassHandle recv_klass, KlassHandle resolved_klass, |
1038 void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, | 1139 void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHandle resolved_method, KlassHandle resolved_klass, |
1039 Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS) { | 1140 Handle recv, KlassHandle recv_klass, bool check_null_and_abstract, TRAPS) { |
1040 // check if receiver exists | 1141 // check if receiver exists |
1041 if (check_null_and_abstract && recv.is_null()) { | 1142 if (check_null_and_abstract && recv.is_null()) { |
1042 THROW(vmSymbols::java_lang_NullPointerException()); | 1143 THROW(vmSymbols::java_lang_NullPointerException()); |
1144 } | |
1145 | |
1146 // check if private interface method | |
1147 if (resolved_klass->is_interface() && resolved_method->is_private()) { | |
1148 ResourceMark rm(THREAD); | |
1149 char buf[200]; | |
1150 jio_snprintf(buf, sizeof(buf), "private interface method requires invokespecial, not invokeinterface: method %s", | |
1151 Method::name_and_sig_as_C_string(resolved_klass(), | |
1152 resolved_method->name(), | |
1153 resolved_method->signature())); | |
1154 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | |
1043 } | 1155 } |
1044 | 1156 |
1045 // check if receiver klass implements the resolved interface | 1157 // check if receiver klass implements the resolved interface |
1046 if (!recv_klass->is_subtype_of(resolved_klass())) { | 1158 if (!recv_klass->is_subtype_of(resolved_klass())) { |
1047 ResourceMark rm(THREAD); | 1159 ResourceMark rm(THREAD); |
1069 Method::name_and_sig_as_C_string(recv_klass(), | 1181 Method::name_and_sig_as_C_string(recv_klass(), |
1070 resolved_method->name(), | 1182 resolved_method->name(), |
1071 resolved_method->signature())); | 1183 resolved_method->signature())); |
1072 } | 1184 } |
1073 // check access | 1185 // check access |
1074 if (sel_method->method_holder()->is_interface()) { | 1186 // Throw Illegal Access Error if sel_method is not public. |
1075 // Method holder is an interface. Throw Illegal Access Error if sel_method | 1187 if (!sel_method->is_public()) { |
1076 // is neither public nor private. | 1188 ResourceMark rm(THREAD); |
1077 if (!(sel_method->is_public() || sel_method->is_private())) { | 1189 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1078 ResourceMark rm(THREAD); | 1190 Method::name_and_sig_as_C_string(recv_klass(), |
1079 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), | 1191 sel_method->name(), |
1080 Method::name_and_sig_as_C_string(recv_klass(), | 1192 sel_method->signature())); |
1081 sel_method->name(), | 1193 } |
1082 sel_method->signature())); | 1194 |
1083 } | |
1084 } | |
1085 else { | |
1086 // Method holder is a class. Throw Illegal Access Error if sel_method | |
1087 // is not public. | |
1088 if (!sel_method->is_public()) { | |
1089 ResourceMark rm(THREAD); | |
1090 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), | |
1091 Method::name_and_sig_as_C_string(recv_klass(), | |
1092 sel_method->name(), | |
1093 sel_method->signature())); | |
1094 } | |
1095 } | |
1096 // check if abstract | 1195 // check if abstract |
1097 if (check_null_and_abstract && sel_method->is_abstract()) { | 1196 if (check_null_and_abstract && sel_method->is_abstract()) { |
1098 ResourceMark rm(THREAD); | 1197 ResourceMark rm(THREAD); |
1099 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), | 1198 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1100 Method::name_and_sig_as_C_string(recv_klass(), | 1199 Method::name_and_sig_as_C_string(recv_klass(), |
1107 assert(vtable_index == sel_method->vtable_index(), "sanity check"); | 1206 assert(vtable_index == sel_method->vtable_index(), "sanity check"); |
1108 result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK); | 1207 result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK); |
1109 return; | 1208 return; |
1110 } | 1209 } |
1111 int itable_index = resolved_method()->itable_index(); | 1210 int itable_index = resolved_method()->itable_index(); |
1211 | |
1212 if (TraceItables && Verbose) { | |
1213 ResourceMark rm(THREAD); | |
1214 tty->print("invokeinterface selected method: receiver-class:%s, resolved-class:%s, method:%s, method_holder:%s, access_flags: ", | |
1215 (recv_klass.is_null() ? "<NULL>" : recv_klass->internal_name()), | |
1216 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | |
1217 Method::name_and_sig_as_C_string(resolved_klass(), | |
1218 resolved_method->name(), | |
1219 resolved_method->signature()), | |
1220 sel_method->method_holder()->internal_name() | |
1221 ); | |
1222 sel_method->access_flags().print_on(tty); | |
1223 if (sel_method->method_holder()->is_interface() && | |
1224 !sel_method->is_abstract()) { | |
1225 tty->print("default"); | |
1226 } | |
1227 if (resolved_method->is_overpass()) { | |
1228 tty->print("overpass"); | |
1229 } | |
1230 tty->cr(); | |
1231 } | |
1112 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); | 1232 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); |
1113 } | 1233 } |
1114 | 1234 |
1115 | 1235 |
1116 methodHandle LinkResolver::linktime_resolve_interface_method_or_null( | 1236 methodHandle LinkResolver::linktime_resolve_interface_method_or_null( |