hotspot/src/share/vm/classfile/systemDictionary.cpp
changeset 2534 08dac9ce0cd7
parent 2332 5c7b6f4ce0a1
child 2570 ecc7862946d4
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Apr 08 00:12:59 2009 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Wed Apr 08 10:56:49 2009 -0700
@@ -31,6 +31,7 @@
 Dictionary*       SystemDictionary::_shared_dictionary = NULL;
 LoaderConstraintTable* SystemDictionary::_loader_constraints = NULL;
 ResolutionErrorTable* SystemDictionary::_resolution_errors = NULL;
+SymbolPropertyTable* SystemDictionary::_invoke_method_table = NULL;
 
 
 int         SystemDictionary::_number_of_modifications = 0;
@@ -966,6 +967,8 @@
   instanceKlassHandle k = ClassFileParser(st).parseClassFile(class_name,
                                                              class_loader,
                                                              protection_domain,
+                                                             host_klass,
+                                                             cp_patches,
                                                              parsed_name,
                                                              THREAD);
 
@@ -1691,6 +1694,10 @@
   // represent classes we're actively loading.
   placeholders_do(blk);
 
+  // Visit extra methods
+  if (invoke_method_table() != NULL)
+    invoke_method_table()->oops_do(blk);
+
   // Loader constraints. We must keep the symbolOop used in the name alive.
   constraints()->always_strong_classes_do(blk);
 
@@ -1726,6 +1733,10 @@
   // Adjust dictionary
   dictionary()->oops_do(f);
 
+  // Visit extra methods
+  if (invoke_method_table() != NULL)
+    invoke_method_table()->oops_do(f);
+
   // Partially loaded classes
   placeholders()->oops_do(f);
 
@@ -1798,6 +1809,8 @@
 
 void SystemDictionary::methods_do(void f(methodOop)) {
   dictionary()->methods_do(f);
+  if (invoke_method_table() != NULL)
+    invoke_method_table()->methods_do(f);
 }
 
 // ----------------------------------------------------------------------------
@@ -1830,6 +1843,7 @@
   _number_of_modifications = 0;
   _loader_constraints = new LoaderConstraintTable(_loader_constraint_size);
   _resolution_errors = new ResolutionErrorTable(_resolution_error_size);
+  // _invoke_method_table is allocated lazily in find_method_handle_invoke()
 
   // Allocate private object used as system class loader lock
   _system_loader_lock_obj = oopFactory::new_system_objArray(0, CHECK);
@@ -1891,6 +1905,9 @@
       wk_klass_name_limits[0] = s;
     }
   }
+
+  // move the starting value forward to the limit:
+  start_id = limit_id;
 }
 
 
@@ -1924,6 +1941,17 @@
   instanceKlass::cast(WK_KLASS(final_reference_klass))->set_reference_type(REF_FINAL);
   instanceKlass::cast(WK_KLASS(phantom_reference_klass))->set_reference_type(REF_PHANTOM);
 
+  WKID meth_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
+  WKID meth_group_end   = WK_KLASS_ENUM_NAME(WrongMethodTypeException_klass);
+  initialize_wk_klasses_until(meth_group_start, scan, CHECK);
+  if (EnableMethodHandles) {
+    initialize_wk_klasses_through(meth_group_start, scan, CHECK);
+  }
+  if (_well_known_klasses[meth_group_start] == NULL) {
+    // Skip the rest of the method handle classes, if MethodHandle is not loaded.
+    scan = WKID(meth_group_end+1);
+  }
+
   initialize_wk_klasses_until(WKID_LIMIT, scan, CHECK);
 
   _box_klasses[T_BOOLEAN] = WK_KLASS(boolean_klass);
@@ -2254,6 +2282,91 @@
 }
 
 
+methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
+                                                      Handle class_loader,
+                                                      Handle protection_domain,
+                                                      TRAPS) {
+  if (!EnableMethodHandles)  return NULL;
+  assert(class_loader.is_null() && protection_domain.is_null(),
+         "cannot load specialized versions of MethodHandle.invoke");
+  if (invoke_method_table() == NULL) {
+    // create this side table lazily
+    _invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
+  }
+  unsigned int hash  = invoke_method_table()->compute_hash(signature);
+  int          index = invoke_method_table()->hash_to_index(hash);
+  SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature);
+  if (spe == NULL || spe->property_oop() == NULL) {
+    // Must create lots of stuff here, but outside of the SystemDictionary lock.
+    Handle mt = compute_method_handle_type(signature(),
+                                           class_loader, protection_domain,
+                                           CHECK_NULL);
+    KlassHandle  mh_klass = SystemDictionaryHandles::MethodHandle_klass();
+    methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature,
+                                                       mt, CHECK_NULL);
+    // Now grab the lock.  We might have to throw away the new method,
+    // if a racing thread has managed to install one at the same time.
+    {
+      MutexLocker ml(SystemDictionary_lock, Thread::current());
+      spe = invoke_method_table()->find_entry(index, hash, signature);
+      if (spe == NULL)
+        spe = invoke_method_table()->add_entry(index, hash, signature);
+      if (spe->property_oop() == NULL)
+        spe->set_property_oop(m());
+    }
+  }
+  methodOop m = (methodOop) spe->property_oop();
+  assert(m->is_method(), "");
+  return m;
+}
+
+// Ask Java code to find or construct a java.dyn.MethodType for the given
+// signature, as interpreted relative to the given class loader.
+// Because of class loader constraints, all method handle usage must be
+// consistent with this loader.
+Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
+                                                    Handle class_loader,
+                                                    Handle protection_domain,
+                                                    TRAPS) {
+  Handle empty;
+  int npts = ArgumentCount(signature()).size();
+  objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::class_klass(), npts, CHECK_(empty));
+  int arg = 0;
+  Handle rt;                            // the return type from the signature
+  for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) {
+    oop mirror;
+    if (!ss.is_object()) {
+      mirror = Universe::java_mirror(ss.type());
+    } else {
+      symbolOop    name_oop = ss.as_symbol(CHECK_(empty));
+      symbolHandle name(THREAD, name_oop);
+      klassOop klass = resolve_or_fail(name,
+                                       class_loader, protection_domain,
+                                       true, CHECK_(empty));
+      mirror = Klass::cast(klass)->java_mirror();
+    }
+    if (ss.at_return_type())
+      rt = Handle(THREAD, mirror);
+    else
+      pts->obj_at_put(arg++, mirror);
+  }
+  assert(arg == npts, "");
+
+  // call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true)
+  bool varargs = false, trusted = true;
+  JavaCallArguments args(Handle(THREAD, rt()));
+  args.push_oop(pts());
+  args.push_int(false);
+  args.push_int(trusted);
+  JavaValue result(T_OBJECT);
+  JavaCalls::call_static(&result,
+                         SystemDictionary::MethodType_klass(),
+                         vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(),
+                         &args, CHECK_(empty));
+  return Handle(THREAD, (oop) result.get_jobject());
+}
+
+
 // Since the identity hash code for symbols changes when the symbols are
 // moved from the regular perm gen (hash in the mark word) to the shared
 // spaces (hash is the address), the classes loaded into the dictionary