Thu, 23 Jun 2011 17:14:06 -0700
7056328: JSR 292 invocation sometimes fails in adapters for types not on boot class path
Reviewed-by: never
1.1 --- a/src/cpu/sparc/vm/templateTable_sparc.cpp Wed Jun 22 14:45:37 2011 -0700 1.2 +++ b/src/cpu/sparc/vm/templateTable_sparc.cpp Thu Jun 23 17:14:06 2011 -0700 1.3 @@ -266,7 +266,7 @@ 1.4 1.5 void TemplateTable::ldc(bool wide) { 1.6 transition(vtos, vtos); 1.7 - Label call_ldc, notInt, notString, notClass, exit; 1.8 + Label call_ldc, notInt, isString, notString, notClass, exit; 1.9 1.10 if (wide) { 1.11 __ get_2_byte_integer_at_bcp(1, G3_scratch, O1, InterpreterMacroAssembler::Unsigned); 1.12 @@ -317,8 +317,11 @@ 1.13 1.14 __ bind(notInt); 1.15 // __ cmp(O2, JVM_CONSTANT_String); 1.16 + __ brx(Assembler::equal, true, Assembler::pt, isString); 1.17 + __ delayed()->cmp(O2, JVM_CONSTANT_Object); 1.18 __ brx(Assembler::notEqual, true, Assembler::pt, notString); 1.19 __ delayed()->ldf(FloatRegisterImpl::S, O0, O1, Ftos_f); 1.20 + __ bind(isString); 1.21 __ ld_ptr(O0, O1, Otos_i); 1.22 __ verify_oop(Otos_i); 1.23 __ push(atos);
2.1 --- a/src/cpu/x86/vm/templateTable_x86_32.cpp Wed Jun 22 14:45:37 2011 -0700 2.2 +++ b/src/cpu/x86/vm/templateTable_x86_32.cpp Thu Jun 23 17:14:06 2011 -0700 2.3 @@ -373,15 +373,17 @@ 2.4 __ jcc(Assembler::equal, L); 2.5 __ cmpl(rdx, JVM_CONSTANT_String); 2.6 __ jcc(Assembler::equal, L); 2.7 + __ cmpl(rdx, JVM_CONSTANT_Object); 2.8 + __ jcc(Assembler::equal, L); 2.9 __ stop("unexpected tag type in ldc"); 2.10 __ bind(L); 2.11 } 2.12 #endif 2.13 Label isOop; 2.14 // atos and itos 2.15 - // String is only oop type we will see here 2.16 - __ cmpl(rdx, JVM_CONSTANT_String); 2.17 - __ jccb(Assembler::equal, isOop); 2.18 + // Integer is only non-oop type we will see here 2.19 + __ cmpl(rdx, JVM_CONSTANT_Integer); 2.20 + __ jccb(Assembler::notEqual, isOop); 2.21 __ movl(rax, Address(rcx, rbx, Address::times_ptr, base_offset)); 2.22 __ push(itos); 2.23 __ jmp(Done);
3.1 --- a/src/cpu/x86/vm/templateTable_x86_64.cpp Wed Jun 22 14:45:37 2011 -0700 3.2 +++ b/src/cpu/x86/vm/templateTable_x86_64.cpp Thu Jun 23 17:14:06 2011 -0700 3.3 @@ -385,6 +385,8 @@ 3.4 __ jcc(Assembler::equal, L); 3.5 __ cmpl(rdx, JVM_CONSTANT_String); 3.6 __ jcc(Assembler::equal, L); 3.7 + __ cmpl(rdx, JVM_CONSTANT_Object); 3.8 + __ jcc(Assembler::equal, L); 3.9 __ stop("unexpected tag type in ldc"); 3.10 __ bind(L); 3.11 }
4.1 --- a/src/share/vm/ci/ciEnv.cpp Wed Jun 22 14:45:37 2011 -0700 4.2 +++ b/src/share/vm/ci/ciEnv.cpp Thu Jun 23 17:14:06 2011 -0700 4.3 @@ -50,6 +50,7 @@ 4.4 #include "oops/oop.inline.hpp" 4.5 #include "oops/oop.inline2.hpp" 4.6 #include "prims/jvmtiExport.hpp" 4.7 +#include "prims/methodHandleWalk.hpp" 4.8 #include "runtime/init.hpp" 4.9 #include "runtime/reflection.hpp" 4.10 #include "runtime/sharedRuntime.hpp" 4.11 @@ -371,6 +372,7 @@ 4.12 // ------------------------------------------------------------------ 4.13 // ciEnv::get_klass_by_name_impl 4.14 ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass, 4.15 + constantPoolHandle cpool, 4.16 ciSymbol* name, 4.17 bool require_local) { 4.18 ASSERT_IN_VM; 4.19 @@ -386,7 +388,7 @@ 4.20 sym->utf8_length()-2, 4.21 KILL_COMPILE_ON_FATAL_(_unloaded_ciinstance_klass)); 4.22 ciSymbol* strippedname = get_symbol(strippedsym); 4.23 - return get_klass_by_name_impl(accessing_klass, strippedname, require_local); 4.24 + return get_klass_by_name_impl(accessing_klass, cpool, strippedname, require_local); 4.25 } 4.26 4.27 // Check for prior unloaded klass. The SystemDictionary's answers 4.28 @@ -443,6 +445,7 @@ 4.29 // Get element ciKlass recursively. 4.30 ciKlass* elem_klass = 4.31 get_klass_by_name_impl(accessing_klass, 4.32 + cpool, 4.33 get_symbol(elem_sym), 4.34 require_local); 4.35 if (elem_klass != NULL && elem_klass->is_loaded()) { 4.36 @@ -451,6 +454,19 @@ 4.37 } 4.38 } 4.39 4.40 + if (found_klass() == NULL && !cpool.is_null() && cpool->has_preresolution()) { 4.41 + // Look inside the constant pool for pre-resolved class entries. 4.42 + for (int i = cpool->length() - 1; i >= 1; i--) { 4.43 + if (cpool->tag_at(i).is_klass()) { 4.44 + klassOop kls = cpool->resolved_klass_at(i); 4.45 + if (Klass::cast(kls)->name() == sym) { 4.46 + found_klass = KlassHandle(THREAD, kls); 4.47 + break; 4.48 + } 4.49 + } 4.50 + } 4.51 + } 4.52 + 4.53 if (found_klass() != NULL) { 4.54 // Found it. Build a CI handle. 4.55 return get_object(found_klass())->as_klass(); 4.56 @@ -468,6 +484,7 @@ 4.57 ciSymbol* klass_name, 4.58 bool require_local) { 4.59 GUARDED_VM_ENTRY(return get_klass_by_name_impl(accessing_klass, 4.60 + constantPoolHandle(), 4.61 klass_name, 4.62 require_local);) 4.63 } 4.64 @@ -508,13 +525,14 @@ 4.65 if (klass.is_null()) { 4.66 // Not found in constant pool. Use the name to do the lookup. 4.67 ciKlass* k = get_klass_by_name_impl(accessor, 4.68 + cpool, 4.69 get_symbol(klass_name), 4.70 false); 4.71 // Calculate accessibility the hard way. 4.72 if (!k->is_loaded()) { 4.73 is_accessible = false; 4.74 } else if (k->loader() != accessor->loader() && 4.75 - get_klass_by_name_impl(accessor, k->name(), true) == NULL) { 4.76 + get_klass_by_name_impl(accessor, cpool, k->name(), true) == NULL) { 4.77 // Loaded only remotely. Not linked yet. 4.78 is_accessible = false; 4.79 } else { 4.80 @@ -565,7 +583,7 @@ 4.81 index = cpc_entry->constant_pool_index(); 4.82 oop obj = cpc_entry->f1(); 4.83 if (obj != NULL) { 4.84 - assert(obj->is_instance(), "must be an instance"); 4.85 + assert(obj->is_instance() || obj->is_array(), "must be a Java reference"); 4.86 ciObject* ciobj = get_object(obj); 4.87 return ciConstant(T_OBJECT, ciobj); 4.88 } 4.89 @@ -607,7 +625,7 @@ 4.90 return ciConstant(T_OBJECT, klass->java_mirror()); 4.91 } else if (tag.is_object()) { 4.92 oop obj = cpool->object_at(index); 4.93 - assert(obj->is_instance(), "must be an instance"); 4.94 + assert(obj->is_instance() || obj->is_array(), "must be a Java reference"); 4.95 ciObject* ciobj = get_object(obj); 4.96 return ciConstant(T_OBJECT, ciobj); 4.97 } else if (tag.is_method_type()) { 4.98 @@ -729,9 +747,35 @@ 4.99 Symbol* name_sym = cpool->name_ref_at(index); 4.100 Symbol* sig_sym = cpool->signature_ref_at(index); 4.101 4.102 + if (cpool->has_preresolution() 4.103 + || (holder == ciEnv::MethodHandle_klass() && 4.104 + methodOopDesc::is_method_handle_invoke_name(name_sym))) { 4.105 + // Short-circuit lookups for JSR 292-related call sites. 4.106 + // That is, do not rely only on name-based lookups, because they may fail 4.107 + // if the names are not resolvable in the boot class loader (7056328). 4.108 + switch (bc) { 4.109 + case Bytecodes::_invokevirtual: 4.110 + case Bytecodes::_invokeinterface: 4.111 + case Bytecodes::_invokespecial: 4.112 + case Bytecodes::_invokestatic: 4.113 + { 4.114 + methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index, bc); 4.115 + if (m != NULL) { 4.116 + return get_object(m)->as_method(); 4.117 + } 4.118 + } 4.119 + } 4.120 + } 4.121 + 4.122 if (holder_is_accessible) { // Our declared holder is loaded. 4.123 instanceKlass* lookup = declared_holder->get_instanceKlass(); 4.124 methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc); 4.125 + if (m != NULL && 4.126 + (bc == Bytecodes::_invokestatic 4.127 + ? instanceKlass::cast(m->method_holder())->is_not_initialized() 4.128 + : !instanceKlass::cast(m->method_holder())->is_loaded())) { 4.129 + m = NULL; 4.130 + } 4.131 if (m != NULL) { 4.132 // We found the method. 4.133 return get_object(m)->as_method(); 4.134 @@ -1046,7 +1090,7 @@ 4.135 // ciEnv::find_system_klass 4.136 ciKlass* ciEnv::find_system_klass(ciSymbol* klass_name) { 4.137 VM_ENTRY_MARK; 4.138 - return get_klass_by_name_impl(NULL, klass_name, false); 4.139 + return get_klass_by_name_impl(NULL, constantPoolHandle(), klass_name, false); 4.140 } 4.141 4.142 // ------------------------------------------------------------------
5.1 --- a/src/share/vm/ci/ciEnv.hpp Wed Jun 22 14:45:37 2011 -0700 5.2 +++ b/src/share/vm/ci/ciEnv.hpp Thu Jun 23 17:14:06 2011 -0700 5.3 @@ -137,6 +137,7 @@ 5.4 5.5 // Implementation methods for loading and constant pool access. 5.6 ciKlass* get_klass_by_name_impl(ciKlass* accessing_klass, 5.7 + constantPoolHandle cpool, 5.8 ciSymbol* klass_name, 5.9 bool require_local); 5.10 ciKlass* get_klass_by_index_impl(constantPoolHandle cpool,
6.1 --- a/src/share/vm/ci/ciField.cpp Wed Jun 22 14:45:37 2011 -0700 6.2 +++ b/src/share/vm/ci/ciField.cpp Thu Jun 23 17:14:06 2011 -0700 6.3 @@ -287,7 +287,7 @@ 6.4 } 6.5 6.6 ciType* ciField::compute_type_impl() { 6.7 - ciKlass* type = CURRENT_ENV->get_klass_by_name_impl(_holder, _signature, false); 6.8 + ciKlass* type = CURRENT_ENV->get_klass_by_name_impl(_holder, constantPoolHandle(), _signature, false); 6.9 if (!type->is_primitive_type() && is_shared()) { 6.10 // We must not cache a pointer to an unshared type, in a shared field. 6.11 bool type_is_also_shared = false;
7.1 --- a/src/share/vm/ci/ciMethod.cpp Wed Jun 22 14:45:37 2011 -0700 7.2 +++ b/src/share/vm/ci/ciMethod.cpp Thu Jun 23 17:14:06 2011 -0700 7.3 @@ -125,7 +125,8 @@ 7.4 _name = env->get_symbol(h_m()->name()); 7.5 _holder = env->get_object(h_m()->method_holder())->as_instance_klass(); 7.6 ciSymbol* sig_symbol = env->get_symbol(h_m()->signature()); 7.7 - _signature = new (env->arena()) ciSignature(_holder, sig_symbol); 7.8 + constantPoolHandle cpool = h_m()->constants(); 7.9 + _signature = new (env->arena()) ciSignature(_holder, cpool, sig_symbol); 7.10 _method_data = NULL; 7.11 // Take a snapshot of these values, so they will be commensurate with the MDO. 7.12 if (ProfileInterpreter || TieredCompilation) { 7.13 @@ -152,7 +153,7 @@ 7.14 // These fields are always filled in. 7.15 _name = name; 7.16 _holder = holder; 7.17 - _signature = new (CURRENT_ENV->arena()) ciSignature(_holder, signature); 7.18 + _signature = new (CURRENT_ENV->arena()) ciSignature(_holder, constantPoolHandle(), signature); 7.19 _intrinsic_id = vmIntrinsics::_none; 7.20 _liveness = NULL; 7.21 _can_be_statically_bound = false;
8.1 --- a/src/share/vm/ci/ciMethodHandle.cpp Wed Jun 22 14:45:37 2011 -0700 8.2 +++ b/src/share/vm/ci/ciMethodHandle.cpp Thu Jun 23 17:14:06 2011 -0700 8.3 @@ -41,6 +41,16 @@ 8.4 VM_ENTRY_MARK; 8.5 Handle h(get_oop()); 8.6 methodHandle callee(_callee->get_methodOop()); 8.7 + assert(callee->is_method_handle_invoke(), ""); 8.8 + oop mt1 = callee->method_handle_type(); 8.9 + oop mt2 = java_lang_invoke_MethodHandle::type(h()); 8.10 + if (!java_lang_invoke_MethodType::equals(mt1, mt2)) { 8.11 + if (PrintMiscellaneous && (Verbose || WizardMode)) { 8.12 + tty->print_cr("ciMethodHandle::get_adapter: types not equal"); 8.13 + mt1->print(); mt2->print(); 8.14 + } 8.15 + return NULL; 8.16 + } 8.17 // We catch all exceptions here that could happen in the method 8.18 // handle compiler and stop the VM. 8.19 MethodHandleCompiler mhc(h, callee->name(), callee->signature(), _profile.count(), is_invokedynamic, THREAD); 8.20 @@ -53,7 +63,7 @@ 8.21 if (PrintMiscellaneous && (Verbose || WizardMode)) { 8.22 tty->print("*** ciMethodHandle::get_adapter => "); 8.23 PENDING_EXCEPTION->print(); 8.24 - tty->print("*** get_adapter (%s): ", is_invokedynamic ? "indy" : "mh"); ((ciObject*)this)->print(); //@@ 8.25 + tty->print("*** get_adapter (%s): ", is_invokedynamic ? "indy" : "mh"); ((ciObject*)this)->print(); 8.26 } 8.27 CLEAR_PENDING_EXCEPTION; 8.28 return NULL;
9.1 --- a/src/share/vm/ci/ciObjArrayKlass.cpp Wed Jun 22 14:45:37 2011 -0700 9.2 +++ b/src/share/vm/ci/ciObjArrayKlass.cpp Thu Jun 23 17:14:06 2011 -0700 9.3 @@ -93,6 +93,7 @@ 9.4 // element klass by name. 9.5 _element_klass = CURRENT_THREAD_ENV->get_klass_by_name_impl( 9.6 this, 9.7 + constantPoolHandle(), 9.8 construct_array_name(base_element_klass()->name(), 9.9 dimension() - 1), 9.10 false);
10.1 --- a/src/share/vm/ci/ciSignature.cpp Wed Jun 22 14:45:37 2011 -0700 10.2 +++ b/src/share/vm/ci/ciSignature.cpp Thu Jun 23 17:14:06 2011 -0700 10.3 @@ -35,7 +35,7 @@ 10.4 10.5 // ------------------------------------------------------------------ 10.6 // ciSignature::ciSignature 10.7 -ciSignature::ciSignature(ciKlass* accessing_klass, ciSymbol* symbol) { 10.8 +ciSignature::ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* symbol) { 10.9 ASSERT_IN_VM; 10.10 EXCEPTION_CONTEXT; 10.11 _accessing_klass = accessing_klass; 10.12 @@ -64,7 +64,7 @@ 10.13 CLEAR_PENDING_EXCEPTION; 10.14 } else { 10.15 ciSymbol* klass_name = env->get_symbol(name); 10.16 - type = env->get_klass_by_name_impl(_accessing_klass, klass_name, false); 10.17 + type = env->get_klass_by_name_impl(_accessing_klass, cpool, klass_name, false); 10.18 } 10.19 } 10.20 _types->append(type);
11.1 --- a/src/share/vm/ci/ciSignature.hpp Wed Jun 22 14:45:37 2011 -0700 11.2 +++ b/src/share/vm/ci/ciSignature.hpp Thu Jun 23 17:14:06 2011 -0700 11.3 @@ -44,7 +44,7 @@ 11.4 11.5 friend class ciMethod; 11.6 11.7 - ciSignature(ciKlass* accessing_klass, ciSymbol* signature); 11.8 + ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature); 11.9 11.10 void get_all_klasses(); 11.11
12.1 --- a/src/share/vm/classfile/javaClasses.cpp Wed Jun 22 14:45:37 2011 -0700 12.2 +++ b/src/share/vm/classfile/javaClasses.cpp Thu Jun 23 17:14:06 2011 -0700 12.3 @@ -2574,6 +2574,18 @@ 12.4 return name; 12.5 } 12.6 12.7 +bool java_lang_invoke_MethodType::equals(oop mt1, oop mt2) { 12.8 + if (rtype(mt1) != rtype(mt2)) 12.9 + return false; 12.10 + if (ptype_count(mt1) != ptype_count(mt2)) 12.11 + return false; 12.12 + for (int i = ptype_count(mt1) - 1; i >= 0; i--) { 12.13 + if (ptype(mt1, i) != ptype(mt2, i)) 12.14 + return false; 12.15 + } 12.16 + return true; 12.17 +} 12.18 + 12.19 oop java_lang_invoke_MethodType::rtype(oop mt) { 12.20 assert(is_instance(mt), "must be a MethodType"); 12.21 return mt->obj_field(_rtype_offset);
13.1 --- a/src/share/vm/classfile/javaClasses.hpp Wed Jun 22 14:45:37 2011 -0700 13.2 +++ b/src/share/vm/classfile/javaClasses.hpp Thu Jun 23 17:14:06 2011 -0700 13.3 @@ -1079,6 +1079,8 @@ 13.4 return obj != NULL && obj->klass() == SystemDictionary::MethodType_klass(); 13.5 } 13.6 13.7 + static bool equals(oop mt1, oop mt2); 13.8 + 13.9 // Accessors for code generation: 13.10 static int rtype_offset_in_bytes() { return _rtype_offset; } 13.11 static int ptypes_offset_in_bytes() { return _ptypes_offset; }
14.1 --- a/src/share/vm/classfile/systemDictionary.cpp Wed Jun 22 14:45:37 2011 -0700 14.2 +++ b/src/share/vm/classfile/systemDictionary.cpp Thu Jun 23 17:14:06 2011 -0700 14.3 @@ -2367,6 +2367,8 @@ 14.4 // Link m to his method type, if it is suitably generic. 14.5 oop mtform = java_lang_invoke_MethodType::form(mt()); 14.6 if (mtform != NULL && mt() == java_lang_invoke_MethodTypeForm::erasedType(mtform) 14.7 + // vmlayout must be an invokeExact: 14.8 + && name_id == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name) 14.9 && java_lang_invoke_MethodTypeForm::vmlayout_offset_in_bytes() > 0) { 14.10 java_lang_invoke_MethodTypeForm::init_vmlayout(mtform, m()); 14.11 }
15.1 --- a/src/share/vm/interpreter/linkResolver.cpp Wed Jun 22 14:45:37 2011 -0700 15.2 +++ b/src/share/vm/interpreter/linkResolver.cpp Thu Jun 23 17:14:06 2011 -0700 15.3 @@ -294,6 +294,16 @@ 15.4 Symbol* method_signature = pool->signature_ref_at(index); 15.5 KlassHandle current_klass(THREAD, pool->pool_holder()); 15.6 15.7 + if (pool->has_preresolution() 15.8 + || (resolved_klass() == SystemDictionary::MethodHandle_klass() && 15.9 + methodOopDesc::is_method_handle_invoke_name(method_name))) { 15.10 + methodOop result_oop = constantPoolOopDesc::method_at_if_loaded(pool, index); 15.11 + if (result_oop != NULL) { 15.12 + resolved_method = methodHandle(THREAD, result_oop); 15.13 + return; 15.14 + } 15.15 + } 15.16 + 15.17 resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK); 15.18 } 15.19
16.1 --- a/src/share/vm/oops/constantPoolKlass.cpp Wed Jun 22 14:45:37 2011 -0700 16.2 +++ b/src/share/vm/oops/constantPoolKlass.cpp Thu Jun 23 17:14:06 2011 -0700 16.3 @@ -310,10 +310,14 @@ 16.4 st->print(" - flags: 0x%x", cp->flags()); 16.5 if (cp->has_pseudo_string()) st->print(" has_pseudo_string"); 16.6 if (cp->has_invokedynamic()) st->print(" has_invokedynamic"); 16.7 + if (cp->has_preresolution()) st->print(" has_preresolution"); 16.8 st->cr(); 16.9 } 16.10 + if (cp->pool_holder() != NULL) { 16.11 + bool extra = (instanceKlass::cast(cp->pool_holder())->constants() != cp); 16.12 + st->print_cr(" - holder: " INTPTR_FORMAT "%s", cp->pool_holder(), (extra? " (extra)" : "")); 16.13 + } 16.14 st->print_cr(" - cache: " INTPTR_FORMAT, cp->cache()); 16.15 - 16.16 for (int index = 1; index < cp->length(); index++) { // Index 0 is unused 16.17 st->print(" - %3d : ", index); 16.18 cp->tag_at(index).print_on(st); 16.19 @@ -414,10 +418,15 @@ 16.20 st->print("constant pool [%d]", cp->length()); 16.21 if (cp->has_pseudo_string()) st->print("/pseudo_string"); 16.22 if (cp->has_invokedynamic()) st->print("/invokedynamic"); 16.23 + if (cp->has_preresolution()) st->print("/preresolution"); 16.24 if (cp->operands() != NULL) st->print("/operands[%d]", cp->operands()->length()); 16.25 cp->print_address_on(st); 16.26 st->print(" for "); 16.27 cp->pool_holder()->print_value_on(st); 16.28 + if (cp->pool_holder() != NULL) { 16.29 + bool extra = (instanceKlass::cast(cp->pool_holder())->constants() != cp); 16.30 + if (extra) st->print(" (extra)"); 16.31 + } 16.32 if (cp->cache() != NULL) { 16.33 st->print(" cache=" PTR_FORMAT, cp->cache()); 16.34 }
17.1 --- a/src/share/vm/oops/constantPoolOop.cpp Wed Jun 22 14:45:37 2011 -0700 17.2 +++ b/src/share/vm/oops/constantPoolOop.cpp Thu Jun 23 17:14:06 2011 -0700 17.3 @@ -266,6 +266,29 @@ 17.4 } 17.5 17.6 17.7 +methodOop constantPoolOopDesc::method_at_if_loaded(constantPoolHandle cpool, 17.8 + int which, Bytecodes::Code invoke_code) { 17.9 + assert(!constantPoolCacheOopDesc::is_secondary_index(which), "no indy instruction here"); 17.10 + if (cpool->cache() == NULL) return false; // nothing to load yet 17.11 + int cache_index = which - CPCACHE_INDEX_TAG; 17.12 + if (!(cache_index >= 0 && cache_index < cpool->cache()->length())) { 17.13 + if (PrintMiscellaneous && (Verbose||WizardMode)) { 17.14 + tty->print_cr("bad operand %d for %d in:", which, invoke_code); cpool->print(); 17.15 + } 17.16 + return NULL; 17.17 + } 17.18 + ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index); 17.19 + if (invoke_code != Bytecodes::_illegal) 17.20 + return e->get_method_if_resolved(invoke_code, cpool); 17.21 + Bytecodes::Code bc; 17.22 + if ((bc = e->bytecode_1()) != (Bytecodes::Code)0) 17.23 + return e->get_method_if_resolved(bc, cpool); 17.24 + if ((bc = e->bytecode_2()) != (Bytecodes::Code)0) 17.25 + return e->get_method_if_resolved(bc, cpool); 17.26 + return NULL; 17.27 +} 17.28 + 17.29 + 17.30 Symbol* constantPoolOopDesc::impl_name_ref_at(int which, bool uncached) { 17.31 int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached)); 17.32 return symbol_at(name_index);
18.1 --- a/src/share/vm/oops/constantPoolOop.hpp Wed Jun 22 14:45:37 2011 -0700 18.2 +++ b/src/share/vm/oops/constantPoolOop.hpp Thu Jun 23 17:14:06 2011 -0700 18.3 @@ -103,7 +103,8 @@ 18.4 18.5 enum FlagBit { 18.6 FB_has_invokedynamic = 1, 18.7 - FB_has_pseudo_string = 2 18.8 + FB_has_pseudo_string = 2, 18.9 + FB_has_preresolution = 3 18.10 }; 18.11 18.12 int flags() const { return _flags; } 18.13 @@ -179,8 +180,10 @@ 18.14 18.15 bool has_pseudo_string() const { return flag_at(FB_has_pseudo_string); } 18.16 bool has_invokedynamic() const { return flag_at(FB_has_invokedynamic); } 18.17 + bool has_preresolution() const { return flag_at(FB_has_preresolution); } 18.18 void set_pseudo_string() { set_flag_at(FB_has_pseudo_string); } 18.19 void set_invokedynamic() { set_flag_at(FB_has_invokedynamic); } 18.20 + void set_preresolution() { set_flag_at(FB_has_preresolution); } 18.21 18.22 // Klass holding pool 18.23 klassOop pool_holder() const { return _pool_holder; } 18.24 @@ -663,6 +666,8 @@ 18.25 friend class SystemDictionary; 18.26 18.27 // Used by compiler to prevent classloading. 18.28 + static methodOop method_at_if_loaded (constantPoolHandle this_oop, int which, 18.29 + Bytecodes::Code bc = Bytecodes::_illegal); 18.30 static klassOop klass_at_if_loaded (constantPoolHandle this_oop, int which); 18.31 static klassOop klass_ref_at_if_loaded (constantPoolHandle this_oop, int which); 18.32 // Same as above - but does LinkResolving.
19.1 --- a/src/share/vm/oops/cpCacheOop.cpp Wed Jun 22 14:45:37 2011 -0700 19.2 +++ b/src/share/vm/oops/cpCacheOop.cpp Thu Jun 23 17:14:06 2011 -0700 19.3 @@ -295,6 +295,50 @@ 19.4 } 19.5 19.6 19.7 +methodOop ConstantPoolCacheEntry::get_method_if_resolved(Bytecodes::Code invoke_code, constantPoolHandle cpool) { 19.8 + assert(invoke_code > (Bytecodes::Code)0, "bad query"); 19.9 + if (is_secondary_entry()) { 19.10 + return cpool->cache()->entry_at(main_entry_index())->get_method_if_resolved(invoke_code, cpool); 19.11 + } 19.12 + // Decode the action of set_method and set_interface_call 19.13 + if (bytecode_1() == invoke_code) { 19.14 + oop f1 = _f1; 19.15 + if (f1 != NULL) { 19.16 + switch (invoke_code) { 19.17 + case Bytecodes::_invokeinterface: 19.18 + assert(f1->is_klass(), ""); 19.19 + return klassItable::method_for_itable_index(klassOop(f1), (int) f2()); 19.20 + case Bytecodes::_invokestatic: 19.21 + case Bytecodes::_invokespecial: 19.22 + assert(f1->is_method(), ""); 19.23 + return methodOop(f1); 19.24 + } 19.25 + } 19.26 + } 19.27 + if (bytecode_2() == invoke_code) { 19.28 + switch (invoke_code) { 19.29 + case Bytecodes::_invokevirtual: 19.30 + if (is_vfinal()) { 19.31 + // invokevirtual 19.32 + methodOop m = methodOop((intptr_t) f2()); 19.33 + assert(m->is_method(), ""); 19.34 + return m; 19.35 + } else { 19.36 + int holder_index = cpool->uncached_klass_ref_index_at(constant_pool_index()); 19.37 + if (cpool->tag_at(holder_index).is_klass()) { 19.38 + klassOop klass = cpool->resolved_klass_at(holder_index); 19.39 + if (!Klass::cast(klass)->oop_is_instance()) 19.40 + klass = SystemDictionary::Object_klass(); 19.41 + return instanceKlass::cast(klass)->method_at_vtable((int) f2()); 19.42 + } 19.43 + } 19.44 + } 19.45 + } 19.46 + return NULL; 19.47 +} 19.48 + 19.49 + 19.50 + 19.51 class LocalOopClosure: public OopClosure { 19.52 private: 19.53 void (*_f)(oop*);
20.1 --- a/src/share/vm/oops/cpCacheOop.hpp Wed Jun 22 14:45:37 2011 -0700 20.2 +++ b/src/share/vm/oops/cpCacheOop.hpp Thu Jun 23 17:14:06 2011 -0700 20.3 @@ -194,6 +194,8 @@ 20.4 methodHandle signature_invoker // determines signature information 20.5 ); 20.6 20.7 + methodOop get_method_if_resolved(Bytecodes::Code invoke_code, constantPoolHandle cpool); 20.8 + 20.9 // For JVM_CONSTANT_InvokeDynamic cache entries: 20.10 void initialize_bootstrap_method_index_in_cache(int bsm_cache_index); 20.11 int bootstrap_method_index_in_cache();
21.1 --- a/src/share/vm/oops/methodOop.cpp Wed Jun 22 14:45:37 2011 -0700 21.2 +++ b/src/share/vm/oops/methodOop.cpp Thu Jun 23 17:14:06 2011 -0700 21.3 @@ -928,14 +928,40 @@ 21.4 name->increment_refcount(); 21.5 signature->increment_refcount(); 21.6 21.7 + // record non-BCP method types in the constant pool 21.8 + GrowableArray<KlassHandle>* extra_klasses = NULL; 21.9 + for (int i = -1, len = java_lang_invoke_MethodType::ptype_count(method_type()); i < len; i++) { 21.10 + oop ptype = (i == -1 21.11 + ? java_lang_invoke_MethodType::rtype(method_type()) 21.12 + : java_lang_invoke_MethodType::ptype(method_type(), i)); 21.13 + klassOop klass = check_non_bcp_klass(java_lang_Class::as_klassOop(ptype)); 21.14 + if (klass != NULL) { 21.15 + if (extra_klasses == NULL) 21.16 + extra_klasses = new GrowableArray<KlassHandle>(len+1); 21.17 + bool dup = false; 21.18 + for (int j = 0; j < extra_klasses->length(); j++) { 21.19 + if (extra_klasses->at(j) == klass) { dup = true; break; } 21.20 + } 21.21 + if (!dup) 21.22 + extra_klasses->append(KlassHandle(THREAD, klass)); 21.23 + } 21.24 + } 21.25 + 21.26 + int extra_klass_count = (extra_klasses == NULL ? 0 : extra_klasses->length()); 21.27 + int cp_length = _imcp_limit + extra_klass_count; 21.28 constantPoolHandle cp; 21.29 { 21.30 - constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty)); 21.31 + constantPoolOop cp_oop = oopFactory::new_constantPool(cp_length, IsSafeConc, CHECK_(empty)); 21.32 cp = constantPoolHandle(THREAD, cp_oop); 21.33 } 21.34 cp->symbol_at_put(_imcp_invoke_name, name); 21.35 cp->symbol_at_put(_imcp_invoke_signature, signature); 21.36 cp->string_at_put(_imcp_method_type_value, Universe::the_null_string()); 21.37 + for (int j = 0; j < extra_klass_count; j++) { 21.38 + KlassHandle klass = extra_klasses->at(j); 21.39 + cp->klass_at_put(_imcp_limit + j, klass()); 21.40 + } 21.41 + cp->set_preresolution(); 21.42 cp->set_pool_holder(holder()); 21.43 21.44 // set up the fancy stuff: 21.45 @@ -984,6 +1010,14 @@ 21.46 return m; 21.47 } 21.48 21.49 +klassOop methodOopDesc::check_non_bcp_klass(klassOop klass) { 21.50 + if (klass != NULL && Klass::cast(klass)->class_loader() != NULL) { 21.51 + if (Klass::cast(klass)->oop_is_objArray()) 21.52 + klass = objArrayKlass::cast(klass)->bottom_klass(); 21.53 + return klass; 21.54 + } 21.55 + return NULL; 21.56 +} 21.57 21.58 21.59 methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length,
22.1 --- a/src/share/vm/oops/methodOop.hpp Wed Jun 22 14:45:37 2011 -0700 22.2 +++ b/src/share/vm/oops/methodOop.hpp Thu Jun 23 17:14:06 2011 -0700 22.3 @@ -600,6 +600,7 @@ 22.4 Symbol* signature, //anything at all 22.5 Handle method_type, 22.6 TRAPS); 22.7 + static klassOop check_non_bcp_klass(klassOop klass); 22.8 // these operate only on invoke methods: 22.9 oop method_handle_type() const; 22.10 static jint* method_type_offsets_chain(); // series of pointer-offsets, terminated by -1
23.1 --- a/src/share/vm/prims/methodHandleWalk.cpp Wed Jun 22 14:45:37 2011 -0700 23.2 +++ b/src/share/vm/prims/methodHandleWalk.cpp Thu Jun 23 17:14:06 2011 -0700 23.3 @@ -425,6 +425,8 @@ 23.4 ArgToken arg = _outgoing.at(arg_slot); 23.5 assert(dest == arg.basic_type(), ""); 23.6 arg = make_conversion(T_OBJECT, dest_klass, Bytecodes::_checkcast, arg, CHECK_(empty)); 23.7 + // replace the object by the result of the cast, to make the compiler happy: 23.8 + change_argument(T_OBJECT, arg_slot, T_OBJECT, arg); 23.9 debug_only(dest_klass = (klassOop)badOop); 23.10 break; 23.11 } 23.12 @@ -467,7 +469,7 @@ 23.13 ArgToken arglist[2]; 23.14 arglist[0] = arg; // outgoing 'this' 23.15 arglist[1] = ArgToken(); // sentinel 23.16 - arg = make_invoke(NULL, unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); 23.17 + arg = make_invoke(methodHandle(), unboxer, Bytecodes::_invokevirtual, false, 1, &arglist[0], CHECK_(empty)); 23.18 change_argument(T_OBJECT, arg_slot, dest, arg); 23.19 break; 23.20 } 23.21 @@ -483,7 +485,7 @@ 23.22 ArgToken arglist[2]; 23.23 arglist[0] = arg; // outgoing value 23.24 arglist[1] = ArgToken(); // sentinel 23.25 - arg = make_invoke(NULL, boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); 23.26 + arg = make_invoke(methodHandle(), boxer, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(empty)); 23.27 change_argument(src, arg_slot, T_OBJECT, arg); 23.28 break; 23.29 } 23.30 @@ -599,8 +601,9 @@ 23.31 lose("bad vmlayout slot", CHECK_(empty)); 23.32 } 23.33 // FIXME: consider inlining the invokee at the bytecode level 23.34 - ArgToken ret = make_invoke(methodOop(invoker), vmIntrinsics::_none, 23.35 + ArgToken ret = make_invoke(methodHandle(THREAD, methodOop(invoker)), vmIntrinsics::_invokeGeneric, 23.36 Bytecodes::_invokevirtual, false, 1+argc, &arglist[0], CHECK_(empty)); 23.37 + // The iid = _invokeGeneric really means to adjust reference types as needed. 23.38 DEBUG_ONLY(invoker = NULL); 23.39 if (rtype == T_OBJECT) { 23.40 klassOop rklass = java_lang_Class::as_klassOop( java_lang_invoke_MethodType::rtype(recursive_mtype()) ); 23.41 @@ -657,7 +660,7 @@ 23.42 arglist[0] = array_arg; // value to check 23.43 arglist[1] = length_arg; // length to check 23.44 arglist[2] = ArgToken(); // sentinel 23.45 - make_invoke(NULL, vmIntrinsics::_checkSpreadArgument, 23.46 + make_invoke(methodHandle(), vmIntrinsics::_checkSpreadArgument, 23.47 Bytecodes::_invokestatic, false, 2, &arglist[0], CHECK_(empty)); 23.48 23.49 // Spread out the array elements. 23.50 @@ -680,7 +683,7 @@ 23.51 ArgToken offset_arg = make_prim_constant(T_INT, &offset_jvalue, CHECK_(empty)); 23.52 ArgToken element_arg = make_fetch(element_type, element_klass(), aload_op, array_arg, offset_arg, CHECK_(empty)); 23.53 change_argument(T_VOID, ap, element_type, element_arg); 23.54 - ap += type2size[element_type]; 23.55 + //ap += type2size[element_type]; // don't do this; insert next arg to *right* of previous 23.56 } 23.57 break; 23.58 } 23.59 @@ -731,7 +734,7 @@ 23.60 } 23.61 assert(ap == _outgoing_argc, ""); 23.62 arglist[ap] = ArgToken(); // add a sentinel, for the sake of asserts 23.63 - return make_invoke(chain().last_method_oop(), 23.64 + return make_invoke(chain().last_method(), 23.65 vmIntrinsics::_none, 23.66 chain().last_invoke_code(), true, 23.67 ap, arglist, THREAD); 23.68 @@ -853,7 +856,6 @@ 23.69 if (src != dst) { 23.70 if (MethodHandles::same_basic_type_for_returns(src, dst, /*raw*/ true)) { 23.71 if (MethodHandles::is_float_fixed_reinterpretation_cast(src, dst)) { 23.72 - if (for_return) Untested("MHW return raw conversion"); // still untested 23.73 vmIntrinsics::ID iid = vmIntrinsics::for_raw_conversion(src, dst); 23.74 if (iid == vmIntrinsics::_none) { 23.75 lose("no raw conversion method", CHECK); 23.76 @@ -865,18 +867,24 @@ 23.77 assert(arg.token_type() >= tt_symbolic || src == arg.basic_type(), "sanity"); 23.78 arglist[0] = arg; // outgoing 'this' 23.79 arglist[1] = ArgToken(); // sentinel 23.80 - arg = make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK); 23.81 + arg = make_invoke(methodHandle(), iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK); 23.82 change_argument(src, slot, dst, arg); 23.83 } else { 23.84 // return type conversion 23.85 - klassOop arg_klass = NULL; 23.86 - arglist[0] = make_parameter(src, arg_klass, -1, CHECK); // return value 23.87 - arglist[1] = ArgToken(); // sentinel 23.88 - (void) make_invoke(NULL, iid, Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK); 23.89 + if (_return_conv == vmIntrinsics::_none) { 23.90 + _return_conv = iid; 23.91 + } else if (_return_conv == vmIntrinsics::for_raw_conversion(dst, src)) { 23.92 + _return_conv = vmIntrinsics::_none; 23.93 + } else if (_return_conv != zero_return_conv()) { 23.94 + lose(err_msg("requested raw return conversion not allowed: %s -> %s (before %s)", type2name(src), type2name(dst), vmIntrinsics::name_at(_return_conv)), CHECK); 23.95 + } 23.96 } 23.97 } else { 23.98 // Nothing to do. 23.99 } 23.100 + } else if (for_return && (!is_subword_type(src) || !is_subword_type(dst))) { 23.101 + // This can occur in exception-throwing MHs, which have a fictitious return value encoded as Void or Empty. 23.102 + _return_conv = zero_return_conv(); 23.103 } else if (src == T_OBJECT && is_java_primitive(dst)) { 23.104 // ref-to-prim: discard ref, push zero 23.105 lose("requested ref-to-prim conversion not expected", CHECK); 23.106 @@ -896,6 +904,7 @@ 23.107 _thread(THREAD), 23.108 _bytecode(THREAD, 50), 23.109 _constants(THREAD, 10), 23.110 + _non_bcp_klasses(THREAD, 5), 23.111 _cur_stack(0), 23.112 _max_stack(0), 23.113 _rtype(T_ILLEGAL) 23.114 @@ -908,6 +917,15 @@ 23.115 _name_index = cpool_symbol_put(name); 23.116 _signature_index = cpool_symbol_put(signature); 23.117 23.118 + // To make the resulting methods more recognizable by 23.119 + // stack walkers and compiler heuristics, 23.120 + // we put them in holder class MethodHandle. 23.121 + // See klass_is_method_handle_adapter_holder 23.122 + // and methodOopDesc::is_method_handle_adapter. 23.123 + _target_klass = SystemDictionaryHandles::MethodHandle_klass(); 23.124 + 23.125 + check_non_bcp_klasses(java_lang_invoke_MethodHandle::type(root()), CHECK); 23.126 + 23.127 // Get return type klass. 23.128 Handle first_mtype(THREAD, chain().method_type_oop()); 23.129 // _rklass is NULL for primitives. 23.130 @@ -929,6 +947,7 @@ 23.131 assert(_thread == THREAD, "must be same thread"); 23.132 methodHandle nullHandle; 23.133 (void) walk(CHECK_(nullHandle)); 23.134 + record_non_bcp_klasses(); 23.135 return get_method_oop(CHECK_(nullHandle)); 23.136 } 23.137 23.138 @@ -1197,10 +1216,18 @@ 23.139 } 23.140 case T_OBJECT: { 23.141 Handle value = arg.object(); 23.142 - if (value.is_null()) 23.143 + if (value.is_null()) { 23.144 emit_bc(Bytecodes::_aconst_null); 23.145 - else 23.146 - emit_bc(Bytecodes::_ldc, cpool_object_put(value)); 23.147 + break; 23.148 + } 23.149 + if (java_lang_Class::is_instance(value())) { 23.150 + klassOop k = java_lang_Class::as_klassOop(value()); 23.151 + if (k != NULL) { 23.152 + emit_bc(Bytecodes::_ldc, cpool_klass_put(k)); 23.153 + break; 23.154 + } 23.155 + } 23.156 + emit_bc(Bytecodes::_ldc, cpool_object_put(value)); 23.157 break; 23.158 } 23.159 default: 23.160 @@ -1260,6 +1287,7 @@ 23.161 index = src.index(); 23.162 } 23.163 emit_bc(op, cpool_klass_put(tk)); 23.164 + check_non_bcp_klass(tk, CHECK_(src)); 23.165 // Allocate a new local for the type so that we don't hide the 23.166 // previous type from the verifier. 23.167 index = new_local_index(type); 23.168 @@ -1292,15 +1320,15 @@ 23.169 23.170 // Emit bytecodes for the given invoke instruction. 23.171 MethodHandleWalker::ArgToken 23.172 -MethodHandleCompiler::make_invoke(methodOop m, vmIntrinsics::ID iid, 23.173 +MethodHandleCompiler::make_invoke(methodHandle m, vmIntrinsics::ID iid, 23.174 Bytecodes::Code op, bool tailcall, 23.175 int argc, MethodHandleWalker::ArgToken* argv, 23.176 TRAPS) { 23.177 ArgToken zero; 23.178 - if (m == NULL) { 23.179 + if (m.is_null()) { 23.180 // Get the intrinsic methodOop. 23.181 - m = vmIntrinsics::method_for(iid); 23.182 - if (m == NULL) { 23.183 + m = methodHandle(THREAD, vmIntrinsics::method_for(iid)); 23.184 + if (m.is_null()) { 23.185 lose(vmIntrinsics::name_at(iid), CHECK_(zero)); 23.186 } 23.187 } 23.188 @@ -1309,18 +1337,46 @@ 23.189 Symbol* name = m->name(); 23.190 Symbol* signature = m->signature(); 23.191 23.192 + if (iid == vmIntrinsics::_invokeGeneric && 23.193 + argc >= 1 && argv[0].token_type() == tt_constant) { 23.194 + assert(m->intrinsic_id() == vmIntrinsics::_invokeExact, ""); 23.195 + Handle receiver = argv[0].object(); 23.196 + Handle rtype(THREAD, java_lang_invoke_MethodHandle::type(receiver())); 23.197 + Handle mtype(THREAD, m->method_handle_type()); 23.198 + if (rtype() != mtype()) { 23.199 + assert(java_lang_invoke_MethodType::form(rtype()) == 23.200 + java_lang_invoke_MethodType::form(mtype()), 23.201 + "must be the same shape"); 23.202 + // customize m to the exact required rtype 23.203 + bool has_non_bcp_klass = check_non_bcp_klasses(rtype(), CHECK_(zero)); 23.204 + TempNewSymbol sig2 = java_lang_invoke_MethodType::as_signature(rtype(), true, CHECK_(zero)); 23.205 + methodHandle m2; 23.206 + if (!has_non_bcp_klass) { 23.207 + methodOop m2_oop = SystemDictionary::find_method_handle_invoke(m->name(), sig2, 23.208 + KlassHandle(), CHECK_(zero)); 23.209 + m2 = methodHandle(THREAD, m2_oop); 23.210 + } 23.211 + if (m2.is_null()) { 23.212 + // just build it fresh 23.213 + m2 = methodOopDesc::make_invoke_method(klass, m->name(), sig2, rtype, CHECK_(zero)); 23.214 + if (m2.is_null()) 23.215 + lose(err_msg("no customized invoker %s", sig2->as_utf8()), CHECK_(zero)); 23.216 + } 23.217 + m = m2; 23.218 + signature = m->signature(); 23.219 + } 23.220 + } 23.221 + 23.222 + check_non_bcp_klass(klass, CHECK_(zero)); 23.223 + if (m->is_method_handle_invoke()) { 23.224 + check_non_bcp_klasses(m->method_handle_type(), CHECK_(zero)); 23.225 + } 23.226 + 23.227 // Count the number of arguments, not the size 23.228 ArgumentCount asc(signature); 23.229 assert(argc == asc.size() + ((op == Bytecodes::_invokestatic || op == Bytecodes::_invokedynamic) ? 0 : 1), 23.230 "argc mismatch"); 23.231 23.232 - if (tailcall) { 23.233 - // Actually, in order to make these methods more recognizable, 23.234 - // let's put them in holder class MethodHandle. That way stack 23.235 - // walkers and compiler heuristics can recognize them. 23.236 - _target_klass = SystemDictionary::MethodHandle_klass(); 23.237 - } 23.238 - 23.239 // Inline the method. 23.240 InvocationCounter* ic = m->invocation_counter(); 23.241 ic->set_carry_flag(); 23.242 @@ -1353,7 +1409,7 @@ 23.243 int signature_index = cpool_symbol_put(signature); 23.244 int name_and_type_index = cpool_name_and_type_put(name_index, signature_index); 23.245 int klass_index = cpool_klass_put(klass); 23.246 - int methodref_index = cpool_methodref_put(klass_index, name_and_type_index); 23.247 + int methodref_index = cpool_methodref_put(op, klass_index, name_and_type_index, m); 23.248 23.249 // Generate invoke. 23.250 switch (op) { 23.251 @@ -1380,6 +1436,20 @@ 23.252 stack_push(rbt); // The return value is already pushed onto the stack. 23.253 ArgToken ret; 23.254 if (tailcall) { 23.255 + if (return_conv() == zero_return_conv()) { 23.256 + rbt = T_VOID; // discard value 23.257 + } else if (return_conv() != vmIntrinsics::_none) { 23.258 + // return value conversion 23.259 + int index = new_local_index(rbt); 23.260 + emit_store(rbt, index); 23.261 + ArgToken arglist[2]; 23.262 + arglist[0] = ArgToken(tt_temporary, rbt, index); 23.263 + arglist[1] = ArgToken(); // sentinel 23.264 + ret = make_invoke(methodHandle(), return_conv(), Bytecodes::_invokestatic, false, 1, &arglist[0], CHECK_(zero)); 23.265 + set_return_conv(vmIntrinsics::_none); 23.266 + rbt = ret.basic_type(); 23.267 + emit_load(rbt, ret.index()); 23.268 + } 23.269 if (rbt != _rtype) { 23.270 if (rbt == T_VOID) { 23.271 // push a zero of the right sort 23.272 @@ -1425,6 +1495,7 @@ 23.273 case T_OBJECT: 23.274 if (_rklass.not_null() && _rklass() != SystemDictionary::Object_klass() && !Klass::cast(_rklass())->is_interface()) { 23.275 emit_bc(Bytecodes::_checkcast, cpool_klass_put(_rklass())); 23.276 + check_non_bcp_klass(_rklass(), CHECK_(zero)); 23.277 } 23.278 emit_bc(Bytecodes::_areturn); 23.279 break; 23.280 @@ -1525,6 +1596,52 @@ 23.281 return index; 23.282 } 23.283 23.284 +bool MethodHandleCompiler::check_non_bcp_klasses(Handle method_type, TRAPS) { 23.285 + bool res = false; 23.286 + for (int i = -1, len = java_lang_invoke_MethodType::ptype_count(method_type()); i < len; i++) { 23.287 + oop ptype = (i == -1 23.288 + ? java_lang_invoke_MethodType::rtype(method_type()) 23.289 + : java_lang_invoke_MethodType::ptype(method_type(), i)); 23.290 + res |= check_non_bcp_klass(java_lang_Class::as_klassOop(ptype), CHECK_(false)); 23.291 + } 23.292 + return res; 23.293 +} 23.294 + 23.295 +bool MethodHandleCompiler::check_non_bcp_klass(klassOop klass, TRAPS) { 23.296 + klass = methodOopDesc::check_non_bcp_klass(klass); 23.297 + if (klass != NULL) { 23.298 + Symbol* name = Klass::cast(klass)->name(); 23.299 + for (int i = _non_bcp_klasses.length() - 1; i >= 0; i--) { 23.300 + klassOop k2 = _non_bcp_klasses.at(i)(); 23.301 + if (Klass::cast(k2)->name() == name) { 23.302 + if (k2 != klass) { 23.303 + lose(err_msg("unsupported klass name alias %s", name->as_utf8()), THREAD); 23.304 + } 23.305 + return true; 23.306 + } 23.307 + } 23.308 + _non_bcp_klasses.append(KlassHandle(THREAD, klass)); 23.309 + return true; 23.310 + } 23.311 + return false; 23.312 +} 23.313 + 23.314 +void MethodHandleCompiler::record_non_bcp_klasses() { 23.315 + // Append extra klasses to constant pool, to guide klass lookup. 23.316 + for (int k = 0; k < _non_bcp_klasses.length(); k++) { 23.317 + klassOop non_bcp_klass = _non_bcp_klasses.at(k)(); 23.318 + bool add_to_cp = true; 23.319 + for (int j = 1; j < _constants.length(); j++) { 23.320 + ConstantValue* cv = _constants.at(j); 23.321 + if (cv != NULL && cv->tag() == JVM_CONSTANT_Class 23.322 + && cv->klass_oop() == non_bcp_klass) { 23.323 + add_to_cp = false; 23.324 + break; 23.325 + } 23.326 + } 23.327 + if (add_to_cp) cpool_klass_put(non_bcp_klass); 23.328 + } 23.329 +} 23.330 23.331 constantPoolHandle MethodHandleCompiler::get_constant_pool(TRAPS) const { 23.332 constantPoolHandle nullHandle; 23.333 @@ -1544,6 +1661,8 @@ 23.334 case JVM_CONSTANT_Double: cpool->double_at_put( i, cv->get_jdouble() ); break; 23.335 case JVM_CONSTANT_Class: cpool->klass_at_put( i, cv->klass_oop() ); break; 23.336 case JVM_CONSTANT_Methodref: cpool->method_at_put( i, cv->first_index(), cv->second_index()); break; 23.337 + case JVM_CONSTANT_InterfaceMethodref: 23.338 + cpool->interface_method_at_put(i, cv->first_index(), cv->second_index()); break; 23.339 case JVM_CONSTANT_NameAndType: cpool->name_and_type_at_put(i, cv->first_index(), cv->second_index()); break; 23.340 case JVM_CONSTANT_Object: cpool->object_at_put( i, cv->object_oop() ); break; 23.341 default: ShouldNotReachHere(); 23.342 @@ -1558,6 +1677,8 @@ 23.343 } 23.344 } 23.345 23.346 + cpool->set_preresolution(); 23.347 + 23.348 // Set the constant pool holder to the target method's class. 23.349 cpool->set_pool_holder(_target_klass()); 23.350 23.351 @@ -1606,6 +1727,33 @@ 23.352 Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(empty)); // Use fake class. 23.353 Rewriter::relocate_and_link(_target_klass(), methods, CHECK_(empty)); // Use fake class. 23.354 23.355 + // Pre-resolve selected CP cache entries, to avoid problems with class loader scoping. 23.356 + constantPoolCacheHandle cpc(THREAD, cpool->cache()); 23.357 + for (int i = 0; i < cpc->length(); i++) { 23.358 + ConstantPoolCacheEntry* e = cpc->entry_at(i); 23.359 + assert(!e->is_secondary_entry(), "no indy instructions in here, yet"); 23.360 + int constant_pool_index = e->constant_pool_index(); 23.361 + ConstantValue* cv = _constants.at(constant_pool_index); 23.362 + if (!cv->has_linkage()) continue; 23.363 + methodHandle m = cv->linkage(); 23.364 + int index; 23.365 + switch (cv->tag()) { 23.366 + case JVM_CONSTANT_Methodref: 23.367 + index = m->vtable_index(); 23.368 + if (m->is_static()) { 23.369 + e->set_method(Bytecodes::_invokestatic, m, index); 23.370 + } else { 23.371 + e->set_method(Bytecodes::_invokespecial, m, index); 23.372 + e->set_method(Bytecodes::_invokevirtual, m, index); 23.373 + } 23.374 + break; 23.375 + case JVM_CONSTANT_InterfaceMethodref: 23.376 + index = klassItable::compute_itable_index(m()); 23.377 + e->set_interface_call(m, index); 23.378 + break; 23.379 + } 23.380 + } 23.381 + 23.382 // Set the invocation counter's count to the invoke count of the 23.383 // original call site. 23.384 InvocationCounter* ic = m->invocation_counter(); 23.385 @@ -1696,6 +1844,9 @@ 23.386 _param_state(0), 23.387 _temp_num(0) 23.388 { 23.389 + out->print("MethodHandle:"); 23.390 + java_lang_invoke_MethodType::print_signature(java_lang_invoke_MethodHandle::type(root()), out); 23.391 + out->print(" : #"); 23.392 start_params(); 23.393 } 23.394 virtual ArgToken make_parameter(BasicType type, klassOop tk, int argnum, TRAPS) { 23.395 @@ -1759,12 +1910,12 @@ 23.396 _strbuf.print(")"); 23.397 return maybe_make_temp("fetch", type, "x"); 23.398 } 23.399 - virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, 23.400 + virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, 23.401 Bytecodes::Code op, bool tailcall, 23.402 int argc, ArgToken* argv, TRAPS) { 23.403 Symbol* name; 23.404 Symbol* sig; 23.405 - if (m != NULL) { 23.406 + if (m.not_null()) { 23.407 name = m->name(); 23.408 sig = m->signature(); 23.409 } else {
24.1 --- a/src/share/vm/prims/methodHandleWalk.hpp Wed Jun 22 14:45:37 2011 -0700 24.2 +++ b/src/share/vm/prims/methodHandleWalk.hpp Thu Jun 23 17:14:06 2011 -0700 24.3 @@ -98,6 +98,7 @@ 24.4 int bound_arg_slot() { assert(is_bound(), ""); return _arg_slot; } 24.5 oop bound_arg_oop() { assert(is_bound(), ""); return BoundMethodHandle_argument_oop(); } 24.6 24.7 + methodHandle last_method() { assert(is_last(), ""); return _last_method; } 24.8 methodOop last_method_oop() { assert(is_last(), ""); return _last_method(); } 24.9 Bytecodes::Code last_invoke_code() { assert(is_last(), ""); return _last_invoke; } 24.10 24.11 @@ -181,6 +182,8 @@ 24.12 GrowableArray<ArgToken> _outgoing; // current outgoing parameter slots 24.13 int _outgoing_argc; // # non-empty outgoing slots 24.14 24.15 + vmIntrinsics::ID _return_conv; // Return conversion required by raw retypes. 24.16 + 24.17 // Replace a value of type old_type at slot (and maybe slot+1) with the new value. 24.18 // If old_type != T_VOID, remove the old argument at that point. 24.19 // If new_type != T_VOID, insert the new argument at that point. 24.20 @@ -219,7 +222,8 @@ 24.21 : _chain(root, THREAD), 24.22 _for_invokedynamic(for_invokedynamic), 24.23 _outgoing(THREAD, 10), 24.24 - _outgoing_argc(0) 24.25 + _outgoing_argc(0), 24.26 + _return_conv(vmIntrinsics::_none) 24.27 { 24.28 _local_index = for_invokedynamic ? 0 : 1; 24.29 } 24.30 @@ -228,6 +232,10 @@ 24.31 24.32 bool for_invokedynamic() const { return _for_invokedynamic; } 24.33 24.34 + vmIntrinsics::ID return_conv() const { return _return_conv; } 24.35 + void set_return_conv(vmIntrinsics::ID c) { _return_conv = c; } 24.36 + static vmIntrinsics::ID zero_return_conv() { return vmIntrinsics::_min; } 24.37 + 24.38 int new_local_index(BasicType bt) { 24.39 //int index = _for_invokedynamic ? _local_index : _local_index - 1; 24.40 int index = _local_index; 24.41 @@ -243,9 +251,9 @@ 24.42 virtual ArgToken make_oop_constant(oop con, TRAPS) = 0; 24.43 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS) = 0; 24.44 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS) = 0; 24.45 - virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS) = 0; 24.46 + virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS) = 0; 24.47 24.48 - // For make_invoke, the methodOop can be NULL if the intrinsic ID 24.49 + // For make_invoke, the methodHandle can be NULL if the intrinsic ID 24.50 // is something other than vmIntrinsics::_none. 24.51 24.52 // and in case anyone cares to related the previous actions to the chain: 24.53 @@ -280,6 +288,7 @@ 24.54 JavaValue _value; 24.55 Handle _handle; 24.56 Symbol* _sym; 24.57 + methodHandle _method; // pre-linkage 24.58 24.59 public: 24.60 // Constructor for oop types. 24.61 @@ -328,11 +337,21 @@ 24.62 jlong get_jlong() const { return _value.get_jlong(); } 24.63 jfloat get_jfloat() const { return _value.get_jfloat(); } 24.64 jdouble get_jdouble() const { return _value.get_jdouble(); } 24.65 + 24.66 + void set_linkage(methodHandle method) { 24.67 + assert(_method.is_null(), ""); 24.68 + _method = method; 24.69 + } 24.70 + bool has_linkage() const { return _method.not_null(); } 24.71 + methodHandle linkage() const { return _method; } 24.72 }; 24.73 24.74 // Fake constant pool. 24.75 GrowableArray<ConstantValue*> _constants; 24.76 24.77 + // Non-BCP classes that appear in associated MethodTypes (require special handling). 24.78 + GrowableArray<KlassHandle> _non_bcp_klasses; 24.79 + 24.80 // Accumulated compiler state: 24.81 GrowableArray<unsigned char> _bytecode; 24.82 24.83 @@ -368,15 +387,20 @@ 24.84 return _constants.append(cv); 24.85 } 24.86 24.87 - int cpool_oop_reference_put(int tag, int first_index, int second_index) { 24.88 + int cpool_oop_reference_put(int tag, int first_index, int second_index, methodHandle method) { 24.89 if (first_index == 0 && second_index == 0) return 0; 24.90 assert(first_index != 0 && second_index != 0, "no zero indexes"); 24.91 ConstantValue* cv = new ConstantValue(tag, first_index, second_index); 24.92 + if (method.not_null()) cv->set_linkage(method); 24.93 return _constants.append(cv); 24.94 } 24.95 24.96 int cpool_primitive_put(BasicType type, jvalue* con); 24.97 24.98 + bool check_non_bcp_klasses(Handle method_type, TRAPS); 24.99 + bool check_non_bcp_klass(klassOop klass, TRAPS); 24.100 + void record_non_bcp_klasses(); 24.101 + 24.102 int cpool_int_put(jint value) { 24.103 jvalue con; con.i = value; 24.104 return cpool_primitive_put(T_INT, &con); 24.105 @@ -403,11 +427,12 @@ 24.106 int cpool_klass_put(klassOop klass) { 24.107 return cpool_oop_put(JVM_CONSTANT_Class, klass); 24.108 } 24.109 - int cpool_methodref_put(int class_index, int name_and_type_index) { 24.110 - return cpool_oop_reference_put(JVM_CONSTANT_Methodref, class_index, name_and_type_index); 24.111 + int cpool_methodref_put(Bytecodes::Code op, int class_index, int name_and_type_index, methodHandle method) { 24.112 + int tag = (op == Bytecodes::_invokeinterface ? JVM_CONSTANT_InterfaceMethodref : JVM_CONSTANT_Methodref); 24.113 + return cpool_oop_reference_put(tag, class_index, name_and_type_index, method); 24.114 } 24.115 int cpool_name_and_type_put(int name_index, int signature_index) { 24.116 - return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index); 24.117 + return cpool_oop_reference_put(JVM_CONSTANT_NameAndType, name_index, signature_index, methodHandle()); 24.118 } 24.119 24.120 void emit_bc(Bytecodes::Code op, int index = 0, int args_size = -1); 24.121 @@ -428,7 +453,7 @@ 24.122 24.123 virtual ArgToken make_conversion(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& src, TRAPS); 24.124 virtual ArgToken make_fetch(BasicType type, klassOop tk, Bytecodes::Code op, const ArgToken& base, const ArgToken& offset, TRAPS); 24.125 - virtual ArgToken make_invoke(methodOop m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); 24.126 + virtual ArgToken make_invoke(methodHandle m, vmIntrinsics::ID iid, Bytecodes::Code op, bool tailcall, int argc, ArgToken* argv, TRAPS); 24.127 24.128 // Get a real constant pool. 24.129 constantPoolHandle get_constant_pool(TRAPS) const;
25.1 --- a/src/share/vm/prims/methodHandles.cpp Wed Jun 22 14:45:37 2011 -0700 25.2 +++ b/src/share/vm/prims/methodHandles.cpp Thu Jun 23 17:14:06 2011 -0700 25.3 @@ -24,12 +24,14 @@ 25.4 25.5 #include "precompiled.hpp" 25.6 #include "classfile/symbolTable.hpp" 25.7 +#include "compiler/compileBroker.hpp" 25.8 #include "interpreter/interpreter.hpp" 25.9 #include "interpreter/oopMapCache.hpp" 25.10 #include "memory/allocation.inline.hpp" 25.11 #include "memory/oopFactory.hpp" 25.12 #include "prims/methodHandles.hpp" 25.13 #include "prims/methodHandleWalk.hpp" 25.14 +#include "runtime/compilationPolicy.hpp" 25.15 #include "runtime/javaCalls.hpp" 25.16 #include "runtime/reflection.hpp" 25.17 #include "runtime/signature.hpp" 25.18 @@ -767,7 +769,9 @@ 25.19 m = NULL; 25.20 // try again with a different class loader... 25.21 } 25.22 - if (m != NULL) { 25.23 + if (m != NULL && 25.24 + m->is_method_handle_invoke() && 25.25 + java_lang_invoke_MethodType::equals(polymorphic_method_type(), m->method_handle_type())) { 25.26 int mods = (m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS); 25.27 java_lang_invoke_MemberName::set_vmtarget(mname(), m); 25.28 java_lang_invoke_MemberName::set_vmindex(mname(), m->vtable_index()); 25.29 @@ -986,6 +990,48 @@ 25.30 // This is for debugging and reflection. 25.31 oop MethodHandles::encode_target(Handle mh, int format, TRAPS) { 25.32 assert(java_lang_invoke_MethodHandle::is_instance(mh()), "must be a MH"); 25.33 + if (format == ETF_FORCE_DIRECT_HANDLE || 25.34 + format == ETF_COMPILE_DIRECT_HANDLE) { 25.35 + // Internal function for stress testing. 25.36 + Handle mt = java_lang_invoke_MethodHandle::type(mh()); 25.37 + int invocation_count = 10000; 25.38 + TempNewSymbol signature = java_lang_invoke_MethodType::as_signature(mt(), true, CHECK_NULL); 25.39 + bool omit_receiver_argument = true; 25.40 + MethodHandleCompiler mhc(mh, vmSymbols::invoke_name(), signature, invocation_count, omit_receiver_argument, CHECK_NULL); 25.41 + methodHandle m = mhc.compile(CHECK_NULL); 25.42 + if (StressMethodHandleWalk && Verbose || PrintMiscellaneous) { 25.43 + tty->print_cr("MethodHandleNatives.getTarget(%s)", 25.44 + format == ETF_FORCE_DIRECT_HANDLE ? "FORCE_DIRECT" : "COMPILE_DIRECT"); 25.45 + if (Verbose) { 25.46 + m->print_codes(); 25.47 + } 25.48 + } 25.49 + if (StressMethodHandleWalk) { 25.50 + InterpreterOopMap mask; 25.51 + OopMapCache::compute_one_oop_map(m, m->code_size() - 1, &mask); 25.52 + } 25.53 + if ((format == ETF_COMPILE_DIRECT_HANDLE || 25.54 + CompilationPolicy::must_be_compiled(m)) 25.55 + && !instanceKlass::cast(m->method_holder())->is_not_initialized() 25.56 + && CompilationPolicy::can_be_compiled(m)) { 25.57 + // Force compilation 25.58 + CompileBroker::compile_method(m, InvocationEntryBci, 25.59 + CompLevel_initial_compile, 25.60 + methodHandle(), 0, "MethodHandleNatives.getTarget", 25.61 + CHECK_NULL); 25.62 + } 25.63 + // Now wrap m in a DirectMethodHandle. 25.64 + instanceKlassHandle dmh_klass(THREAD, SystemDictionary::DirectMethodHandle_klass()); 25.65 + Handle dmh = dmh_klass->allocate_instance_handle(CHECK_NULL); 25.66 + JavaValue ignore_result(T_VOID); 25.67 + Symbol* init_name = vmSymbols::object_initializer_name(); 25.68 + Symbol* init_sig = vmSymbols::notifyGenericMethodType_signature(); 25.69 + JavaCalls::call_special(&ignore_result, dmh, 25.70 + SystemDictionaryHandles::MethodHandle_klass(), init_name, init_sig, 25.71 + java_lang_invoke_MethodHandle::type(mh()), CHECK_NULL); 25.72 + MethodHandles::init_DirectMethodHandle(dmh, m, false, CHECK_NULL); 25.73 + return dmh(); 25.74 + } 25.75 if (format == ETF_HANDLE_OR_METHOD_NAME) { 25.76 oop target = java_lang_invoke_MethodHandle::vmtarget(mh()); 25.77 if (target == NULL) { 25.78 @@ -1221,6 +1267,12 @@ 25.79 klassOop aklass_oop = SystemDictionary::resolve_or_null(name, loader, domain, CHECK); 25.80 if (aklass_oop != NULL) 25.81 aklass = KlassHandle(THREAD, aklass_oop); 25.82 + if (aklass.is_null() && 25.83 + pklass.not_null() && 25.84 + loader.is_null() && 25.85 + pklass->name() == name) 25.86 + // accept name equivalence here, since that's the best we can do 25.87 + aklass = pklass; 25.88 } 25.89 } else { 25.90 // for method handle invokers we don't look at the name in the signature 25.91 @@ -2654,6 +2706,17 @@ 25.92 } 25.93 InterpreterOopMap mask; 25.94 OopMapCache::compute_one_oop_map(m, m->code_size() - 1, &mask); 25.95 + // compile to object code if -Xcomp or WizardMode 25.96 + if ((WizardMode || 25.97 + CompilationPolicy::must_be_compiled(m)) 25.98 + && !instanceKlass::cast(m->method_holder())->is_not_initialized() 25.99 + && CompilationPolicy::can_be_compiled(m)) { 25.100 + // Force compilation 25.101 + CompileBroker::compile_method(m, InvocationEntryBci, 25.102 + CompLevel_initial_compile, 25.103 + methodHandle(), 0, "StressMethodHandleWalk", 25.104 + CHECK); 25.105 + } 25.106 } 25.107 } 25.108 25.109 @@ -2773,7 +2836,12 @@ 25.110 // Build a BMH on top of a DMH or another BMH: 25.111 MethodHandles::init_BoundMethodHandle(mh, target, argnum, CHECK); 25.112 } 25.113 - stress_method_handle_walk(mh, CHECK); 25.114 + 25.115 + if (StressMethodHandleWalk) { 25.116 + if (mh->klass() == SystemDictionary::BoundMethodHandle_klass()) 25.117 + stress_method_handle_walk(mh, CHECK); 25.118 + // else don't, since the subclass has not yet initialized its own fields 25.119 + } 25.120 } 25.121 JVM_END 25.122
26.1 --- a/src/share/vm/prims/methodHandles.hpp Wed Jun 22 14:45:37 2011 -0700 26.2 +++ b/src/share/vm/prims/methodHandles.hpp Thu Jun 23 17:14:06 2011 -0700 26.3 @@ -588,6 +588,8 @@ 26.4 ETF_DIRECT_HANDLE = 1, // ultimate method handle (will be a DMH, may be self) 26.5 ETF_METHOD_NAME = 2, // ultimate method as MemberName 26.6 ETF_REFLECT_METHOD = 3, // ultimate method as java.lang.reflect object (sans refClass) 26.7 + ETF_FORCE_DIRECT_HANDLE = 64, 26.8 + ETF_COMPILE_DIRECT_HANDLE = 65, 26.9 26.10 // ad hoc constants 26.11 OP_ROT_ARGS_DOWN_LIMIT_BIAS = -1