mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 22:34:27 +02:00
6655638: dynamic languages need method handles
Initial implementation, with known omissions (x86/64, sparc, compiler optim., c-oops, C++ interp.) Reviewed-by: kvn, twisti, never
This commit is contained in:
parent
318da3f68c
commit
ce0c084720
63 changed files with 5815 additions and 70 deletions
|
@ -304,6 +304,12 @@ void methodOopDesc::cleanup_inline_caches() {
|
|||
}
|
||||
|
||||
|
||||
int methodOopDesc::extra_stack_words() {
|
||||
// not an inline function, to avoid a header dependency on Interpreter
|
||||
return extra_stack_entries() * Interpreter::stackElementSize();
|
||||
}
|
||||
|
||||
|
||||
void methodOopDesc::compute_size_of_parameters(Thread *thread) {
|
||||
symbolHandle h_signature(thread, signature());
|
||||
ArgumentSizeComputer asc(h_signature);
|
||||
|
@ -564,6 +570,11 @@ void methodOopDesc::set_signature_handler(address handler) {
|
|||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
methodDataOop mdo = method_data();
|
||||
if (mdo != NULL
|
||||
&& (uint)mdo->decompile_count() > (uint)PerMethodRecompilationCutoff) {
|
||||
|
@ -651,7 +662,7 @@ void methodOopDesc::link_method(methodHandle h_method, TRAPS) {
|
|||
assert(entry != NULL, "interpreter entry must be non-null");
|
||||
// Sets both _i2i_entry and _from_interpreted_entry
|
||||
set_interpreter_entry(entry);
|
||||
if (is_native()) {
|
||||
if (is_native() && !is_method_handle_invoke()) {
|
||||
set_native_function(
|
||||
SharedRuntime::native_method_throw_unsatisfied_link_error_entry(),
|
||||
!native_bind_event_is_interesting);
|
||||
|
@ -783,6 +794,100 @@ bool methodOopDesc::should_not_be_cached() const {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Constant pool structure for invoke methods:
|
||||
enum {
|
||||
_imcp_invoke_name = 1, // utf8: 'invoke'
|
||||
_imcp_invoke_signature, // utf8: (variable symbolOop)
|
||||
_imcp_method_type_value, // string: (variable java/dyn/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 };
|
||||
if (pchase[0] == -1) {
|
||||
jint step0 = in_bytes(constants_offset());
|
||||
jint step1 = (constantPoolOopDesc::header_size() + _imcp_method_type_value) * HeapWordSize;
|
||||
// do this in reverse to avoid races:
|
||||
OrderAccess::release_store(&pchase[1], step1);
|
||||
OrderAccess::release_store(&pchase[0], step0);
|
||||
}
|
||||
return pchase;
|
||||
}
|
||||
|
||||
methodHandle methodOopDesc::make_invoke_method(KlassHandle holder,
|
||||
symbolHandle signature,
|
||||
Handle method_type, TRAPS) {
|
||||
methodHandle empty;
|
||||
|
||||
assert(holder() == SystemDictionary::MethodHandle_klass(),
|
||||
"must be a JSR 292 magic type");
|
||||
|
||||
if (TraceMethodHandles) {
|
||||
tty->print("Creating invoke method for ");
|
||||
signature->print_value();
|
||||
tty->cr();
|
||||
}
|
||||
|
||||
constantPoolHandle cp;
|
||||
{
|
||||
constantPoolOop cp_oop = oopFactory::new_constantPool(_imcp_limit, IsSafeConc, CHECK_(empty));
|
||||
cp = constantPoolHandle(THREAD, cp_oop);
|
||||
}
|
||||
cp->symbol_at_put(_imcp_invoke_name, vmSymbols::invoke_name());
|
||||
cp->symbol_at_put(_imcp_invoke_signature, signature());
|
||||
cp->string_at_put(_imcp_method_type_value, vmSymbols::void_signature());
|
||||
cp->set_pool_holder(holder());
|
||||
|
||||
// set up the fancy stuff:
|
||||
cp->pseudo_string_at_put(_imcp_method_type_value, method_type());
|
||||
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, IsSafeConc, CHECK_(empty));
|
||||
m = methodHandle(THREAD, m_oop);
|
||||
}
|
||||
m->set_constants(cp());
|
||||
m->set_name_index(_imcp_invoke_name);
|
||||
m->set_signature_index(_imcp_invoke_signature);
|
||||
assert(m->name() == vmSymbols::invoke_name(), "");
|
||||
assert(m->signature() == signature(), "");
|
||||
#ifdef CC_INTERP
|
||||
ResultTypeFinder rtf(signature());
|
||||
m->set_result_index(rtf.type());
|
||||
#endif
|
||||
m->compute_size_of_parameters(THREAD);
|
||||
m->set_exception_table(Universe::the_empty_int_array());
|
||||
|
||||
// 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)
|
||||
m->print_on(tty);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
|
||||
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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue