hotspot/src/share/vm/prims/methodHandles.cpp
changeset 13728 882756847a04
parent 13396 1b2b5f740ee0
child 13732 a9865f5514fc
--- a/hotspot/src/share/vm/prims/methodHandles.cpp	Fri Aug 31 16:39:35 2012 -0700
+++ b/hotspot/src/share/vm/prims/methodHandles.cpp	Sat Sep 01 13:25:18 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -124,49 +124,49 @@
 }
 
 oop MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
-  klassOop target_klass = target_oop->klass();
+  Klass* target_klass = target_oop->klass();
   if (target_klass == SystemDictionary::reflect_Field_klass()) {
     oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
     int slot  = java_lang_reflect_Field::slot(target_oop);  // fd.index()
     int mods  = java_lang_reflect_Field::modifiers(target_oop);
     oop type  = java_lang_reflect_Field::type(target_oop);
     oop name  = java_lang_reflect_Field::name(target_oop);
-    klassOop k = java_lang_Class::as_klassOop(clazz);
-    intptr_t offset = instanceKlass::cast(k)->field_offset(slot);
+    Klass* k = java_lang_Class::as_Klass(clazz);
+    intptr_t offset = InstanceKlass::cast(k)->field_offset(slot);
     return init_field_MemberName(mname_oop, k, accessFlags_from(mods), type, name, offset);
   } else if (target_klass == SystemDictionary::reflect_Method_klass()) {
     oop clazz  = java_lang_reflect_Method::clazz(target_oop);
     int slot   = java_lang_reflect_Method::slot(target_oop);
-    klassOop k = java_lang_Class::as_klassOop(clazz);
+    Klass* k = java_lang_Class::as_Klass(clazz);
     if (k != NULL && Klass::cast(k)->oop_is_instance()) {
-      methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
+      Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
       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);
     int slot   = java_lang_reflect_Constructor::slot(target_oop);
-    klassOop k = java_lang_Class::as_klassOop(clazz);
+    Klass* k = java_lang_Class::as_Klass(clazz);
     if (k != NULL && Klass::cast(k)->oop_is_instance()) {
-      methodOop m = instanceKlass::cast(k)->method_with_idnum(slot);
+      Method* m = InstanceKlass::cast(k)->method_with_idnum(slot);
       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);
+    Metadata* 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);
+    Klass* k         = java_lang_Class::as_Klass(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");
+      assert(vmtarget->is_klass(), "field vmtarget is Klass*");
       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);
+      return init_field_MemberName(mname_oop, (Klass*)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), k);
+      assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
+      return init_method_MemberName(mname_oop, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k);
     } else {
       return NULL;
     }
@@ -174,12 +174,12 @@
   return NULL;
 }
 
-oop MethodHandles::init_method_MemberName(oop mname_oop, methodOop m, bool do_dispatch,
-                                          klassOop receiver_limit) {
+oop MethodHandles::init_method_MemberName(oop mname_oop, Method* m, bool do_dispatch,
+                                          Klass* 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();
+  int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch
+  Klass* mklass = m->method_holder();
   if (receiver_limit == NULL)
     receiver_limit = mklass;
   if (m->is_initializer()) {
@@ -198,7 +198,7 @@
     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();
+    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);
@@ -214,7 +214,7 @@
   // 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
-  // root to help keep alive the methodOop.
+  // root to help keep alive the Method*.
   // If relevant, the vtable or itable value is stored as vmindex.
   // This is done eagerly, since it is readily available without
   // constructing any new objects.
@@ -238,7 +238,7 @@
     vmindex = klassItable::compute_itable_index(m());
   } else if (m->can_be_statically_bound()) {
     // LinkResolver reports vtable index even for final methods!
-    vmindex = methodOopDesc::nonvirtual_vtable_index;
+    vmindex = Method::nonvirtual_vtable_index;
   } else {
     vmindex = info.vtable_index();
   }
@@ -247,13 +247,13 @@
   return Handle(THREAD, res);
 }
 
