--- 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<KlassHandle>* 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<KlassHandle>(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