hotspot/src/share/vm/oops/methodOop.cpp
changeset 13391 30245956af37
parent 13285 5c78ade8d6a3
child 13392 1ef07ae0723d
--- a/hotspot/src/share/vm/oops/methodOop.cpp	Mon Jul 23 13:04:59 2012 -0700
+++ b/hotspot/src/share/vm/oops/methodOop.cpp	Tue Jul 24 10:51:00 2012 -0700
@@ -40,7 +40,7 @@
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "prims/jvmtiExport.hpp"
-#include "prims/methodHandleWalk.hpp"
+#include "prims/methodHandles.hpp"
 #include "prims/nativeLookup.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/compilationPolicy.hpp"
@@ -552,6 +552,7 @@
 
 void methodOopDesc::set_native_function(address function, bool post_event_flag) {
   assert(function != NULL, "use clear_native_function to unregister natives");
+  assert(!is_method_handle_intrinsic() || function == SharedRuntime::native_method_throw_unsatisfied_link_error_entry(), "");
   address* native_function = native_function_addr();
 
   // We can see racers trying to place the same native function into place. Once
@@ -581,12 +582,14 @@
 
 
 bool methodOopDesc::has_native_function() const {
+  assert(!is_method_handle_intrinsic(), "");
   address func = native_function();
   return (func != NULL && func != SharedRuntime::native_method_throw_unsatisfied_link_error_entry());
 }
 
 
 void methodOopDesc::clear_native_function() {
+  // Note: is_method_handle_intrinsic() is allowed here.
   set_native_function(
     SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
     !native_bind_event_is_interesting);
@@ -606,10 +609,6 @@
 
 
 bool methodOopDesc::is_not_compilable(int comp_level) const {
-  if (is_method_handle_invoke()) {
-    // compilers must recognize this method specially, or not at all
-    return true;
-  }
   if (number_of_breakpoints() > 0) {
     return true;
   }
@@ -709,7 +708,7 @@
   assert(entry != NULL, "interpreter entry must be non-null");
   // Sets both _i2i_entry and _from_interpreted_entry
   set_interpreter_entry(entry);
-  if (is_native() && !is_method_handle_invoke()) {
+  if (is_native() && !is_method_handle_intrinsic()) {
     set_native_function(
       SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
       !native_bind_event_is_interesting);
@@ -797,13 +796,13 @@
   OrderAccess::storestore();
 #ifdef SHARK
   mh->_from_interpreted_entry = code->insts_begin();
-#else
+#else //!SHARK
   mh->_from_compiled_entry = code->verified_entry_point();
   OrderAccess::storestore();
   // Instantly compiled code can execute.
-  mh->_from_interpreted_entry = mh->get_i2c_entry();
-#endif // SHARK
-
+  if (!mh->is_method_handle_intrinsic())
+    mh->_from_interpreted_entry = mh->get_i2c_entry();
+#endif //!SHARK
 }
 
 
@@ -855,106 +854,51 @@
   return false;
 }
 
-bool methodOopDesc::is_method_handle_invoke_name(vmSymbols::SID name_sid) {
-  switch (name_sid) {
-  case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name):
-  case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name):
-    return true;
-  }
-  if (AllowInvokeGeneric
-      && name_sid == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name))
-    return true;
-  return false;
-}
-
 // Constant pool structure for invoke methods:
 enum {
-  _imcp_invoke_name = 1,        // utf8: 'invokeExact' or 'invokeGeneric'
+  _imcp_invoke_name = 1,        // utf8: 'invokeExact', etc.
   _imcp_invoke_signature,       // utf8: (variable Symbol*)
-  _imcp_method_type_value,      // string: (variable java/lang/invoke/MethodType, sic)
   _imcp_limit
 };
 
