< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page
rev 52749 : Bootstrap method consolidation
* clean up and simplify JDK support code for BSM invocation
* simplify JVM bootstrap handshake: use BootstrapCallInfo only
* remove unused JVM paths and data fields
* move bootstrap argument processing from MethodHandleNatives to ConstantPool
* remove ConstantGroup; merge argument access into BootstrapCallInfo
* adjust BSM argument access: remove copyArguments, add argumentRef API
* add metadata-free BSM modes, including symbolic arguments from CP

@@ -2510,11 +2510,10 @@
 methodHandle SystemDictionary::find_method_handle_invoker(Klass* klass,
                                                           Symbol* name,
                                                           Symbol* signature,
                                                           Klass* accessing_klass,
                                                           Handle *appendix_result,
-                                                          Handle *method_type_result,
                                                           TRAPS) {
   methodHandle empty;
   assert(THREAD->can_call_java() ,"");
   Handle method_type =
     SystemDictionary::find_method_handle_type(signature, accessing_klass, CHECK_(empty));

@@ -2543,11 +2542,10 @@
                          SystemDictionary::MethodHandleNatives_klass(),
                          vmSymbols::linkMethod_name(),
                          vmSymbols::linkMethod_signature(),
                          &args, CHECK_(empty));
   Handle mname(THREAD, (oop) result.get_jobject());
-  (*method_type_result) = method_type;
   return unpack_method_and_appendix(mname, accessing_klass, appendix_box, appendix_result, THREAD);
 }
 
 // Decide if we can globally cache a lookup of this class, to be returned to any client that asks.
 // We must ensure that all class loaders everywhere will reach this class, for any client.

@@ -2584,10 +2582,11 @@
 Handle SystemDictionary::find_java_mirror_for_type(Symbol* signature,
                                                    Klass* accessing_klass,
                                                    Handle class_loader,
                                                    Handle protection_domain,
                                                    SignatureStream::FailureMode failure_mode,
+                                                   bool check_access,
                                                    TRAPS) {
   Handle empty;
 
   assert(accessing_klass == NULL || (class_loader.is_null() && protection_domain.is_null()),
          "one or the other, or perhaps neither");

@@ -2624,11 +2623,11 @@
       return Handle();  // report failure this way
     }
     Handle mirror(THREAD, constant_type_klass->java_mirror());
 
     // Check accessibility, emulating ConstantPool::verify_constant_pool_resolve.
-    if (accessing_klass != NULL) {
+    if (check_access && accessing_klass != NULL) {
       Klass* sel_klass = constant_type_klass;
       bool fold_type_to_class = true;
       LinkResolver::check_klass_accessability(accessing_klass, sel_klass,
                                               fold_type_to_class, CHECK_(empty));
     }

@@ -2732,31 +2731,10 @@
 
   // report back to the caller with the MethodType
   return method_type;
 }
 
-Handle SystemDictionary::find_field_handle_type(Symbol* signature,
-                                                Klass* accessing_klass,
-                                                TRAPS) {
-  Handle empty;
-  ResourceMark rm(THREAD);
-  SignatureStream ss(signature, /*is_method=*/ false);
-  if (!ss.is_done()) {
-    Handle class_loader, protection_domain;
-    if (accessing_klass != NULL) {
-      class_loader      = Handle(THREAD, accessing_klass->class_loader());
-      protection_domain = Handle(THREAD, accessing_klass->protection_domain());
-    }
-    oop mirror = ss.as_java_mirror(class_loader, protection_domain, SignatureStream::NCDFError, CHECK_(empty));
-    ss.next();
-    if (ss.is_done()) {
-      return Handle(THREAD, mirror);
-    }
-  }
-  return empty;
-}
-
 // Ask Java code to find or construct a method handle constant.
 Handle SystemDictionary::link_method_handle_constant(Klass* caller,
                                                      int ref_kind, //e.g., JVM_REF_invokeVirtual
                                                      Klass* callee,
                                                      Symbol* name,

@@ -2804,112 +2782,94 @@
                          vmSymbols::linkMethodHandleConstant_signature(),
                          &args, CHECK_(empty));
   return Handle(THREAD, (oop) result.get_jobject());
 }
 
