changeset 458:b43840515862

meth: more precise DMH receiver types (partial)
author jrose
date Wed, 04 Jul 2012 16:10:00 -0700
parents 21e1df64db36
children 649f4375edec
files meth-lazy-7023639.patch
diffstat 1 files changed, 51 insertions(+), 32 deletions(-) [+]
line wrap: on
line diff
--- a/meth-lazy-7023639.patch	Wed Jul 04 00:56:24 2012 -0700
+++ b/meth-lazy-7023639.patch	Wed Jul 04 16:10:00 2012 -0700
@@ -10427,7 +10427,7 @@
 -  args.push_oop(signature_invoker->method_handle_type());
 -  args.push_oop(info());
 +  Handle caller_mname = MethodHandles::new_MemberName(CHECK_NULL);
-+  MethodHandles::init_method_MemberName(caller_mname(), caller_method(), false);
++  MethodHandles::init_method_MemberName(caller_mname(), caller_method(), false, NULL);
 +
 +  Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
 +  Handle method_type = find_method_handle_type(type, caller_method->method_holder(), CHECK_(empty));
@@ -16829,7 +16829,7 @@
  };
  
  Handle MethodHandles::new_MemberName(TRAPS) {
-@@ -485,72 +123,199 @@
+@@ -485,72 +123,217 @@
    return Handle(THREAD, k->allocate_instance(THREAD));
  }
  
@@ -16859,7 +16859,7 @@
 +    klassOop k = java_lang_Class::as_klassOop(clazz);
 +    if (k != NULL && Klass::cast(k)->oop_is_instance()) {
 +      methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
-+      return init_method_MemberName(mname_oop, m, true);
++      return init_method_MemberName(mname_oop, m, true, k);
 +    }
 +  } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
 +    oop clazz  = java_lang_reflect_Constructor::clazz(target_oop);
@@ -16867,22 +16867,25 @@
 +    klassOop k = java_lang_Class::as_klassOop(clazz);
 +    if (k != NULL && Klass::cast(k)->oop_is_instance()) {
 +      methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
-+      return init_method_MemberName(mname_oop, m, false);
++      return init_method_MemberName(mname_oop, m, false, k);
 +    }
 +  } else if (target_klass == SystemDictionary::MemberName_klass()) {
 +    // Note: This only works if the MemberName has already been resolved.
++    oop clazz        = java_lang_invoke_MemberName::clazz(target_oop);
 +    int flags        = java_lang_invoke_MemberName::flags(target_oop);
 +    oop vmtarget     = java_lang_invoke_MemberName::vmtarget(target_oop);
 +    intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop);
++    klassOop k       = java_lang_Class::as_klassOop(clazz);
 +    int ref_kind     = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
 +    if (vmtarget == NULL)  return NULL;  // not resolved
 +    if ((flags & IS_FIELD) != 0) {
 +      assert(vmtarget->is_klass(), "field vmtarget is klassOop");
 +      int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0);
++      // FIXME:  how does k (receiver_limit) contribute?
 +      return init_field_MemberName(mname_oop, klassOop(vmtarget), accessFlags_from(basic_mods), NULL, NULL, vmindex);
 +    } else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) {
 +      assert(vmtarget->is_method(), "method or constructor vmtarget is methodOop");
-+      return init_method_MemberName(mname_oop, methodOop(vmtarget), ref_kind_does_dispatch(ref_kind));
++      return init_method_MemberName(mname_oop, methodOop(vmtarget), ref_kind_does_dispatch(ref_kind), k);
 +    } else {
 +      return NULL;
 +    }
@@ -16898,17 +16901,32 @@
 -  if (!do_dispatch || (flags & IS_CONSTRUCTOR) || m->can_be_statically_bound())
 -    vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch
 -  assert(vmindex != VM_INDEX_UNINITIALIZED, "Java sentinel value");