-oop methodOopDesc::method_handle_type() const {
-  if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; }
-  oop mt = constants()->resolved_string_at(_imcp_method_type_value);
-  assert(mt->klass() == SystemDictionary::MethodType_klass(), "");
-  return mt;
-}
-
-jint* methodOopDesc::method_type_offsets_chain() {
-  static jint pchase[] = { -1, -1, -1, -1 };
-  if (pchase[0] == -1) {
-    jint step0 = in_bytes(const_offset());
-    jint step1 = in_bytes(constMethodOopDesc::constants_offset());
-    jint step2 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize;
-    // do this in reverse to avoid races:
-    OrderAccess::release_store(&pchase[2], step2);
-    OrderAccess::release_store(&pchase[1], step1);
-    OrderAccess::release_store(&pchase[0], step0);
-  }
-  return pchase;
+// Test if this method is an MH adapter frame generated by Java code.
+// Cf. java/lang/invoke/InvokerBytecodeGenerator
+bool methodOopDesc::is_compiled_lambda_form() const {
+  return intrinsic_id() == vmIntrinsics::_compiledLambdaForm;
 }
 
-//------------------------------------------------------------------------------
-// methodOopDesc::is_method_handle_adapter
-//
-// Tests if this method is an internal adapter frame from the
-// MethodHandleCompiler.
-// Must be consistent with MethodHandleCompiler::get_method_oop().
-bool methodOopDesc::is_method_handle_adapter() const {
-  if (is_synthetic() &&
-      !is_native() &&   // has code from MethodHandleCompiler
-      is_method_handle_invoke_name(name()) &&
-      MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder())) {
-    assert(!is_method_handle_invoke(), "disjoint");
-    return true;
-  } else {
-    return false;
-  }
+// Test if this method is an internal MH primitive method.
+bool methodOopDesc::is_method_handle_intrinsic() const {
+  vmIntrinsics::ID iid = intrinsic_id();
+  return (MethodHandles::is_signature_polymorphic(iid) &&
+          MethodHandles::is_signature_polymorphic_intrinsic(iid));
 }
 
-methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
-                                               Symbol* name,
-                                               Symbol* signature,
-                                               Handle method_type, TRAPS) {
+bool methodOopDesc::has_member_arg() const {
+  vmIntrinsics::ID iid = intrinsic_id();
+  return (MethodHandles::is_signature_polymorphic(iid) &&
+          MethodHandles::has_member_arg(iid));
+}
+
+// Make an instance of a signature-polymorphic internal MH primitive.
+methodHandle methodOopDesc::make_method_handle_intrinsic(vmIntrinsics::ID iid,
+                                                         Symbol* signature,
+                                                         TRAPS) {
   ResourceMark rm;
   methodHandle empty;
 
-  assert(holder() == SystemDictionary::MethodHandle_klass(),
-         "must be a JSR 292 magic type");
-
+  KlassHandle holder = SystemDictionary::MethodHandle_klass();
+  Symbol* name = MethodHandles::signature_polymorphic_intrinsic_name(iid);
+  assert(iid == MethodHandles::signature_polymorphic_name_id(name), "");
   if (TraceMethodHandles) {
-    tty->print("Creating invoke method for ");
-    signature->print_value();
-    tty->cr();
+    tty->print_cr("make_method_handle_intrinsic MH.%s%s", name->as_C_string(), signature->as_C_string());
   }
 
   // invariant:   cp->symbol_at_put is preceded by a refcount increment (more usually a lookup)
   name->increment_refcount();
   signature->increment_refcount();
 
-  // record non-BCP method types in the constant pool
-  GrowableArray<KlassHandle>* extra_klasses = NULL;
-  for (int i = -1, len = java_lang_invoke_MethodType::ptype_count(method_type()); i < len; i++) {
-    oop ptype = (i == -1
-                 ? java_lang_invoke_MethodType::rtype(method_type())
-                 : java_lang_invoke_MethodType::ptype(method_type(), i));
-    klassOop klass = check_non_bcp_klass(java_lang_Class::as_klassOop(ptype));
-    if (klass != NULL) {
-      if (extra_klasses == NULL)
-        extra_klasses = new GrowableArray<KlassHandle>(len+1);
-      bool dup = false;
-      for (int j = 0; j < extra_klasses->length(); j++) {
-        if (extra_klasses->at(j) == klass) { dup = true; break; }
-      }
-      if (!dup)
-        extra_klasses->append(KlassHandle(THREAD, klass));
-    }
-  }
-
-  int extra_klass_count = (extra_klasses == NULL ? 0 : extra_klasses->length());
-  int cp_length = _imcp_limit + extra_klass_count;
+  int cp_length = _imcp_limit;
   constantPoolHandle cp;
   {
     constantPoolOop cp_oop = oopFactory::new_constantPool(cp_length, IsSafeConc, CHECK_(empty));
@@ -962,19 +906,17 @@
   }
   cp->symbol_at_put(_imcp_invoke_name,       name);
   cp->symbol_at_put(_imcp_invoke_signature,  signature);
-  cp->string_at_put(_imcp_method_type_value, Universe::the_null_string());
-  for (int j = 0; j < extra_klass_count; j++) {
-    KlassHandle klass = extra_klasses->at(j);
-    cp->klass_at_put(_imcp_limit + j, klass());
-  }
   cp->set_preresolution();
   cp->set_pool_holder(holder());
 
-  // set up the fancy stuff:
-  cp->pseudo_string_at_put(_imcp_method_type_value, method_type());
+  // decide on access bits:  public or not?
+  int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL);
+  bool must_be_static = MethodHandles::is_signature_polymorphic_static(iid);
+  if (must_be_static)  flags_bits |= JVM_ACC_STATIC;
+  assert((flags_bits & JVM_ACC_PUBLIC) == 0, "do not expose these methods");
+
   methodHandle m;
   {
-    int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL);
     methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits),
                                              0, 0, 0, 0, IsSafeConc, CHECK_(empty));
     m = methodHandle(THREAD, m_oop);
