src/share/vm/prims/methodHandles.cpp

changeset 5732
b2e698d2276c
parent 5354
c1bd7b5bdc70
child 5848
ac9cb1d5a202
     1.1 --- a/src/share/vm/prims/methodHandles.cpp	Tue Sep 17 23:12:27 2013 +0200
     1.2 +++ b/src/share/vm/prims/methodHandles.cpp	Fri Sep 13 22:38:02 2013 -0400
     1.3 @@ -127,25 +127,37 @@
     1.4  }
     1.5  
     1.6  oop MethodHandles::init_MemberName(Handle mname, Handle target) {
     1.7 +  // This method is used from java.lang.invoke.MemberName constructors.
     1.8 +  // It fills in the new MemberName from a java.lang.reflect.Member.
     1.9    Thread* thread = Thread::current();
    1.10    oop target_oop = target();
    1.11    Klass* target_klass = target_oop->klass();
    1.12    if (target_klass == SystemDictionary::reflect_Field_klass()) {
    1.13      oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
    1.14      int slot  = java_lang_reflect_Field::slot(target_oop);  // fd.index()
    1.15 -    int mods  = java_lang_reflect_Field::modifiers(target_oop);
    1.16 -    oop type  = java_lang_reflect_Field::type(target_oop);
    1.17 -    oop name  = java_lang_reflect_Field::name(target_oop);
    1.18      KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
    1.19 -    intptr_t offset = InstanceKlass::cast(k())->field_offset(slot);
    1.20 -    return init_field_MemberName(mname, k, accessFlags_from(mods), type, name, offset);
    1.21 +    if (!k.is_null() && k->oop_is_instance()) {
    1.22 +      fieldDescriptor fd(InstanceKlass::cast(k()), slot);
    1.23 +      oop mname2 = init_field_MemberName(mname, fd);
    1.24 +      if (mname2 != NULL) {
    1.25 +        // Since we have the reified name and type handy, add them to the result.
    1.26 +        if (java_lang_invoke_MemberName::name(mname2) == NULL)
    1.27 +          java_lang_invoke_MemberName::set_name(mname2, java_lang_reflect_Field::name(target_oop));
    1.28 +        if (java_lang_invoke_MemberName::type(mname2) == NULL)
    1.29 +          java_lang_invoke_MemberName::set_type(mname2, java_lang_reflect_Field::type(target_oop));
    1.30 +      }
    1.31 +      return mname2;
    1.32 +    }
    1.33    } else if (target_klass == SystemDictionary::reflect_Method_klass()) {
    1.34      oop clazz  = java_lang_reflect_Method::clazz(target_oop);
    1.35      int slot   = java_lang_reflect_Method::slot(target_oop);
    1.36      KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
    1.37      if (!k.is_null() && k->oop_is_instance()) {
    1.38        Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
    1.39 -      return init_method_MemberName(mname, m, true, k);
    1.40 +      if (m == NULL || is_signature_polymorphic(m->intrinsic_id()))
    1.41 +        return NULL;            // do not resolve unless there is a concrete signature
    1.42 +      CallInfo info(m, k());
    1.43 +      return init_method_MemberName(mname, info);
    1.44      }
    1.45    } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) {
    1.46      oop clazz  = java_lang_reflect_Constructor::clazz(target_oop);
    1.47 @@ -153,65 +165,50 @@
    1.48      KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
    1.49      if (!k.is_null() && k->oop_is_instance()) {
    1.50        Method* m = InstanceKlass::cast(k())->method_with_idnum(slot);
    1.51 -      return init_method_MemberName(mname, m, false, k);
    1.52 -    }
    1.53 -  } else if (target_klass == SystemDictionary::MemberName_klass()) {
    1.54 -    // Note: This only works if the MemberName has already been resolved.
    1.55 -    oop clazz        = java_lang_invoke_MemberName::clazz(target_oop);
    1.56 -    int flags        = java_lang_invoke_MemberName::flags(target_oop);
    1.57 -    Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop);
    1.58 -    intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop);
    1.59 -    KlassHandle k(thread, java_lang_Class::as_Klass(clazz));
    1.60 -    int ref_kind     = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK;
    1.61 -    if (vmtarget == NULL)  return NULL;  // not resolved
    1.62 -    if ((flags & IS_FIELD) != 0) {
    1.63 -      assert(vmtarget->is_klass(), "field vmtarget is Klass*");
    1.64 -      int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0);
    1.65 -      // FIXME:  how does k (receiver_limit) contribute?
    1.66 -      KlassHandle k_vmtarget(thread, (Klass*)vmtarget);
    1.67 -      return init_field_MemberName(mname, k_vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex);
    1.68 -    } else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) {
    1.69 -      assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
    1.70 -      return init_method_MemberName(mname, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k);
    1.71 -    } else {
    1.72 -      return NULL;
    1.73 +      if (m == NULL)  return NULL;
    1.74 +      CallInfo info(m, k());
    1.75 +      return init_method_MemberName(mname, info);
    1.76      }
    1.77    }
    1.78    return NULL;
    1.79  }
    1.80  
    1.81 -oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispatch,
    1.82 -                                          KlassHandle receiver_limit_h) {
    1.83 -  Klass* receiver_limit = receiver_limit_h();
    1.84 -  AccessFlags mods = m->access_flags();
    1.85 -  int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
    1.86 -  int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch
    1.87 -  Klass* mklass = m->method_holder();
    1.88 -  if (receiver_limit == NULL)
    1.89 -    receiver_limit = mklass;
    1.90 -  if (m->is_initializer()) {
    1.91 -    flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
    1.92 -  } else if (mods.is_static()) {
    1.93 -    flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT);
    1.94 -  } else if (receiver_limit != mklass &&
    1.95 -             !receiver_limit->is_subtype_of(mklass)) {
    1.96 -    return NULL;  // bad receiver limit
    1.97 -  } else if (do_dispatch && receiver_limit->is_interface() &&
    1.98 -             mklass->is_interface()) {
    1.99 +oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) {
   1.100 +  assert(info.resolved_appendix().is_null(), "only normal methods here");
   1.101 +  KlassHandle receiver_limit = info.resolved_klass();
   1.102 +  methodHandle m = info.resolved_method();
   1.103 +  int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS );
   1.104 +  int vmindex = Method::invalid_vtable_index;
   1.105 +
   1.106 +  switch (info.call_kind()) {
   1.107 +  case CallInfo::itable_call:
   1.108 +    vmindex = info.itable_index();
   1.109 +    // More importantly, the itable index only works with the method holder.
   1.110 +    receiver_limit = m->method_holder();
   1.111 +    assert(receiver_limit->verify_itable_index(vmindex), "");
   1.112      flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT);
   1.113 -    receiver_limit = mklass;  // ignore passed-in limit; interfaces are interconvertible
   1.114 -    vmindex = klassItable::compute_itable_index(m);
   1.115 -  } else if (do_dispatch && mklass != receiver_limit && mklass->is_interface()) {
   1.116 +    break;
   1.117 +
   1.118 +  case CallInfo::vtable_call:
   1.119 +    vmindex = info.vtable_index();
   1.120      flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
   1.121 -    // it is a miranda method, so m->vtable_index is not what we want
   1.122 -    ResourceMark rm;
   1.123 -    klassVtable* vt = InstanceKlass::cast(receiver_limit)->vtable();
   1.124 -    vmindex = vt->index_of_miranda(m->name(), m->signature());
   1.125 -  } else if (!do_dispatch || m->can_be_statically_bound()) {
   1.126 -    flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
   1.127 -  } else {
   1.128 -    flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT);
   1.129 -    vmindex = m->vtable_index();
   1.130 +    assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe");
   1.131 +    break;
   1.132 +
   1.133 +  case CallInfo::direct_call:
   1.134 +    vmindex = Method::nonvirtual_vtable_index;
   1.135 +    if (m->is_static()) {
   1.136 +      flags |= IS_METHOD      | (JVM_REF_invokeStatic  << REFERENCE_KIND_SHIFT);
   1.137 +    } else if (m->is_initializer()) {
   1.138 +      flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
   1.139 +      assert(receiver_limit == m->method_holder(), "constructor call must be exactly typed");
   1.140 +    } else {
   1.141 +      flags |= IS_METHOD      | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT);
   1.142 +      assert(receiver_limit->is_subtype_of(m->method_holder()), "special call must be type-safe");
   1.143 +    }
   1.144 +    break;
   1.145 +
   1.146 +  default:  assert(false, "bad CallInfo");  return NULL;
   1.147    }
   1.148  
   1.149    // @CallerSensitive annotation detected
   1.150 @@ -221,7 +218,7 @@
   1.151  
   1.152    oop mname_oop = mname();
   1.153    java_lang_invoke_MemberName::set_flags(   mname_oop, flags);
   1.154 -  java_lang_invoke_MemberName::set_vmtarget(mname_oop, m);
   1.155 +  java_lang_invoke_MemberName::set_vmtarget(mname_oop, m());
   1.156    java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex);   // vtable/itable index
   1.157    java_lang_invoke_MemberName::set_clazz(   mname_oop, receiver_limit->java_mirror());
   1.158    // Note:  name and type can be lazily computed by resolve_MemberName,
   1.159 @@ -237,59 +234,19 @@
   1.160    return mname();
   1.161  }
   1.162  
   1.163 -Handle MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) {
   1.164 -  Handle empty;
   1.165 -  if (info.resolved_appendix().not_null()) {
   1.166 -    // The resolved MemberName must not be accompanied by an appendix argument,
   1.167 -    // since there is no way to bind this value into the MemberName.
   1.168 -    // Caller is responsible to prevent this from happening.
   1.169 -    THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty);
   1.170 -  }
   1.171 -  methodHandle m = info.resolved_method();
   1.172 -  KlassHandle defc = info.resolved_klass();
   1.173 -  int vmindex = Method::invalid_vtable_index;
   1.174 -  if (defc->is_interface() && m->method_holder()->is_interface()) {
   1.175 -    // static interface methods do not reference vtable or itable
   1.176 -    if (m->is_static()) {
   1.177 -      vmindex = Method::nonvirtual_vtable_index;
   1.178 -    }
   1.179 -    // interface methods invoked via invokespecial also
   1.180 -    // do not reference vtable or itable.
   1.181 -    int ref_kind = ((java_lang_invoke_MemberName::flags(mname()) >>
   1.182 -                     REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK);
   1.183 -    if (ref_kind == JVM_REF_invokeSpecial) {
   1.184 -      vmindex = Method::nonvirtual_vtable_index;
   1.185 -    }
   1.186 -    // If neither m is static nor ref_kind is invokespecial,
   1.187 -    // set it to itable index.
   1.188 -    if (vmindex == Method::invalid_vtable_index) {
   1.189 -      // LinkResolver does not report itable indexes!  (fix this?)
   1.190 -      vmindex = klassItable::compute_itable_index(m());
   1.191 -    }
   1.192 -  } else if (m->can_be_statically_bound()) {
   1.193 -    // LinkResolver reports vtable index even for final methods!
   1.194 -    vmindex = Method::nonvirtual_vtable_index;
   1.195 -  } else {
   1.196 -    vmindex = info.vtable_index();
   1.197 -  }
   1.198 -  oop res = init_method_MemberName(mname, m(), (vmindex >= 0), defc());
   1.199 -  assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), "");
   1.200 -  return Handle(THREAD, res);
   1.201 -}
   1.202 -
   1.203 -oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder,
   1.204 -                                         AccessFlags mods, oop type, oop name,
   1.205 -                                         intptr_t offset, bool is_setter) {
   1.206 -  int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
   1.207 -  flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
   1.208 +oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool is_setter) {
   1.209 +  int flags = (jushort)( fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
   1.210 +  flags |= IS_FIELD | ((fd.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
   1.211    if (is_setter)  flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
   1.212 -  Metadata* vmtarget = field_holder();
   1.213 -  int vmindex  = offset;  // determines the field uniquely when combined with static bit
   1.214 +  Metadata* vmtarget = fd.field_holder();
   1.215 +  int vmindex        = fd.offset();  // determines the field uniquely when combined with static bit
   1.216    oop mname_oop = mname();
   1.217    java_lang_invoke_MemberName::set_flags(mname_oop,    flags);
   1.218    java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
   1.219    java_lang_invoke_MemberName::set_vmindex(mname_oop,  vmindex);
   1.220 -  java_lang_invoke_MemberName::set_clazz(mname_oop,    field_holder->java_mirror());
   1.221 +  java_lang_invoke_MemberName::set_clazz(mname_oop,    fd.field_holder()->java_mirror());
   1.222 +  oop type = field_signature_type_or_null(fd.signature());
   1.223 +  oop name = field_name_or_null(fd.name());
   1.224    if (name != NULL)
   1.225      java_lang_invoke_MemberName::set_name(mname_oop,   name);
   1.226    if (type != NULL)
   1.227 @@ -305,19 +262,6 @@
   1.228    return mname();
   1.229  }
   1.230  
   1.231 -Handle MethodHandles::init_field_MemberName(Handle mname, FieldAccessInfo& info, TRAPS) {
   1.232 -  return Handle();
   1.233 -#if 0 // FIXME
   1.234 -  KlassHandle field_holder = info.klass();
   1.235 -  intptr_t    field_offset = info.field_offset();
   1.236 -  return init_field_MemberName(mname_oop, field_holder(),
   1.237 -                               info.access_flags(),
   1.238 -                               type, name,
   1.239 -                               field_offset, false /*is_setter*/);
   1.240 -#endif
   1.241 -}
   1.242 -
   1.243 -
   1.244  // JVM 2.9 Special Methods:
   1.245  // A method is signature polymorphic if and only if all of the following conditions hold :
   1.246  // * It is declared in the java.lang.invoke.MethodHandle class.
   1.247 @@ -573,12 +517,12 @@
   1.248    return SystemDictionary::Object_klass()->java_mirror();
   1.249  }
   1.250  
   1.251 -static oop field_name_or_null(Symbol* s) {
   1.252 +oop MethodHandles::field_name_or_null(Symbol* s) {
   1.253    if (s == NULL)  return NULL;
   1.254    return StringTable::lookup(s);
   1.255  }
   1.256  
   1.257 -static oop field_signature_type_or_null(Symbol* s) {
   1.258 +oop MethodHandles::field_signature_type_or_null(Symbol* s) {
   1.259    if (s == NULL)  return NULL;
   1.260    BasicType bt = FieldType::basic_type(s);
   1.261    if (is_java_primitive(bt)) {
   1.262 @@ -701,7 +645,14 @@
   1.263            return empty;
   1.264          }
   1.265        }
   1.266 -      return init_method_MemberName(mname, result, THREAD);
   1.267 +      if (result.resolved_appendix().not_null()) {
   1.268 +        // The resolved MemberName must not be accompanied by an appendix argument,
   1.269 +        // since there is no way to bind this value into the MemberName.
   1.270 +        // Caller is responsible to prevent this from happening.
   1.271 +        THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty);
   1.272 +      }
   1.273 +      oop mname2 = init_method_MemberName(mname, result);
   1.274 +      return Handle(THREAD, mname2);
   1.275      }
   1.276    case IS_CONSTRUCTOR:
   1.277      {
   1.278 @@ -719,22 +670,21 @@
   1.279          }
   1.280        }
   1.281        assert(result.is_statically_bound(), "");
   1.282 -      return init_method_MemberName(mname, result, THREAD);
   1.283 +      oop mname2 = init_method_MemberName(mname, result);
   1.284 +      return Handle(THREAD, mname2);
   1.285      }
   1.286    case IS_FIELD:
   1.287      {
   1.288 -      // This is taken from LinkResolver::resolve_field, sans access checks.
   1.289 -      fieldDescriptor fd; // find_field initializes fd if found
   1.290 -      KlassHandle sel_klass(THREAD, InstanceKlass::cast(defc())->find_field(name, type, &fd));
   1.291 -      // check if field exists; i.e., if a klass containing the field def has been selected
   1.292 -      if (sel_klass.is_null())  return empty;  // should not happen
   1.293 -      oop type = field_signature_type_or_null(fd.signature());
   1.294 -      oop name = field_name_or_null(fd.name());
   1.295 -      bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind));
   1.296 -      mname = Handle(THREAD,
   1.297 -                     init_field_MemberName(mname, sel_klass,
   1.298 -                                           fd.access_flags(), type, name, fd.offset(), is_setter));
   1.299 -      return mname;
   1.300 +      fieldDescriptor result; // find_field initializes fd if found
   1.301 +      {
   1.302 +        assert(!HAS_PENDING_EXCEPTION, "");
   1.303 +        LinkResolver::resolve_field(result, defc, name, type, KlassHandle(), Bytecodes::_nop, false, false, THREAD);
   1.304 +        if (HAS_PENDING_EXCEPTION) {
   1.305 +          return empty;
   1.306 +        }
   1.307 +      }
   1.308 +      oop mname2 = init_field_MemberName(mname, result, ref_kind_is_setter(ref_kind));
   1.309 +      return Handle(THREAD, mname2);
   1.310      }
   1.311    default:
   1.312      THROW_MSG_(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format", empty);
   1.313 @@ -793,7 +743,6 @@
   1.314      }
   1.315    case IS_FIELD:
   1.316      {
   1.317 -      // This is taken from LinkResolver::resolve_field, sans access checks.
   1.318        assert(vmtarget->is_klass(), "field vmtarget is Klass*");
   1.319        if (!((Klass*) vmtarget)->oop_is_instance())  break;
   1.320        instanceKlassHandle defc(THREAD, (Klass*) vmtarget);
   1.321 @@ -872,11 +821,7 @@
   1.322          Handle result(thread, results->obj_at(rfill++));
   1.323          if (!java_lang_invoke_MemberName::is_instance(result()))
   1.324            return -99;  // caller bug!
   1.325 -        oop type = field_signature_type_or_null(st.signature());
   1.326 -        oop name = field_name_or_null(st.name());
   1.327 -        oop saved = MethodHandles::init_field_MemberName(result, st.klass(),
   1.328 -                                                         st.access_flags(), type, name,
   1.329 -                                                         st.offset());
   1.330 +        oop saved = MethodHandles::init_field_MemberName(result, st.field_descriptor());
   1.331          if (saved != result())
   1.332            results->obj_at_put(rfill-1, saved);  // show saved instance to user
   1.333        } else if (++overflow >= overflow_limit) {
   1.334 @@ -926,7 +871,8 @@
   1.335          Handle result(thread, results->obj_at(rfill++));
   1.336          if (!java_lang_invoke_MemberName::is_instance(result()))
   1.337            return -99;  // caller bug!
   1.338 -        oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL);
   1.339 +        CallInfo info(m);
   1.340 +        oop saved = MethodHandles::init_method_MemberName(result, info);
   1.341          if (saved != result())
   1.342            results->obj_at_put(rfill-1, saved);  // show saved instance to user
   1.343        } else if (++overflow >= overflow_limit) {
   1.344 @@ -1227,7 +1173,8 @@
   1.345      x = ((Klass*) vmtarget)->java_mirror();
   1.346    } else if (vmtarget->is_method()) {
   1.347      Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
   1.348 -    x = MethodHandles::init_method_MemberName(mname2, (Method*)vmtarget, false, NULL);
   1.349 +    CallInfo info((Method*)vmtarget);
   1.350 +    x = MethodHandles::init_method_MemberName(mname2, info);
   1.351    }
   1.352    result->obj_at_put(1, x);
   1.353    return JNIHandles::make_local(env, result());

mercurial