Skip to content

Commit

Permalink
8283306: re-resolving indirect call to non-entrant nmethod can crash
Browse files Browse the repository at this point in the history
Reviewed-by: thartmann, never
  • Loading branch information
dean-long committed May 5, 2022
1 parent 4957bc7 commit 6d7e446
Showing 1 changed file with 30 additions and 26 deletions.
56 changes: 30 additions & 26 deletions src/hotspot/share/runtime/sharedRuntime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1817,35 +1817,39 @@ methodHandle SharedRuntime::reresolve_call_site(TRAPS) {
// CLEANUP - with lazy deopt shouldn't need this lock
nmethodLocker nmlock(caller_nm);

// Check relocations for the matching call to 1) avoid false positives,
// and 2) determine the type.
if (call_addr != NULL) {
// On x86 the logic for finding a call instruction is blindly checking for a call opcode 5
// bytes back in the instruction stream so we must also check for reloc info.
RelocIterator iter(caller_nm, call_addr, call_addr+1);
int ret = iter.next(); // Get item
bool ret = iter.next(); // Get item
if (ret) {
assert(iter.addr() == call_addr, "must find call");
if (iter.type() == relocInfo::static_call_type) {
is_static_call = true;
} else {
assert(iter.type() == relocInfo::virtual_call_type ||
iter.type() == relocInfo::opt_virtual_call_type
, "unexpected relocInfo. type");
}
} else {
assert(!UseInlineCaches, "relocation info. must exist for this address");
}

// Cleaning the inline cache will force a new resolve. This is more robust
// than directly setting it to the new destination, since resolving of calls
// is always done through the same code path. (experience shows that it
// leads to very hard to track down bugs, if an inline cache gets updated
// to a wrong method). It should not be performance critical, since the
// resolve is only done once.

for (;;) {
ICRefillVerifier ic_refill_verifier;
if (!clear_ic_at_addr(caller_nm, call_addr, is_static_call)) {
InlineCacheBuffer::refill_ic_stubs();
} else {
break;
bool is_static_call = false;
switch (iter.type()) {
case relocInfo::static_call_type:
is_static_call = true;

case relocInfo::virtual_call_type:
case relocInfo::opt_virtual_call_type:
// Cleaning the inline cache will force a new resolve. This is more robust
// than directly setting it to the new destination, since resolving of calls
// is always done through the same code path. (experience shows that it
// leads to very hard to track down bugs, if an inline cache gets updated
// to a wrong method). It should not be performance critical, since the
// resolve is only done once.
guarantee(iter.addr() == call_addr, "must find call");
for (;;) {
ICRefillVerifier ic_refill_verifier;
if (!clear_ic_at_addr(caller_nm, call_addr, is_static_call)) {
InlineCacheBuffer::refill_ic_stubs();
} else {
break;
}
}
break;
default:
break;
}
}
}
Expand Down

1 comment on commit 6d7e446

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.