-// Ask Java to compute a constant by invoking a BSM given a Dynamic_info CP entry
-Handle SystemDictionary::link_dynamic_constant(Klass* caller,
-                                               int condy_index,
-                                               Handle bootstrap_specifier,
-                                               Symbol* name,
-                                               Symbol* type,
-                                               TRAPS) {
-  Handle empty;
-  Handle bsm, info;
-  if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
-    bsm = bootstrap_specifier;
-  } else {
-    assert(bootstrap_specifier->is_objArray(), "");
-    objArrayOop args = (objArrayOop) bootstrap_specifier();
-    assert(args->length() == 2, "");
-    bsm  = Handle(THREAD, args->obj_at(0));
-    info = Handle(THREAD, args->obj_at(1));
-  }
-  guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()),
-            "caller must supply a valid BSM");
-
-  // This should not happen.  JDK code should take care of that.
-  if (caller == NULL) {
-    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad dynamic constant", empty);
+// Ask Java to run a bootstrap method, in order to create a dynamic call site
+// while linking an invokedynamic op, or compute a constant for Dynamic_info CP entry
+// with linkage results being stored back into the bootstrap specifier.
+void SystemDictionary::invoke_bootstrap_method(BootstrapInfo& bootstrap_specifier, TRAPS) {
+  ResourceMark rm;
+  bootstrap_specifier.resolve_bsm(CHECK);
+  bootstrap_specifier.resolve_metadata(CHECK);
+  BootstrapInfo::BSMMode bsm_mode = bootstrap_specifier.bsm_mode();
+  ConstantPool::BootstrapArgumentReferenceMode arg_mode = ConstantPool::R_IFPRESENT;
+  if (bsm_mode == BootstrapInfo::_metadata ||
+      (bsm_mode == BootstrapInfo::_expression &&
+       bootstrap_specifier.name() == vmSymbols::invoke_name()))
+    // We know the BSM is going to immediately use all the arguments.
+    arg_mode = ConstantPool::R_FORCE;
+  // Otherwise, it can't hurt to pre-pack the object array with present arguments.
+  bootstrap_specifier.resolve_args(arg_mode, CHECK);
+  if (arg_mode != ConstantPool::R_FORCE) {
+    // If we are going tentative, also grab the symbolic reference data.
+    bootstrap_specifier.resolve_args(ConstantPool::R_SYMREF, CHECK);
+  }
+
+  Handle caller(THREAD, bootstrap_specifier.caller_mirror());
+  typeArrayOop index_info_oop = oopFactory::new_intArray(2, CHECK);
+  typeArrayHandle index_info(THREAD, index_info_oop);
+  index_info->int_at_put(0, bootstrap_specifier.argc());
+  index_info->int_at_put(1, bootstrap_specifier.bss_index());
+
+  bool has_appendix = bootstrap_specifier.is_method_call();
+  objArrayHandle appendix_box;
+  if (has_appendix) {
+    // Some method calls may require an appendix argument.  Arrange to receive it.
+    objArrayOop appendix_box_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(), 1, CHECK);
+    appendix_box = objArrayHandle(THREAD, appendix_box_oop);
+    assert(appendix_box->obj_at(0) == NULL, "");
   }
-
-  Handle constant_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
-
-  // Resolve the constant type in the context of the caller class
-  Handle type_mirror = find_java_mirror_for_type(type, caller, SignatureStream::NCDFError,
-                                                 CHECK_(empty));
-
-  // call java.lang.invoke.MethodHandleNatives::linkConstantDyanmic(caller, condy_index, bsm, type, info)
-  JavaCallArguments args;
-  args.push_oop(Handle(THREAD, caller->java_mirror()));
-  args.push_int(condy_index);
-  args.push_oop(bsm);
-  args.push_oop(constant_name);
-  args.push_oop(type_mirror);
-  args.push_oop(info);
+  Handle request;
+  if (bootstrap_specifier.indy_index() != 0) {
+    // request is call-site specific
+    request = Handle(THREAD, SystemDictionary::CallSite_klass()->java_mirror());
+  }
+
+  Handle cpool = reflect_ConstantPool::create_from_pool(bootstrap_specifier.pool()(), CHECK);
+  Handle arg_indexes(THREAD, bootstrap_specifier.arg_indexes()());
+  Handle arg_values(THREAD,  bootstrap_specifier.arg_values()());
+
+  // call java.lang.invoke.MethodHandleNatives::bootstrapMethodHelper(cpool, bss_index, indy_index, argc, bsm, name, type, argIndexes, argValues, request, &appendix)
+  JavaCallArguments args(11);
+  args.push_oop(cpool);
+  args.push_int(bootstrap_specifier.bss_index());
+  args.push_int(bootstrap_specifier.indy_index());
+  args.push_int(bootstrap_specifier.argc());
+  args.push_oop(bootstrap_specifier.bsm());
+  args.push_oop(bootstrap_specifier.name_arg());
+  args.push_oop(bootstrap_specifier.type_arg());
+  args.push_oop(bootstrap_specifier.arg_indexes());
+  args.push_oop(bootstrap_specifier.arg_values());
+  args.push_oop(request);
+  args.push_oop(appendix_box);
   JavaValue result(T_OBJECT);
   JavaCalls::call_static(&result,
                          SystemDictionary::MethodHandleNatives_klass(),
-                         vmSymbols::linkDynamicConstant_name(),
-                         vmSymbols::linkDynamicConstant_signature(),
-                         &args, CHECK_(empty));
-
-  return Handle(THREAD, (oop) result.get_jobject());
-}
-
-// Ask Java code to find or construct a java.lang.invoke.CallSite for the given
-// name and signature, as interpreted relative to the given class loader.
-methodHandle SystemDictionary::find_dynamic_call_site_invoker(Klass* caller,
-                                                              int indy_index,
-                                                              Handle bootstrap_specifier,
-                                                              Symbol* name,
-                                                              Symbol* type,
-                                                              Handle *appendix_result,
-                                                              Handle *method_type_result,
-                                                              TRAPS) {
-  methodHandle empty;
-  Handle bsm, info;
-  if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
-    bsm = bootstrap_specifier;
+                         vmSymbols::bootstrapMethodHelper_name(),
+                         vmSymbols::bootstrapMethodHelper_signature(),
+                         &args, CHECK);
+  if (has_appendix) {
+    Handle appendix;
+    Handle mname(THREAD, (oop) result.get_jobject());
+    methodHandle method = unpack_method_and_appendix(mname,
+                                                     bootstrap_specifier.caller(),
+                                                     appendix_box,
+                                                     &appendix, CHECK);
+    bootstrap_specifier.set_resolved_method(method, appendix);
   } else {
-    objArrayOop args = (objArrayOop) bootstrap_specifier();
-    assert(args->length() == 2, "");
-    bsm  = Handle(THREAD, args->obj_at(0));
-    info = Handle(THREAD, args->obj_at(1));
+    Handle value(THREAD, (oop) result.get_jobject());
+    bootstrap_specifier.set_resolved_value(value);
   }