@@ -982,33 +924,26 @@
   m->set_constants(cp());
   m->set_name_index(_imcp_invoke_name);
   m->set_signature_index(_imcp_invoke_signature);
-  assert(is_method_handle_invoke_name(m->name()), "");
+  assert(MethodHandles::is_signature_polymorphic_name(m->name()), "");
   assert(m->signature() == signature, "");
-  assert(m->is_method_handle_invoke(), "");
 #ifdef CC_INTERP
   ResultTypeFinder rtf(signature);
   m->set_result_index(rtf.type());
 #endif
   m->compute_size_of_parameters(THREAD);
   m->init_intrinsic_id();
-  assert(m->intrinsic_id() == vmIntrinsics::_invokeExact ||
-         m->intrinsic_id() == vmIntrinsics::_invokeGeneric, "must be an invoker");
+  assert(m->is_method_handle_intrinsic(), "");
+#ifdef ASSERT
+  if (!MethodHandles::is_signature_polymorphic(m->intrinsic_id()))  m->print();
+  assert(MethodHandles::is_signature_polymorphic(m->intrinsic_id()), "must be an invoker");
+  assert(m->intrinsic_id() == iid, "correctly predicted iid");
+#endif //ASSERT
 
   // Finally, set up its entry points.
-  assert(m->method_handle_type() == method_type(), "");
   assert(m->can_be_statically_bound(), "");
   m->set_vtable_index(methodOopDesc::nonvirtual_vtable_index);
   m->link_method(m, CHECK_(empty));
 
-#ifdef ASSERT
-  // Make sure the pointer chase works.
-  address p = (address) m();
-  for (jint* pchase = method_type_offsets_chain(); (*pchase) != -1; pchase++) {
-    p = *(address*)(p + (*pchase));
-  }
-  assert((oop)p == method_type(), "pointer chase is correct");
-#endif
-
   if (TraceMethodHandles && (Verbose || WizardMode))
     m->print_on(tty);
 
@@ -1025,7 +960,7 @@
 }
 
 
-methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
+methodHandle methodOopDesc::clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
                                                 u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) {
   // Code below does not work for native methods - they should never get rewritten anyway
   assert(!m->is_native(), "cannot rewrite native methods");
@@ -1142,7 +1077,9 @@
 
   // ditto for method and signature:
   vmSymbols::SID  name_id = vmSymbols::find_sid(name());
-  if (name_id == vmSymbols::NO_SID)  return;
+  if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle)
+      && name_id == vmSymbols::NO_SID)
+    return;
   vmSymbols::SID   sig_id = vmSymbols::find_sid(signature());
   if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle)
       && sig_id == vmSymbols::NO_SID)  return;
@@ -1171,21 +1108,10 @@
 
   // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*.
   case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle):
-    if (is_static() || !is_native())  break;
-    switch (name_id) {
-    case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name):
-      if (!AllowInvokeGeneric)  break;
-    case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name):
-      id = vmIntrinsics::_invokeGeneric;
-      break;
-    case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name):
-      id = vmIntrinsics::_invokeExact;
-      break;
-    }
-    break;
-  case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_InvokeDynamic):
-    if (!is_static() || !is_native())  break;
-    id = vmIntrinsics::_invokeDynamic;
+    if (!is_native())  break;
+    id = MethodHandles::signature_polymorphic_name_id(method_holder(), name());
+    if (is_static() != MethodHandles::is_signature_polymorphic_static(id))
+      id = vmIntrinsics::_none;
     break;
   }
 
@@ -1198,6 +1124,12 @@
 
 // These two methods are static since a GC may move the methodOopDesc
 bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) {
+  if (THREAD->is_Compiler_thread()) {
+    // There is nothing useful this routine can do from within the Compile thread.
+    // Hopefully, the signature contains only well-known classes.
+    // We could scan for this and return true/false, but the caller won't care.
+    return false;
+  }
   bool sig_is_loaded = true;
   Handle class_loader(THREAD, instanceKlass::cast(m->method_holder())->class_loader());
   Handle protection_domain(THREAD, Klass::cast(m->method_holder())->protection_domain());
@@ -1251,6 +1183,8 @@
 #endif
   name()->print_symbol_on(st);
   if (WizardMode) signature()->print_symbol_on(st);
+  else if (MethodHandles::is_signature_polymorphic(intrinsic_id()))
+    MethodHandles::print_as_basic_type_signature_on(st, signature(), true);
 }
 
 // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array