< prev index next >
src/hotspot/share/runtime/sharedRuntime.cpp
Print this page
@@ -1245,13 +1245,14 @@
}
// Resolves a call.
methodHandle SharedRuntime::resolve_helper(JavaThread *thread,
bool is_virtual,
- bool is_optimized, TRAPS) {
+ bool is_optimized,
+ bool* caller_is_c1, TRAPS) {
methodHandle callee_method;
- callee_method = resolve_sub_helper(thread, is_virtual, is_optimized, THREAD);
+ callee_method = resolve_sub_helper(thread, is_virtual, is_optimized, caller_is_c1, THREAD);
if (JvmtiExport::can_hotswap_or_post_breakpoint()) {
int retry_count = 0;
while (!HAS_PENDING_EXCEPTION && callee_method->is_old() &&
callee_method->method_holder() != SystemDictionary::Object_klass()) {
// If has a pending exception then there is no need to re-try to
@@ -1264,11 +1265,11 @@
// in the middle of resolve. If it is looping here more than 100 times
// means then there could be a bug here.
guarantee((retry_count++ < 100),
"Could not resolve to latest version of redefined method");
// method is redefined in the middle of resolve so re-try.
- callee_method = resolve_sub_helper(thread, is_virtual, is_optimized, THREAD);
+ callee_method = resolve_sub_helper(thread, is_virtual, is_optimized, caller_is_c1, THREAD);
}
}
return callee_method;
}
@@ -1295,27 +1296,28 @@
#ifdef ASSERT
address dest_entry_point = callee == NULL ? 0 : callee->entry_point(); // used below
#endif
bool is_nmethod = caller_nm->is_nmethod();
+ bool caller_is_c1 = caller_nm->is_c1();
if (is_virtual) {
Klass* receiver_klass = NULL;
- if (ValueTypePassFieldsAsArgs && callee_method->method_holder()->is_value()) {
+ if (ValueTypePassFieldsAsArgs && !caller_is_c1 && callee_method->method_holder()->is_value()) {
// If the receiver is a value type that is passed as fields, no oop is available
receiver_klass = callee_method->method_holder();
} else {
assert(receiver.not_null() || invoke_code == Bytecodes::_invokehandle, "sanity check");
receiver_klass = invoke_code == Bytecodes::_invokehandle ? NULL : receiver->klass();
}
bool static_bound = call_info.resolved_method()->can_be_statically_bound();
CompiledIC::compute_monomorphic_entry(callee_method, receiver_klass,
- is_optimized, static_bound, is_nmethod, virtual_call_info,
+ is_optimized, static_bound, is_nmethod, caller_is_c1, virtual_call_info,
CHECK_false);
} else {
// static call
- CompiledStaticCall::compute_entry(callee_method, is_nmethod, static_call_info);
+ CompiledStaticCall::compute_entry(callee_method, caller_nm, static_call_info);
}
// grab lock, check for deoptimization and potentially patch caller
{
CompiledICLocker ml(caller_nm);
@@ -1356,19 +1358,21 @@
// Resolves a call. The compilers generate code for calls that go here
// and are patched with the real destination of the call.
methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread,
bool is_virtual,
- bool is_optimized, TRAPS) {
+ bool is_optimized,
+ bool* caller_is_c1, TRAPS) {
ResourceMark rm(thread);
RegisterMap cbl_map(thread, false);
frame caller_frame = thread->last_frame().sender(&cbl_map);
CodeBlob* caller_cb = caller_frame.cb();
guarantee(caller_cb != NULL && caller_cb->is_compiled(), "must be called from compiled method");
CompiledMethod* caller_nm = caller_cb->as_compiled_method_or_null();
+ *caller_is_c1 = caller_nm->is_c1();
// make sure caller is not getting deoptimized
// and removed before we are done with it.
// CLEANUP - with lazy deopt shouldn't need this lock
nmethodLocker caller_lock(caller_nm);
@@ -1475,19 +1479,18 @@
assert(!caller_frame.is_interpreted_frame() && !caller_frame.is_entry_frame(), "unexpected frame");
#endif /* ASSERT */
methodHandle callee_method;
bool is_optimized = false;
+ bool caller_is_c1 = false;
JRT_BLOCK
- callee_method = SharedRuntime::handle_ic_miss_helper(thread, is_optimized, CHECK_NULL);
+ callee_method = SharedRuntime::handle_ic_miss_helper(thread, is_optimized, caller_is_c1, CHECK_NULL);
// Return Method* through TLS
thread->set_vm_result_2(callee_method());
JRT_BLOCK_END
// return compiled code entry point after potential safepoints
- assert(callee_method->verified_code_entry() != NULL, "Jump to zero!");
- assert(callee_method->verified_value_ro_code_entry() != NULL, "Jump to zero!");
- return is_optimized ? callee_method->verified_code_entry() : callee_method->verified_value_ro_code_entry();
+ return entry_for_handle_wrong_method(callee_method, is_optimized, caller_is_c1);
JRT_END
// Handle call site that has been made non-entrant
JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method(JavaThread* thread))
@@ -1515,19 +1518,18 @@
}
// Must be compiled to compiled path which is safe to stackwalk
methodHandle callee_method;
bool is_optimized = false;
+ bool caller_is_c1 = false;
JRT_BLOCK
// Force resolving of caller (if we called from compiled frame)
- callee_method = SharedRuntime::reresolve_call_site(thread, is_optimized, CHECK_NULL);
+ callee_method = SharedRuntime::reresolve_call_site(thread, is_optimized, caller_is_c1, CHECK_NULL);
thread->set_vm_result_2(callee_method());
JRT_BLOCK_END
// return compiled code entry point after potential safepoints
- assert(callee_method->verified_code_entry() != NULL, "Jump to zero!");
- assert(callee_method->verified_value_ro_code_entry() != NULL, "Jump to zero!");
- return is_optimized ? callee_method->verified_code_entry() : callee_method->verified_value_ro_code_entry();
+ return entry_for_handle_wrong_method(callee_method, is_optimized, caller_is_c1);
JRT_END
// Handle abstract method call
JRT_BLOCK_ENTRY(address, SharedRuntime::handle_wrong_method_abstract(JavaThread* thread))
// Verbose error message for AbstractMethodError.
@@ -1561,55 +1563,64 @@
// resolve a static call and patch code
JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_static_call_C(JavaThread *thread ))
methodHandle callee_method;
+ bool caller_is_c1;
JRT_BLOCK
- callee_method = SharedRuntime::resolve_helper(thread, false, false, CHECK_NULL);
+ callee_method = SharedRuntime::resolve_helper(thread, false, false, &caller_is_c1, CHECK_NULL);
thread->set_vm_result_2(callee_method());
JRT_BLOCK_END
// return compiled code entry point after potential safepoints
- assert(callee_method->verified_code_entry() != NULL, "Jump to zero!");
- return callee_method->verified_code_entry();
+ address entry = caller_is_c1 ?
+ callee_method->verified_value_code_entry() : callee_method->verified_code_entry();
+ assert(entry != NULL, "Jump to zero!");
+ return entry;
JRT_END
// resolve virtual call and update inline cache to monomorphic
JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_virtual_call_C(JavaThread *thread ))
methodHandle callee_method;
+ bool caller_is_c1;
JRT_BLOCK
- callee_method = SharedRuntime::resolve_helper(thread, true, false, CHECK_NULL);
+ callee_method = SharedRuntime::resolve_helper(thread, true, false, &caller_is_c1, CHECK_NULL);
thread->set_vm_result_2(callee_method());
JRT_BLOCK_END
// return compiled code entry point after potential safepoints
- assert(callee_method->verified_value_ro_code_entry() != NULL, "Jump to zero!");
- return callee_method->verified_value_ro_code_entry();
+ address entry = caller_is_c1 ?
+ callee_method->verified_value_code_entry() : callee_method->verified_value_ro_code_entry();
+ assert(entry != NULL, "Jump to zero!");
+ return entry;
JRT_END
// Resolve a virtual call that can be statically bound (e.g., always
// monomorphic, so it has no inline cache). Patch code to resolved target.
JRT_BLOCK_ENTRY(address, SharedRuntime::resolve_opt_virtual_call_C(JavaThread *thread))
methodHandle callee_method;
+ bool caller_is_c1;
JRT_BLOCK
- callee_method = SharedRuntime::resolve_helper(thread, true, true, CHECK_NULL);
+ callee_method = SharedRuntime::resolve_helper(thread, true, true, &caller_is_c1, CHECK_NULL);
thread->set_vm_result_2(callee_method());
JRT_BLOCK_END
// return compiled code entry point after potential safepoints
- assert(callee_method->verified_code_entry() != NULL, "Jump to zero!");
- return callee_method->verified_code_entry();
+ address entry = caller_is_c1 ?
+ callee_method->verified_value_code_entry() : callee_method->verified_code_entry();
+ assert(entry != NULL, "Jump to zero!");
+ return entry;
JRT_END
// The handle_ic_miss_helper_internal function returns false if it failed due
// to either running out of vtable stubs or ic stubs due to IC transitions
// to transitional states. The needs_ic_stub_refill value will be set if
// the failure was due to running out of IC stubs, in which case handle_ic_miss_helper
// refills the IC stubs and tries again.
bool SharedRuntime::handle_ic_miss_helper_internal(Handle receiver, CompiledMethod* caller_nm,
const frame& caller_frame, methodHandle callee_method,
Bytecodes::Code bc, CallInfo& call_info,
- bool& needs_ic_stub_refill, bool& is_optimized, TRAPS) {
+ bool& needs_ic_stub_refill, bool& is_optimized, bool caller_is_c1, TRAPS) {
CompiledICLocker ml(caller_nm);
CompiledIC* inline_cache = CompiledIC_before(caller_nm, caller_frame.pc());
bool should_be_mono = false;
if (inline_cache->is_optimized()) {
if (TraceCallFixup) {
@@ -1654,19 +1665,20 @@
Klass* receiver_klass = receiver()->klass();
inline_cache->compute_monomorphic_entry(callee_method,
receiver_klass,
inline_cache->is_optimized(),
false, caller_nm->is_nmethod(),
+ caller_nm->is_c1(),
info, CHECK_false);
if (!inline_cache->set_to_monomorphic(info)) {
needs_ic_stub_refill = true;
return false;
}
} else if (!inline_cache->is_megamorphic() && !inline_cache->is_clean()) {
// Potential change to megamorphic
- bool successful = inline_cache->set_to_megamorphic(&call_info, bc, needs_ic_stub_refill, CHECK_false);
+ bool successful = inline_cache->set_to_megamorphic(&call_info, bc, needs_ic_stub_refill, caller_is_c1, CHECK_false);
if (needs_ic_stub_refill) {
return false;
}
if (!successful) {
if (!inline_cache->set_to_clean()) {
@@ -1678,11 +1690,11 @@
// Either clean or megamorphic
}
return true;
}
-methodHandle SharedRuntime::handle_ic_miss_helper(JavaThread *thread, bool& is_optimized, TRAPS) {
+methodHandle SharedRuntime::handle_ic_miss_helper(JavaThread *thread, bool& is_optimized, bool& caller_is_c1, TRAPS) {
ResourceMark rm(thread);
CallInfo call_info;
Bytecodes::Code bc;
// receiver is NULL for static calls. An exception is thrown for NULL
@@ -1698,11 +1710,11 @@
// plain ic_miss) and the site will be converted to an optimized virtual call site
// never to miss again. I don't believe C2 will produce code like this but if it
// did this would still be the correct thing to do for it too, hence no ifdef.
//
if (call_info.resolved_method()->can_be_statically_bound()) {
- methodHandle callee_method = SharedRuntime::reresolve_call_site(thread, is_optimized, CHECK_(methodHandle()));
+ methodHandle callee_method = SharedRuntime::reresolve_call_site(thread, is_optimized, caller_is_c1, CHECK_(methodHandle()));
if (TraceCallFixup) {
RegisterMap reg_map(thread, false);
frame caller_frame = thread->last_frame().sender(®_map);
ResourceMark rm(thread);
tty->print("converting IC miss to reresolve (%s) call to", Bytecodes::name(bc));
@@ -1748,16 +1760,17 @@
// that refills them.
RegisterMap reg_map(thread, false);
frame caller_frame = thread->last_frame().sender(®_map);
CodeBlob* cb = caller_frame.cb();
CompiledMethod* caller_nm = cb->as_compiled_method();
+ caller_is_c1 = caller_nm->is_c1();
for (;;) {
ICRefillVerifier ic_refill_verifier;
bool needs_ic_stub_refill = false;
bool successful = handle_ic_miss_helper_internal(receiver, caller_nm, caller_frame, callee_method,
- bc, call_info, needs_ic_stub_refill, is_optimized, CHECK_(methodHandle()));
+ bc, call_info, needs_ic_stub_refill, is_optimized, caller_is_c1, CHECK_(methodHandle()));
if (successful || !needs_ic_stub_refill) {
return callee_method;
} else {
InlineCacheBuffer::refill_ic_stubs();
}
@@ -1785,11 +1798,11 @@
// Resets a call-site in compiled code so it will get resolved again.
// This routines handles both virtual call sites, optimized virtual call
// sites, and static call sites. Typically used to change a call sites
// destination from compiled to interpreted.
//
-methodHandle SharedRuntime::reresolve_call_site(JavaThread *thread, bool& is_optimized, TRAPS) {
+methodHandle SharedRuntime::reresolve_call_site(JavaThread *thread, bool& is_optimized, bool& caller_is_c1, TRAPS) {
ResourceMark rm(thread);
RegisterMap reg_map(thread, false);
frame stub_frame = thread->last_frame();
assert(stub_frame.is_runtime_frame(), "must be a runtimeStub");
frame caller = stub_frame.sender(®_map);
@@ -1803,10 +1816,11 @@
address pc = caller.pc();
// Check for static or virtual call
bool is_static_call = false;
CompiledMethod* caller_nm = CodeCache::find_compiled(pc);
+ caller_is_c1 = caller_nm->is_c1();
// Default call_addr is the location of the "basic" call.
// Determine the address of the call we a reresolving. With
// Inline Caches we will always find a recognizable call.
// With Inline Caches disabled we may or may not find a
< prev index next >