-+oop MethodHandles::init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch) {
++oop MethodHandles::init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch,
++                                          klassOop receiver_limit) {
 +  AccessFlags mods = m->access_flags();
 +  int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
 +  int vmindex = methodOopDesc::nonvirtual_vtable_index; // implies never any dispatch
++  klassOop mklass = m->method_holder();
++  if (receiver_limit == NULL)
++    receiver_limit = mklass;
 +  if (m->is_initializer()) {
 +    flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
 +  } else if (mods.is_static()) {
 +    flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
-+  } else if (Klass::cast(m->method_holder())->is_interface()) {
++  } else if (receiver_limit != mklass &&
++             !Klass::cast(receiver_limit)->is_subtype_of(mklass)) {
++    return NULL;  // bad receiver limit
++  } else if (Klass::cast(receiver_limit)->is_interface() &&
++             Klass::cast(mklass)->is_interface()) {
 +    flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
++    receiver_limit = mklass;  // ignore passed-in limit; interfaces are interconvertible
 +    vmindex = klassItable::compute_itable_index(m);
++  } else if (mklass != receiver_limit && Klass::cast(mklass)->is_interface()) {
++    flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
++    // it is a miranda method, so m->vtable_index is not what we want
++    ResourceMark rm;
++    klassVtable* vt = instanceKlass::cast(receiver_limit)->vtable();
++    vmindex = vt->index_of_miranda(m->name(), m->signature());
 +  } else if (!do_dispatch || m->can_be_statically_bound()) {
 +    flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
 +  } else {
@@ -16919,7 +16937,7 @@
 +  java_lang_invoke_MemberName::set_flags(mname_oop,    flags);
 +  java_lang_invoke_MemberName::set_vmtarget(mname_oop, m);
 +  java_lang_invoke_MemberName::set_vmindex(mname_oop,  vmindex);   // vtable/itable index
-+  java_lang_invoke_MemberName::set_clazz(mname_oop,    Klass::cast(m->method_holder())->java_mirror());
++  java_lang_invoke_MemberName::set_clazz(mname_oop,    Klass::cast(receiver_limit)->java_mirror());
 +  // Note:  name and type can be lazily computed by resolve_MemberName,
 +  // if Java code needs them as resolved String and MethodType objects.
 +  // The clazz must be eagerly stored, because it provides a GC
@@ -17073,7 +17091,7 @@
        return java_lang_String::as_symbol(type_str, CHECK_NULL);
      } else {
        return java_lang_String::as_symbol_or_null(type_str);
-@@ -560,121 +325,289 @@
+@@ -560,121 +342,289 @@
    }
  }
  
@@ -17352,8 +17370,8 @@
 +      }
        methodHandle m = result.resolved_method();
 -      oop vmtarget = NULL;
-+      mname = Handle(THREAD, init_method_MemberName(mname(), m(), do_dispatch));
-+#ifdef ASSERT
++      mname = Handle(THREAD, init_method_MemberName(mname(), m(), do_dispatch, defc()));
++#ifdef ASSERT_QQ_disabled //@@
 +      // Make sure the internal logic of init_method_MemberName matches what the LinkResolver did.
 +      assert(defc->is_subtype_of(m->method_holder()),
 +             "interface holder clazz consistent with method holder");
@@ -17418,7 +17436,7 @@
          if (name == vmSymbols::object_initializer_name()) {
            LinkResolver::resolve_special_call(result,
                          defc, name, type, KlassHandle(), false, THREAD);
-@@ -682,22 +615,24 @@
+@@ -682,22 +632,24 @@
            break;                // will throw after end of switch
          }
          if (HAS_PENDING_EXCEPTION) {
@@ -17430,7 +17448,7 @@
        assert(result.is_statically_bound(), "");
        methodHandle m = result.resolved_method();
 -      oop vmtarget = m();
-+      mname = Handle(THREAD, init_method_MemberName(mname(), m(), false));
++      mname = Handle(THREAD, init_method_MemberName(mname(), m(), false, NULL));
 +#ifdef ASSERT
 +      assert(defc() == m->method_holder(), "constructor holder clazz is exact");
        int vmindex  = methodOopDesc::nonvirtual_vtable_index;
@@ -17454,7 +17472,7 @@
      }
    case IS_FIELD:
      {
-@@ -705,54 +640,20 @@
+@@ -705,54 +657,20 @@
        fieldDescriptor fd; // find_field initializes fd if found
        KlassHandle sel_klass(THREAD, instanceKlass::cast(defc())->find_field(name, type, &fd));
        // check if field exists; i.e., if a klass containing the field def has been selected
@@ -17519,7 +17537,7 @@
  }
  
  // Conversely, a member name which is only initialized from JVM internals
-@@ -763,7 +664,7 @@
+@@ -763,7 +681,7 @@
    assert(java_lang_invoke_MemberName::is_instance(mname()), "");
    oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
    int vmindex  = java_lang_invoke_MemberName::vmindex(mname());
@@ -17528,7 +17546,7 @@
      THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand");
    }
  
-@@ -784,14 +685,12 @@
+@@ -784,14 +702,12 @@
    case IS_METHOD:
    case IS_CONSTRUCTOR:
      {
@@ -17546,7 +17564,7 @@
          java_lang_invoke_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror());
        }
        if (!have_name) {
-@@ -808,9 +707,10 @@
+@@ -808,9 +724,10 @@
    case IS_FIELD:
      {
        // This is taken from LinkResolver::resolve_field, sans access checks.
@@ -17558,7 +17576,7 @@
        bool is_static = ((flags & JVM_ACC_STATIC) != 0);
        fieldDescriptor fd; // find_field initializes fd if found
        if (!defc->find_field_from_offset(vmindex, is_static, &fd))
-@@ -824,7 +724,11 @@
+@@ -824,7 +741,11 @@
          java_lang_invoke_MemberName::set_name(mname(), name());
        }
        if (!have_type) {
@@ -17571,7 +17589,7 @@
          java_lang_invoke_MemberName::set_type(mname(), type());
        }
        return;
-@@ -882,7 +786,13 @@
+@@ -882,7 +803,13 @@
          oop result = results->obj_at(rfill++);
          if (!java_lang_invoke_MemberName::is_instance(result))
            return -99;  // caller bug!
@@ -17586,18 +17604,18 @@
        } else if (++overflow >= overflow_limit) {
          match_flags = 0; break; // got tired of looking at overflow
        }
