提交 0a144141 编写于 作者: J jrose

6939134: JSR 292 adjustments to method handle invocation

Summary: split MethodHandle.invoke into invokeExact and invokeGeneric; also clean up JVM-to-Java interfaces
Reviewed-by: twisti
上级 f72f23cb
...@@ -290,6 +290,21 @@ void trace_method_handle_stub(const char* adaptername, ...@@ -290,6 +290,21 @@ void trace_method_handle_stub(const char* adaptername,
} }
#endif // PRODUCT #endif // PRODUCT
// which conversion op types are implemented here?
int MethodHandles::adapter_conversion_ops_supported_mask() {
return ((1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY)
|(1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW)
|(1<<sun_dyn_AdapterMethodHandle::OP_CHECK_CAST)
|(1<<sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM)
|(1<<sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM)
|(1<<sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS)
|(1<<sun_dyn_AdapterMethodHandle::OP_ROT_ARGS)
|(1<<sun_dyn_AdapterMethodHandle::OP_DUP_ARGS)
|(1<<sun_dyn_AdapterMethodHandle::OP_DROP_ARGS)
//|(1<<sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG!
);
// FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// MethodHandles::generate_method_handle_stub // MethodHandles::generate_method_handle_stub
......
...@@ -262,6 +262,22 @@ void trace_method_handle_stub(const char* adaptername, ...@@ -262,6 +262,22 @@ void trace_method_handle_stub(const char* adaptername,
} }
#endif //PRODUCT #endif //PRODUCT
// which conversion op types are implemented here?
int MethodHandles::adapter_conversion_ops_supported_mask() {
return ((1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_ONLY)
|(1<<sun_dyn_AdapterMethodHandle::OP_RETYPE_RAW)
|(1<<sun_dyn_AdapterMethodHandle::OP_CHECK_CAST)
|(1<<sun_dyn_AdapterMethodHandle::OP_PRIM_TO_PRIM)
|(1<<sun_dyn_AdapterMethodHandle::OP_REF_TO_PRIM)
|(1<<sun_dyn_AdapterMethodHandle::OP_SWAP_ARGS)
|(1<<sun_dyn_AdapterMethodHandle::OP_ROT_ARGS)
|(1<<sun_dyn_AdapterMethodHandle::OP_DUP_ARGS)
|(1<<sun_dyn_AdapterMethodHandle::OP_DROP_ARGS)
//|(1<<sun_dyn_AdapterMethodHandle::OP_SPREAD_ARGS) //BUG!
);
// FIXME: MethodHandlesTest gets a crash if we enable OP_SPREAD_ARGS.
}
// Generate an "entry" field for a method handle. // Generate an "entry" field for a method handle.
// This determines how the method handle will respond to calls. // This determines how the method handle will respond to calls.
void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) { void MethodHandles::generate_method_handle_stub(MacroAssembler* _masm, MethodHandles::EntryKind ek) {
......
...@@ -1062,7 +1062,7 @@ class LIR_OpJavaCall: public LIR_OpCall { ...@@ -1062,7 +1062,7 @@ class LIR_OpJavaCall: public LIR_OpCall {
is_invokedynamic() // An invokedynamic is always a MethodHandle call site. is_invokedynamic() // An invokedynamic is always a MethodHandle call site.
|| ||
(method()->holder()->name() == ciSymbol::java_dyn_MethodHandle() && (method()->holder()->name() == ciSymbol::java_dyn_MethodHandle() &&
method()->name() == ciSymbol::invoke_name()); methodOopDesc::is_method_handle_invoke_name(method()->name()->sid()));
} }
intptr_t vtable_offset() const { intptr_t vtable_offset() const {
......
...@@ -731,26 +731,29 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool, ...@@ -731,26 +731,29 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
// ciEnv::get_fake_invokedynamic_method_impl // ciEnv::get_fake_invokedynamic_method_impl
ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool, ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
int index, Bytecodes::Code bc) { int index, Bytecodes::Code bc) {
// Compare the following logic with InterpreterRuntime::resolve_invokedynamic.
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic"); assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
// Get the CallSite from the constant pool cache. bool is_resolved = cpool->cache()->main_entry_at(index)->is_resolved(bc);
ConstantPoolCacheEntry* cpc_entry = cpool->cache()->secondary_entry_at(index); if (is_resolved && (oop) cpool->cache()->secondary_entry_at(index)->f1() == NULL)
assert(cpc_entry != NULL && cpc_entry->is_secondary_entry(), "sanity"); // FIXME: code generation could allow for null (unlinked) call site
Handle call_site = cpc_entry->f1(); is_resolved = false;
// Call site might not be linked yet. // Call site might not be resolved yet. We could create a real invoker method from the
if (call_site.is_null()) { // compiler, but it is simpler to stop the code path here with an unlinked method.
if (!is_resolved) {
ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass(); ciInstanceKlass* mh_klass = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol(); ciSymbol* sig_sym = get_object(cpool->signature_ref_at(index))->as_symbol();
return get_unloaded_method(mh_klass, ciSymbol::invoke_name(), sig_sym); return get_unloaded_method(mh_klass, ciSymbol::invokeExact_name(), sig_sym);
} }
// Get the methodOop from the CallSite. // Get the invoker methodOop from the constant pool.
methodOop method_oop = (methodOop) java_dyn_CallSite::vmmethod(call_site()); intptr_t f2_value = cpool->cache()->main_entry_at(index)->f2();
assert(method_oop != NULL, "sanity"); methodOop signature_invoker = methodOop(f2_value);
assert(method_oop->is_method_handle_invoke(), "consistent"); assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
"correct result from LinkResolver::resolve_invokedynamic");
return get_object(method_oop)->as_method(); return get_object(signature_invoker)->as_method();
} }
......
...@@ -103,7 +103,7 @@ void ciObjectFactory::init_shared_objects() { ...@@ -103,7 +103,7 @@ void ciObjectFactory::init_shared_objects() {
for (i = vmSymbols::FIRST_SID; i < vmSymbols::SID_LIMIT; i++) { for (i = vmSymbols::FIRST_SID; i < vmSymbols::SID_LIMIT; i++) {
symbolHandle sym_handle = vmSymbolHandles::symbol_handle_at((vmSymbols::SID) i); symbolHandle sym_handle = vmSymbolHandles::symbol_handle_at((vmSymbols::SID) i);
assert(vmSymbols::find_sid(sym_handle()) == i, "1-1 mapping"); assert(vmSymbols::find_sid(sym_handle()) == i, "1-1 mapping");
ciSymbol* sym = new (_arena) ciSymbol(sym_handle); ciSymbol* sym = new (_arena) ciSymbol(sym_handle, (vmSymbols::SID) i);
init_ident_of(sym); init_ident_of(sym);
_shared_ci_symbols[i] = sym; _shared_ci_symbols[i] = sym;
} }
...@@ -273,7 +273,8 @@ ciObject* ciObjectFactory::create_new_object(oop o) { ...@@ -273,7 +273,8 @@ ciObject* ciObjectFactory::create_new_object(oop o) {
if (o->is_symbol()) { if (o->is_symbol()) {
symbolHandle h_o(THREAD, (symbolOop)o); symbolHandle h_o(THREAD, (symbolOop)o);
return new (arena()) ciSymbol(h_o); assert(vmSymbols::find_sid(h_o()) == vmSymbols::NO_SID, "");
return new (arena()) ciSymbol(h_o, vmSymbols::NO_SID);
} else if (o->is_klass()) { } else if (o->is_klass()) {
KlassHandle h_k(THREAD, (klassOop)o); KlassHandle h_k(THREAD, (klassOop)o);
Klass* k = ((klassOop)o)->klass_part(); Klass* k = ((klassOop)o)->klass_part();
......
...@@ -29,7 +29,17 @@ ...@@ -29,7 +29,17 @@
// ciSymbol::ciSymbol // ciSymbol::ciSymbol
// //
// Preallocated handle variant. Used with handles from vmSymboHandles. // Preallocated handle variant. Used with handles from vmSymboHandles.
ciSymbol::ciSymbol(symbolHandle h_s) : ciObject(h_s) { ciSymbol::ciSymbol(symbolHandle h_s, vmSymbols::SID sid)
: ciObject(h_s), _sid(sid)
{
assert(sid_ok(), "must be in vmSymbols");
}
// Normal case for non-famous symbols.
ciSymbol::ciSymbol(symbolOop s)
: ciObject(s), _sid(vmSymbols::NO_SID)
{
assert(sid_ok(), "must not be in vmSymbols");
} }
// ciSymbol // ciSymbol
......
...@@ -36,8 +36,11 @@ class ciSymbol : public ciObject { ...@@ -36,8 +36,11 @@ class ciSymbol : public ciObject {
friend class ciObjArrayKlass; friend class ciObjArrayKlass;
private: private:
ciSymbol(symbolOop s) : ciObject(s) {} const vmSymbols::SID _sid;
ciSymbol(symbolHandle s); // for use with vmSymbolHandles DEBUG_ONLY( bool sid_ok() { return vmSymbols::find_sid(get_symbolOop()) == _sid; } )
ciSymbol(symbolOop s); // normal case, for symbols not mentioned in vmSymbols
ciSymbol(symbolHandle s, vmSymbols::SID sid); // for use with vmSymbolHandles
symbolOop get_symbolOop() const { return (symbolOop)get_oop(); } symbolOop get_symbolOop() const { return (symbolOop)get_oop(); }
...@@ -52,6 +55,9 @@ private: ...@@ -52,6 +55,9 @@ private:
static ciSymbol* make_impl(const char* s); static ciSymbol* make_impl(const char* s);
public: public:
// The enumeration ID from vmSymbols, or vmSymbols::NO_SID if none.
vmSymbols::SID sid() const { return _sid; }
// The text of the symbol as a null-terminated utf8 string. // The text of the symbol as a null-terminated utf8 string.
const char* as_utf8(); const char* as_utf8();
int utf8_length(); int utf8_length();
......
...@@ -1837,7 +1837,8 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf ...@@ -1837,7 +1837,8 @@ methodHandle ClassFileParser::parse_method(constantPoolHandle cp, bool is_interf
_has_vanilla_constructor = true; _has_vanilla_constructor = true;
} }
if (EnableMethodHandles && m->is_method_handle_invoke()) { if (EnableMethodHandles && (m->is_method_handle_invoke() ||
m->is_method_handle_adapter())) {
THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(), THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(),
"Method handle invokers must be defined internally to the VM", nullHandle); "Method handle invokers must be defined internally to the VM", nullHandle);
} }
......
...@@ -561,10 +561,11 @@ SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t, ...@@ -561,10 +561,11 @@ SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t,
SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash, SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
symbolHandle sym) { symbolHandle sym,
assert(index == index_for(sym), "incorrect index?"); intptr_t sym_mode) {
assert(index == index_for(sym, sym_mode), "incorrect index?");
for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) { for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
if (p->hash() == hash && p->symbol() == sym()) { if (p->hash() == hash && p->symbol() == sym() && p->symbol_mode() == sym_mode) {
return p; return p;
} }
} }
...@@ -573,12 +574,12 @@ SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int has ...@@ -573,12 +574,12 @@ SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int has
SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash, SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
symbolHandle sym) { symbolHandle sym, intptr_t sym_mode) {
assert_locked_or_safepoint(SystemDictionary_lock); assert_locked_or_safepoint(SystemDictionary_lock);
assert(index == index_for(sym), "incorrect index?"); assert(index == index_for(sym, sym_mode), "incorrect index?");
assert(find_entry(index, hash, sym) == NULL, "no double entry"); assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry");
SymbolPropertyEntry* p = new_entry(hash, sym()); SymbolPropertyEntry* p = new_entry(hash, sym(), sym_mode);
Hashtable::add_entry(index, p); Hashtable::add_entry(index, p);
return p; return p;
} }
......
...@@ -223,12 +223,16 @@ class DictionaryEntry : public HashtableEntry { ...@@ -223,12 +223,16 @@ class DictionaryEntry : public HashtableEntry {
class SymbolPropertyEntry : public HashtableEntry { class SymbolPropertyEntry : public HashtableEntry {
friend class VMStructs; friend class VMStructs;
private: private:
intptr_t _symbol_mode; // secondary key
oop _property_oop; oop _property_oop;
address _property_data; address _property_data;
public: public:
symbolOop symbol() const { return (symbolOop) literal(); } symbolOop symbol() const { return (symbolOop) literal(); }
intptr_t symbol_mode() const { return _symbol_mode; }
void set_symbol_mode(intptr_t m) { _symbol_mode = m; }
oop property_oop() const { return _property_oop; } oop property_oop() const { return _property_oop; }
void set_property_oop(oop p) { _property_oop = p; } void set_property_oop(oop p) { _property_oop = p; }
...@@ -248,6 +252,7 @@ class SymbolPropertyEntry : public HashtableEntry { ...@@ -248,6 +252,7 @@ class SymbolPropertyEntry : public HashtableEntry {
void print_on(outputStream* st) const { void print_on(outputStream* st) const {
symbol()->print_value_on(st); symbol()->print_value_on(st);
st->print("/mode="INTX_FORMAT, symbol_mode());
st->print(" -> "); st->print(" -> ");
bool printed = false; bool printed = false;
if (property_oop() != NULL) { if (property_oop() != NULL) {
...@@ -285,8 +290,9 @@ private: ...@@ -285,8 +290,9 @@ private:
ShouldNotReachHere(); ShouldNotReachHere();
} }
SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol) { SymbolPropertyEntry* new_entry(unsigned int hash, symbolOop symbol, intptr_t symbol_mode) {
SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol); SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable::new_entry(hash, symbol);
entry->set_symbol_mode(symbol_mode);
entry->set_property_oop(NULL); entry->set_property_oop(NULL);
entry->set_property_data(NULL); entry->set_property_data(NULL);
return entry; return entry;
...@@ -300,16 +306,20 @@ public: ...@@ -300,16 +306,20 @@ public:
Hashtable::free_entry(entry); Hashtable::free_entry(entry);
} }
unsigned int compute_hash(symbolHandle sym) { unsigned int compute_hash(symbolHandle sym, intptr_t symbol_mode) {
// Use the regular identity_hash. // Use the regular identity_hash.
return Hashtable::compute_hash(sym); return Hashtable::compute_hash(sym) ^ symbol_mode;
}
int index_for(symbolHandle name, intptr_t symbol_mode) {
return hash_to_index(compute_hash(name, symbol_mode));
} }
// need not be locked; no state change // need not be locked; no state change
SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name); SymbolPropertyEntry* find_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode);
// must be done under SystemDictionary_lock // must be done under SystemDictionary_lock
SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name); SymbolPropertyEntry* add_entry(int index, unsigned int hash, symbolHandle name, intptr_t name_mode);
// GC support // GC support
void oops_do(OopClosure* f); void oops_do(OopClosure* f);
......
...@@ -2446,24 +2446,20 @@ oop java_dyn_MethodTypeForm::erasedType(oop mtform) { ...@@ -2446,24 +2446,20 @@ oop java_dyn_MethodTypeForm::erasedType(oop mtform) {
// Support for java_dyn_CallSite // Support for java_dyn_CallSite
int java_dyn_CallSite::_type_offset;
int java_dyn_CallSite::_target_offset; int java_dyn_CallSite::_target_offset;
int java_dyn_CallSite::_vmmethod_offset; int java_dyn_CallSite::_caller_method_offset;
int java_dyn_CallSite::_caller_bci_offset;
void java_dyn_CallSite::compute_offsets() { void java_dyn_CallSite::compute_offsets() {
if (!EnableInvokeDynamic) return; if (!EnableInvokeDynamic) return;
klassOop k = SystemDictionary::CallSite_klass(); klassOop k = SystemDictionary::CallSite_klass();
if (k != NULL) { if (k != NULL) {
compute_offset(_type_offset, k, vmSymbols::type_name(), vmSymbols::java_dyn_MethodType_signature(), true); compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature());
compute_offset(_target_offset, k, vmSymbols::target_name(), vmSymbols::java_dyn_MethodHandle_signature(), true); compute_offset(_caller_method_offset, k, vmSymbols::vmmethod_name(), vmSymbols::sun_dyn_MemberName_signature());
compute_offset(_vmmethod_offset, k, vmSymbols::vmmethod_name(), vmSymbols::object_signature(), true); compute_offset(_caller_bci_offset, k, vmSymbols::vmindex_name(), vmSymbols::int_signature());
} }
} }
oop java_dyn_CallSite::type(oop site) {
return site->obj_field(_type_offset);
}
oop java_dyn_CallSite::target(oop site) { oop java_dyn_CallSite::target(oop site) {
return site->obj_field(_target_offset); return site->obj_field(_target_offset);
} }
...@@ -2472,12 +2468,20 @@ void java_dyn_CallSite::set_target(oop site, oop target) { ...@@ -2472,12 +2468,20 @@ void java_dyn_CallSite::set_target(oop site, oop target) {
site->obj_field_put(_target_offset, target); site->obj_field_put(_target_offset, target);
} }
oop java_dyn_CallSite::vmmethod(oop site) { oop java_dyn_CallSite::caller_method(oop site) {
return site->obj_field(_vmmethod_offset); return site->obj_field(_caller_method_offset);
}
void java_dyn_CallSite::set_caller_method(oop site, oop ref) {
site->obj_field_put(_caller_method_offset, ref);
}
jint java_dyn_CallSite::caller_bci(oop site) {
return site->int_field(_caller_bci_offset);
} }
void java_dyn_CallSite::set_vmmethod(oop site, oop ref) { void java_dyn_CallSite::set_caller_bci(oop site, jint bci) {
site->obj_field_put(_vmmethod_offset, ref); site->int_field_put(_caller_bci_offset, bci);
} }
......
...@@ -1068,21 +1068,22 @@ class java_dyn_CallSite: AllStatic { ...@@ -1068,21 +1068,22 @@ class java_dyn_CallSite: AllStatic {
friend class JavaClasses; friend class JavaClasses;
private: private:
static int _type_offset;
static int _target_offset; static int _target_offset;
static int _vmmethod_offset; static int _caller_method_offset;
static int _caller_bci_offset;
static void compute_offsets(); static void compute_offsets();
public: public:
// Accessors // Accessors
static oop type(oop site);
static oop target(oop site); static oop target(oop site);
static void set_target(oop site, oop target); static void set_target(oop site, oop target);
static oop vmmethod(oop site); static oop caller_method(oop site);
static void set_vmmethod(oop site, oop ref); static void set_caller_method(oop site, oop ref);
static jint caller_bci(oop site);
static void set_caller_bci(oop site, jint bci);
// Testers // Testers
static bool is_subclass(klassOop klass) { static bool is_subclass(klassOop klass) {
...@@ -1094,8 +1095,8 @@ public: ...@@ -1094,8 +1095,8 @@ public:
// Accessors for code generation: // Accessors for code generation:
static int target_offset_in_bytes() { return _target_offset; } static int target_offset_in_bytes() { return _target_offset; }
static int type_offset_in_bytes() { return _type_offset; } static int caller_method_offset_in_bytes() { return _caller_method_offset; }
static int vmmethod_offset_in_bytes() { return _vmmethod_offset; } static int caller_bci_offset_in_bytes() { return _caller_bci_offset; }
}; };
......
...@@ -2341,7 +2341,8 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature, ...@@ -2341,7 +2341,8 @@ char* SystemDictionary::check_signature_loaders(symbolHandle signature,
} }
methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, methodOop SystemDictionary::find_method_handle_invoke(symbolHandle name,
symbolHandle signature,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS) { TRAPS) {
...@@ -2352,26 +2353,28 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, ...@@ -2352,26 +2353,28 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
// create this side table lazily // create this side table lazily
_invoke_method_table = new SymbolPropertyTable(_invoke_method_size); _invoke_method_table = new SymbolPropertyTable(_invoke_method_size);
} }
unsigned int hash = invoke_method_table()->compute_hash(signature); vmSymbols::SID name_id = vmSymbols::find_sid(name());
assert(name_id != vmSymbols::NO_SID, "must be a known name");
unsigned int hash = invoke_method_table()->compute_hash(signature, name_id);
int index = invoke_method_table()->hash_to_index(hash); int index = invoke_method_table()->hash_to_index(hash);
SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature); SymbolPropertyEntry* spe = invoke_method_table()->find_entry(index, hash, signature, name_id);
if (spe == NULL || spe->property_oop() == NULL) { if (spe == NULL || spe->property_oop() == NULL) {
// Must create lots of stuff here, but outside of the SystemDictionary lock. // Must create lots of stuff here, but outside of the SystemDictionary lock.
if (THREAD->is_Compiler_thread()) if (THREAD->is_Compiler_thread())
return NULL; // do not attempt from within compiler return NULL; // do not attempt from within compiler
Handle mt = compute_method_handle_type(signature(), Handle mt = find_method_handle_type(signature(),
class_loader, protection_domain, class_loader, protection_domain,
CHECK_NULL); CHECK_NULL);
KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass(); KlassHandle mh_klass = SystemDictionaryHandles::MethodHandle_klass();
methodHandle m = methodOopDesc::make_invoke_method(mh_klass, signature, methodHandle m = methodOopDesc::make_invoke_method(mh_klass, name, signature,
mt, CHECK_NULL); mt, CHECK_NULL);
// Now grab the lock. We might have to throw away the new method, // 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. // if a racing thread has managed to install one at the same time.
{ {
MutexLocker ml(SystemDictionary_lock, Thread::current()); MutexLocker ml(SystemDictionary_lock, Thread::current());
spe = invoke_method_table()->find_entry(index, hash, signature); spe = invoke_method_table()->find_entry(index, hash, signature, name_id);
if (spe == NULL) if (spe == NULL)
spe = invoke_method_table()->add_entry(index, hash, signature); spe = invoke_method_table()->add_entry(index, hash, signature, name_id);
if (spe->property_oop() == NULL) if (spe->property_oop() == NULL)
spe->set_property_oop(m()); spe->set_property_oop(m());
} }
...@@ -2385,10 +2388,10 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature, ...@@ -2385,10 +2388,10 @@ methodOop SystemDictionary::find_method_handle_invoke(symbolHandle signature,
// signature, as interpreted relative to the given class loader. // signature, as interpreted relative to the given class loader.
// Because of class loader constraints, all method handle usage must be // Because of class loader constraints, all method handle usage must be
// consistent with this loader. // consistent with this loader.
Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, Handle SystemDictionary::find_method_handle_type(symbolHandle signature,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS) { TRAPS) {
Handle empty; Handle empty;
int npts = ArgumentCount(signature()).size(); int npts = ArgumentCount(signature()).size();
objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty)); objArrayHandle pts = oopFactory::new_objArray(SystemDictionary::Class_klass(), npts, CHECK_(empty));
...@@ -2413,16 +2416,14 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, ...@@ -2413,16 +2416,14 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
} }
assert(arg == npts, ""); assert(arg == npts, "");
// call MethodType java.dyn.MethodType::makeImpl(Class rt, Class[] pts, false, true) // call sun.dyn.MethodHandleNatives::findMethodType(Class rt, Class[] pts) -> MethodType
bool varargs = false, trusted = true;
JavaCallArguments args(Handle(THREAD, rt())); JavaCallArguments args(Handle(THREAD, rt()));
args.push_oop(pts()); args.push_oop(pts());
args.push_int(false);
args.push_int(trusted);
JavaValue result(T_OBJECT); JavaValue result(T_OBJECT);
JavaCalls::call_static(&result, JavaCalls::call_static(&result,
SystemDictionary::MethodType_klass(), SystemDictionary::MethodHandleNatives_klass(),
vmSymbols::makeImpl_name(), vmSymbols::makeImpl_signature(), vmSymbols::findMethodHandleType_name(),
vmSymbols::findMethodHandleType_signature(),
&args, CHECK_(empty)); &args, CHECK_(empty));
return Handle(THREAD, (oop) result.get_jobject()); return Handle(THREAD, (oop) result.get_jobject());
} }
...@@ -2430,29 +2431,34 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature, ...@@ -2430,29 +2431,34 @@ Handle SystemDictionary::compute_method_handle_type(symbolHandle signature,
// Ask Java code to find or construct a java.dyn.CallSite for the given // Ask Java code to find or construct a java.dyn.CallSite for the given
// name and signature, as interpreted relative to the given class loader. // name and signature, as interpreted relative to the given class loader.
Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller, Handle SystemDictionary::make_dynamic_call_site(Handle bootstrap_method,
int caller_method_idnum,
int caller_bci,
symbolHandle name, symbolHandle name,
methodHandle mh_invdyn, methodHandle signature_invoker,
Handle info,
methodHandle caller_method,
int caller_bci,
TRAPS) { TRAPS) {
Handle empty; Handle empty;
// call java.dyn.CallSite::makeSite(caller, name, mtype, cmid, cbci) Handle caller_mname = MethodHandles::new_MemberName(CHECK_(empty));
MethodHandles::init_MemberName(caller_mname(), caller_method());
// call sun.dyn.MethodHandleNatives::makeDynamicCallSite(bootm, name, mtype, info, caller_mname, caller_pos)
oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle! oop name_str_oop = StringTable::intern(name(), CHECK_(empty)); // not a handle!
JavaCallArguments args(Handle(THREAD, caller->java_mirror())); JavaCallArguments args(Handle(THREAD, bootstrap_method()));
args.push_oop(name_str_oop); args.push_oop(name_str_oop);
args.push_oop(mh_invdyn->method_handle_type()); args.push_oop(signature_invoker->method_handle_type());
args.push_int(caller_method_idnum); args.push_oop(info());
args.push_oop(caller_mname());
args.push_int(caller_bci); args.push_int(caller_bci);
JavaValue result(T_OBJECT); JavaValue result(T_OBJECT);
JavaCalls::call_static(&result, JavaCalls::call_static(&result,
SystemDictionary::CallSite_klass(), SystemDictionary::MethodHandleNatives_klass(),
vmSymbols::makeSite_name(), vmSymbols::makeSite_signature(), vmSymbols::makeDynamicCallSite_name(),
vmSymbols::makeDynamicCallSite_signature(),
&args, CHECK_(empty)); &args, CHECK_(empty));
oop call_site_oop = (oop) result.get_jobject(); oop call_site_oop = (oop) result.get_jobject();
assert(call_site_oop->is_oop() assert(call_site_oop->is_oop()
/*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane"); /*&& java_dyn_CallSite::is_instance(call_site_oop)*/, "must be sane");
java_dyn_CallSite::set_vmmethod(call_site_oop, mh_invdyn());
if (TraceMethodHandles) { if (TraceMethodHandles) {
#ifndef PRODUCT #ifndef PRODUCT
tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop); tty->print_cr("Linked invokedynamic bci=%d site="INTPTR_FORMAT":", caller_bci, call_site_oop);
...@@ -2463,9 +2469,7 @@ Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller, ...@@ -2463,9 +2469,7 @@ Handle SystemDictionary::make_dynamic_call_site(KlassHandle caller,
return call_site_oop; return call_site_oop;
} }
Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, TRAPS) {
KlassHandle search_bootstrap_klass,
TRAPS) {
Handle empty; Handle empty;
if (!caller->oop_is_instance()) return empty; if (!caller->oop_is_instance()) return empty;
...@@ -2476,57 +2480,12 @@ Handle SystemDictionary::find_bootstrap_method(KlassHandle caller, ...@@ -2476,57 +2480,12 @@ Handle SystemDictionary::find_bootstrap_method(KlassHandle caller,
if (TraceMethodHandles) { if (TraceMethodHandles) {
tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop); tty->print_cr("bootstrap method for "PTR_FORMAT" cached as "PTR_FORMAT":", ik(), boot_method_oop);
} }
NOT_PRODUCT(if (!boot_method_oop->is_oop()) { tty->print_cr("*** boot MH of "PTR_FORMAT" = "PTR_FORMAT, ik(), boot_method_oop); ik()->print(); });
assert(boot_method_oop->is_oop() assert(boot_method_oop->is_oop()
&& java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane"); && java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
return Handle(THREAD, boot_method_oop); return Handle(THREAD, boot_method_oop);
} }
boot_method_oop = NULL; // GC safety
// call java.dyn.Linkage::findBootstrapMethod(caller, sbk)
JavaCallArguments args(Handle(THREAD, ik->java_mirror()));
if (search_bootstrap_klass.is_null())
args.push_oop(Handle());
else
args.push_oop(search_bootstrap_klass->java_mirror());
JavaValue result(T_OBJECT);
JavaCalls::call_static(&result,
SystemDictionary::Linkage_klass(),
vmSymbols::findBootstrapMethod_name(),
vmSymbols::findBootstrapMethod_signature(),
&args, CHECK_(empty));
boot_method_oop = (oop) result.get_jobject();
if (boot_method_oop != NULL) {
if (TraceMethodHandles) {
#ifndef PRODUCT
tty->print_cr("--------");
tty->print_cr("bootstrap method for "PTR_FORMAT" computed as "PTR_FORMAT":", ik(), boot_method_oop);
ik()->print();
boot_method_oop->print();
tty->print_cr("========");
#endif //PRODUCT
}
assert(boot_method_oop->is_oop()
&& java_dyn_MethodHandle::is_instance(boot_method_oop), "must be sane");
// probably no race conditions, but let's be careful:
if (Atomic::cmpxchg_ptr(boot_method_oop, ik->adr_bootstrap_method(), NULL) == NULL)
ik->set_bootstrap_method(boot_method_oop);
else
boot_method_oop = ik->bootstrap_method();
} else {
if (TraceMethodHandles) {
#ifndef PRODUCT
tty->print_cr("--------");
tty->print_cr("bootstrap method for "PTR_FORMAT" computed as NULL:", ik());
ik()->print();
tty->print_cr("========");
#endif //PRODUCT
}
boot_method_oop = ik->bootstrap_method();
}
return Handle(THREAD, boot_method_oop); return empty;
} }
// Since the identity hash code for symbols changes when the symbols are // Since the identity hash code for symbols changes when the symbols are
......
...@@ -136,6 +136,7 @@ class SymbolPropertyTable; ...@@ -136,6 +136,7 @@ class SymbolPropertyTable;
template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \ template(MethodHandle_klass, java_dyn_MethodHandle, Opt) \
template(MemberName_klass, sun_dyn_MemberName, Opt) \ template(MemberName_klass, sun_dyn_MemberName, Opt) \
template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \ template(MethodHandleImpl_klass, sun_dyn_MethodHandleImpl, Opt) \
template(MethodHandleNatives_klass, sun_dyn_MethodHandleNatives, Opt) \
template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \ template(AdapterMethodHandle_klass, sun_dyn_AdapterMethodHandle, Opt) \
template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \ template(BoundMethodHandle_klass, sun_dyn_BoundMethodHandle, Opt) \
template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \ template(DirectMethodHandle_klass, sun_dyn_DirectMethodHandle, Opt) \
...@@ -463,29 +464,29 @@ public: ...@@ -463,29 +464,29 @@ public:
// JSR 292 // JSR 292
// find the java.dyn.MethodHandles::invoke method for a given signature // find the java.dyn.MethodHandles::invoke method for a given signature
static methodOop find_method_handle_invoke(symbolHandle signature, static methodOop find_method_handle_invoke(symbolHandle name,
symbolHandle signature,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS); TRAPS);
// ask Java to compute the java.dyn.MethodType object for a given signature // ask Java to compute a java.dyn.MethodType object for a given signature
static Handle compute_method_handle_type(symbolHandle signature, static Handle find_method_handle_type(symbolHandle signature,
Handle class_loader, Handle class_loader,
Handle protection_domain, Handle protection_domain,
TRAPS); TRAPS);
// ask Java to create a dynamic call site, while linking an invokedynamic op // ask Java to create a dynamic call site, while linking an invokedynamic op
static Handle make_dynamic_call_site(KlassHandle caller, static Handle make_dynamic_call_site(Handle bootstrap_method,
int caller_method_idnum, // Callee information:
int caller_bci,
symbolHandle name, symbolHandle name,
methodHandle mh_invoke, methodHandle signature_invoker,
Handle info,
// Caller information:
methodHandle caller_method,
int caller_bci,
TRAPS); TRAPS);
// coordinate with Java about bootstrap methods // coordinate with Java about bootstrap methods
static Handle find_bootstrap_method(KlassHandle caller, static Handle find_bootstrap_method(KlassHandle caller, TRAPS);
// This argument is non-null only when a
// classfile attribute has been found:
KlassHandle search_bootstrap_klass,
TRAPS);
// Utility for printing loader "name" as part of tracing constraints // Utility for printing loader "name" as part of tracing constraints
static const char* loader_name(oop loader) { static const char* loader_name(oop loader) {
......
...@@ -137,6 +137,7 @@ ...@@ -137,6 +137,7 @@
template(java_lang_CloneNotSupportedException, "java/lang/CloneNotSupportedException") \ template(java_lang_CloneNotSupportedException, "java/lang/CloneNotSupportedException") \
template(java_lang_IllegalAccessException, "java/lang/IllegalAccessException") \ template(java_lang_IllegalAccessException, "java/lang/IllegalAccessException") \
template(java_lang_IllegalArgumentException, "java/lang/IllegalArgumentException") \ template(java_lang_IllegalArgumentException, "java/lang/IllegalArgumentException") \
template(java_lang_IllegalStateException, "java/lang/IllegalStateException") \
template(java_lang_IllegalMonitorStateException, "java/lang/IllegalMonitorStateException") \ template(java_lang_IllegalMonitorStateException, "java/lang/IllegalMonitorStateException") \
template(java_lang_IllegalThreadStateException, "java/lang/IllegalThreadStateException") \ template(java_lang_IllegalThreadStateException, "java/lang/IllegalThreadStateException") \
template(java_lang_IndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException") \ template(java_lang_IndexOutOfBoundsException, "java/lang/IndexOutOfBoundsException") \
...@@ -201,6 +202,11 @@ ...@@ -201,6 +202,11 @@
template(newField_signature, "(Lsun/reflect/FieldInfo;)Ljava/lang/reflect/Field;") \ template(newField_signature, "(Lsun/reflect/FieldInfo;)Ljava/lang/reflect/Field;") \
template(newMethod_name, "newMethod") \ template(newMethod_name, "newMethod") \
template(newMethod_signature, "(Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Method;") \ template(newMethod_signature, "(Lsun/reflect/MethodInfo;)Ljava/lang/reflect/Method;") \
/* the following two names must be in order: */ \
template(invokeExact_name, "invokeExact") \
template(invokeGeneric_name, "invokeGeneric") \
template(invokeVarargs_name, "invokeVarargs") \
template(star_name, "*") /*not really a name*/ \
template(invoke_name, "invoke") \ template(invoke_name, "invoke") \
template(override_name, "override") \ template(override_name, "override") \
template(parameterTypes_name, "parameterTypes") \ template(parameterTypes_name, "parameterTypes") \
...@@ -231,16 +237,17 @@ ...@@ -231,16 +237,17 @@
template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \ template(java_dyn_MethodTypeForm, "java/dyn/MethodTypeForm") \
template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \ template(java_dyn_MethodTypeForm_signature, "Ljava/dyn/MethodTypeForm;") \
template(sun_dyn_MemberName, "sun/dyn/MemberName") \ template(sun_dyn_MemberName, "sun/dyn/MemberName") \
template(sun_dyn_MemberName_signature, "Lsun/dyn/MemberName;") \
template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \ template(sun_dyn_MethodHandleImpl, "sun/dyn/MethodHandleImpl") \
template(sun_dyn_MethodHandleNatives, "sun/dyn/MethodHandleNatives") \
template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \ template(sun_dyn_AdapterMethodHandle, "sun/dyn/AdapterMethodHandle") \
template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \ template(sun_dyn_BoundMethodHandle, "sun/dyn/BoundMethodHandle") \
template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \ template(sun_dyn_DirectMethodHandle, "sun/dyn/DirectMethodHandle") \
template(makeImpl_name, "makeImpl") /*MethodType::makeImpl*/ \ /* internal up-calls made only by the JVM, via class sun.dyn.MethodHandleNatives: */ \
template(makeImpl_signature, "(Ljava/lang/Class;[Ljava/lang/Class;ZZ)Ljava/dyn/MethodType;") \ template(findMethodHandleType_name, "findMethodHandleType") \
template(makeSite_name, "makeSite") /*CallSite::makeSite*/ \ template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/dyn/MethodType;") \
template(makeSite_signature, "(Ljava/lang/Class;Ljava/lang/String;Ljava/dyn/MethodType;II)Ljava/dyn/CallSite;") \ template(makeDynamicCallSite_name, "makeDynamicCallSite") \
template(findBootstrapMethod_name, "findBootstrapMethod") \ template(makeDynamicCallSite_signature, "(Ljava/dyn/MethodHandle;Ljava/lang/String;Ljava/dyn/MethodType;Ljava/lang/Object;Lsun/dyn/MemberName;I)Ljava/dyn/CallSite;") \
template(findBootstrapMethod_signature, "(Ljava/lang/Class;Ljava/lang/Class;)Ljava/dyn/MethodHandle;") \
NOT_LP64( do_alias(machine_word_signature, int_signature) ) \ NOT_LP64( do_alias(machine_word_signature, int_signature) ) \
LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \ LP64_ONLY( do_alias(machine_word_signature, long_signature) ) \
\ \
...@@ -408,8 +415,9 @@ ...@@ -408,8 +415,9 @@
template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \ template(void_classloader_signature, "()Ljava/lang/ClassLoader;") \
template(void_object_signature, "()Ljava/lang/Object;") \ template(void_object_signature, "()Ljava/lang/Object;") \
template(void_class_signature, "()Ljava/lang/Class;") \ template(void_class_signature, "()Ljava/lang/Class;") \
template(void_string_signature, "()Ljava/lang/String;") \ template(void_string_signature, "()Ljava/lang/String;") \
template(object_array_object_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\ template(object_array_object_signature, "([Ljava/lang/Object;)Ljava/lang/Object;") \
template(object_object_array_object_signature, "(Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;")\
template(exception_void_signature, "(Ljava/lang/Exception;)V") \ template(exception_void_signature, "(Ljava/lang/Exception;)V") \
template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \ template(protectiondomain_signature, "[Ljava/security/ProtectionDomain;") \
template(accesscontrolcontext_signature, "Ljava/security/AccessControlContext;") \ template(accesscontrolcontext_signature, "Ljava/security/AccessControlContext;") \
...@@ -863,11 +871,15 @@ ...@@ -863,11 +871,15 @@
do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \ do_intrinsic(_Object_init, java_lang_Object, object_initializer_name, void_method_signature, F_R) \
/* (symbol object_initializer_name defined above) */ \ /* (symbol object_initializer_name defined above) */ \
\ \
do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_array_object_object_signature, F_R) \ do_intrinsic(_invoke, java_lang_reflect_Method, invoke_name, object_object_array_object_signature, F_R) \
/* (symbols invoke_name and invoke_signature defined above) */ \ /* (symbols invoke_name and invoke_signature defined above) */ \
do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \ do_intrinsic(_checkSpreadArgument, sun_dyn_MethodHandleImpl, checkSpreadArgument_name, checkSpreadArgument_signature, F_S) \
do_name( checkSpreadArgument_name, "checkSpreadArgument") \ do_name( checkSpreadArgument_name, "checkSpreadArgument") \
do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \ do_name( checkSpreadArgument_signature, "(Ljava/lang/Object;I)V") \
do_intrinsic(_invokeExact, java_dyn_MethodHandle, invokeExact_name, object_array_object_signature, F_RN) \
do_intrinsic(_invokeGeneric, java_dyn_MethodHandle, invokeGeneric_name, object_array_object_signature, F_RN) \
do_intrinsic(_invokeVarargs, java_dyn_MethodHandle, invokeVarargs_name, object_array_object_signature, F_R) \
do_intrinsic(_invokeDynamic, java_dyn_InvokeDynamic, star_name, object_array_object_signature, F_SN) \
\ \
/* unboxing methods: */ \ /* unboxing methods: */ \
do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \ do_intrinsic(_booleanValue, java_lang_Boolean, booleanValue_name, void_boolean_signature, F_R) \
......
...@@ -2867,6 +2867,7 @@ methodHandles.hpp frame.inline.hpp ...@@ -2867,6 +2867,7 @@ methodHandles.hpp frame.inline.hpp
methodHandles.hpp globals.hpp methodHandles.hpp globals.hpp
methodHandles.hpp interfaceSupport.hpp methodHandles.hpp interfaceSupport.hpp
methodHandles.hpp javaClasses.hpp methodHandles.hpp javaClasses.hpp
methodHandles.hpp no_precompiled_headers
methodHandles.hpp vmSymbols.hpp methodHandles.hpp vmSymbols.hpp
methodHandles.cpp allocation.inline.hpp methodHandles.cpp allocation.inline.hpp
...@@ -2930,6 +2931,7 @@ methodOop.cpp interpreter.hpp ...@@ -2930,6 +2931,7 @@ methodOop.cpp interpreter.hpp
methodOop.cpp jvmtiExport.hpp methodOop.cpp jvmtiExport.hpp
methodOop.cpp klassOop.hpp methodOop.cpp klassOop.hpp
methodOop.cpp methodDataOop.hpp methodOop.cpp methodDataOop.hpp
methodOop.cpp methodHandleWalk.hpp
methodOop.cpp methodOop.hpp methodOop.cpp methodOop.hpp
methodOop.cpp nativeLookup.hpp methodOop.cpp nativeLookup.hpp
methodOop.cpp oop.inline.hpp methodOop.cpp oop.inline.hpp
...@@ -4075,6 +4077,7 @@ systemDictionary.cpp jvmtiEnvBase.hpp ...@@ -4075,6 +4077,7 @@ systemDictionary.cpp jvmtiEnvBase.hpp
systemDictionary.cpp klass.inline.hpp systemDictionary.cpp klass.inline.hpp
systemDictionary.cpp loaderConstraints.hpp systemDictionary.cpp loaderConstraints.hpp
systemDictionary.cpp methodDataOop.hpp systemDictionary.cpp methodDataOop.hpp
systemDictionary.cpp methodHandles.hpp
systemDictionary.cpp mutexLocker.hpp systemDictionary.cpp mutexLocker.hpp
systemDictionary.cpp objArrayKlass.hpp systemDictionary.cpp objArrayKlass.hpp
systemDictionary.cpp oop.inline.hpp systemDictionary.cpp oop.inline.hpp
......
...@@ -691,24 +691,21 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { ...@@ -691,24 +691,21 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
methodHandle caller_method(thread, method(thread)); methodHandle caller_method(thread, method(thread));
// first determine if there is a bootstrap method // first find the bootstrap method
{ KlassHandle caller_klass(thread, caller_method->method_holder());
KlassHandle caller_klass(thread, caller_method->method_holder()); Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, CHECK);
Handle bootm = SystemDictionary::find_bootstrap_method(caller_klass, KlassHandle(), CHECK);
if (bootm.is_null()) {
// If there is no bootstrap method, throw IncompatibleClassChangeError.
// This is a valid generic error type for resolution (JLS 12.3.3).
char buf[200];
jio_snprintf(buf, sizeof(buf), "Class %s has not declared a bootstrap method for invokedynamic",
(Klass::cast(caller_klass()))->external_name());
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
}
}
constantPoolHandle pool(thread, caller_method->constants()); constantPoolHandle pool(thread, caller_method->constants());
pool->set_invokedynamic(); // mark header to flag active call sites pool->set_invokedynamic(); // mark header to flag active call sites
int site_index = four_byte_index(thread); int caller_bci = 0;
int site_index = 0;
{ address caller_bcp = bcp(thread);
caller_bci = caller_method->bci_from(caller_bcp);
site_index = Bytes::get_native_u4(caller_bcp+1);
}
assert(site_index == four_byte_index(thread), "");
assert(constantPoolCacheOopDesc::is_secondary_index(site_index), "proper format");
// there is a second CPC entries that is of interest; it caches signature info: // there is a second CPC entries that is of interest; it caches signature info:
int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index(); int main_index = pool->cache()->secondary_entry_at(site_index)->main_entry_index();
...@@ -732,23 +729,32 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) { ...@@ -732,23 +729,32 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invokedynamic(JavaThread* thread)) {
// The method (f2 entry) of the main entry is the MH.invoke for the // The method (f2 entry) of the main entry is the MH.invoke for the
// invokedynamic target call signature. // invokedynamic target call signature.
intptr_t f2_value = pool->cache()->entry_at(main_index)->f2(); intptr_t f2_value = pool->cache()->entry_at(main_index)->f2();
methodHandle mh_invdyn(THREAD, (methodOop) f2_value); methodHandle signature_invoker(THREAD, (methodOop) f2_value);
assert(mh_invdyn.not_null() && mh_invdyn->is_method() && mh_invdyn->is_method_handle_invoke(), assert(signature_invoker.not_null() && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
"correct result from LinkResolver::resolve_invokedynamic"); "correct result from LinkResolver::resolve_invokedynamic");
symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index)); symbolHandle call_site_name(THREAD, pool->name_ref_at(site_index));
Handle info; // NYI: Other metadata from a new kind of CP entry. (Annotations?)
// this is the index which gets stored on the CallSite object (as "callerPosition"):
int call_site_position = constantPoolCacheOopDesc::decode_secondary_index(site_index);
Handle call_site Handle call_site
= SystemDictionary::make_dynamic_call_site(caller_method->method_holder(), = SystemDictionary::make_dynamic_call_site(bootm,
caller_method->method_idnum(), // Callee information:
caller_method->bci_from(bcp(thread)),
call_site_name, call_site_name,
mh_invdyn, signature_invoker,
info,
// Caller information:
caller_method,
caller_bci,
CHECK); CHECK);
// In the secondary entry, the f1 field is the call site, and the f2 (index) // In the secondary entry, the f1 field is the call site, and the f2 (index)
// field is some data about the invoke site. // field is some data about the invoke site. Currently, it is just the BCI.
int extra_data = 0; // Later, it might be changed to help manage inlining dependencies.
pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site(), extra_data); pool->cache()->secondary_entry_at(site_index)->set_dynamic_call(call_site, signature_invoker);
} }
IRT_END IRT_END
......
...@@ -138,6 +138,15 @@ void LinkResolver::resolve_klass_no_update(KlassHandle& result, constantPoolHand ...@@ -138,6 +138,15 @@ void LinkResolver::resolve_klass_no_update(KlassHandle& result, constantPoolHand
void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { void LinkResolver::lookup_method_in_klasses(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
methodOop result_oop = klass->uncached_lookup_method(name(), signature()); methodOop result_oop = klass->uncached_lookup_method(name(), signature());
if (EnableMethodHandles && result_oop != NULL) {
switch (result_oop->intrinsic_id()) {
case vmIntrinsics::_invokeExact:
case vmIntrinsics::_invokeGeneric:
case vmIntrinsics::_invokeDynamic:
// Do not link directly to these. The VM must produce a synthetic one using lookup_implicit_method.
return;
}
}
result = methodHandle(THREAD, result_oop); result = methodHandle(THREAD, result_oop);
} }
...@@ -165,8 +174,10 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle ...@@ -165,8 +174,10 @@ void LinkResolver::lookup_method_in_interfaces(methodHandle& result, KlassHandle
void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) { void LinkResolver::lookup_implicit_method(methodHandle& result, KlassHandle klass, symbolHandle name, symbolHandle signature, TRAPS) {
if (EnableMethodHandles && MethodHandles::enabled() && if (EnableMethodHandles && MethodHandles::enabled() &&
name == vmSymbolHandles::invoke_name() && klass() == SystemDictionary::MethodHandle_klass()) { klass() == SystemDictionary::MethodHandle_klass() &&
methodOop result_oop = SystemDictionary::find_method_handle_invoke(signature, methodOopDesc::is_method_handle_invoke_name(name())) {
methodOop result_oop = SystemDictionary::find_method_handle_invoke(name,
signature,
Handle(), Handle(),
Handle(), Handle(),
CHECK); CHECK);
...@@ -239,7 +250,7 @@ void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHa ...@@ -239,7 +250,7 @@ void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHa
// The class is java.dyn.MethodHandle // The class is java.dyn.MethodHandle
resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
symbolHandle method_name = vmSymbolHandles::invoke_name(); symbolHandle method_name = vmSymbolHandles::invokeExact_name();
symbolHandle method_signature(THREAD, pool->signature_ref_at(index)); symbolHandle method_signature(THREAD, pool->signature_ref_at(index));
KlassHandle current_klass (THREAD, pool->pool_holder()); KlassHandle current_klass (THREAD, pool->pool_holder());
...@@ -1041,10 +1052,10 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po ...@@ -1041,10 +1052,10 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po
// At this point, we only need the signature, and can ignore the name. // At this point, we only need the signature, and can ignore the name.
symbolHandle method_signature(THREAD, pool->signature_ref_at(raw_index)); // raw_index works directly symbolHandle method_signature(THREAD, pool->signature_ref_at(raw_index)); // raw_index works directly
symbolHandle method_name = vmSymbolHandles::invoke_name(); symbolHandle method_name = vmSymbolHandles::invokeExact_name();
KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass(); KlassHandle resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
// JSR 292: this must be an implicitly generated method MethodHandle.invoke(*...) // JSR 292: this must be an implicitly generated method MethodHandle.invokeExact(*...)
// The extra MH receiver will be inserted into the stack on every call. // The extra MH receiver will be inserted into the stack on every call.
methodHandle resolved_method; methodHandle resolved_method;
lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK); lookup_implicit_method(resolved_method, resolved_klass, method_name, method_signature, CHECK);
......
...@@ -1045,7 +1045,7 @@ bool universe_post_init() { ...@@ -1045,7 +1045,7 @@ bool universe_post_init() {
k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_reflect_Method(), true, CHECK_false); k = SystemDictionary::resolve_or_fail(vmSymbolHandles::java_lang_reflect_Method(), true, CHECK_false);
k_h = instanceKlassHandle(THREAD, k); k_h = instanceKlassHandle(THREAD, k);
k_h->link_class(CHECK_false); k_h->link_class(CHECK_false);
m = k_h->find_method(vmSymbols::invoke_name(), vmSymbols::object_array_object_object_signature()); m = k_h->find_method(vmSymbols::invoke_name(), vmSymbols::object_object_array_object_signature());
if (m == NULL || m->is_static()) { if (m == NULL || m->is_static()) {
THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(), THROW_MSG_(vmSymbols::java_lang_NoSuchMethodException(),
"java.lang.reflect.Method.invoke", false); "java.lang.reflect.Method.invoke", false);
......
...@@ -218,18 +218,19 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) ...@@ -218,18 +218,19 @@ void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index)
} }
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, int extra_data) { void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site,
methodOop method = (methodOop) java_dyn_CallSite::vmmethod(call_site()); methodHandle signature_invoker) {
assert(method->is_method(), "must be initialized properly"); int param_size = signature_invoker->size_of_parameters();
int param_size = method->size_of_parameters();
assert(param_size >= 1, "method argument size must include MH.this"); assert(param_size >= 1, "method argument size must include MH.this");
param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic param_size -= 1; // do not count MH.this; it is not stacked for invokedynamic
if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) { if (Atomic::cmpxchg_ptr(call_site(), &_f1, NULL) == NULL) {
// racing threads might be trying to install their own favorites // racing threads might be trying to install their own favorites
set_f1(call_site()); set_f1(call_site());
} }
set_f2(extra_data); //set_f2(0);
set_flags(as_flags(as_TosState(method->result_type()), method->is_final_method(), false, false, false, true) | param_size); bool is_final = true;
assert(signature_invoker->is_final_method(), "is_final");
set_flags(as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size);
// do not do set_bytecode on a secondary CP cache entry // do not do set_bytecode on a secondary CP cache entry
//set_bytecode_1(Bytecodes::_invokedynamic); //set_bytecode_1(Bytecodes::_invokedynamic);
} }
......
...@@ -181,7 +181,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { ...@@ -181,7 +181,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC {
void set_dynamic_call( void set_dynamic_call(
Handle call_site, // Resolved java.dyn.CallSite (f1) Handle call_site, // Resolved java.dyn.CallSite (f1)
int extra_data // (f2) methodHandle signature_invoker // determines signature information
); );
void set_parameter_size(int value) { void set_parameter_size(int value) {
......
...@@ -236,8 +236,10 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) { ...@@ -236,8 +236,10 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) {
assert(obj->is_method(), "must be method"); assert(obj->is_method(), "must be method");
Klass::oop_print_on(obj, st); Klass::oop_print_on(obj, st);
methodOop m = methodOop(obj); methodOop m = methodOop(obj);
// get the effect of PrintOopAddress, always, for methods:
st->print (" - this oop: "INTPTR_FORMAT, (intptr_t)m);
st->print (" - method holder: "); m->method_holder()->print_value_on(st); st->cr(); st->print (" - method holder: "); m->method_holder()->print_value_on(st); st->cr();
st->print (" - constants: " INTPTR_FORMAT, " ", (address)m->constants()); st->print (" - constants: "INTPTR_FORMAT" ", (address)m->constants());
m->constants()->print_value_on(st); st->cr(); m->constants()->print_value_on(st); st->cr();
st->print (" - access: 0x%x ", m->access_flags().as_int()); m->access_flags().print_on(st); st->cr(); st->print (" - access: 0x%x ", m->access_flags().as_int()); m->access_flags().print_on(st); st->cr();
st->print (" - name: "); m->name()->print_value_on(st); st->cr(); st->print (" - name: "); m->name()->print_value_on(st); st->cr();
...@@ -246,6 +248,10 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) { ...@@ -246,6 +248,10 @@ void methodKlass::oop_print_on(oop obj, outputStream* st) {
st->print_cr(" - max locals: %d", m->max_locals()); st->print_cr(" - max locals: %d", m->max_locals());
st->print_cr(" - size of params: %d", m->size_of_parameters()); st->print_cr(" - size of params: %d", m->size_of_parameters());
st->print_cr(" - method size: %d", m->method_size()); st->print_cr(" - method size: %d", m->method_size());
if (m->intrinsic_id() != vmIntrinsics::_none)
st->print_cr(" - intrinsic id: %d %s", m->intrinsic_id(), vmIntrinsics::name_at(m->intrinsic_id()));
if (m->highest_tier_compile() != CompLevel_none)
st->print_cr(" - highest tier: %d", m->highest_tier_compile());
st->print_cr(" - vtable index: %d", m->_vtable_index); st->print_cr(" - vtable index: %d", m->_vtable_index);
st->print_cr(" - i2i entry: " INTPTR_FORMAT, m->interpreter_entry()); st->print_cr(" - i2i entry: " INTPTR_FORMAT, m->interpreter_entry());
st->print_cr(" - adapter: " INTPTR_FORMAT, m->adapter()); st->print_cr(" - adapter: " INTPTR_FORMAT, m->adapter());
......
...@@ -807,9 +807,19 @@ bool methodOopDesc::should_not_be_cached() const { ...@@ -807,9 +807,19 @@ bool methodOopDesc::should_not_be_cached() const {
return false; return false;
} }
bool methodOopDesc::is_method_handle_invoke_name(vmSymbols::SID name_sid) {
switch (name_sid) {
case vmSymbols::VM_SYMBOL_ENUM_NAME(invoke_name): // FIXME: remove this transitional form
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeExact_name):
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name):
return true;
}
return false;
}
// Constant pool structure for invoke methods: // Constant pool structure for invoke methods:
enum { enum {
_imcp_invoke_name = 1, // utf8: 'invoke' _imcp_invoke_name = 1, // utf8: 'invokeExact' or 'invokeGeneric'
_imcp_invoke_signature, // utf8: (variable symbolOop) _imcp_invoke_signature, // utf8: (variable symbolOop)
_imcp_method_type_value, // string: (variable java/dyn/MethodType, sic) _imcp_method_type_value, // string: (variable java/dyn/MethodType, sic)
_imcp_limit _imcp_limit
...@@ -839,14 +849,15 @@ jint* methodOopDesc::method_type_offsets_chain() { ...@@ -839,14 +849,15 @@ jint* methodOopDesc::method_type_offsets_chain() {
// //
// Tests if this method is an internal adapter frame from the // Tests if this method is an internal adapter frame from the
// MethodHandleCompiler. // MethodHandleCompiler.
// Must be consistent with MethodHandleCompiler::get_method_oop().
bool methodOopDesc::is_method_handle_adapter() const { bool methodOopDesc::is_method_handle_adapter() const {
return ((name() == vmSymbols::invoke_name() && return (is_method_handle_invoke_name(name()) &&
method_holder() == SystemDictionary::MethodHandle_klass()) is_synthetic() &&
|| MethodHandleCompiler::klass_is_method_handle_adapter_holder(method_holder()));
method_holder() == SystemDictionary::InvokeDynamic_klass());
} }
methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
symbolHandle name,
symbolHandle signature, symbolHandle signature,
Handle method_type, TRAPS) { Handle method_type, TRAPS) {
methodHandle empty; methodHandle empty;
...@@ -865,7 +876,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, ...@@ -865,7 +876,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty)); constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty));
cp = constantPoolHandle(THREAD, cp_oop); cp = constantPoolHandle(THREAD, cp_oop);
} }
cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name()); cp->symbol_at_put(_imcp_invoke_name, name());
cp->symbol_at_put(_imcp_invoke_signature, signature()); cp->symbol_at_put(_imcp_invoke_signature, signature());
cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature()); cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature());
cp->set_pool_holder(holder()); cp->set_pool_holder(holder());
...@@ -882,7 +893,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder, ...@@ -882,7 +893,7 @@ methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
m->set_constants(cp()); m->set_constants(cp());
m->set_name_index(_imcp_invoke_name); m->set_name_index(_imcp_invoke_name);
m->set_signature_index(_imcp_invoke_signature); m->set_signature_index(_imcp_invoke_signature);
assert(m->name() == vmSymbols::invoke_name(), ""); assert(is_method_handle_invoke_name(m->name()), "");
assert(m->signature() == signature(), ""); assert(m->signature() == signature(), "");
#ifdef CC_INTERP #ifdef CC_INTERP
ResultTypeFinder rtf(signature()); ResultTypeFinder rtf(signature());
...@@ -1033,6 +1044,24 @@ void methodOopDesc::init_intrinsic_id() { ...@@ -1033,6 +1044,24 @@ void methodOopDesc::init_intrinsic_id() {
id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags);
break; break;
} }
break;
// Signature-polymorphic methods: MethodHandle.invoke*, InvokeDynamic.*.
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_MethodHandle):
if (is_static() || !is_native()) break;
switch (name_id) {
case vmSymbols::VM_SYMBOL_ENUM_NAME(invokeGeneric_name):
id = vmIntrinsics::_invokeGeneric; break;
default:
if (is_method_handle_invoke_name(name()))
id = vmIntrinsics::_invokeExact;
break;
}
break;
case vmSymbols::VM_SYMBOL_ENUM_NAME(java_dyn_InvokeDynamic):
if (!is_static() || !is_native()) break;
id = vmIntrinsics::_invokeDynamic;
break;
} }
if (id != vmIntrinsics::_none) { if (id != vmIntrinsics::_none) {
......
...@@ -525,11 +525,16 @@ class methodOopDesc : public oopDesc { ...@@ -525,11 +525,16 @@ class methodOopDesc : public oopDesc {
// JSR 292 support // JSR 292 support
bool is_method_handle_invoke() const { return access_flags().is_method_handle_invoke(); } bool is_method_handle_invoke() const { return access_flags().is_method_handle_invoke(); }
static bool is_method_handle_invoke_name(vmSymbols::SID name_sid);
static bool is_method_handle_invoke_name(symbolOop name) {
return is_method_handle_invoke_name(vmSymbols::find_sid(name));
}
// Tests if this method is an internal adapter frame from the // Tests if this method is an internal adapter frame from the
// MethodHandleCompiler. // MethodHandleCompiler.
bool is_method_handle_adapter() const; bool is_method_handle_adapter() const;
static methodHandle make_invoke_method(KlassHandle holder, static methodHandle make_invoke_method(KlassHandle holder,
symbolHandle signature, symbolHandle name, //invokeExact or invokeGeneric
symbolHandle signature, //anything at all
Handle method_type, Handle method_type,
TRAPS); TRAPS);
// these operate only on invoke methods: // these operate only on invoke methods:
......
...@@ -477,12 +477,7 @@ InlineTree *InlineTree::build_inline_tree_for_callee( ciMethod* callee_method, J ...@@ -477,12 +477,7 @@ InlineTree *InlineTree::build_inline_tree_for_callee( ciMethod* callee_method, J
} }
int new_depth_adjust = 0; int new_depth_adjust = 0;
if (caller_jvms->method() != NULL) { if (caller_jvms->method() != NULL) {
if ((caller_jvms->method()->name() == ciSymbol::invoke_name() &&
caller_jvms->method()->holder()->name() == ciSymbol::java_dyn_MethodHandle())
|| caller_jvms->method()->holder()->name() == ciSymbol::java_dyn_InvokeDynamic())
/* @@@ FIXME:
if (caller_jvms->method()->is_method_handle_adapter()) if (caller_jvms->method()->is_method_handle_adapter())
*/
new_depth_adjust -= 1; // don't count actions in MH or indy adapter frames new_depth_adjust -= 1; // don't count actions in MH or indy adapter frames
else if (callee_method->is_method_handle_invoke()) { else if (callee_method->is_method_handle_invoke()) {
new_depth_adjust -= 1; // don't count method handle calls from java.dyn implem new_depth_adjust -= 1; // don't count method handle calls from java.dyn implem
......
...@@ -1173,9 +1173,9 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { ...@@ -1173,9 +1173,9 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
// has no receiver, normal MH calls do. // has no receiver, normal MH calls do.
int flags_bits; int flags_bits;
if (for_invokedynamic()) if (for_invokedynamic())
flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_STATIC); flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SYNTHETIC | JVM_ACC_STATIC);
else else
flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL); flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SYNTHETIC);
bool is_conc_safe = true; bool is_conc_safe = true;
methodOop m_oop = oopFactory::new_method(bytecode_length(), methodOop m_oop = oopFactory::new_method(bytecode_length(),
...@@ -1217,6 +1217,7 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const { ...@@ -1217,6 +1217,7 @@ methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
} }
#endif //PRODUCT #endif //PRODUCT
assert(m->is_method_handle_adapter(), "must be recognized as an adapter");
return m; return m;
} }
......
...@@ -366,6 +366,13 @@ enum { ...@@ -366,6 +366,13 @@ enum {
VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED VM_INDEX_UNINITIALIZED = sun_dyn_MemberName::VM_INDEX_UNINITIALIZED
}; };
Handle MethodHandles::new_MemberName(TRAPS) {
Handle empty;
instanceKlassHandle k(THREAD, SystemDictionary::MemberName_klass());
if (!k->is_initialized()) k->initialize(CHECK_(empty));
return Handle(THREAD, k->allocate_instance(THREAD));
}
void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) { void MethodHandles::init_MemberName(oop mname_oop, oop target_oop) {
if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) { if (target_oop->klass() == SystemDictionary::reflect_Field_klass()) {
oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder()
...@@ -394,16 +401,18 @@ void MethodHandles::init_MemberName(oop mname_oop, methodOop m, bool do_dispatch ...@@ -394,16 +401,18 @@ void MethodHandles::init_MemberName(oop mname_oop, methodOop m, bool do_dispatch
sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget);
sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); sun_dyn_MemberName::set_vmindex(mname_oop, vmindex);
sun_dyn_MemberName::set_flags(mname_oop, flags); sun_dyn_MemberName::set_flags(mname_oop, flags);
sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(m->method_holder())->java_mirror());
} }
void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) { void MethodHandles::init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset) {
int flags = (IS_FIELD | (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS )); int flags = (IS_FIELD | (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS ));
oop vmtarget = field_holder; oop vmtarget = field_holder;
int vmindex = offset; // implies no info yet int vmindex = offset; // determines the field uniquely when combined with static bit
assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex"); assert(vmindex != VM_INDEX_UNINITIALIZED, "bad alias on vmindex");
sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget); sun_dyn_MemberName::set_vmtarget(mname_oop, vmtarget);
sun_dyn_MemberName::set_vmindex(mname_oop, vmindex); sun_dyn_MemberName::set_vmindex(mname_oop, vmindex);
sun_dyn_MemberName::set_flags(mname_oop, flags); sun_dyn_MemberName::set_flags(mname_oop, flags);
sun_dyn_MemberName::set_clazz(mname_oop, Klass::cast(field_holder)->java_mirror());
} }
...@@ -467,7 +476,7 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) { ...@@ -467,7 +476,7 @@ void MethodHandles::resolve_MemberName(Handle mname, TRAPS) {
name_str = NULL; // safety name_str = NULL; // safety
// convert the external string or reflective type to an internal signature // convert the external string or reflective type to an internal signature
bool force_signature = (name() == vmSymbols::invoke_name()); bool force_signature = methodOopDesc::is_method_handle_invoke_name(name());
symbolHandle type; { symbolHandle type; {
symbolOop type_sym = NULL; symbolOop type_sym = NULL;
if (java_dyn_MethodType::is_instance(type_str)) { if (java_dyn_MethodType::is_instance(type_str)) {
...@@ -775,6 +784,20 @@ int MethodHandles::find_MemberNames(klassOop k, ...@@ -775,6 +784,20 @@ int MethodHandles::find_MemberNames(klassOop k,
} }
// Decode this java.lang.Class object into an instanceKlass, if possible.
// Throw IAE if not
instanceKlassHandle MethodHandles::resolve_instance_klass(oop java_mirror_oop, TRAPS) {
instanceKlassHandle empty;
klassOop caller = NULL;
if (java_lang_Class::is_instance(java_mirror_oop)) {
caller = java_lang_Class::as_klassOop(java_mirror_oop);
}
if (caller == NULL || !Klass::cast(caller)->oop_is_instance()) {
THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), "not a class", empty);
}
return instanceKlassHandle(THREAD, caller);
}
// Decode the vmtarget field of a method handle. // Decode the vmtarget field of a method handle.
...@@ -2115,31 +2138,26 @@ JVM_ENTRY(void, MHI_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh, ...@@ -2115,31 +2138,26 @@ JVM_ENTRY(void, MHI_init_DMH(JNIEnv *env, jobject igcls, jobject mh_jh,
KlassHandle caller(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh))); KlassHandle caller(THREAD, java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh)));
// If this were a bytecode, the first access check would be against // If this were a bytecode, the first access check would be against
// the "reference class" mentioned in the CONSTANT_Methodref. // the "reference class" mentioned in the CONSTANT_Methodref.
// For that class, we use the defining class of m, // We don't know at this point which class that was, and if we
// or a more specific receiver limit if available. // check against m.method_holder we might get the wrong answer.
klassOop reference_klass = m->method_holder(); // OK approximation // So we just make sure to handle this check when the resolution
if (receiver_limit != NULL && receiver_limit != reference_klass) { // happens, when we call resolve_MemberName.
if (!Klass::cast(receiver_limit)->is_subtype_of(reference_klass)) //
THROW_MSG(vmSymbols::java_lang_InternalError(), "receiver limit out of bounds"); // Java code bug // (A public class can inherit public members from private supers,
reference_klass = receiver_limit; // and it would be wrong to check access against the private super
} // if the original symbolic reference was against the public class.)
// Emulate LinkResolver::check_klass_accessability. //
if (!Reflection::verify_class_access(caller->as_klassOop(),
reference_klass,
true)) {
THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(m->method_holder())->external_name());
}
// If there were a bytecode, the next step would be to lookup the method // If there were a bytecode, the next step would be to lookup the method
// in the reference class, then then check the method's access bits. // in the reference class, then then check the method's access bits.
// Emulate LinkResolver::check_method_accessability. // Emulate LinkResolver::check_method_accessability.
klassOop resolved_klass = m->method_holder(); klassOop resolved_klass = m->method_holder();
if (!Reflection::verify_field_access(caller->as_klassOop(), if (!Reflection::verify_field_access(caller->as_klassOop(),
resolved_klass, reference_klass, resolved_klass, resolved_klass,
m->access_flags(), m->access_flags(),
true)) { true)) {
// %%% following cutout belongs in Reflection::verify_field_access? // %%% following cutout belongs in Reflection::verify_field_access?
bool same_pm = Reflection::is_same_package_member(caller->as_klassOop(), bool same_pm = Reflection::is_same_package_member(caller->as_klassOop(),
reference_klass, THREAD); resolved_klass, THREAD);
if (!same_pm) { if (!same_pm) {
THROW_MSG(vmSymbols::java_lang_InternalError(), m->name_and_sig_as_C_string()); THROW_MSG(vmSymbols::java_lang_InternalError(), m->name_and_sig_as_C_string());
} }
...@@ -2244,6 +2262,8 @@ JVM_ENTRY(jint, MHI_getConstant(JNIEnv *env, jobject igcls, jint which)) { ...@@ -2244,6 +2262,8 @@ JVM_ENTRY(jint, MHI_getConstant(JNIEnv *env, jobject igcls, jint which)) {
case MethodHandles::GC_JVM_STACK_MOVE_UNIT: case MethodHandles::GC_JVM_STACK_MOVE_UNIT:
// return number of words per slot, signed according to stack direction // return number of words per slot, signed according to stack direction
return MethodHandles::stack_move_unit(); return MethodHandles::stack_move_unit();
case MethodHandles::GC_CONV_OP_IMPLEMENTED_MASK:
return MethodHandles::adapter_conversion_ops_supported_mask();
} }
return 0; return 0;
} }
...@@ -2342,7 +2362,22 @@ JVM_END ...@@ -2342,7 +2362,22 @@ JVM_END
JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) { JVM_ENTRY(void, MHI_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh)) {
if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); } if (mname_jh == NULL) { THROW(vmSymbols::java_lang_InternalError()); }
Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh)); Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
// %%% take caller into account!
// The trusted Java code that calls this method should already have performed
// access checks on behalf of the given caller. But, we can verify this.
if (VerifyMethodHandles && caller_jh != NULL) {
klassOop reference_klass = java_lang_Class::as_klassOop(sun_dyn_MemberName::clazz(mname()));
if (reference_klass != NULL) {
// Emulate LinkResolver::check_klass_accessability.
klassOop caller = java_lang_Class::as_klassOop(JNIHandles::resolve_non_null(caller_jh));
if (!Reflection::verify_class_access(caller,
reference_klass,
true)) {
THROW_MSG(vmSymbols::java_lang_InternalError(), Klass::cast(reference_klass)->external_name());
}
}
}
MethodHandles::resolve_MemberName(mname, CHECK); MethodHandles::resolve_MemberName(mname, CHECK);
} }
JVM_END JVM_END
...@@ -2387,12 +2422,48 @@ JVM_ENTRY(jint, MHI_getMembers(JNIEnv *env, jobject igcls, ...@@ -2387,12 +2422,48 @@ JVM_ENTRY(jint, MHI_getMembers(JNIEnv *env, jobject igcls,
} }
JVM_END JVM_END
JVM_ENTRY(void, MHI_registerBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh, jobject bsm_jh)) {
instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD);
ik->link_class(CHECK);
if (!java_dyn_MethodHandle::is_instance(JNIHandles::resolve(bsm_jh))) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "method handle");
}
const char* err = NULL;
if (ik->is_initialized() || ik->is_in_error_state()) {
err = "too late: class is already initialized";
} else {
ObjectLocker ol(ik, THREAD); // note: this should be a recursive lock
if (ik->is_not_initialized() ||
(ik->is_being_initialized() && ik->is_reentrant_initialization(THREAD))) {
if (ik->bootstrap_method() != NULL) {
err = "class is already equipped with a bootstrap method";
} else {
ik->set_bootstrap_method(JNIHandles::resolve_non_null(bsm_jh));
err = NULL;
}
} else {
err = "class is already initialized";
if (ik->is_being_initialized())
err = "class is already being initialized in a different thread";
}
}
if (err != NULL) {
THROW_MSG(vmSymbols::java_lang_IllegalStateException(), err);
}
}
JVM_END
JVM_ENTRY(jobject, MHI_getBootstrap(JNIEnv *env, jobject igcls, jclass caller_jh)) {
instanceKlassHandle ik = MethodHandles::resolve_instance_klass(caller_jh, THREAD);
return JNIHandles::make_local(THREAD, ik->bootstrap_method());
}
JVM_END
JVM_ENTRY(void, MH_linkCallSite(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) { JVM_ENTRY(void, MHI_setCallSiteTarget(JNIEnv *env, jobject igcls, jobject site_jh, jobject target_jh)) {
// No special action required, yet. // No special action required, yet.
oop site_oop = JNIHandles::resolve(site_jh); oop site_oop = JNIHandles::resolve(site_jh);
if (site_oop == NULL || site_oop->klass() != SystemDictionary::CallSite_klass()) if (!java_dyn_CallSite::is_instance(site_oop))
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "call site"); THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "not a CallSite");
java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh)); java_dyn_CallSite::set_target(site_oop, JNIHandles::resolve(target_jh));
} }
JVM_END JVM_END
...@@ -2442,7 +2513,9 @@ static JNINativeMethod methods[] = { ...@@ -2442,7 +2513,9 @@ static JNINativeMethod methods[] = {
// More entry points specifically for EnableInvokeDynamic. // More entry points specifically for EnableInvokeDynamic.
static JNINativeMethod methods2[] = { static JNINativeMethod methods2[] = {
{CC"linkCallSite", CC"("CST MH")V", FN_PTR(MH_linkCallSite)} {CC"registerBootstrap", CC"("CLS MH")V", FN_PTR(MHI_registerBootstrap)},
{CC"getBootstrap", CC"("CLS")"MH, FN_PTR(MHI_getBootstrap)},
{CC"setCallSiteTarget", CC"("CST MH")V", FN_PTR(MHI_setCallSiteTarget)}
}; };
......
...@@ -216,6 +216,9 @@ class MethodHandles: AllStatic { ...@@ -216,6 +216,9 @@ class MethodHandles: AllStatic {
return (conv >> CONV_VMINFO_SHIFT) & CONV_VMINFO_MASK; return (conv >> CONV_VMINFO_SHIFT) & CONV_VMINFO_MASK;
} }
// Bit mask of conversion_op values. May vary by platform.
static int adapter_conversion_ops_supported_mask();
// Offset in words that the interpreter stack pointer moves when an argument is pushed. // Offset in words that the interpreter stack pointer moves when an argument is pushed.
// The stack_move value must always be a multiple of this. // The stack_move value must always be a multiple of this.
static int stack_move_unit() { static int stack_move_unit() {
...@@ -262,8 +265,9 @@ class MethodHandles: AllStatic { ...@@ -262,8 +265,9 @@ class MethodHandles: AllStatic {
// working with member names // working with member names
static void resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type static void resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type
static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing
static Handle new_MemberName(TRAPS); // must be followed by init_MemberName
static void init_MemberName(oop mname_oop, oop target); // compute vmtarget/vmindex from target static void init_MemberName(oop mname_oop, oop target); // compute vmtarget/vmindex from target
static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch); static void init_MemberName(oop mname_oop, methodOop m, bool do_dispatch = true);
static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset); static void init_MemberName(oop mname_oop, klassOop field_holder, AccessFlags mods, int offset);
static int find_MemberNames(klassOop k, symbolOop name, symbolOop sig, static int find_MemberNames(klassOop k, symbolOop name, symbolOop sig,
int mflags, klassOop caller, int mflags, klassOop caller,
...@@ -300,6 +304,7 @@ class MethodHandles: AllStatic { ...@@ -300,6 +304,7 @@ class MethodHandles: AllStatic {
// format of query to getConstant: // format of query to getConstant:
GC_JVM_PUSH_LIMIT = 0, GC_JVM_PUSH_LIMIT = 0,
GC_JVM_STACK_MOVE_UNIT = 1, GC_JVM_STACK_MOVE_UNIT = 1,
GC_CONV_OP_IMPLEMENTED_MASK = 2,
// format of result from getTarget / encode_target: // format of result from getTarget / encode_target:
ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method) ETF_HANDLE_OR_METHOD_NAME = 0, // all available data (immediate MH or method)
...@@ -311,6 +316,11 @@ class MethodHandles: AllStatic { ...@@ -311,6 +316,11 @@ class MethodHandles: AllStatic {
static oop encode_target(Handle mh, int format, TRAPS); // report vmtarget (to Java code) static oop encode_target(Handle mh, int format, TRAPS); // report vmtarget (to Java code)
static bool class_cast_needed(klassOop src, klassOop dst); static bool class_cast_needed(klassOop src, klassOop dst);
static instanceKlassHandle resolve_instance_klass(oop java_mirror_oop, TRAPS);
static instanceKlassHandle resolve_instance_klass(jclass java_mirror_jh, TRAPS) {
return resolve_instance_klass(JNIHandles::resolve(java_mirror_jh), THREAD);
}
private: private:
// These checkers operate on a pair of whole MethodTypes: // These checkers operate on a pair of whole MethodTypes:
static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end, static const char* check_method_type_change(oop src_mtype, int src_beg, int src_end,
......
...@@ -1557,7 +1557,7 @@ char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread, ...@@ -1557,7 +1557,7 @@ char* SharedRuntime::generate_wrong_method_type_message(JavaThread* thread,
methodOop actual_method = MethodHandles::decode_method(actual, methodOop actual_method = MethodHandles::decode_method(actual,
kignore, fignore); kignore, fignore);
if (actual_method != NULL) { if (actual_method != NULL) {
if (actual_method->name() == vmSymbols::invoke_name()) if (methodOopDesc::is_method_handle_invoke_name(actual_method->name()))
mhName = "$"; mhName = "$";
else else
mhName = actual_method->signature()->as_C_string(); mhName = actual_method->signature()->as_C_string();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册