diff -r 50c604cb0d5f -r 30245956af37 hotspot/src/share/vm/oops/methodOop.cpp --- a/hotspot/src/share/vm/oops/methodOop.cpp Mon Jul 23 13:04:59 2012 -0700 +++ b/hotspot/src/share/vm/oops/methodOop.cpp Tue Jul 24 10:51:00 2012 -0700 @@ -40,7 +40,7 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" -#include "prims/methodHandleWalk.hpp" +#include "prims/methodHandles.hpp" #include "prims/nativeLookup.hpp" #include "runtime/arguments.hpp" #include "runtime/compilationPolicy.hpp" @@ -552,6 +552,7 @@ void methodOopDesc::set_native_function(address function, bool post_event_flag) { assert(function != NULL, "use clear_native_function to unregister natives"); + assert(!is_method_handle_intrinsic() || function == SharedRuntime::native_method_throw_unsatisfied_link_error_entry(), ""); address* native_function = native_function_addr(); // We can see racers trying to place the same native function into place. Once @@ -581,12 +582,14 @@ bool methodOopDesc::has_native_function() const { + assert(!is_method_handle_intrinsic(), ""); address func = native_function(); return (func != NULL && func != SharedRuntime::native_method_throw_unsatisfied_link_error_entry()); } void methodOopDesc::clear_native_function() { + // Note: is_method_handle_intrinsic() is allowed here. set_native_function( SharedRuntime::native_method_throw_unsatisfied_link_error_entry(), !native_bind_event_is_interesting); @@ -606,10 +609,6 @@ bool methodOopDesc::is_not_compilable(int comp_level) const { - if (is_method_handle_invoke()) { - // compilers must recognize this method specially, or not at all - return true; - } if (number_of_breakpoints() > 0) { return true; } @@ -709,7 +708,7 @@ assert(entry != NULL, "interpreter entry must be non-null"); // Sets both _i2i_entry and _from_interpreted_entry set_interpreter_entry(entry); - if (is_native() && !is_method_handle_invoke()) { + if (is_native() && !is_method_handle_intrinsic()) { set_native_function( SharedRuntime::native_method_throw_unsatisfied_link_error_entry(), !native_bind_event_is_interesting); @@ -797,13 +796,13 @@ OrderAccess::storestore(); #ifdef SHARK mh->_from_interpreted_entry = code->insts_begin(); -#else +#else //!SHARK mh->_from_compiled_entry = code->verified_entry_point(); OrderAccess::storestore(); // Instantly compiled code can execute. - mh->_from_interpreted_entry = mh->get_i2c_entry(); -#endif // SHARK - + if (!mh->is_method_handle_intrinsic()) + mh->_from_interpreted_entry = mh->get_i2c_entry(); +#endif //!SHARK } @@ -855,106 +854,51 @@ return false; } -bool methodOopDesc::is_method_handle_invoke_name(vmSymbols::SID name_sid) { - switch (name_sid) { - case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name): - return true; - } - if (AllowInvokeGeneric - && name_sid == vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name)) - return true; - return false; -} - // Constant pool structure for invoke methods: enum { - _imcp_invoke_name = 1, // utf8: 'invokeExact' or 'invokeGeneric' + _imcp_invoke_name = 1, // utf8: 'invokeExact', etc. _imcp_invoke_signature, // utf8: (variable Symbol*) - _imcp_method_type_value, // string: (variable java/lang/invoke/MethodType, sic) _imcp_limit }; -oop methodOopDesc::method_handle_type() const { - if (!is_method_handle_invoke()) { assert(false, "caller resp."); return NULL; } - oop mt = constants()->resolved_string_at(_imcp_method_type_value); - assert(mt->klass() == SystemDictionary::MethodType_klass(), ""); - return mt; -} - -jint* methodOopDesc::method_type_offsets_chain() { - static jint pchase[] = { -1, -1, -1, -1 }; - if (pchase[0] == -1) { - jint step0 = in_bytes(const_offset()); - jint step1 = in_bytes(constMethodOopDesc::constants_offset()); - jint step2 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize; - // do this in reverse to avoid races: - OrderAccess::release_store(&pchase[2], step2); - OrderAccess::release_store(&pchase[1], step1); - OrderAccess::release_store(&pchase[0], step0); - } - return pchase; +// Test if this method is an MH adapter frame generated by Java code. +// Cf. java/lang/invoke/InvokerBytecodeGenerator +bool methodOopDesc::is_compiled_lambda_form() const { + return intrinsic_id() == vmIntrinsics::_compiledLambdaForm; } -//------------------------------------------------------------------------------ -// methodOopDesc::is_method_handle_adapter -// -// Tests if this method is an internal adapter frame from the -// MethodHandleCompiler. -// Must be consistent with MethodHandleCompiler::get_method_oop(). -bool methodOopDesc::is_method_handle_adapter() const { - if (is_synthetic() && - !is_native() && // has code from MethodHandleCompiler - is_method_handle_invoke_name(name()) && - MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder())) { - assert(!is_method_handle_invoke(), "disjoint"); - return true; - } else { - return false; - } +// Test if this method is an internal MH primitive method. +bool methodOopDesc::is_method_handle_intrinsic() const { + vmIntrinsics::ID iid = intrinsic_id(); + return (MethodHandles::is_signature_polymorphic(iid) && + MethodHandles::is_signature_polymorphic_intrinsic(iid)); } -methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, - Symbol* name, - Symbol* signature, - Handle method_type, TRAPS) { +bool methodOopDesc::has_member_arg() const { + vmIntrinsics::ID iid = intrinsic_id(); + return (MethodHandles::is_signature_polymorphic(iid) && + MethodHandles::has_member_arg(iid)); +} + +// Make an instance of a signature-polymorphic internal MH primitive. +methodHandle methodOopDesc::make_method_handle_intrinsic(vmIntrinsics::ID iid, + Symbol* signature, + TRAPS) { ResourceMark rm; methodHandle empty; - assert(holder() == SystemDictionary::MethodHandle_klass(), - "must be a JSR 292 magic type"); - + KlassHandle holder = SystemDictionary::MethodHandle_klass(); + Symbol* name = MethodHandles::signature_polymorphic_intrinsic_name(iid); + assert(iid == MethodHandles::signature_polymorphic_name_id(name), ""); if (TraceMethodHandles) { - tty->print("Creating invoke method for "); - signature->print_value(); - tty->cr(); + tty->print_cr("make_method_handle_intrinsic MH.%s%s", name->as_C_string(), signature->as_C_string()); } // invariant: cp->symbol_at_put is preceded by a refcount increment (more usually a lookup) name->increment_refcount(); signature->increment_refcount(); - // record non-BCP method types in the constant pool - GrowableArray* extra_klasses = NULL; - for (int i = -1, len = java_lang_invoke_MethodType::ptype_count(method_type()); i < len; i++) { - oop ptype = (i == -1 - ? java_lang_invoke_MethodType::rtype(method_type()) - : java_lang_invoke_MethodType::ptype(method_type(), i)); - klassOop klass = check_non_bcp_klass(java_lang_Class::as_klassOop(ptype)); - if (klass != NULL) { - if (extra_klasses == NULL) - extra_klasses = new GrowableArray(len+1); - bool dup = false; - for (int j = 0; j < extra_klasses->length(); j++) { - if (extra_klasses->at(j) == klass) { dup = true; break; } - } - if (!dup) - extra_klasses->append(KlassHandle(THREAD, klass)); - } - } - - int extra_klass_count = (extra_klasses == NULL ? 0 : extra_klasses->length()); - int cp_length = _imcp_limit + extra_klass_count; + int cp_length = _imcp_limit; constantPoolHandle cp; { constantPoolOop cp_oop = oopFactory::new_constantPool(cp_length, IsSafeConc, CHECK_(empty)); @@ -962,19 +906,17 @@ } cp->symbol_at_put(_imcp_invoke_name, name); cp->symbol_at_put(_imcp_invoke_signature, signature); - cp->string_at_put(_imcp_method_type_value, Universe::the_null_string()); - for (int j = 0; j < extra_klass_count; j++) { - KlassHandle klass = extra_klasses->at(j); - cp->klass_at_put(_imcp_limit + j, klass()); - } cp->set_preresolution(); cp->set_pool_holder(holder()); - // set up the fancy stuff: - cp->pseudo_string_at_put(_imcp_method_type_value, method_type()); + // decide on access bits: public or not? + int flags_bits = (JVM_ACC_NATIVE | JVM_ACC_SYNTHETIC | JVM_ACC_FINAL); + bool must_be_static = MethodHandles::is_signature_polymorphic_static(iid); + if (must_be_static) flags_bits |= JVM_ACC_STATIC; + assert((flags_bits & JVM_ACC_PUBLIC) == 0, "do not expose these methods"); + methodHandle m; { - int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL); methodOop m_oop = oopFactory::new_method(0, accessFlags_from(flags_bits), 0, 0, 0, 0, IsSafeConc, CHECK_(empty)); m = methodHandle(THREAD, m_oop); @@ -982,33 +924,26 @@ m->set_constants(cp()); m->set_name_index(_imcp_invoke_name); m->set_signature_index(_imcp_invoke_signature); - assert(is_method_handle_invoke_name(m->name()), ""); + assert(MethodHandles::is_signature_polymorphic_name(m->name()), ""); assert(m->signature() == signature, ""); - assert(m->is_method_handle_invoke(), ""); #ifdef CC_INTERP ResultTypeFinder rtf(signature); m->set_result_index(rtf.type()); #endif m->compute_size_of_parameters(THREAD); m->init_intrinsic_id(); - assert(m->intrinsic_id() == vmIntrinsics::_invokeExact || - m->intrinsic_id() == vmIntrinsics::_invokeGeneric, "must be an invoker"); + assert(m->is_method_handle_intrinsic(), ""); +#ifdef ASSERT + if (!MethodHandles::is_signature_polymorphic(m->intrinsic_id())) m->print(); + assert(MethodHandles::is_signature_polymorphic(m->intrinsic_id()), "must be an invoker"); + assert(m->intrinsic_id() == iid, "correctly predicted iid"); +#endif //ASSERT // Finally, set up its entry points. - assert(m->method_handle_type() == method_type(), ""); assert(m->can_be_statically_bound(), ""); m->set_vtable_index(methodOopDesc::nonvirtual_vtable_index); m->link_method(m, CHECK_(empty)); -#ifdef ASSERT - // Make sure the pointer chase works. - address p = (address) m(); - for (jint* pchase = method_type_offsets_chain(); (*pchase) != -1; pchase++) { - p = *(address*)(p + (*pchase)); - } - assert((oop)p == method_type(), "pointer chase is correct"); -#endif - if (TraceMethodHandles && (Verbose || WizardMode)) m->print_on(tty); @@ -1025,7 +960,7 @@ } -methodHandle methodOopDesc:: clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length, +methodHandle methodOopDesc::clone_with_new_data(methodHandle m, u_char* new_code, int new_code_length, u_char* new_compressed_linenumber_table, int new_compressed_linenumber_size, TRAPS) { // Code below does not work for native methods - they should never get rewritten anyway assert(!m->is_native(), "cannot rewrite native methods"); @@ -1142,7 +1077,9 @@ // ditto for method and signature: vmSymbols::SID name_id = vmSymbols::find_sid(name()); - if (name_id == vmSymbols::NO_SID) return; + if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle) + && name_id == vmSymbols::NO_SID) + return; vmSymbols::SID sig_id = vmSymbols::find_sid(signature()); if (klass_id != vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle) && sig_id == vmSymbols::NO_SID) return; @@ -1171,21 +1108,10 @@ // Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*. case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_MethodHandle): - if (is_static() || !is_native()) break; - switch (name_id) { - case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name): - if (!AllowInvokeGeneric) break; - case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name): - id = vmIntrinsics::_invokeGeneric; - break; - case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name): - id = vmIntrinsics::_invokeExact; - break; - } - break; - case vmSymbols::VM_SYMBOL_ENUM_NAME(java_lang_invoke_InvokeDynamic): - if (!is_static() || !is_native()) break; - id = vmIntrinsics::_invokeDynamic; + if (!is_native()) break; + id = MethodHandles::signature_polymorphic_name_id(method_holder(), name()); + if (is_static() != MethodHandles::is_signature_polymorphic_static(id)) + id = vmIntrinsics::_none; break; } @@ -1198,6 +1124,12 @@ // These two methods are static since a GC may move the methodOopDesc bool methodOopDesc::load_signature_classes(methodHandle m, TRAPS) { + if (THREAD->is_Compiler_thread()) { + // There is nothing useful this routine can do from within the Compile thread. + // Hopefully, the signature contains only well-known classes. + // We could scan for this and return true/false, but the caller won't care. + return false; + } bool sig_is_loaded = true; Handle class_loader(THREAD, instanceKlass::cast(m->method_holder())->class_loader()); Handle protection_domain(THREAD, Klass::cast(m->method_holder())->protection_domain()); @@ -1251,6 +1183,8 @@ #endif name()->print_symbol_on(st); if (WizardMode) signature()->print_symbol_on(st); + else if (MethodHandles::is_signature_polymorphic(intrinsic_id())) + MethodHandles::print_as_basic_type_signature_on(st, signature(), true); } // This is only done during class loading, so it is OK to assume method_idnum matches the methods() array