-oop MethodHandles::init_field_MemberName(oop mname_oop, klassOop field_holder,
+oop MethodHandles::init_field_MemberName(oop mname_oop, Klass* field_holder,
                                          AccessFlags mods, oop type, oop name,
                                          intptr_t offset, bool is_setter) {
   int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS );
   flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT);
   if (is_setter)  flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT);
-  oop vmtarget = field_holder;
+  Metadata* vmtarget = field_holder;
   int vmindex  = offset;  // determines the field uniquely when combined with static bit
   java_lang_invoke_MemberName::set_flags(mname_oop,    flags);
   java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget);
@@ -276,7 +276,7 @@
 
 Handle MethodHandles::init_field_MemberName(oop mname_oop, FieldAccessInfo& info, TRAPS) {
   return Handle();
-#if 0
+#if 0 // FIXME
   KlassHandle field_holder = info.klass();
   intptr_t    field_offset = info.field_offset();
   return init_field_MemberName(mname_oop, field_holder(),
@@ -293,7 +293,7 @@
 // * It has a single formal parameter of type Object[].
 // * It has a return type of Object.
 // * It has the ACC_VARARGS and ACC_NATIVE flags set.
-bool MethodHandles::is_method_handle_invoke_name(klassOop klass, Symbol* name) {
+bool MethodHandles::is_method_handle_invoke_name(Klass* klass, Symbol* name) {
   if (klass == NULL)
     return false;
   // The following test will fail spuriously during bootstrap of MethodHandle itself:
@@ -302,7 +302,7 @@
   if (Klass::cast(klass)->name() != vmSymbols::java_lang_invoke_MethodHandle())
     return false;
   Symbol* poly_sig = vmSymbols::object_array_object_signature();
-  methodOop m = instanceKlass::cast(klass)->find_method(name, poly_sig);
+  Method* m = InstanceKlass::cast(klass)->find_method(name, poly_sig);
   if (m == NULL)  return false;
   int required = JVM_ACC_NATIVE | JVM_ACC_VARARGS;
   int flags = m->access_flags().as_int();
@@ -351,7 +351,7 @@
   }
 
   // Cover the case of invokeExact and any future variants of invokeFoo.
-  klassOop mh_klass = SystemDictionary::well_known_klass(
+  Klass* mh_klass = SystemDictionary::well_known_klass(
                               SystemDictionary::WK_KLASS_ENUM_NAME(MethodHandle_klass) );
   if (mh_klass != NULL && is_method_handle_invoke_name(mh_klass, name))
     return vmIntrinsics::_invokeGeneric;
@@ -361,7 +361,7 @@
   return vmIntrinsics::_none;
 }
 
-vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(klassOop klass, Symbol* name) {
+vmIntrinsics::ID MethodHandles::signature_polymorphic_name_id(Klass* klass, Symbol* name) {
   if (klass != NULL &&
       Klass::cast(klass)->name() == vmSymbols::java_lang_invoke_MethodHandle()) {
     vmIntrinsics::ID iid = signature_polymorphic_name_id(name);
@@ -568,7 +568,7 @@
       if (s->byte_at(0) == 'L' && s->byte_at(len-1) == ';') {
         TempNewSymbol cname = SymbolTable::probe((const char*)&s->bytes()[1], len-2);
         if (cname == NULL)  return NULL;
-        klassOop wkk = SystemDictionary::find_well_known_klass(cname);
+        Klass* wkk = SystemDictionary::find_well_known_klass(cname);
         if (wkk == NULL)  return NULL;
         return Klass::cast(wkk)->java_mirror();
       }
@@ -577,9 +577,10 @@
   return NULL;
 }
 
+
 // An unresolved member name is a mere symbolic reference.
 // Resolving it plants a vmtarget/vmindex in it,
-// which refers dirctly to JVM internals.
+// which refers directly to JVM internals.
 Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
   Handle empty;
   assert(java_lang_invoke_MemberName::is_instance(mname()), "");
@@ -587,7 +588,7 @@
   if (java_lang_invoke_MemberName::vmtarget(mname()) != NULL) {
     // Already resolved.
     DEBUG_ONLY(int vmindex = java_lang_invoke_MemberName::vmindex(mname()));
-    assert(vmindex >= methodOopDesc::nonvirtual_vtable_index, "");
+    assert(vmindex >= Method::nonvirtual_vtable_index, "");
     return mname;
   }
 
@@ -609,13 +610,13 @@
 
   instanceKlassHandle defc;
   {
-    klassOop defc_klassOop = java_lang_Class::as_klassOop(defc_oop());
-    if (defc_klassOop == NULL)  return empty;  // a primitive; no resolution possible
-    if (!Klass::cast(defc_klassOop)->oop_is_instance()) {
-      if (!Klass::cast(defc_klassOop)->oop_is_array())  return empty;
-      defc_klassOop = SystemDictionary::Object_klass();
+    Klass* defc_klass = java_lang_Class::as_Klass(defc_oop());
+    if (defc_klass == NULL)  return empty;  // a primitive; no resolution possible
+    if (!Klass::cast(defc_klass)->oop_is_instance()) {
+      if (!Klass::cast(defc_klass)->oop_is_array())  return empty;
+      defc_klass = SystemDictionary::Object_klass();
     }
-    defc = instanceKlassHandle(THREAD, defc_klassOop);
+    defc = instanceKlassHandle(THREAD, defc_klass);
   }
   if (defc.is_null()) {
     THROW_MSG_(vmSymbols::java_lang_InternalError(), "primitive class", empty);
@@ -705,14 +706,14 @@
     {
       // This is taken from LinkResolver::resolve_field, sans access checks.
       fieldDescriptor fd; // find_field initializes fd if found
-      KlassHandle sel_klass(THREAD, instanceKlass::cast(defc())->find_field(name, type, &fd));
+      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
       if (sel_klass.is_null())  return empty;  // should not happen
       oop type = field_signature_type_or_null(fd.signature());
       oop name = field_name_or_null(fd.name());
       bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind));
       mname = Handle(THREAD,
-                     init_field_MemberName(mname(), sel_klass->as_klassOop(),
+                     init_field_MemberName(mname(), sel_klass(),
                                            fd.access_flags(), type, name, fd.offset(), is_setter));
       return mname;
     }
@@ -729,7 +730,7 @@
 // which refers directly to JVM internals.
 void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) {
   assert(java_lang_invoke_MemberName::is_instance(mname()), "");
-  oop vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
+  Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
   int vmindex  = java_lang_invoke_MemberName::vmindex(mname());
   if (vmtarget == NULL) {
     THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "nothing to expand");
@@ -752,12 +753,12 @@
   case IS_METHOD:
   case IS_CONSTRUCTOR:
     {
-      assert(vmtarget->is_method(), "method or constructor vmtarget is methodOop");
-      methodHandle m(THREAD, methodOop(vmtarget));
+      assert(vmtarget->is_method(), "method or constructor vmtarget is Method*");
+      methodHandle m(THREAD, (Method*)vmtarget);
       DEBUG_ONLY(vmtarget = NULL);  // safety
       if (m.is_null())  break;
       if (!have_defc) {
-        klassOop defc = m->method_holder();
+        Klass* defc = m->method_holder();
         java_lang_invoke_MemberName::set_clazz(mname(), Klass::cast(defc)->java_mirror());
       }
       if (!have_name) {
@@ -774,9 +775,9 @@
   case IS_FIELD:
     {
       // This is taken from LinkResolver::resolve_field, sans access checks.
-      assert(vmtarget->is_klass(), "field vmtarget is klassOop");
-      if (!Klass::cast((klassOop) vmtarget)->oop_is_instance())  break;
-      instanceKlassHandle defc(THREAD, (klassOop) vmtarget);
+      assert(vmtarget->is_klass(), "field vmtarget is Klass*");
+      if (!Klass::cast((Klass*) vmtarget)->oop_is_instance())  break;
+      instanceKlassHandle defc(THREAD, (Klass*) vmtarget);
       DEBUG_ONLY(vmtarget = NULL);  // safety
       bool is_static = ((flags & JVM_ACC_STATIC) != 0);
       fieldDescriptor fd; // find_field initializes fd if found
@@ -804,9 +805,9 @@
   THROW_MSG(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format");
 }
 
-int MethodHandles::find_MemberNames(klassOop k,
+int MethodHandles::find_MemberNames(Klass* k,
                                     Symbol* name, Symbol* sig,
-                                    int mflags, klassOop caller,
+                                    int mflags, Klass* caller,
                                     int skip, objArrayOop results) {
   DEBUG_ONLY(No_Safepoint_Verifier nsv);
   // this code contains no safepoints!
@@ -855,7 +856,7 @@
           return -99;  // caller bug!
         oop type = field_signature_type_or_null(st.signature());
         oop name = field_name_or_null(st.name());
-        oop saved = MethodHandles::init_field_MemberName(result, st.klass()->as_klassOop(),
+        oop saved = MethodHandles::init_field_MemberName(result, st.klass()(),
                                                          st.access_flags(), type, name,
                                                          st.offset());
         if (saved != result)
@@ -892,7 +893,7 @@
       // caller will accept either sort; no need to adjust name
     }
     for (MethodStream st(k, local_only, !search_intfc); !st.eos(); st.next()) {
-      methodOop m = st.method();
+      Method* m = st.method();
       Symbol* m_name = m->name();
       if (m_name == clinit_name)
         continue;
@@ -919,7 +920,6 @@
   // return number of elements we at leasted wanted to initialize
   return rfill + overflow;
 }
-
 //
 // Here are the native methods in java.lang.invoke.MethodHandleNatives
 // They are the private interface between this JVM and the HotSpot-specific
@@ -928,6 +928,7 @@
 // Note:  We use a JVM_ENTRY macro to define each of these, for this is the way
 // that intrinsic (non-JNI) native methods are defined in HotSpot.
 //
+
 JVM_ENTRY(jint, MHN_getConstant(JNIEnv *env, jobject igcls, jint which)) {
   switch (which) {
   case MethodHandles::GC_COUNT_GWT:
@@ -1033,10 +1034,10 @@
   // access checks on behalf of the given caller.  But, we can verify this.
   if (VerifyMethodHandles && caller_jh != NULL &&
       java_lang_invoke_MemberName::clazz(mname()) != NULL) {
-    klassOop reference_klass = java_lang_Class::as_klassOop(java_lang_invoke_MemberName::clazz(mname()));
+    Klass* reference_klass = java_lang_Class::as_Klass(java_lang_invoke_MemberName::clazz(mname()));
     if (reference_klass != NULL) {
       // Emulate LinkResolver::check_klass_accessability.
-      klassOop caller = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh));
+      Klass* caller = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(caller_jh));
       if (!Reflection::verify_class_access(caller,
                                            reference_klass,
                                            true)) {
@@ -1107,22 +1108,19 @@
   if (mname_jh == NULL)  return NULL;
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   intptr_t vmindex  = java_lang_invoke_MemberName::vmindex(mname());
-  Handle   vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
+  Metadata* vmtarget = java_lang_invoke_MemberName::vmtarget(mname());
   objArrayHandle result = oopFactory::new_objArray(SystemDictionary::Object_klass(), 2, CHECK_NULL);
   jvalue vmindex_value; vmindex_value.j = (long)vmindex;
   oop x = java_lang_boxing_object::create(T_LONG, &vmindex_value, CHECK_NULL);
   result->obj_at_put(0, x);
   x = NULL;
-  if (vmtarget.is_null() || vmtarget->is_instance()) {
-    x = vmtarget();
+  if (vmtarget == NULL) {
+    x = NULL;
   } else if (vmtarget->is_klass()) {
-    x = Klass::cast((klassOop) vmtarget())->java_mirror();
-  } else {
+    x = Klass::cast((Klass*) vmtarget)->java_mirror();
+  } else if (vmtarget->is_method()) {
     Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL);
-    if (vmtarget->is_method())
-      x = MethodHandles::init_method_MemberName(mname2(), methodOop(vmtarget()), false, NULL);
-    else
-      x = MethodHandles::init_MemberName(mname2(), vmtarget());
+    x = MethodHandles::init_method_MemberName(mname2(), (Method*)vmtarget, false, NULL);
   }
   result->obj_at_put(1, x);
   return JNIHandles::make_local(env, result());
@@ -1137,7 +1135,7 @@
                                jclass clazz_jh, jstring name_jh, jstring sig_jh,
                                int mflags, jclass caller_jh, jint skip, jobjectArray results_jh)) {
   if (clazz_jh == NULL || results_jh == NULL)  return -1;
-  KlassHandle k(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(clazz_jh)));
+  KlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(clazz_jh)));
 
   objArrayHandle results(THREAD, (objArrayOop) JNIHandles::resolve(results_jh));
   if (results.is_null() || !results->is_objArray())  return -1;
@@ -1157,7 +1155,7 @@
   if (caller_jh != NULL) {
     oop caller_oop = JNIHandles::resolve_non_null(caller_jh);
     if (!java_lang_Class::is_instance(caller_oop))  return -1;
-    caller = KlassHandle(THREAD, java_lang_Class::as_klassOop(caller_oop));
+    caller = KlassHandle(THREAD, java_lang_Class::as_Klass(caller_oop));
   }
 
   if (name != NULL && sig != NULL && results.not_null()) {
@@ -1196,6 +1194,20 @@
 }
 JVM_END
 
+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");
+    return NULL;
+}
+JVM_END
+
+JVM_ENTRY(jobject, MH_invokeExact_UOE(JNIEnv *env, jobject igmh, jobjectArray igargs)) {
+    TempNewSymbol UOE_name = SymbolTable::new_symbol("java/lang/UnsupportedOperationException", CHECK_NULL);
+    THROW_MSG_NULL(UOE_name, "MethodHandle.invokeExact cannot be invoked reflectively");
+    return NULL;
+}
+JVM_END
+
 /// JVM_RegisterMethodHandleMethods
 
 #undef CS  // Solaris builds complain
@@ -1233,6 +1245,11 @@
   {CC"getMemberVMInfo",           CC"("MEM")"OBJ,                        FN_PTR(MHN_getMemberVMInfo)}
 };
 
+static JNINativeMethod invoke_methods[] = {
+  {CC"invoke",                    CC"(["OBJ")"OBJ,                       FN_PTR(MH_invoke_UOE)},
+  {CC"invokeExact",               CC"(["OBJ")"OBJ,                       FN_PTR(MH_invokeExact_UOE)}
+};
+
 // This one function is exported, used by NativeLookup.
 
 JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
@@ -1258,6 +1275,9 @@
     ThreadToNativeFromVM ttnfv(thread);
 
     status = env->RegisterNatives(MHN_class, required_methods_JDK8, sizeof(required_methods_JDK8)/sizeof(JNINativeMethod));
+    if (status == JNI_OK && !env->ExceptionOccurred()) {
+      status = env->RegisterNatives(MH_class, invoke_methods, sizeof(invoke_methods)/sizeof(JNINativeMethod));
+    }
     if (status != JNI_OK || env->ExceptionOccurred()) {
       warning("JSR 292 method handle code is mismatched to this JVM.  Disabling support.");
       enable_MH = false;