mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
6993078: JSR 292 too many pushes: Lesp points into register window
Reviewed-by: kvn, never
This commit is contained in:
parent
abc5f94df7
commit
868bf68a3e
5 changed files with 28 additions and 27 deletions
|
@ -3289,8 +3289,6 @@ void TemplateTable::invokedynamic(int byte_no) {
|
||||||
/*virtual*/ false, /*vfinal*/ false, /*indy*/ true);
|
/*virtual*/ false, /*vfinal*/ false, /*indy*/ true);
|
||||||
__ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
|
__ mov(SP, O5_savedSP); // record SP that we wanted the callee to restore
|
||||||
|
|
||||||
__ verify_oop(G5_callsite);
|
|
||||||
|
|
||||||
// profile this call
|
// profile this call
|
||||||
__ profile_call(O4);
|
__ profile_call(O4);
|
||||||
|
|
||||||
|
@ -3303,8 +3301,10 @@ void TemplateTable::invokedynamic(int byte_no) {
|
||||||
__ sll(Rret, LogBytesPerWord, Rret);
|
__ sll(Rret, LogBytesPerWord, Rret);
|
||||||
__ ld_ptr(Rtemp, Rret, Rret); // get return address
|
__ ld_ptr(Rtemp, Rret, Rret); // get return address
|
||||||
|
|
||||||
|
__ verify_oop(G5_callsite);
|
||||||
__ load_heap_oop(G5_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle);
|
__ load_heap_oop(G5_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, Rscratch), G3_method_handle);
|
||||||
__ null_check(G3_method_handle);
|
__ null_check(G3_method_handle);
|
||||||
|
__ verify_oop(G3_method_handle);
|
||||||
|
|
||||||
// Adjust Rret first so Llast_SP can be same as Rret
|
// Adjust Rret first so Llast_SP can be same as Rret
|
||||||
__ add(Rret, -frame::pc_return_offset, O7);
|
__ add(Rret, -frame::pc_return_offset, O7);
|
||||||
|
|
|
@ -3074,6 +3074,7 @@ void TemplateTable::invokeinterface(int byte_no) {
|
||||||
|
|
||||||
void TemplateTable::invokedynamic(int byte_no) {
|
void TemplateTable::invokedynamic(int byte_no) {
|
||||||
transition(vtos, vtos);
|
transition(vtos, vtos);
|
||||||
|
assert(byte_no == f1_oop, "use this argument");
|
||||||
|
|
||||||
if (!EnableInvokeDynamic) {
|
if (!EnableInvokeDynamic) {
|
||||||
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
// We should not encounter this bytecode if !EnableInvokeDynamic.
|
||||||
|
@ -3086,7 +3087,6 @@ void TemplateTable::invokedynamic(int byte_no) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(byte_no == f1_oop, "use this argument");
|
|
||||||
prepare_invoke(rax, rbx, byte_no);
|
prepare_invoke(rax, rbx, byte_no);
|
||||||
|
|
||||||
// rax: CallSite object (f1)
|
// rax: CallSite object (f1)
|
||||||
|
@ -3097,14 +3097,14 @@ void TemplateTable::invokedynamic(int byte_no) {
|
||||||
Register rax_callsite = rax;
|
Register rax_callsite = rax;
|
||||||
Register rcx_method_handle = rcx;
|
Register rcx_method_handle = rcx;
|
||||||
|
|
||||||
if (ProfileInterpreter) {
|
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
||||||
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
// profile this call
|
||||||
// profile this call
|
__ profile_call(rsi);
|
||||||
__ profile_call(rsi);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rcx)));
|
__ verify_oop(rax_callsite);
|
||||||
|
__ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rdx)));
|
||||||
__ null_check(rcx_method_handle);
|
__ null_check(rcx_method_handle);
|
||||||
|
__ verify_oop(rcx_method_handle);
|
||||||
__ prepare_to_jump_from_interpreted();
|
__ prepare_to_jump_from_interpreted();
|
||||||
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3128,7 +3128,6 @@ void TemplateTable::invokedynamic(int byte_no) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(byte_no == f1_oop, "use this argument");
|
|
||||||
prepare_invoke(rax, rbx, byte_no);
|
prepare_invoke(rax, rbx, byte_no);
|
||||||
|
|
||||||
// rax: CallSite object (f1)
|
// rax: CallSite object (f1)
|
||||||
|
@ -3139,14 +3138,14 @@ void TemplateTable::invokedynamic(int byte_no) {
|
||||||
Register rax_callsite = rax;
|
Register rax_callsite = rax;
|
||||||
Register rcx_method_handle = rcx;
|
Register rcx_method_handle = rcx;
|
||||||
|
|
||||||
if (ProfileInterpreter) {
|
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
||||||
// %%% should make a type profile for any invokedynamic that takes a ref argument
|
// profile this call
|
||||||
// profile this call
|
__ profile_call(r13);
|
||||||
__ profile_call(r13);
|
|
||||||
}
|
|
||||||
|
|
||||||
__ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rcx)));
|
__ verify_oop(rax_callsite);
|
||||||
|
__ load_heap_oop(rcx_method_handle, Address(rax_callsite, __ delayed_value(java_lang_invoke_CallSite::target_offset_in_bytes, rdx)));
|
||||||
__ null_check(rcx_method_handle);
|
__ null_check(rcx_method_handle);
|
||||||
|
__ verify_oop(rcx_method_handle);
|
||||||
__ prepare_to_jump_from_interpreted();
|
__ prepare_to_jump_from_interpreted();
|
||||||
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
__ jump_to_method_handle_entry(rcx_method_handle, rdx);
|
||||||
}
|
}
|
||||||
|
|
|
@ -756,7 +756,7 @@ ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||||
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
|
assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
|
||||||
|
|
||||||
bool is_resolved = cpool->cache()->main_entry_at(index)->is_resolved(bc);
|
bool is_resolved = cpool->cache()->main_entry_at(index)->is_resolved(bc);
|
||||||
if (is_resolved && (oop) cpool->cache()->secondary_entry_at(index)->f1() == NULL)
|
if (is_resolved && cpool->cache()->secondary_entry_at(index)->is_f1_null())
|
||||||
// FIXME: code generation could allow for null (unlinked) call site
|
// FIXME: code generation could allow for null (unlinked) call site
|
||||||
is_resolved = false;
|
is_resolved = false;
|
||||||
|
|
||||||
|
@ -770,7 +770,7 @@ ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
|
||||||
|
|
||||||
// Get the invoker methodOop from the constant pool.
|
// Get the invoker methodOop from the constant pool.
|
||||||
oop f1_value = cpool->cache()->main_entry_at(index)->f1();
|
oop f1_value = cpool->cache()->main_entry_at(index)->f1();
|
||||||
methodOop signature_invoker = methodOop(f1_value);
|
methodOop signature_invoker = (methodOop) f1_value;
|
||||||
assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
assert(signature_invoker != NULL && signature_invoker->is_method() && signature_invoker->is_method_handle_invoke(),
|
||||||
"correct result from LinkResolver::resolve_invokedynamic");
|
"correct result from LinkResolver::resolve_invokedynamic");
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ void ConstantPoolCacheEntry::set_f1_if_null_atomic(oop f1) {
|
||||||
void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL);
|
void* result = Atomic::cmpxchg_ptr(f1, f1_addr, NULL);
|
||||||
bool success = (result == NULL);
|
bool success = (result == NULL);
|
||||||
if (success) {
|
if (success) {
|
||||||
update_barrier_set(f1_addr, f1);
|
update_barrier_set((void*) f1_addr, f1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,21 +275,23 @@ int ConstantPoolCacheEntry::bootstrap_method_index_in_cache() {
|
||||||
return (int) bsm_cache_index;
|
return (int) bsm_cache_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site,
|
void ConstantPoolCacheEntry::set_dynamic_call(Handle call_site, methodHandle signature_invoker) {
|
||||||
methodHandle signature_invoker) {
|
|
||||||
assert(is_secondary_entry(), "");
|
assert(is_secondary_entry(), "");
|
||||||
|
// NOTE: it's important that all other values are set before f1 is
|
||||||
|
// set since some users short circuit on f1 being set
|
||||||
|
// (i.e. non-null) and that may result in uninitialized values for
|
||||||
|
// other racing threads (e.g. flags).
|
||||||
int param_size = signature_invoker->size_of_parameters();
|
int param_size = signature_invoker->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) {
|
|
||||||
// racing threads might be trying to install their own favorites
|
|
||||||
set_f1(call_site());
|
|
||||||
}
|
|
||||||
bool is_final = true;
|
bool is_final = true;
|
||||||
assert(signature_invoker->is_final_method(), "is_final");
|
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);
|
int flags = as_flags(as_TosState(signature_invoker->result_type()), is_final, false, false, false, true) | param_size;
|
||||||
|
assert(_flags == 0 || _flags == flags, "flags should be the same");
|
||||||
|
set_flags(flags);
|
||||||
// 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);
|
||||||
|
set_f1_if_null_atomic(call_site()); // This must be the last one to set (see NOTE above)!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue