8029507: Enhance JVM method processing

Thu, 05 Dec 2013 00:36:42 -0800

author
jrose
date
Thu, 05 Dec 2013 00:36:42 -0800
changeset 6246
9063bd8808a7
parent 6245
e254e5940c19
child 6247
1b46c3672650
child 6563
4e0d161dd1fb

8029507: Enhance JVM method processing
Summary: update MemberName.clazz correctly in MemberName.resolve; also pass lookupClass to MethodHandles::resolve_MemberName
Reviewed-by: acorn, vlivanov

src/share/vm/prims/methodHandles.cpp file | annotate | diff | comparison | revisions
src/share/vm/prims/methodHandles.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/prims/methodHandles.cpp	Thu Dec 05 16:37:29 2013 +0400
     1.2 +++ b/src/share/vm/prims/methodHandles.cpp	Thu Dec 05 00:36:42 2013 -0800
     1.3 @@ -175,8 +175,8 @@
     1.4  
     1.5  oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
     1.6    assert(info.resolved_appendix().is_null(), "only normal methods here");
     1.7 -  KlassHandle receiver_limit = info.resolved_klass();
     1.8    methodHandle m = info.resolved_method();
     1.9 +  KlassHandle m_klass = m->method_holder();
    1.10    int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
    1.11    int vmindex = Method::invalid_vtable_index;
    1.12  
    1.13 @@ -184,14 +184,13 @@
    1.14    case CallInfo::itable_call:
    1.15      vmindex = info.itable_index();
    1.16      // More importantly, the itable index only works with the method holder.
    1.17 -    receiver_limit = m->method_holder();
    1.18 -    assert(receiver_limit->verify_itable_index(vmindex), "");
    1.19 +    assert(m_klass->verify_itable_index(vmindex), "");
    1.20      flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
    1.21      if (TraceInvokeDynamic) {
    1.22        ResourceMark rm;
    1.23 -      tty->print_cr("memberName: invokeinterface method_holder::method: %s, receiver: %s, itableindex: %d, access_flags:",
    1.24 -            Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
    1.25 -            receiver_limit()->internal_name(), vmindex);
    1.26 +      tty->print_cr("memberName: invokeinterface method_holder::method: %s, itableindex: %d, access_flags:",
    1.27 +            Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()),
    1.28 +            vmindex);
    1.29         m->access_flags().print_on(tty);
    1.30         if (!m->is_abstract()) {
    1.31           tty->print("default");
    1.32 @@ -203,12 +202,35 @@
    1.33    case CallInfo::vtable_call:
    1.34      vmindex = info.vtable_index();
    1.35      flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
    1.36 -    assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe");
    1.37 +    assert(info.resolved_klass()->is_subtype_of(m_klass()), "virtual call must be type-safe");
    1.38 +    if (m_klass->is_interface()) {
    1.39 +      // This is a vtable call to an interface method (abstract "miranda method" or default method).
    1.40 +      // The vtable index is meaningless without a class (not interface) receiver type, so get one.
    1.41 +      // (LinkResolver should help us figure this out.)
    1.42 +      KlassHandle m_klass_non_interface = info.resolved_klass();
    1.43 +      if (m_klass_non_interface->is_interface()) {
    1.44 +        m_klass_non_interface = SystemDictionary::Object_klass();
    1.45 +#ifdef ASSERT
    1.46 +        { ResourceMark rm;
    1.47 +          Method* m2 = m_klass_non_interface->vtable()->method_at(vmindex);
    1.48 +          assert(m->name() == m2->name() && m->signature() == m2->signature(),
    1.49 +                 err_msg("at %d, %s != %s", vmindex,
    1.50 +                         m->name_and_sig_as_C_string(), m2->name_and_sig_as_C_string()));
    1.51 +        }
    1.52 +#endif //ASSERT
    1.53 +      }
    1.54 +      if (!m->is_public()) {
    1.55 +        assert(m->is_public(), "virtual call must be to public interface method");
    1.56 +        return NULL;  // elicit an error later in product build
    1.57 +      }
    1.58 +      assert(info.resolved_klass()->is_subtype_of(m_klass_non_interface()), "virtual call must be type-safe");
    1.59 +      m_klass = m_klass_non_interface;
    1.60 +    }
    1.61      if (TraceInvokeDynamic) {
    1.62        ResourceMark rm;
    1.63        tty->print_cr("memberName: invokevirtual method_holder::method: %s, receiver: %s, vtableindex: %d, access_flags:",
    1.64 -            Method::name_and_sig_as_C_string(receiver_limit(), m->name(), m->signature()),
    1.65 -            receiver_limit()->internal_name(), vmindex);
    1.66 +            Method::name_and_sig_as_C_string(m->method_holder(), m->name(), m->signature()),
    1.67 +            m_klass->internal_name(), vmindex);
    1.68         m->access_flags().print_on(tty);
    1.69         if (m->is_default_method()) {
    1.70           tty->print("default");
    1.71 @@ -223,10 +245,8 @@
    1.72        flags |= IS_METHOD      | (JVM_REF_invokeStatic  << REFERENCE_KIND_SHIFT);
    1.73      } else if (m->is_initializer()) {
    1.74        flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
    1.75 -      assert(receiver_limit == m->method_holder(), "constructor call must be exactly typed");
    1.76      } else {
    1.77        flags |= IS_METHOD      | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
    1.78 -      assert(receiver_limit->is_subtype_of(m->method_holder()), "special call must be type-safe");
    1.79      }
    1.80      break;
    1.81  
    1.82 @@ -242,7 +262,7 @@
    1.83    java_lang_invoke_MemberName::set_flags(   mname_oop, flags);
    1.84    java_lang_invoke_MemberName::set_vmtarget(mname_oop, m());
    1.85    java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex);   // vtable/itable index
    1.86 -  java_lang_invoke_MemberName::set_clazz(   mname_oop, receiver_limit->java_mirror());
    1.87 +  java_lang_invoke_MemberName::set_clazz(   mname_oop, m_klass->java_mirror());
    1.88    // Note:  name and type can be lazily computed by resolve_MemberName,
    1.89    // if Java code needs them as resolved String and MethodType objects.
    1.90    // The clazz must be eagerly stored, because it provides a GC
    1.91 @@ -569,7 +589,7 @@
    1.92  // An unresolved member name is a mere symbolic reference.
    1.93  // Resolving it plants a vmtarget/vmindex in it,
    1.94  // which refers directly to JVM internals.
    1.95 -Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
    1.96 +Handle MethodHandles::resolve_MemberName(Handle mname, KlassHandle caller, TRAPS) {
    1.97    Handle empty;
    1.98    assert(java_lang_invoke_MemberName::is_instance(mname()), "");
    1.99  
   1.100 @@ -646,20 +666,20 @@
   1.101          assert(!HAS_PENDING_EXCEPTION, "");
   1.102          if (ref_kind == JVM_REF_invokeStatic) {
   1.103            LinkResolver::resolve_static_call(result,
   1.104 -                        defc, name, type, KlassHandle(), false, false, THREAD);
   1.105 +                        defc, name, type, caller, caller.not_null(), false, THREAD);
   1.106          } else if (ref_kind == JVM_REF_invokeInterface) {
   1.107            LinkResolver::resolve_interface_call(result, Handle(), defc,
   1.108 -                        defc, name, type, KlassHandle(), false, false, THREAD);
   1.109 +                        defc, name, type, caller, caller.not_null(), false, THREAD);
   1.110          } else if (mh_invoke_id != vmIntrinsics::_none) {
   1.111            assert(!is_signature_polymorphic_static(mh_invoke_id), "");
   1.112            LinkResolver::resolve_handle_call(result,
   1.113 -                        defc, name, type, KlassHandle(), THREAD);
   1.114 +                        defc, name, type, caller, THREAD);
   1.115          } else if (ref_kind == JVM_REF_invokeSpecial) {
   1.116            LinkResolver::resolve_special_call(result,
   1.117 -                        defc, name, type, KlassHandle(), false, THREAD);
   1.118 +                        defc, name, type, caller, caller.not_null(), THREAD);
   1.119          } else if (ref_kind == JVM_REF_invokeVirtual) {
   1.120            LinkResolver::resolve_virtual_call(result, Handle(), defc,
   1.121 -                        defc, name, type, KlassHandle(), false, false, THREAD);
   1.122 +                        defc, name, type, caller, caller.not_null(), false, THREAD);
   1.123          } else {
   1.124            assert(false, err_msg("ref_kind=%d", ref_kind));
   1.125          }
   1.126 @@ -683,7 +703,7 @@
   1.127          assert(!HAS_PENDING_EXCEPTION, "");
   1.128          if (name == vmSymbols::object_initializer_name()) {
   1.129            LinkResolver::resolve_special_call(result,
   1.130 -                        defc, name, type, KlassHandle(), false, THREAD);
   1.131 +                        defc, name, type, caller, caller.not_null(), THREAD);
   1.132          } else {
   1.133            break;                // will throw after end of switch
   1.134          }
   1.135 @@ -700,7 +720,7 @@
   1.136        fieldDescriptor result; // find_field initializes fd if found
   1.137        {
   1.138          assert(!HAS_PENDING_EXCEPTION, "");
   1.139 -        LinkResolver::resolve_field(result, defc, name, type, KlassHandle(), Bytecodes::_nop, false, false, THREAD);
   1.140 +        LinkResolver::resolve_field(result, defc, name, type, caller, Bytecodes::_nop, false, false, THREAD);
   1.141          if (HAS_PENDING_EXCEPTION) {
   1.142            return empty;
   1.143          }
   1.144 @@ -1121,7 +1141,11 @@
   1.145      }
   1.146    }
   1.147  
   1.148 -  Handle resolved = MethodHandles::resolve_MemberName(mname, CHECK_NULL);
   1.149 +  KlassHandle caller(THREAD,
   1.150 +                     caller_jh == NULL ? (Klass*) NULL :
   1.151 +                     java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh)));
   1.152 +  Handle resolved = MethodHandles::resolve_MemberName(mname, caller, CHECK_NULL);
   1.153 +
   1.154    if (resolved.is_null()) {
   1.155      int flags = java_lang_invoke_MemberName::flags(mname());
   1.156      int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
     2.1 --- a/src/share/vm/prims/methodHandles.hpp	Thu Dec 05 16:37:29 2013 +0400
     2.2 +++ b/src/share/vm/prims/methodHandles.hpp	Thu Dec 05 00:36:42 2013 -0800
     2.3 @@ -55,7 +55,7 @@
     2.4  
     2.5   public:
     2.6    // working with member names
     2.7 -  static Handle resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type
     2.8 +  static Handle resolve_MemberName(Handle mname, KlassHandle caller, TRAPS); // compute vmtarget/vmindex from name/type
     2.9    static void expand_MemberName(Handle mname, int suppress, TRAPS);  // expand defc/name/type if missing
    2.10    static Handle new_MemberName(TRAPS);  // must be followed by init_MemberName
    2.11    static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target

mercurial