mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-18 01:54:47 +02:00
8256425: Obsolete Biased Locking in JDK 18
Reviewed-by: kvn, dholmes, dcubed, rrich
This commit is contained in:
parent
595446bff4
commit
2fd7943ec1
165 changed files with 293 additions and 5261 deletions
|
@ -56,7 +56,6 @@
|
|||
#include "prims/vectorSupport.hpp"
|
||||
#include "prims/methodHandles.hpp"
|
||||
#include "runtime/atomic.hpp"
|
||||
#include "runtime/biasedLocking.hpp"
|
||||
#include "runtime/deoptimization.hpp"
|
||||
#include "runtime/escapeBarrier.hpp"
|
||||
#include "runtime/fieldDescriptor.hpp"
|
||||
|
@ -311,9 +310,6 @@ bool Deoptimization::deoptimize_objects_internal(JavaThread* thread, GrowableArr
|
|||
realloc_failures = rematerialize_objects(thread, Unpack_none, cm, deoptee, map, chunk, deoptimized_objects);
|
||||
}
|
||||
|
||||
// Revoke biases of objects with eliminated locks in the given frame.
|
||||
Deoptimization::revoke_for_object_deoptimization(deoptee_thread, deoptee, &map, thread);
|
||||
|
||||
// MonitorInfo structures used in eliminate_locks are not GC safe.
|
||||
NoSafepointVerifier no_safepoint;
|
||||
|
||||
|
@ -383,10 +379,6 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread
|
|||
}
|
||||
#endif // COMPILER2_OR_JVMCI
|
||||
|
||||
// Revoke biases, done with in java state.
|
||||
// No safepoints allowed after this
|
||||
revoke_from_deopt_handler(current, deoptee, &map);
|
||||
|
||||
// Ensure that no safepoint is taken after pointers have been stored
|
||||
// in fields of rematerialized objects. If a safepoint occurs from here on
|
||||
// out the java state residing in the vframeArray will be missed.
|
||||
|
@ -1442,20 +1434,10 @@ bool Deoptimization::relock_objects(JavaThread* thread, GrowableArray<MonitorInf
|
|||
if (!mon_info->owner_is_scalar_replaced()) {
|
||||
Handle obj(thread, mon_info->owner());
|
||||
markWord mark = obj->mark();
|
||||
if (UseBiasedLocking && mark.has_bias_pattern()) {
|
||||
// New allocated objects may have the mark set to anonymously biased.
|
||||
// Also the deoptimized method may called methods with synchronization
|
||||
// where the thread-local object is bias locked to the current thread.
|
||||
assert(mark.is_biased_anonymously() ||
|
||||
mark.biased_locker() == deoptee_thread, "should be locked to current thread");
|
||||
// Reset mark word to unbiased prototype.
|
||||
markWord unbiased_prototype = markWord::prototype().set_age(mark.age());
|
||||
obj->set_mark(unbiased_prototype);
|
||||
} else if (exec_mode == Unpack_none) {
|
||||
if (exec_mode == Unpack_none) {
|
||||
if (mark.has_locker() && fr.sp() > (intptr_t*)mark.locker()) {
|
||||
// With exec_mode == Unpack_none obj may be thread local and locked in
|
||||
// a callee frame. In this case the bias was revoked before in revoke_for_object_deoptimization().
|
||||
// Make the lock in the callee a recursive lock and restore the displaced header.
|
||||
// a callee frame. Make the lock in the callee a recursive lock and restore the displaced header.
|
||||
markWord dmw = mark.displaced_mark_helper();
|
||||
mark.locker()->set_displaced_header(markWord::encode((BasicLock*) NULL));
|
||||
obj->set_mark(dmw);
|
||||
|
@ -1595,98 +1577,6 @@ void Deoptimization::pop_frames_failed_reallocs(JavaThread* thread, vframeArray*
|
|||
}
|
||||
#endif
|
||||
|
||||
static void collect_monitors(compiledVFrame* cvf, GrowableArray<Handle>* objects_to_revoke,
|
||||
bool only_eliminated) {
|
||||
GrowableArray<MonitorInfo*>* monitors = cvf->monitors();
|
||||
Thread* thread = Thread::current();
|
||||
for (int i = 0; i < monitors->length(); i++) {
|
||||
MonitorInfo* mon_info = monitors->at(i);
|
||||
if (mon_info->eliminated() == only_eliminated &&
|
||||
!mon_info->owner_is_scalar_replaced() &&
|
||||
mon_info->owner() != NULL) {
|
||||
objects_to_revoke->append(Handle(thread, mon_info->owner()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void get_monitors_from_stack(GrowableArray<Handle>* objects_to_revoke, JavaThread* thread,
|
||||
frame fr, RegisterMap* map, bool only_eliminated) {
|
||||
// Unfortunately we don't have a RegisterMap available in most of
|
||||
// the places we want to call this routine so we need to walk the
|
||||
// stack again to update the register map.
|
||||
if (map == NULL || !map->update_map()) {
|
||||
StackFrameStream sfs(thread, true /* update */, true /* process_frames */);
|
||||
bool found = false;
|
||||
while (!found && !sfs.is_done()) {
|
||||
frame* cur = sfs.current();
|
||||
sfs.next();
|
||||
found = cur->id() == fr.id();
|
||||
}
|
||||
assert(found, "frame to be deoptimized not found on target thread's stack");
|
||||
map = sfs.register_map();
|
||||
}
|
||||
|
||||
vframe* vf = vframe::new_vframe(&fr, map, thread);
|
||||
compiledVFrame* cvf = compiledVFrame::cast(vf);
|
||||
// Revoke monitors' biases in all scopes
|
||||
while (!cvf->is_top()) {
|
||||
collect_monitors(cvf, objects_to_revoke, only_eliminated);
|
||||
cvf = compiledVFrame::cast(cvf->sender());
|
||||
}
|
||||
collect_monitors(cvf, objects_to_revoke, only_eliminated);
|
||||
}
|
||||
|
||||
void Deoptimization::revoke_from_deopt_handler(JavaThread* thread, frame fr, RegisterMap* map) {
|
||||
if (!UseBiasedLocking) {
|
||||
return;
|
||||
}
|
||||
assert(thread == Thread::current(), "should be");
|
||||
ResourceMark rm(thread);
|
||||
HandleMark hm(thread);
|
||||
GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>();
|
||||
get_monitors_from_stack(objects_to_revoke, thread, fr, map, false);
|
||||
|
||||
int len = objects_to_revoke->length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
oop obj = (objects_to_revoke->at(i))();
|
||||
BiasedLocking::revoke_own_lock(thread, objects_to_revoke->at(i));
|
||||
assert(!obj->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
}
|
||||
|
||||
// Revoke the bias of objects with eliminated locking to prepare subsequent relocking.
|
||||
void Deoptimization::revoke_for_object_deoptimization(JavaThread* deoptee_thread, frame fr,
|
||||
RegisterMap* map, JavaThread* thread) {
|
||||
if (!UseBiasedLocking) {
|
||||
return;
|
||||
}
|
||||
GrowableArray<Handle>* objects_to_revoke = new GrowableArray<Handle>();
|
||||
assert(KeepStackGCProcessedMark::stack_is_kept_gc_processed(deoptee_thread), "must be");
|
||||
// Collect monitors but only those with eliminated locking.
|
||||
get_monitors_from_stack(objects_to_revoke, deoptee_thread, fr, map, true);
|
||||
|
||||
int len = objects_to_revoke->length();
|
||||
for (int i = 0; i < len; i++) {
|
||||
oop obj = (objects_to_revoke->at(i))();
|
||||
markWord mark = obj->mark();
|
||||
if (!mark.has_bias_pattern() ||
|
||||
mark.is_biased_anonymously() || // eliminated locking does not bias an object if it wasn't before
|
||||
!obj->klass()->prototype_header().has_bias_pattern() || // bulk revoke ignores eliminated monitors
|
||||
(obj->klass()->prototype_header().bias_epoch() != mark.bias_epoch())) { // bulk rebias ignores eliminated monitors
|
||||
// We reach here regularly if there's just eliminated locking on obj.
|
||||
// We must not call BiasedLocking::revoke_own_lock() in this case, as we
|
||||
// would hit assertions because it is a prerequisite that there has to be
|
||||
// non-eliminated locking on obj by deoptee_thread.
|
||||
// Luckily we don't have to revoke here because obj has to be a
|
||||
// non-escaping obj and can be relocked without revoking the bias. See
|
||||
// Deoptimization::relock_objects().
|
||||
continue;
|
||||
}
|
||||
BiasedLocking::revoke(thread, objects_to_revoke->at(i));
|
||||
assert(!objects_to_revoke->at(i)->mark().has_bias_pattern(), "biases should be revoked by now");
|
||||
}
|
||||
}
|
||||
|
||||
void Deoptimization::deoptimize_single_frame(JavaThread* thread, frame fr, Deoptimization::DeoptReason reason) {
|
||||
assert(fr.can_be_deoptimized(), "checking frame type");
|
||||
|
||||
|
@ -1923,12 +1813,11 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr
|
|||
// decremented at the end of unpack_frames().
|
||||
current->inc_in_deopt_handler();
|
||||
|
||||
// We need to update the map if we have biased locking.
|
||||
#if INCLUDE_JVMCI
|
||||
// JVMCI might need to get an exception from the stack, which in turn requires the register map to be valid
|
||||
RegisterMap reg_map(current, true);
|
||||
#else
|
||||
RegisterMap reg_map(current, UseBiasedLocking);
|
||||
RegisterMap reg_map(current, false);
|
||||
#endif
|
||||
frame stub_frame = current->last_frame();
|
||||
frame fr = stub_frame.sender(®_map);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue