1.1 --- a/src/share/vm/classfile/systemDictionary.cpp Sat May 01 02:42:18 2010 -0700 1.2 +++ b/src/share/vm/classfile/systemDictionary.cpp Sat May 01 21:57:35 2010 -0700 1.3 @@ -2343,12 +2343,9 @@ 1.4 1.5 methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name, 1.6 symbolHandle signature, 1.7 - Handle class_loader, 1.8 - Handle protection_domain, 1.9 + KlassHandle accessing_klass, 1.10 TRAPS) { 1.11 if (!EnableMethodHandles) return NULL; 1.12 - assert(class_loader.is_null() && protection_domain.is_null(), 1.13 - "cannot load specialized versions of MethodHandle.invoke"); 1.14 if (invoke_method_table() == NULL) { 1.15 // create this side table lazily 1.16 _invoke_method_table = new SymbolPropertyTable(_invoke_method_size); 1.17 @@ -2358,30 +2355,36 @@ 1.18 unsigned int hash = invoke_method_table()->compute_hash(signature, name_id); 1.19 int index = invoke_method_table()->hash_to_index(hash); 1.20 SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id); 1.21 + methodHandle non_cached_result; 1.22 if (spe == NULL || spe->property_oop() == NULL) { 1.23 + spe = NULL; 1.24 // Must create lots of stuff here, but outside of the SystemDictionary lock. 1.25 if (THREAD->is_Compiler_thread()) 1.26 return NULL; // do not attempt from within compiler 1.27 - Handle mt = find_method_handle_type(signature(), 1.28 - class_loader, protection_domain, 1.29 - CHECK_NULL); 1.30 + bool found_on_bcp = false; 1.31 + Handle mt = find_method_handle_type(signature(), accessing_klass, found_on_bcp, CHECK_NULL); 1.32 KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); 1.33 methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature, 1.34 mt, CHECK_NULL); 1.35 // Now grab the lock. We might have to throw away the new method, 1.36 // if a racing thread has managed to install one at the same time. 1.37 - { 1.38 + if (found_on_bcp) { 1.39 MutexLocker ml(SystemDictionary_lock, Thread::current()); 1.40 spe = invoke_method_table()->find_entry(index, hash, signature, name_id); 1.41 if (spe == NULL) 1.42 spe = invoke_method_table()->add_entry(index, hash, signature, name_id); 1.43 if (spe->property_oop() == NULL) 1.44 spe->set_property_oop(m()); 1.45 + } else { 1.46 + non_cached_result = m; 1.47 } 1.48 } 1.49 - methodOop m = (methodOop) spe->property_oop(); 1.50 - assert(m->is_method(), ""); 1.51 - return m; 1.52 + if (spe != NULL && spe->property_oop() != NULL) { 1.53 + assert(spe->property_oop()->is_method(), ""); 1.54 + return (methodOop) spe->property_oop(); 1.55 + } else { 1.56 + return non_cached_result(); 1.57 + } 1.58 } 1.59 1.60 // Ask Java code to find or construct a java.dyn.MethodType for the given 1.61 @@ -2389,30 +2392,50 @@ 1.62 // Because of class loader constraints, all method handle usage must be 1.63 // consistent with this loader. 1.64 Handle SystemDictionary::find_method_handle_type(symbolHandle signature, 1.65 - Handle class_loader, 1.66 - Handle protection_domain, 1.67 + KlassHandle accessing_klass, 1.68 + bool& return_bcp_flag, 1.69 TRAPS) { 1.70 + Handle class_loader, protection_domain; 1.71 + bool is_on_bcp = true; // keep this true as long as we can materialize from the boot classloader 1.72 Handle empty; 1.73 int npts = ArgumentCount(signature()).size(); 1.74 objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); 1.75 int arg = 0; 1.76 Handle rt; // the return type from the signature 1.77 for (SignatureStream ss(signature()); !ss.is_done(); ss.next()) { 1.78 - oop mirror; 1.79 - if (!ss.is_object()) { 1.80 - mirror = Universe::java_mirror(ss.type()); 1.81 - } else { 1.82 - symbolOop name_oop = ss.as_symbol(CHECK_(empty)); 1.83 - symbolHandle name(THREAD, name_oop); 1.84 - klassOop klass = resolve_or_fail(name, 1.85 - class_loader, protection_domain, 1.86 - true, CHECK_(empty)); 1.87 - mirror = Klass::cast(klass)->java_mirror(); 1.88 + oop mirror = NULL; 1.89 + if (is_on_bcp) { 1.90 + mirror = ss.as_java_mirror(class_loader, protection_domain, 1.91 + SignatureStream::ReturnNull, CHECK_(empty)); 1.92 + if (mirror == NULL) { 1.93 + // fall back from BCP to accessing_klass 1.94 + if (accessing_klass.not_null()) { 1.95 + class_loader = Handle(THREAD, instanceKlass::cast(accessing_klass())->class_loader()); 1.96 + protection_domain = Handle(THREAD, instanceKlass::cast(accessing_klass())->protection_domain()); 1.97 + } 1.98 + is_on_bcp = false; 1.99 + } 1.100 + } 1.101 + if (!is_on_bcp) { 1.102 + // Resolve, throwing a real error if it doesn't work. 1.103 + mirror = ss.as_java_mirror(class_loader, protection_domain, 1.104 + SignatureStream::NCDFError, CHECK_(empty)); 1.105 } 1.106 if (ss.at_return_type()) 1.107 rt = Handle(THREAD, mirror); 1.108 else 1.109 pts->obj_at_put(arg++, mirror); 1.110 + // Check accessibility. 1.111 + if (ss.is_object() && accessing_klass.not_null()) { 1.112 + klassOop sel_klass = java_lang_Class::as_klassOop(mirror); 1.113 + // Emulate constantPoolOopDesc::verify_constant_pool_resolve. 1.114 + if (Klass::cast(sel_klass)->oop_is_objArray()) 1.115 + sel_klass = objArrayKlass::cast(sel_klass)->bottom_klass(); 1.116 + if (Klass::cast(sel_klass)->oop_is_instance()) { 1.117 + KlassHandle sel_kh(THREAD, sel_klass); 1.118 + LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty)); 1.119 + } 1.120 + } 1.121 } 1.122 assert(arg == npts, ""); 1.123 1.124 @@ -2425,6 +2448,9 @@ 1.125 vmSymbols::findMethodHandleType_name(), 1.126 vmSymbols::findMethodHandleType_signature(), 1.127 &args, CHECK_(empty)); 1.128 + 1.129 + // report back to the caller with the MethodType and the "on_bcp" flag 1.130 + return_bcp_flag = is_on_bcp; 1.131 return Handle(THREAD, (oop) result.get_jobject()); 1.132 } 1.133