-  guarantee(java_lang_invoke_MethodHandle::is_instance(bsm()),
-            "caller must supply a valid BSM");
-
-  Handle method_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
-  Handle method_type = find_method_handle_type(type, caller, CHECK_(empty));
 
-  // This should not happen.  JDK code should take care of that.
-  if (caller == NULL || method_type.is_null()) {
-    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad invokedynamic", empty);
+  // sanity check
+  if (!bootstrap_specifier.is_resolved() ||
+      (bootstrap_specifier.is_method_call() &&
+       bootstrap_specifier.resolved_method().is_null())) {
+    // Could be a guarantee but throw IE instead, in case it is JDK bug.
+    THROW_MSG(vmSymbols::java_lang_InternalError(), "bootstrap method call failed");
   }
-
-  objArrayHandle appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK_(empty));
-  assert(appendix_box->obj_at(0) == NULL, "");
-
-  // call java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix)
-  JavaCallArguments args;
-  args.push_oop(Handle(THREAD, caller->java_mirror()));
-  args.push_int(indy_index);
-  args.push_oop(bsm);
-  args.push_oop(method_name);
-  args.push_oop(method_type);
-  args.push_oop(info);
-  args.push_oop(appendix_box);
-  JavaValue result(T_OBJECT);
-  JavaCalls::call_static(&result,
-                         SystemDictionary::MethodHandleNatives_klass(),
-                         vmSymbols::linkCallSite_name(),
-                         vmSymbols::linkCallSite_signature(),
-                         &args, CHECK_(empty));
-  Handle mname(THREAD, (oop) result.get_jobject());
-  (*method_type_result) = method_type;
-  return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
 }
 
 // Protection domain cache table handling
 
 ProtectionDomainCacheEntry* SystemDictionary::cache_get(Handle protection_domain) {
< prev index next >