Mercurial > hg > graal-compiler
comparison src/share/vm/prims/methodHandles.cpp @ 10259:39ead0411f07
8013875: Incorrect vtable index being set during methodHandle creation for static
Summary: Set vtable index as appropriate for static interface methods and for interface methods invoked via invokespecial. To be improved in a later enhancement to CallInfo.
Reviewed-by: jrose, twisti
author | bharadwaj |
---|---|
date | Wed, 08 May 2013 14:18:03 -0700 |
parents | 746b070f5022 |
children | e484fe2abebd |
comparison
equal
deleted
inserted
replaced
10258:0dc028fd5101 | 10259:39ead0411f07 |
---|---|
191 receiver_limit = mklass; | 191 receiver_limit = mklass; |
192 if (m->is_initializer()) { | 192 if (m->is_initializer()) { |
193 flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); | 193 flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); |
194 } else if (mods.is_static()) { | 194 } else if (mods.is_static()) { |
195 flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); | 195 flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); |
196 // Get vindex from itable if method holder is an interface. | |
197 if (m->method_holder()->is_interface()) { | |
198 vmindex = klassItable::compute_itable_index(m); | |
199 } | |
200 } else if (receiver_limit != mklass && | 196 } else if (receiver_limit != mklass && |
201 !receiver_limit->is_subtype_of(mklass)) { | 197 !receiver_limit->is_subtype_of(mklass)) { |
202 return NULL; // bad receiver limit | 198 return NULL; // bad receiver limit |
203 } else if (receiver_limit->is_interface() && | 199 } else if (do_dispatch && receiver_limit->is_interface() && |
204 mklass->is_interface()) { | 200 mklass->is_interface()) { |
205 flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT); | 201 flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT); |
206 receiver_limit = mklass; // ignore passed-in limit; interfaces are interconvertible | 202 receiver_limit = mklass; // ignore passed-in limit; interfaces are interconvertible |
207 vmindex = klassItable::compute_itable_index(m); | 203 vmindex = klassItable::compute_itable_index(m); |
208 } else if (mklass != receiver_limit && mklass->is_interface()) { | 204 } else if (do_dispatch && mklass != receiver_limit && mklass->is_interface()) { |
209 flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); | 205 flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); |
210 // it is a miranda method, so m->vtable_index is not what we want | 206 // it is a miranda method, so m->vtable_index is not what we want |
211 ResourceMark rm; | 207 ResourceMark rm; |
212 klassVtable* vt = InstanceKlass::cast(receiver_limit)->vtable(); | 208 klassVtable* vt = InstanceKlass::cast(receiver_limit)->vtable(); |
213 vmindex = vt->index_of_miranda(m->name(), m->signature()); | 209 vmindex = vt->index_of_miranda(m->name(), m->signature()); |
248 // Caller is responsible to prevent this from happening. | 244 // Caller is responsible to prevent this from happening. |
249 THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty); | 245 THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty); |
250 } | 246 } |
251 methodHandle m = info.resolved_method(); | 247 methodHandle m = info.resolved_method(); |
252 KlassHandle defc = info.resolved_klass(); | 248 KlassHandle defc = info.resolved_klass(); |
253 int vmindex = -1; | 249 int vmindex = Method::invalid_vtable_index; |
254 if (defc->is_interface() && m->method_holder()->is_interface()) { | 250 if (defc->is_interface() && m->method_holder()->is_interface()) { |
255 // LinkResolver does not report itable indexes! (fix this?) | 251 // static interface methods do not reference vtable or itable |
256 vmindex = klassItable::compute_itable_index(m()); | 252 if (m->is_static()) { |
253 vmindex = Method::nonvirtual_vtable_index; | |
254 } | |
255 // interface methods invoked via invokespecial also | |
256 // do not reference vtable or itable. | |
257 int ref_kind = ((java_lang_invoke_MemberName::flags(mname()) >> | |
258 REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK); | |
259 if (ref_kind == JVM_REF_invokeSpecial) { | |
260 vmindex = Method::nonvirtual_vtable_index; | |
261 } | |
262 // If neither m is static nor ref_kind is invokespecial, | |
263 // set it to itable index. | |
264 if (vmindex == Method::invalid_vtable_index) { | |
265 // LinkResolver does not report itable indexes! (fix this?) | |
266 vmindex = klassItable::compute_itable_index(m()); | |
267 } | |
257 } else if (m->can_be_statically_bound()) { | 268 } else if (m->can_be_statically_bound()) { |
258 // LinkResolver reports vtable index even for final methods! | 269 // LinkResolver reports vtable index even for final methods! |
259 vmindex = Method::nonvirtual_vtable_index; | 270 vmindex = Method::nonvirtual_vtable_index; |
260 } else { | 271 } else { |
261 vmindex = info.vtable_index(); | 272 vmindex = info.vtable_index(); |
663 // Time to do the lookup. | 674 // Time to do the lookup. |
664 switch (flags & ALL_KINDS) { | 675 switch (flags & ALL_KINDS) { |
665 case IS_METHOD: | 676 case IS_METHOD: |
666 { | 677 { |
667 CallInfo result; | 678 CallInfo result; |
668 bool do_dispatch = true; // default, neutral setting | |
669 { | 679 { |
670 assert(!HAS_PENDING_EXCEPTION, ""); | 680 assert(!HAS_PENDING_EXCEPTION, ""); |
671 if (ref_kind == JVM_REF_invokeStatic) { | 681 if (ref_kind == JVM_REF_invokeStatic) { |
672 //do_dispatch = false; // no need, since statics are never dispatched | |
673 LinkResolver::resolve_static_call(result, | 682 LinkResolver::resolve_static_call(result, |
674 defc, name, type, KlassHandle(), false, false, THREAD); | 683 defc, name, type, KlassHandle(), false, false, THREAD); |
675 } else if (ref_kind == JVM_REF_invokeInterface) { | 684 } else if (ref_kind == JVM_REF_invokeInterface) { |
676 LinkResolver::resolve_interface_call(result, Handle(), defc, | 685 LinkResolver::resolve_interface_call(result, Handle(), defc, |
677 defc, name, type, KlassHandle(), false, false, THREAD); | 686 defc, name, type, KlassHandle(), false, false, THREAD); |
678 } else if (mh_invoke_id != vmIntrinsics::_none) { | 687 } else if (mh_invoke_id != vmIntrinsics::_none) { |
679 assert(!is_signature_polymorphic_static(mh_invoke_id), ""); | 688 assert(!is_signature_polymorphic_static(mh_invoke_id), ""); |
680 LinkResolver::resolve_handle_call(result, | 689 LinkResolver::resolve_handle_call(result, |
681 defc, name, type, KlassHandle(), THREAD); | 690 defc, name, type, KlassHandle(), THREAD); |
682 } else if (ref_kind == JVM_REF_invokeSpecial) { | 691 } else if (ref_kind == JVM_REF_invokeSpecial) { |
683 do_dispatch = false; // force non-virtual linkage | |
684 LinkResolver::resolve_special_call(result, | 692 LinkResolver::resolve_special_call(result, |
685 defc, name, type, KlassHandle(), false, THREAD); | 693 defc, name, type, KlassHandle(), false, THREAD); |
686 } else if (ref_kind == JVM_REF_invokeVirtual) { | 694 } else if (ref_kind == JVM_REF_invokeVirtual) { |
687 LinkResolver::resolve_virtual_call(result, Handle(), defc, | 695 LinkResolver::resolve_virtual_call(result, Handle(), defc, |
688 defc, name, type, KlassHandle(), false, false, THREAD); | 696 defc, name, type, KlassHandle(), false, false, THREAD); |