< prev index next >

src/hotspot/share/classfile/systemDictionary.cpp

Print this page

        

@@ -38,11 +38,10 @@
 #include "classfile/packageEntry.hpp"
 #include "classfile/placeholders.hpp"
 #include "classfile/protectionDomainCache.hpp"
 #include "classfile/resolutionErrors.hpp"
 #include "classfile/stringTable.hpp"
-#include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
 #include "code/codeCache.hpp"
 #include "compiler/compileBroker.hpp"
 #include "gc/shared/gcTraceTime.inline.hpp"

@@ -55,11 +54,10 @@
 #include "memory/filemap.hpp"
 #include "memory/heapShared.hpp"
 #include "memory/metaspaceClosure.hpp"
 #include "memory/oopFactory.hpp"
 #include "memory/resourceArea.hpp"
-#include "memory/universe.hpp"
 #include "oops/access.inline.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/instanceRefKlass.hpp"
 #include "oops/klass.inline.hpp"
 #include "oops/method.inline.hpp"

@@ -68,10 +66,11 @@
 #include "oops/objArrayOop.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
 #include "oops/typeArrayKlass.hpp"
 #include "prims/jvmtiExport.hpp"
+#include "prims/resolvedMethodTable.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/arguments.hpp"
 #include "runtime/biasedLocking.hpp"
 #include "runtime/fieldType.hpp"
 #include "runtime/handles.inline.hpp"

@@ -86,10 +85,13 @@
 #include "services/threadService.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_CDS
 #include "classfile/systemDictionaryShared.hpp"
 #endif
+#if INCLUDE_JVMCI
+#include "jvmci/jvmciRuntime.hpp"
+#endif
 #if INCLUDE_JFR
 #include "jfr/jfr.hpp"
 #endif
 
 PlaceholderTable*      SystemDictionary::_placeholders        = NULL;

@@ -261,11 +263,11 @@
   assert(class_name != NULL && !FieldType::is_array(class_name), "must be");
   if (FieldType::is_obj(class_name)) {
     ResourceMark rm(THREAD);
     // Ignore wrapping L and ;.
     TempNewSymbol name = SymbolTable::new_symbol(class_name->as_C_string() + 1,
-                                                 class_name->utf8_length() - 2);
+                                   class_name->utf8_length() - 2, CHECK_NULL);
     return resolve_instance_class_or_null(name, class_loader, protection_domain, THREAD);
   } else {
     return resolve_instance_class_or_null(class_name, class_loader, protection_domain, THREAD);
   }
 }

@@ -1821,21 +1823,23 @@
     GCTraceTime(Debug, gc, phases) t("ClassLoaderData", gc_timer);
     assert_locked_or_safepoint(ClassLoaderDataGraph_lock);  // caller locks.
     // First, mark for unload all ClassLoaderData referencing a dead class loader.
     unloading_occurred = ClassLoaderDataGraph::do_unloading();
     if (unloading_occurred) {
-      MutexLocker ml2(is_concurrent ? Module_lock : NULL);
+      MutexLockerEx ml2(is_concurrent ? Module_lock : NULL);
       JFR_ONLY(Jfr::on_unloading_classes();)
 
-      MutexLocker ml1(is_concurrent ? SystemDictionary_lock : NULL);
+      MutexLockerEx ml1(is_concurrent ? SystemDictionary_lock : NULL);
       ClassLoaderDataGraph::clean_module_and_package_info();
       constraints()->purge_loader_constraints();
       resolution_errors()->purge_resolution_errors();
     }
   }
 
   GCTraceTime(Debug, gc, phases) t("Trigger cleanups", gc_timer);
+  // Trigger cleaning the ResolvedMethodTable even if no unloading occurred.
+  ResolvedMethodTable::trigger_cleanup();
 
   if (unloading_occurred) {
     SymbolTable::trigger_cleanup();
 
     // Oops referenced by the protection domain cache table may get unreachable independently

@@ -1919,10 +1923,17 @@
   assert(id >= (int)FIRST_WKID && id < (int)WKID_LIMIT, "oob");
   int sid = wk_init_info[id - FIRST_WKID];
   Symbol* symbol = vmSymbols::symbol_at((vmSymbols::SID)sid);
   InstanceKlass** klassp = &_well_known_klasses[id];
 
+
+#if INCLUDE_JVMCI
+  if (id >= FIRST_JVMCI_WKID) {
+    assert(EnableJVMCI, "resolve JVMCI classes only when EnableJVMCI is true");
+  }
+#endif
+
   if ((*klassp) == NULL) {
     Klass* k = resolve_or_fail(symbol, true, CHECK_0);
     (*klassp) = InstanceKlass::cast(k);
   }
   return ((*klassp) != NULL);

@@ -2007,11 +2018,11 @@
   // JSR 292 classes
   WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
   WKID jsr292_group_end   = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
   resolve_wk_klasses_until(jsr292_group_start, scan, CHECK);
   resolve_wk_klasses_through(jsr292_group_end, scan, CHECK);
-  WKID last = WKID_LIMIT;
+  WKID last = NOT_JVMCI(WKID_LIMIT) JVMCI_ONLY(FIRST_JVMCI_WKID);
   resolve_wk_klasses_until(last, scan, CHECK);
 
   _box_klasses[T_BOOLEAN] = WK_KLASS(Boolean_klass);
   _box_klasses[T_CHAR]    = WK_KLASS(Character_klass);
   _box_klasses[T_FLOAT]   = WK_KLASS(Float_klass);

@@ -2354,11 +2365,11 @@
   }
 
   SignatureStream sig_strm(signature, is_method);
   while (!sig_strm.is_done()) {
     if (sig_strm.is_object()) {
-      Symbol* sig = sig_strm.as_symbol();
+      Symbol* sig = sig_strm.as_symbol(CHECK_NULL);
       if (!add_loader_constraint(sig, loader1, loader2, THREAD)) {
         return sig;
       }
     }
     sig_strm.next();

@@ -2624,11 +2635,11 @@
     if (!can_be_cached) {
       // Resolve, throwing a real error if it doesn't work.
       mirror = ss.as_java_mirror(class_loader, protection_domain,
                                  SignatureStream::NCDFError, CHECK_(empty));
     }
-    assert(mirror != NULL, "%s", ss.as_symbol()->as_C_string());
+    assert(mirror != NULL, "%s", ss.as_symbol(THREAD)->as_C_string());
     if (ss.at_return_type())
       rt = Handle(THREAD, mirror);
     else
       pts->obj_at_put(arg++, mirror);
 

@@ -2740,65 +2751,110 @@
                          vmSymbols::linkMethodHandleConstant_signature(),
                          &args, CHECK_(empty));
   return Handle(THREAD, (oop) result.get_jobject());
 }
 
-// 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) {
-  // Resolve the bootstrap specifier, its name, type, and static arguments
-  bootstrap_specifier.resolve_bsm(CHECK);
+// 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 (bootstrap_specifier.caller() == NULL || bootstrap_specifier.type_arg().is_null()) {
-    THROW_MSG(vmSymbols::java_lang_InternalError(), "Invalid bootstrap method invocation with no caller or type argument");
+  if (caller == NULL) {
+    THROW_MSG_(vmSymbols::java_lang_InternalError(), "bad dynamic constant", empty);
   }
 
-  bool is_indy = bootstrap_specifier.is_method_call();
-  objArrayHandle appendix_box;
-  if (is_indy) {
-    // Some method calls may require an appendix argument.  Arrange to receive it.
-    appendix_box = oopFactory::new_objArray_handle(SystemDictionary::Object_klass(), 1, CHECK);
-    assert(appendix_box->obj_at(0) == NULL, "");
-  }
+  Handle constant_name = java_lang_String::create_from_symbol(name, CHECK_(empty));
 
-  // call condy: java.lang.invoke.MethodHandleNatives::linkDynamicConstant(caller, condy_index, bsm, type, info)
-  //       indy: java.lang.invoke.MethodHandleNatives::linkCallSite(caller, indy_index, bsm, name, mtype, info, &appendix)
+  // 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, bootstrap_specifier.caller_mirror()));
-  args.push_int(bootstrap_specifier.bss_index());
-  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_values());
-  if (is_indy) {
-    args.push_oop(appendix_box);
-  }
+  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);
   JavaValue result(T_OBJECT);
   JavaCalls::call_static(&result,
                          SystemDictionary::MethodHandleNatives_klass(),
-                         is_indy ? vmSymbols::linkCallSite_name() : vmSymbols::linkDynamicConstant_name(),
-                         is_indy ? vmSymbols::linkCallSite_signature() : vmSymbols::linkDynamicConstant_signature(),
-                         &args, CHECK);
-
-  Handle value(THREAD, (oop) result.get_jobject());
-  if (is_indy) {
-    Handle appendix;
-    methodHandle method = unpack_method_and_appendix(value,
-                                                     bootstrap_specifier.caller(),
-                                                     appendix_box,
-                                                     &appendix, CHECK);
-    bootstrap_specifier.set_resolved_method(method, appendix);
+                         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,
+                                                              TRAPS) {
+  methodHandle empty;
+  Handle bsm, info;
+  if (java_lang_invoke_MethodHandle::is_instance(bootstrap_specifier())) {
+    bsm = bootstrap_specifier;
   } else {
-    bootstrap_specifier.set_resolved_value(value);
+    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");
 
-  // sanity check
-  assert(bootstrap_specifier.is_resolved() ||
-         (bootstrap_specifier.is_method_call() &&
-          bootstrap_specifier.resolved_method().not_null()), "bootstrap method call failed");
+  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);
+  }
+
+  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());
+  return unpack_method_and_appendix(mname, caller, appendix_box, appendix_result, THREAD);
 }
 
 // Protection domain cache table handling
 
 ProtectionDomainCacheEntry* SystemDictionary::cache_get(Handle protection_domain) {

@@ -2823,12 +2879,10 @@
 
   _pd_cache_table->print_on(st);
   st->cr();
 }
 
-void SystemDictionary::print() { print_on(tty); }
-
 void SystemDictionary::verify() {
   guarantee(constraints() != NULL,
             "Verify of loader constraints failed");
   guarantee(placeholders()->number_of_entries() >= 0,
             "Verify of placeholders failed");

@@ -2851,29 +2905,17 @@
   assert_locked_or_safepoint(SystemDictionary_lock);
   if (verbose) {
     print_on(st);
   } else {
     CDS_ONLY(SystemDictionaryShared::print_table_statistics(st));
-    ClassLoaderDataGraph::print_table_statistics(st);
+    ClassLoaderDataGraph::print_dictionary_statistics(st);
     placeholders()->print_table_statistics(st, "Placeholder Table");
     constraints()->print_table_statistics(st, "LoaderConstraints Table");
-    pd_cache_table()->print_table_statistics(st, "ProtectionDomainCache Table");
+    _pd_cache_table->print_table_statistics(st, "ProtectionDomainCache Table");
   }
 }
 
-TableStatistics SystemDictionary::placeholders_statistics() {
-  return placeholders()->statistics_calculate();
-}
-
-TableStatistics SystemDictionary::loader_constraints_statistics() {
-  return constraints()->statistics_calculate();
-}
-
-TableStatistics SystemDictionary::protection_domain_cache_statistics() {
-  return pd_cache_table()->statistics_calculate();
-}
-
 // Utility for dumping dictionaries.
 SystemDictionaryDCmd::SystemDictionaryDCmd(outputStream* output, bool heap) :
                                  DCmdWithParser(output, heap),
   _verbose("-verbose", "Dump the content of each dictionary entry for all class loaders",
            "BOOLEAN", false, "false") {
< prev index next >