Mercurial > hg > graal-compiler
comparison src/share/vm/prims/methodHandles.cpp @ 17479:9063bd8808a7
8029507: Enhance JVM method processing
Summary: update MemberName.clazz correctly in MemberName.resolve; also pass lookupClass to MethodHandles::resolve_MemberName
Reviewed-by: acorn, vlivanov
author | jrose |
---|---|
date | Thu, 05 Dec 2013 00:36:42 -0800 |
parents | d95eca175eff |
children | d8041d695d19 78bbf4d43a14 |
comparison
equal
deleted
inserted
replaced
17478:e254e5940c19 | 17479:9063bd8808a7 |
---|---|
173 return NULL; | 173 return NULL; |
174 } | 174 } |
175 | 175 |
176 oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { | 176 oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { |
177 assert(info.resolved_appendix().is_null(), "only normal methods here"); | 177 assert(info.resolved_appendix().is_null(), "only normal methods here"); |
178 KlassHandle receiver_limit = info.resolved_klass(); | |
179 methodHandle m = info.resolved_method(); | 178 methodHandle m = info.resolved_method(); |
179 KlassHandle m_klass = m->method_holder(); | |
180 int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); | 180 int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); |
181 int vmindex = Method::invalid_vtable_index; | 181 int vmindex = Method::invalid_vtable_index; |
182 | 182 |
183 switch (info.call_kind()) { | 183 switch (info.call_kind()) { |
184 case CallInfo::itable_call: | 184 case CallInfo::itable_call: |
185 vmindex = info.itable_index(); | 185 vmindex = info.itable_index(); |
186 // More importantly, the itable index only works with the method holder. | 186 // More importantly, the itable index only works with the method holder. |
187 receiver_limit = m->method_holder(); | 187 assert(m_klass->verify_itable_index(vmindex), ""); |
188 assert(receiver_limit->verify_itable_index(vmindex), ""); | |
189 flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT); | 188 flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT); |
190 if (TraceInvokeDynamic) { | 189 if (TraceInvokeDynamic) { |
191 ResourceMark rm; | 190 ResourceMark rm; |
192 tty->print_cr("memberName: invokeinterface method_holder::method: %s, receiver: %s, itableindex: %d, access_flags:", | 191 tty->print_cr("memberName: invokeinterface method_holder::method: %s, itableindex: %d, access_flags:", |
193 Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()), | 192 Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()), |
194 receiver_limit()->internal_name(), vmindex); | 193 vmindex); |
195 m->access_flags().print_on(tty); | 194 m->access_flags().print_on(tty); |
196 if (!m->is_abstract()) { | 195 if (!m->is_abstract()) { |
197 tty->print("default"); | 196 tty->print("default"); |
198 } | 197 } |
199 tty->cr(); | 198 tty->cr(); |
201 break; | 200 break; |
202 | 201 |
203 case CallInfo::vtable_call: | 202 case CallInfo::vtable_call: |
204 vmindex = info.vtable_index(); | 203 vmindex = info.vtable_index(); |
205 flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); | 204 flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); |
206 assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe"); | 205 assert(info.resolved_klass()->is_subtype_of(m_klass()), "virtual call must be type-safe"); |
206 if (m_klass->is_interface()) { | |
207 // This is a vtable call to an interface method (abstract "miranda method" or default method). | |
208 // The vtable index is meaningless without a class (not interface) receiver type, so get one. | |
209 // (LinkResolver should help us figure this out.) | |
210 KlassHandle m_klass_non_interface = info.resolved_klass(); | |
211 if (m_klass_non_interface->is_interface()) { | |
212 m_klass_non_interface = SystemDictionary::Object_klass(); | |
213 #ifdef ASSERT | |
214 { ResourceMark rm; | |
215 Method* m2 = m_klass_non_interface->vtable()->method_at(vmindex); | |
216 assert(m->name() == m2->name() && m->signature() == m2->signature(), | |
217 err_msg("at %d, %s != %s", vmindex, | |
218 m->name_and_sig_as_C_string(), m2->name_and_sig_as_C_string())); | |
219 } | |
220 #endif //ASSERT | |
221 } | |
222 if (!m->is_public()) { | |
223 assert(m->is_public(), "virtual call must be to public interface method"); | |
224 return NULL; // elicit an error later in product build | |
225 } | |
226 assert(info.resolved_klass()->is_subtype_of(m_klass_non_interface()), "virtual call must be type-safe"); | |
227 m_klass = m_klass_non_interface; | |
228 } | |
207 if (TraceInvokeDynamic) { | 229 if (TraceInvokeDynamic) { |
208 ResourceMark rm; | 230 ResourceMark rm; |
209 tty->print_cr("memberName: invokevirtual method_holder::method: %s, receiver: %s, vtableindex: %d, access_flags:", | 231 tty->print_cr("memberName: invokevirtual method_holder::method: %s, receiver: %s, vtableindex: %d, access_flags:", |
210 Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()), | 232 Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()), |
211 receiver_limit()->internal_name(), vmindex); | 233 m_klass->internal_name(), vmindex); |
212 m->access_flags().print_on(tty); | 234 m->access_flags().print_on(tty); |
213 if (m->is_default_method()) { | 235 if (m->is_default_method()) { |
214 tty->print("default"); | 236 tty->print("default"); |
215 } | 237 } |
216 tty->cr(); | 238 tty->cr(); |
221 vmindex = Method::nonvirtual_vtable_index; | 243 vmindex = Method::nonvirtual_vtable_index; |
222 if (m->is_static()) { | 244 if (m->is_static()) { |
223 flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); | 245 flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); |
224 } else if (m->is_initializer()) { | 246 } else if (m->is_initializer()) { |
225 flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); | 247 flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); |
226 assert(receiver_limit == m->method_holder(), "constructor call must be exactly typed"); | |
227 } else { | 248 } else { |
228 flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); | 249 flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); |
229 assert(receiver_limit->is_subtype_of(m->method_holder()), "special call must be type-safe"); | |
230 } | 250 } |
231 break; | 251 break; |
232 | 252 |
233 default: assert(false, "bad CallInfo"); return NULL; | 253 default: assert(false, "bad CallInfo"); return NULL; |
234 } | 254 } |
240 | 260 |
241 oop mname_oop = mname(); | 261 oop mname_oop = mname(); |
242 java_lang_invoke_MemberName::set_flags( mname_oop, flags); | 262 java_lang_invoke_MemberName::set_flags( mname_oop, flags); |
243 java_lang_invoke_MemberName::set_vmtarget(mname_oop, m()); | 263 java_lang_invoke_MemberName::set_vmtarget(mname_oop, m()); |
244 java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index | 264 java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index |
245 java_lang_invoke_MemberName::set_clazz( mname_oop, receiver_limit->java_mirror()); | 265 java_lang_invoke_MemberName::set_clazz( mname_oop, m_klass->java_mirror()); |
246 // Note: name and type can be lazily computed by resolve_MemberName, | 266 // Note: name and type can be lazily computed by resolve_MemberName, |
247 // if Java code needs them as resolved String and MethodType objects. | 267 // if Java code needs them as resolved String and MethodType objects. |
248 // The clazz must be eagerly stored, because it provides a GC | 268 // The clazz must be eagerly stored, because it provides a GC |
249 // root to help keep alive the Method*. | 269 // root to help keep alive the Method*. |
250 // If relevant, the vtable or itable value is stored as vmindex. | 270 // If relevant, the vtable or itable value is stored as vmindex. |
567 | 587 |
568 | 588 |
569 // An unresolved member name is a mere symbolic reference. | 589 // An unresolved member name is a mere symbolic reference. |
570 // Resolving it plants a vmtarget/vmindex in it, | 590 // Resolving it plants a vmtarget/vmindex in it, |
571 // which refers directly to JVM internals. | 591 // which refers directly to JVM internals. |
572 Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) { | 592 Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS) { |
573 Handle empty; | 593 Handle empty; |
574 assert(java_lang_invoke_MemberName::is_instance(mname()), ""); | 594 assert(java_lang_invoke_MemberName::is_instance(mname()), ""); |
575 | 595 |
576 if (java_lang_invoke_MemberName::vmtarget(mname()) != NULL) { | 596 if (java_lang_invoke_MemberName::vmtarget(mname()) != NULL) { |
577 // Already resolved. | 597 // Already resolved. |
644 CallInfo result; | 664 CallInfo result; |
645 { | 665 { |
646 assert(!HAS_PENDING_EXCEPTION, ""); | 666 assert(!HAS_PENDING_EXCEPTION, ""); |
647 if (ref_kind == JVM_REF_invokeStatic) { | 667 if (ref_kind == JVM_REF_invokeStatic) { |
648 LinkResolver::resolve_static_call(result, | 668 LinkResolver::resolve_static_call(result, |
649 defc, name, type, KlassHandle(), false, false, THREAD); | 669 defc, name, type, caller, caller.not_null(), false, THREAD); |
650 } else if (ref_kind == JVM_REF_invokeInterface) { | 670 } else if (ref_kind == JVM_REF_invokeInterface) { |
651 LinkResolver::resolve_interface_call(result, Handle(), defc, | 671 LinkResolver::resolve_interface_call(result, Handle(), defc, |
652 defc, name, type, KlassHandle(), false, false, THREAD); | 672 defc, name, type, caller, caller.not_null(), false, THREAD); |
653 } else if (mh_invoke_id != vmIntrinsics::_none) { | 673 } else if (mh_invoke_id != vmIntrinsics::_none) { |
654 assert(!is_signature_polymorphic_static(mh_invoke_id), ""); | 674 assert(!is_signature_polymorphic_static(mh_invoke_id), ""); |
655 LinkResolver::resolve_handle_call(result, | 675 LinkResolver::resolve_handle_call(result, |
656 defc, name, type, KlassHandle(), THREAD); | 676 defc, name, type, caller, THREAD); |
657 } else if (ref_kind == JVM_REF_invokeSpecial) { | 677 } else if (ref_kind == JVM_REF_invokeSpecial) { |
658 LinkResolver::resolve_special_call(result, | 678 LinkResolver::resolve_special_call(result, |
659 defc, name, type, KlassHandle(), false, THREAD); | 679 defc, name, type, caller, caller.not_null(), THREAD); |
660 } else if (ref_kind == JVM_REF_invokeVirtual) { | 680 } else if (ref_kind == JVM_REF_invokeVirtual) { |
661 LinkResolver::resolve_virtual_call(result, Handle(), defc, | 681 LinkResolver::resolve_virtual_call(result, Handle(), defc, |
662 defc, name, type, KlassHandle(), false, false, THREAD); | 682 defc, name, type, caller, caller.not_null(), false, THREAD); |
663 } else { | 683 } else { |
664 assert(false, err_msg("ref_kind=%d", ref_kind)); | 684 assert(false, err_msg("ref_kind=%d", ref_kind)); |
665 } | 685 } |
666 if (HAS_PENDING_EXCEPTION) { | 686 if (HAS_PENDING_EXCEPTION) { |
667 return empty; | 687 return empty; |
681 CallInfo result; | 701 CallInfo result; |
682 { | 702 { |
683 assert(!HAS_PENDING_EXCEPTION, ""); | 703 assert(!HAS_PENDING_EXCEPTION, ""); |
684 if (name == vmSymbols::object_initializer_name()) { | 704 if (name == vmSymbols::object_initializer_name()) { |
685 LinkResolver::resolve_special_call(result, | 705 LinkResolver::resolve_special_call(result, |
686 defc, name, type, KlassHandle(), false, THREAD); | 706 defc, name, type, caller, caller.not_null(), THREAD); |
687 } else { | 707 } else { |
688 break; // will throw after end of switch | 708 break; // will throw after end of switch |
689 } | 709 } |
690 if (HAS_PENDING_EXCEPTION) { | 710 if (HAS_PENDING_EXCEPTION) { |
691 return empty; | 711 return empty; |
698 case IS_FIELD: | 718 case IS_FIELD: |
699 { | 719 { |
700 fieldDescriptor result; // find_field initializes fd if found | 720 fieldDescriptor result; // find_field initializes fd if found |
701 { | 721 { |
702 assert(!HAS_PENDING_EXCEPTION, ""); | 722 assert(!HAS_PENDING_EXCEPTION, ""); |
703 LinkResolver::resolve_field(result, defc, name, type, KlassHandle(), Bytecodes::_nop, false, false, THREAD); | 723 LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD); |
704 if (HAS_PENDING_EXCEPTION) { | 724 if (HAS_PENDING_EXCEPTION) { |
705 return empty; | 725 return empty; |
706 } | 726 } |
707 } | 727 } |
708 oop mname2 = init_field_MemberName(mname, result, ref_kind_is_setter(ref_kind)); | 728 oop mname2 = init_field_MemberName(mname, result, ref_kind_is_setter(ref_kind)); |
1119 THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name()); | 1139 THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), reference_klass->external_name()); |
1120 } | 1140 } |
1121 } | 1141 } |
1122 } | 1142 } |
1123 | 1143 |
1124 Handle resolved = MethodHandles::resolve_MemberName(mname, CHECK_NULL); | 1144 KlassHandle caller(THREAD, |
1145 caller_jh == NULL ? (Klass*) NULL : | |
1146 java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh))); | |
1147 Handle resolved = MethodHandles::resolve_MemberName(mname, caller, CHECK_NULL); | |
1148 | |
1125 if (resolved.is_null()) { | 1149 if (resolved.is_null()) { |
1126 int flags = java_lang_invoke_MemberName::flags(mname()); | 1150 int flags = java_lang_invoke_MemberName::flags(mname()); |
1127 int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; | 1151 int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; |
1128 if (!MethodHandles::ref_kind_is_valid(ref_kind)) { | 1152 if (!MethodHandles::ref_kind_is_valid(ref_kind)) { |
1129 THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "obsolete MemberName format"); | 1153 THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "obsolete MemberName format"); |