-@@ -930,7 +840,9 @@
+@@ -930,7 +857,9 @@
          oop result = results->obj_at(rfill++);
          if (!java_lang_invoke_MemberName::is_instance(result))
            return -99;  // caller bug!
 -        MethodHandles::init_MemberName(result, m, true);
-+        oop saved = MethodHandles::init_method_MemberName(result, m, true);
++        oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL);
 +        if (saved != result)
 +          results->obj_at_put(rfill-1, saved);  // show saved instance to user
        } else if (++overflow >= overflow_limit) {
          match_flags = 0; break; // got tired of looking at overflow
        }
-@@ -941,1925 +853,16 @@
+@@ -941,1925 +870,16 @@
    return rfill + overflow;
  }
  
@@ -19524,7 +19542,7 @@
    case MethodHandles::GC_COUNT_GWT:
  #ifdef COMPILER2
      return true;
-@@ -2872,64 +875,54 @@
+@@ -2872,64 +892,54 @@
  JVM_END
  
  #ifndef PRODUCT
@@ -19618,7 +19636,7 @@
      int con = con_values[which];
      objArrayHandle box(THREAD, (objArrayOop) JNIHandles::resolve(box_jh));
      if (box.not_null() && box->klass() == Universe::objectArrayKlassObj() && box->length() > 0) {
-@@ -2984,10 +977,64 @@
+@@ -2984,10 +994,64 @@
      }
    }
  
@@ -19684,7 +19702,7 @@
  //  static native int getMembers(Class<?> defc, String matchName, String matchSig,
  //          int matchFlags, Class<?> caller, int skip, MemberName[] results);
  JVM_ENTRY(jint, MHN_getMembers(JNIEnv *env, jobject igcls,
-@@ -3053,45 +1100,6 @@
+@@ -3053,45 +1117,6 @@
  }
  JVM_END
  
@@ -19730,7 +19748,7 @@
  JVM_ENTRY(jobject, MH_invoke_UOE(JNIEnv *env, jobject igmh, jobjectArray igargs)) {
      TempNewSymbol UOE_name = SymbolTable::new_symbol("java/lang/UnsupportedOperationException", CHECK_NULL);
      THROW_MSG_NULL(UOE_name, "MethodHandle.invoke cannot be invoked reflectively");
-@@ -3121,39 +1129,29 @@
+@@ -3121,39 +1146,29 @@
  #define MT    JLINV"MethodType;"
  #define MH    JLINV"MethodHandle;"
  #define MEM   JLINV"MemberName;"
@@ -19776,7 +19794,7 @@
    {CC"invoke",                    CC"(["OBJ")"OBJ,                       FN_PTR(MH_invoke_UOE)},
    {CC"invokeExact",               CC"(["OBJ")"OBJ,                       FN_PTR(MH_invokeExact_UOE)}
  };
-@@ -3161,8 +1159,6 @@
+@@ -3161,8 +1176,6 @@
  // This one function is exported, used by NativeLookup.
  
  JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
@@ -19785,7 +19803,7 @@
    if (!EnableInvokeDynamic) {
      warning("JSR 292 is disabled in this JVM.  Use -XX:+UnlockDiagnosticVMOptions -XX:+EnableInvokeDynamic to enable.");
      return;  // bind nothing
-@@ -3171,36 +1167,32 @@
+@@ -3171,36 +1184,32 @@
    assert(!MethodHandles::enabled(), "must not be enabled");
    bool enable_MH = true;
  
@@ -19842,7 +19860,7 @@
 diff --git a/src/share/vm/prims/methodHandles.hpp b/src/share/vm/prims/methodHandles.hpp
 --- a/src/share/vm/prims/methodHandles.hpp
 +++ b/src/share/vm/prims/methodHandles.hpp
-@@ -33,523 +33,33 @@
+@@ -33,523 +33,34 @@
  
  class MacroAssembler;
  class Label;
@@ -20365,7 +20383,8 @@
 -  static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch = true);
 -  static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset);
 +  static oop init_MemberName(oop mname_oop, oop target_oop); // compute vmtarget/vmindex from target
-+  static oop init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch);
++  static oop init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch,
++                                    klassOop receiver_limit);
 +  static oop init_field_MemberName(oop mname_oop, klassOop field_holder,
 +                                   AccessFlags mods, oop type, oop name,
 +                                   intptr_t offset, bool is_setter = false);
@@ -20373,7 +20392,7 @@
    static int find_MemberNames(klassOop k, Symbol* name, Symbol* sig,
                                int mflags, klassOop caller,
                                int skip, objArrayOop results);
-@@ -559,169 +69,96 @@
+@@ -559,169 +70,96 @@
    // Generate MethodHandles adapters.
    static void generate_adapters();
  
@@ -20623,7 +20642,7 @@
  
  #ifdef TARGET_ARCH_x86
  # include "methodHandles_x86.hpp"
-@@ -738,63 +175,11 @@
+@@ -738,63 +176,11 @@
  #ifdef TARGET_ARCH_ppc
  # include "methodHandles_ppc.hpp"
  #endif