Mercurial > hg > graal-jvmci-8
comparison src/share/vm/interpreter/linkResolver.cpp @ 12823:ac9cb1d5a202
8009130: Lambda: Fix access controls, loader constraints.
Summary: New default methods list with inherited superinterface methods
Reviewed-by: minqi, sspitsyn, coleenp
author | acorn |
---|---|
date | Mon, 07 Oct 2013 12:20:28 -0400 |
parents | 36b97be47bde |
children | 2f8728d92483 8df6f123d35e |
comparison
equal
deleted
inserted
replaced
12822:cc4f5f8d885e | 12823:ac9cb1d5a202 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. | |
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
3 * | 4 * |
4 * This code is free software; you can redistribute it and/or modify it | 5 * This code is free software; you can redistribute it and/or modify it |
5 * under the terms of the GNU General Public License version 2 only, as | 6 * under the terms of the GNU General Public License version 2 only, as |
6 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
219 //------------------------------------------------------------------------------------------------------------------------ | 220 //------------------------------------------------------------------------------------------------------------------------ |
220 // Method resolution | 221 // Method resolution |
221 // | 222 // |
222 // According to JVM spec. $5.4.3c & $5.4.3d | 223 // According to JVM spec. $5.4.3c & $5.4.3d |
223 | 224 |
225 // Look up method in klasses, including static methods | |
226 // Then look up local default methods | |
224 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { | 227 void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { |
225 Method* result_oop = klass->uncached_lookup_method(name, signature); | 228 Method* result_oop = klass->uncached_lookup_method(name, signature); |
229 if (result_oop == NULL) { | |
230 Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); | |
231 if (default_methods != NULL) { | |
232 result_oop = InstanceKlass::find_method(default_methods, name, signature); | |
233 } | |
234 } | |
235 | |
226 if (EnableInvokeDynamic && result_oop != NULL) { | 236 if (EnableInvokeDynamic && result_oop != NULL) { |
227 vmIntrinsics::ID iid = result_oop->intrinsic_id(); | 237 vmIntrinsics::ID iid = result_oop->intrinsic_id(); |
228 if (MethodHandles::is_signature_polymorphic(iid)) { | 238 if (MethodHandles::is_signature_polymorphic(iid)) { |
229 // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method. | 239 // Do not link directly to these. The VM must produce a synthetic one using lookup_polymorphic_method. |
230 return; | 240 return; |
232 } | 242 } |
233 result = methodHandle(THREAD, result_oop); | 243 result = methodHandle(THREAD, result_oop); |
234 } | 244 } |
235 | 245 |
236 // returns first instance method | 246 // returns first instance method |
247 // Looks up method in classes, then looks up local default methods | |
237 void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { | 248 void LinkResolver::lookup_instance_method_in_klasses(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { |
238 Method* result_oop = klass->uncached_lookup_method(name, signature); | 249 Method* result_oop = klass->uncached_lookup_method(name, signature); |
239 result = methodHandle(THREAD, result_oop); | 250 result = methodHandle(THREAD, result_oop); |
240 while (!result.is_null() && result->is_static()) { | 251 while (!result.is_null() && result->is_static()) { |
241 klass = KlassHandle(THREAD, result->method_holder()->super()); | 252 klass = KlassHandle(THREAD, result->method_holder()->super()); |
242 result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature)); | 253 result = methodHandle(THREAD, klass->uncached_lookup_method(name, signature)); |
243 } | 254 } |
244 } | 255 |
245 | 256 if (result.is_null()) { |
246 | 257 Array<Method*>* default_methods = InstanceKlass::cast(klass())->default_methods(); |
247 int LinkResolver::vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { | 258 if (default_methods != NULL) { |
248 ResourceMark rm(THREAD); | 259 result = methodHandle(InstanceKlass::find_method(default_methods, name, signature)); |
249 klassVtable *vt = InstanceKlass::cast(klass())->vtable(); | 260 assert(result.is_null() || !result->is_static(), "static defaults not allowed"); |
250 return vt->index_of_miranda(name, signature); | 261 } |
262 } | |
263 } | |
264 | |
265 int LinkResolver::vtable_index_of_interface_method(KlassHandle klass, | |
266 methodHandle resolved_method, TRAPS) { | |
267 | |
268 int vtable_index = Method::invalid_vtable_index; | |
269 Symbol* name = resolved_method->name(); | |
270 Symbol* signature = resolved_method->signature(); | |
271 | |
272 // First check in default method array | |
273 if (!resolved_method->is_abstract() && | |
274 (InstanceKlass::cast(klass())->default_methods() != NULL)) { | |
275 int index = InstanceKlass::find_method_index(InstanceKlass::cast(klass())->default_methods(), name, signature); | |
276 if (index >= 0 ) { | |
277 vtable_index = InstanceKlass::cast(klass())->default_vtable_indices()->at(index); | |
278 } | |
279 } | |
280 if (vtable_index == Method::invalid_vtable_index) { | |
281 // get vtable_index for miranda methods | |
282 ResourceMark rm(THREAD); | |
283 klassVtable *vt = InstanceKlass::cast(klass())->vtable(); | |
284 vtable_index = vt->index_of_miranda(name, signature); | |
285 } | |
286 return vtable_index; | |
251 } | 287 } |
252 | 288 |
253 void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { | 289 void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS) { |
254 InstanceKlass *ik = InstanceKlass::cast(klass()); | 290 InstanceKlass *ik = InstanceKlass::cast(klass()); |
255 result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature)); | 291 result = methodHandle(THREAD, ik->lookup_method_in_all_interfaces(name, signature)); |
623 resolved_method->name(), | 659 resolved_method->name(), |
624 resolved_method->signature()), | 660 resolved_method->signature()), |
625 resolved_method->method_holder()->internal_name() | 661 resolved_method->method_holder()->internal_name() |
626 ); | 662 ); |
627 resolved_method->access_flags().print_on(tty); | 663 resolved_method->access_flags().print_on(tty); |
664 if (resolved_method->is_default_method()) { | |
665 tty->print("default"); | |
666 } | |
667 if (resolved_method->is_overpass()) { | |
668 tty->print("overpass"); | |
669 } | |
628 tty->cr(); | 670 tty->cr(); |
629 } | 671 } |
630 } | 672 } |
631 | 673 |
632 //------------------------------------------------------------------------------------------------------------------------ | 674 //------------------------------------------------------------------------------------------------------------------------ |
851 Method::name_and_sig_as_C_string(resolved_klass(), | 893 Method::name_and_sig_as_C_string(resolved_klass(), |
852 resolved_method->name(), | 894 resolved_method->name(), |
853 resolved_method->signature())); | 895 resolved_method->signature())); |
854 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | 896 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
855 } | 897 } |
898 | |
856 if (TraceItables && Verbose) { | 899 if (TraceItables && Verbose) { |
857 ResourceMark rm(THREAD); | 900 ResourceMark rm(THREAD); |
858 tty->print("invokespecial resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", | 901 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()), | 902 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()), |
860 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | 903 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), |
862 resolved_method->name(), | 905 resolved_method->name(), |
863 resolved_method->signature()), | 906 resolved_method->signature()), |
864 resolved_method->method_holder()->internal_name() | 907 resolved_method->method_holder()->internal_name() |
865 ); | 908 ); |
866 resolved_method->access_flags().print_on(tty); | 909 resolved_method->access_flags().print_on(tty); |
867 if (resolved_method->method_holder()->is_interface() && | 910 if (resolved_method->is_default_method()) { |
868 !resolved_method->is_abstract()) { | |
869 tty->print("default"); | 911 tty->print("default"); |
870 } | 912 } |
871 if (resolved_method->is_overpass()) { | 913 if (resolved_method->is_overpass()) { |
872 tty->print("overpass"); | 914 tty->print("overpass"); |
873 } | 915 } |
943 sel_method->name(), | 985 sel_method->name(), |
944 sel_method->signature()), | 986 sel_method->signature()), |
945 sel_method->method_holder()->internal_name() | 987 sel_method->method_holder()->internal_name() |
946 ); | 988 ); |
947 sel_method->access_flags().print_on(tty); | 989 sel_method->access_flags().print_on(tty); |
948 if (sel_method->method_holder()->is_interface() && | 990 if (sel_method->is_default_method()) { |
949 !sel_method->is_abstract()) { | |
950 tty->print("default"); | 991 tty->print("default"); |
992 } | |
993 if (sel_method->is_overpass()) { | |
994 tty->print("overpass"); | |
951 } | 995 } |
952 tty->cr(); | 996 tty->cr(); |
953 } | 997 } |
954 | 998 |
955 // setup result | 999 // setup result |
994 resolved_method->name(), | 1038 resolved_method->name(), |
995 resolved_method->signature())); | 1039 resolved_method->signature())); |
996 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); | 1040 THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf); |
997 } | 1041 } |
998 | 1042 |
999 if (PrintVtables && Verbose) { | 1043 if (PrintVtables && Verbose) { |
1000 ResourceMark rm(THREAD); | 1044 ResourceMark rm(THREAD); |
1001 tty->print("invokevirtual resolved method: caller-class:%s, compile-time-class:%s, method:%s, method_holder:%s, access_flags: ", | 1045 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()), | 1046 (current_klass.is_null() ? "<NULL>" : current_klass->internal_name()), |
1003 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), | 1047 (resolved_klass.is_null() ? "<NULL>" : resolved_klass->internal_name()), |
1004 Method::name_and_sig_as_C_string(resolved_klass(), | 1048 Method::name_and_sig_as_C_string(resolved_klass(), |
1005 resolved_method->name(), | 1049 resolved_method->name(), |
1006 resolved_method->signature()), | 1050 resolved_method->signature()), |
1007 resolved_method->method_holder()->internal_name() | 1051 resolved_method->method_holder()->internal_name() |
1008 ); | 1052 ); |
1009 resolved_method->access_flags().print_on(tty); | 1053 resolved_method->access_flags().print_on(tty); |
1010 if (resolved_method->method_holder()->is_interface() && | 1054 if (resolved_method->is_default_method()) { |
1011 !resolved_method->is_abstract()) { | 1055 tty->print("default"); |
1012 tty->print("default"); | 1056 } |
1013 } | 1057 if (resolved_method->is_overpass()) { |
1014 if (resolved_method->is_overpass()) { | 1058 tty->print("overpass"); |
1015 tty->print("overpass"); | 1059 } |
1016 } | 1060 tty->cr(); |
1017 tty->cr(); | 1061 } |
1018 } | |
1019 } | 1062 } |
1020 | 1063 |
1021 // throws runtime exceptions | 1064 // throws runtime exceptions |
1022 void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, | 1065 void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, |
1023 methodHandle resolved_method, | 1066 methodHandle resolved_method, |
1043 // a missing receiver might result in a bogus lookup. | 1086 // a missing receiver might result in a bogus lookup. |
1044 assert(resolved_method->method_holder()->is_linked(), "must be linked"); | 1087 assert(resolved_method->method_holder()->is_linked(), "must be linked"); |
1045 | 1088 |
1046 // do lookup based on receiver klass using the vtable index | 1089 // do lookup based on receiver klass using the vtable index |
1047 if (resolved_method->method_holder()->is_interface()) { // miranda method | 1090 if (resolved_method->method_holder()->is_interface()) { // miranda method |
1048 vtable_index = vtable_index_of_miranda_method(resolved_klass, | 1091 vtable_index = vtable_index_of_interface_method(resolved_klass, |
1049 resolved_method->name(), | 1092 resolved_method, CHECK); |
1050 resolved_method->signature(), CHECK); | |
1051 | |
1052 assert(vtable_index >= 0 , "we should have valid vtable index at this point"); | 1093 assert(vtable_index >= 0 , "we should have valid vtable index at this point"); |
1053 | 1094 |
1054 InstanceKlass* inst = InstanceKlass::cast(recv_klass()); | 1095 InstanceKlass* inst = InstanceKlass::cast(recv_klass()); |
1055 selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index)); | 1096 selected_method = methodHandle(THREAD, inst->method_at_vtable(vtable_index)); |
1056 } else { | 1097 } else { |
1102 resolved_method->signature()), | 1143 resolved_method->signature()), |
1103 selected_method->method_holder()->internal_name(), | 1144 selected_method->method_holder()->internal_name(), |
1104 vtable_index | 1145 vtable_index |
1105 ); | 1146 ); |
1106 selected_method->access_flags().print_on(tty); | 1147 selected_method->access_flags().print_on(tty); |
1107 if (selected_method->method_holder()->is_interface() && | 1148 if (selected_method->is_default_method()) { |
1108 !selected_method->is_abstract()) { | |
1109 tty->print("default"); | 1149 tty->print("default"); |
1110 } | 1150 } |
1111 if (resolved_method->is_overpass()) { | 1151 if (selected_method->is_overpass()) { |
1112 tty->print("overpass"); | 1152 tty->print("overpass"); |
1113 } | 1153 } |
1114 tty->cr(); | 1154 tty->cr(); |
1115 } | 1155 } |
1116 // setup result | 1156 // setup result |
1189 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), | 1229 THROW_MSG(vmSymbols::java_lang_IllegalAccessError(), |
1190 Method::name_and_sig_as_C_string(recv_klass(), | 1230 Method::name_and_sig_as_C_string(recv_klass(), |
1191 sel_method->name(), | 1231 sel_method->name(), |
1192 sel_method->signature())); | 1232 sel_method->signature())); |
1193 } | 1233 } |
1194 | |
1195 // check if abstract | 1234 // check if abstract |
1196 if (check_null_and_abstract && sel_method->is_abstract()) { | 1235 if (check_null_and_abstract && sel_method->is_abstract()) { |
1197 ResourceMark rm(THREAD); | 1236 ResourceMark rm(THREAD); |
1198 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), | 1237 THROW_MSG(vmSymbols::java_lang_AbstractMethodError(), |
1199 Method::name_and_sig_as_C_string(recv_klass(), | 1238 Method::name_and_sig_as_C_string(recv_klass(), |
1218 resolved_method->name(), | 1257 resolved_method->name(), |
1219 resolved_method->signature()), | 1258 resolved_method->signature()), |
1220 sel_method->method_holder()->internal_name() | 1259 sel_method->method_holder()->internal_name() |
1221 ); | 1260 ); |
1222 sel_method->access_flags().print_on(tty); | 1261 sel_method->access_flags().print_on(tty); |
1223 if (sel_method->method_holder()->is_interface() && | 1262 if (sel_method->is_default_method()) { |
1224 !sel_method->is_abstract()) { | |
1225 tty->print("default"); | 1263 tty->print("default"); |
1226 } | 1264 } |
1227 if (resolved_method->is_overpass()) { | 1265 if (sel_method->is_overpass()) { |
1228 tty->print("overpass"); | 1266 tty->print("overpass"); |
1229 } | 1267 } |
1230 tty->cr(); | 1268 tty->cr(); |
1231 } | 1269 } |
1232 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); | 1270 result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); |