8247281: migrate ObjectMonitor::_object to OopStorage

Co-authored-by: Erik Österlund <erik.osterlund@oracle.com>
Co-authored-by: Daniel Daugherty <daniel.daugherty@oracle.com>
Reviewed-by: eosterlund, coleenp, dholmes, stefank, kbarrett, rkennke, sspitsyn
This commit is contained in:
Daniel D. Daugherty 2020-09-21 22:12:07 +00:00
parent f800af978c
commit d8921ed573
37 changed files with 211 additions and 344 deletions

View file

@ -58,7 +58,6 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
// Root scanning phases // Root scanning phases
_gc_par_phases[ThreadRoots] = new WorkerDataArray<double>("ThreadRoots", "Thread Roots (ms):", max_gc_threads); _gc_par_phases[ThreadRoots] = new WorkerDataArray<double>("ThreadRoots", "Thread Roots (ms):", max_gc_threads);
_gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray<double>("ObjectSynchronizerRoots", "ObjectSynchronizer Roots (ms):", max_gc_threads);
_gc_par_phases[CLDGRoots] = new WorkerDataArray<double>("CLDGRoots", "CLDG Roots (ms):", max_gc_threads); _gc_par_phases[CLDGRoots] = new WorkerDataArray<double>("CLDGRoots", "CLDG Roots (ms):", max_gc_threads);
AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>("AOTCodeRoots", "AOT Root Scan (ms):", max_gc_threads);) AOT_ONLY(_gc_par_phases[AOTCodeRoots] = new WorkerDataArray<double>("AOTCodeRoots", "AOT Root Scan (ms):", max_gc_threads);)
_gc_par_phases[CMRefRoots] = new WorkerDataArray<double>("CMRefRoots", "CM RefProcessor Roots (ms):", max_gc_threads); _gc_par_phases[CMRefRoots] = new WorkerDataArray<double>("CMRefRoots", "CM RefProcessor Roots (ms):", max_gc_threads);

View file

@ -48,7 +48,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
GCWorkerStart, GCWorkerStart,
ExtRootScan, ExtRootScan,
ThreadRoots, ThreadRoots,
ObjectSynchronizerRoots,
CLDGRoots, CLDGRoots,
AOT_ONLY(AOTCodeRoots COMMA) AOT_ONLY(AOTCodeRoots COMMA)
CMRefRoots, CMRefRoots,

View file

@ -180,13 +180,6 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
uint worker_id) { uint worker_id) {
OopClosure* strong_roots = closures->strong_oops(); OopClosure* strong_roots = closures->strong_oops();
{
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::ObjectSynchronizerRoots, worker_id);
if (_process_strong_tasks.try_claim_task(G1RP_PS_ObjectSynchronizer_oops_do)) {
ObjectSynchronizer::oops_do(strong_roots);
}
}
#if INCLUDE_AOT #if INCLUDE_AOT
if (UseAOT) { if (UseAOT) {
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::AOTCodeRoots, worker_id); G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::AOTCodeRoots, worker_id);

View file

@ -54,7 +54,6 @@ class G1RootProcessor : public StackObj {
enum G1H_process_roots_tasks { enum G1H_process_roots_tasks {
G1RP_PS_Universe_oops_do, G1RP_PS_Universe_oops_do,
G1RP_PS_ObjectSynchronizer_oops_do,
G1RP_PS_Management_oops_do, G1RP_PS_Management_oops_do,
G1RP_PS_ClassLoaderDataGraph_oops_do, G1RP_PS_ClassLoaderDataGraph_oops_do,
G1RP_PS_jvmti_oops_do, G1RP_PS_jvmti_oops_do,

View file

@ -2010,10 +2010,6 @@ static void mark_from_roots_work(ParallelRootType::Value root_type, uint worker_
PCMarkAndPushClosure mark_and_push_closure(cm); PCMarkAndPushClosure mark_and_push_closure(cm);
switch (root_type) { switch (root_type) {
case ParallelRootType::object_synchronizer:
ObjectSynchronizer::oops_do(&mark_and_push_closure);
break;
case ParallelRootType::class_loader_data: case ParallelRootType::class_loader_data:
{ {
CLDToOopClosure cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong); CLDToOopClosure cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong);
@ -2224,7 +2220,6 @@ void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
// General strong roots. // General strong roots.
Threads::oops_do(&oop_closure, NULL); Threads::oops_do(&oop_closure, NULL);
ObjectSynchronizer::oops_do(&oop_closure);
OopStorageSet::strong_oops_do(&oop_closure); OopStorageSet::strong_oops_do(&oop_closure);
CLDToOopClosure cld_closure(&oop_closure, ClassLoaderData::_claim_strong); CLDToOopClosure cld_closure(&oop_closure, ClassLoaderData::_claim_strong);
ClassLoaderDataGraph::cld_do(&cld_closure); ClassLoaderDataGraph::cld_do(&cld_closure);

View file

@ -34,7 +34,6 @@ public:
// The order reflects the order these roots are to be processed, // The order reflects the order these roots are to be processed,
// We do not want any holes in the enum as we enumerate these values by incrementing them. // We do not want any holes in the enum as we enumerate these values by incrementing them.
enum Value { enum Value {
object_synchronizer,
class_loader_data, class_loader_data,
code_cache, code_cache,
//"threads" are handled in parallel as a special case //"threads" are handled in parallel as a special case

View file

@ -92,10 +92,6 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i
PSPromoteRootsClosure roots_to_old_closure(pm); PSPromoteRootsClosure roots_to_old_closure(pm);
switch (root_type) { switch (root_type) {
case ParallelRootType::object_synchronizer:
ObjectSynchronizer::oops_do(&roots_closure);
break;
case ParallelRootType::class_loader_data: case ParallelRootType::class_loader_data:
{ {
PSScavengeCLDClosure cld_closure(pm); PSScavengeCLDClosure cld_closure(pm);

View file

@ -817,9 +817,6 @@ void GenCollectedHeap::process_roots(StrongRootsScope* scope,
bool is_par = scope->n_threads() > 1; bool is_par = scope->n_threads() > 1;
Threads::possibly_parallel_oops_do(is_par, strong_roots, roots_from_code_p); Threads::possibly_parallel_oops_do(is_par, strong_roots, roots_from_code_p);
if (_process_strong_tasks->try_claim_task(GCH_PS_ObjectSynchronizer_oops_do)) {
ObjectSynchronizer::oops_do(strong_roots);
}
#if INCLUDE_AOT #if INCLUDE_AOT
if (UseAOT && _process_strong_tasks->try_claim_task(GCH_PS_aot_oops_do)) { if (UseAOT && _process_strong_tasks->try_claim_task(GCH_PS_aot_oops_do)) {
AOTLoader::oops_do(strong_roots); AOTLoader::oops_do(strong_roots);

View file

@ -105,7 +105,6 @@ protected:
// The set of potentially parallel tasks in root scanning. // The set of potentially parallel tasks in root scanning.
enum GCH_strong_roots_tasks { enum GCH_strong_roots_tasks {
GCH_PS_ObjectSynchronizer_oops_do,
GCH_PS_OopStorageSet_oops_do, GCH_PS_OopStorageSet_oops_do,
GCH_PS_ClassLoaderDataGraph_oops_do, GCH_PS_ClassLoaderDataGraph_oops_do,
GCH_PS_CodeCache_oops_do, GCH_PS_CodeCache_oops_do,

View file

@ -38,7 +38,7 @@ class OopStorageSet : public AllStatic {
public: public:
// Must be updated when new OopStorages are introduced // Must be updated when new OopStorages are introduced
static const uint strong_count = 4 JVMTI_ONLY(+ 1); static const uint strong_count = 4 JVMTI_ONLY(+ 1);
static const uint weak_count = 4 JFR_ONLY(+ 1); static const uint weak_count = 5 JFR_ONLY(+ 1);
static const uint all_count = strong_count + weak_count; static const uint all_count = strong_count + weak_count;
private: private:

View file

@ -163,10 +163,6 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
HeapWord* scan_limit = space->scan_limit(); HeapWord* scan_limit = space->scan_limit();
while (cur_obj < scan_limit) { while (cur_obj < scan_limit) {
assert(!space->scanned_block_is_obj(cur_obj) ||
oop(cur_obj)->mark_raw().is_marked() || oop(cur_obj)->mark_raw().is_unlocked() ||
oop(cur_obj)->mark_raw().has_bias_pattern(),
"these are the only valid states during a mark sweep");
if (space->scanned_block_is_obj(cur_obj) && oop(cur_obj)->is_gc_marked()) { if (space->scanned_block_is_obj(cur_obj) && oop(cur_obj)->is_gc_marked()) {
// prefetch beyond cur_obj // prefetch beyond cur_obj
Prefetch::write(cur_obj, interval); Prefetch::write(cur_obj, interval);

View file

@ -256,7 +256,6 @@ private:
ShenandoahConcurrentMark* _cm; ShenandoahConcurrentMark* _cm;
TaskTerminator* _terminator; TaskTerminator* _terminator;
bool _dedup_string; bool _dedup_string;
ShenandoahSharedFlag _claimed_syncroots;
public: public:
ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) : ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) :
@ -294,9 +293,6 @@ public:
ShenandoahStoreValEnqueueBarrier ? &resolve_mark_cl : NULL, ShenandoahStoreValEnqueueBarrier ? &resolve_mark_cl : NULL,
do_nmethods ? &blobsCl : NULL); do_nmethods ? &blobsCl : NULL);
Threads::threads_do(&tc); Threads::threads_do(&tc);
if (ShenandoahStoreValEnqueueBarrier && _claimed_syncroots.try_set()) {
ObjectSynchronizer::oops_do(&resolve_mark_cl);
}
} else { } else {
ShenandoahMarkRefsClosure mark_cl(q, rp); ShenandoahMarkRefsClosure mark_cl(q, rp);
MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations); MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
@ -304,9 +300,6 @@ public:
ShenandoahStoreValEnqueueBarrier ? &mark_cl : NULL, ShenandoahStoreValEnqueueBarrier ? &mark_cl : NULL,
do_nmethods ? &blobsCl : NULL); do_nmethods ? &blobsCl : NULL);
Threads::threads_do(&tc); Threads::threads_do(&tc);
if (ShenandoahStoreValEnqueueBarrier && _claimed_syncroots.try_set()) {
ObjectSynchronizer::oops_do(&mark_cl);
}
} }
} }

View file

@ -39,7 +39,6 @@ class outputStream;
f(CNT_PREFIX ## CodeCacheRoots, DESC_PREFIX "Code Cache Roots") \ f(CNT_PREFIX ## CodeCacheRoots, DESC_PREFIX "Code Cache Roots") \
f(CNT_PREFIX ## VMStrongRoots, DESC_PREFIX "VM Strong Roots") \ f(CNT_PREFIX ## VMStrongRoots, DESC_PREFIX "VM Strong Roots") \
f(CNT_PREFIX ## VMWeakRoots, DESC_PREFIX "VM Weak Roots") \ f(CNT_PREFIX ## VMWeakRoots, DESC_PREFIX "VM Weak Roots") \
f(CNT_PREFIX ## ObjectSynchronizerRoots, DESC_PREFIX "Synchronizer Roots") \
f(CNT_PREFIX ## CLDGRoots, DESC_PREFIX "CLDG Roots") \ f(CNT_PREFIX ## CLDGRoots, DESC_PREFIX "CLDG Roots") \
f(CNT_PREFIX ## JVMTIWeakRoots, DESC_PREFIX "JVMTI Weak Roots") \ f(CNT_PREFIX ## JVMTIWeakRoots, DESC_PREFIX "JVMTI Weak Roots") \
f(CNT_PREFIX ## StringDedupTableRoots, DESC_PREFIX "Dedup Table Roots") \ f(CNT_PREFIX ## StringDedupTableRoots, DESC_PREFIX "Dedup Table Roots") \

View file

@ -36,26 +36,6 @@
#include "memory/resourceArea.hpp" #include "memory/resourceArea.hpp"
#include "runtime/thread.hpp" #include "runtime/thread.hpp"
ShenandoahSerialRoot::ShenandoahSerialRoot(ShenandoahSerialRoot::OopsDo oops_do,
ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase) :
_oops_do(oops_do), _phase(phase), _par_phase(par_phase) {
}
void ShenandoahSerialRoot::oops_do(OopClosure* cl, uint worker_id) {
if (_claimed.try_set()) {
ShenandoahWorkerTimingsTracker timer(_phase, _par_phase, worker_id);
_oops_do(cl);
}
}
ShenandoahSerialRoots::ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase) :
_object_synchronizer_root(&ObjectSynchronizer::oops_do, phase, ShenandoahPhaseTimings::ObjectSynchronizerRoots) {
}
void ShenandoahSerialRoots::oops_do(OopClosure* cl, uint worker_id) {
_object_synchronizer_root.oops_do(cl, worker_id);
}
ShenandoahWeakSerialRoot::ShenandoahWeakSerialRoot(ShenandoahWeakSerialRoot::WeakOopsDo weak_oops_do, ShenandoahWeakSerialRoot::ShenandoahWeakSerialRoot(ShenandoahWeakSerialRoot::WeakOopsDo weak_oops_do,
ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase) : ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase par_phase) :
_weak_oops_do(weak_oops_do), _phase(phase), _par_phase(par_phase) { _weak_oops_do(weak_oops_do), _phase(phase), _par_phase(par_phase) {
@ -179,7 +159,6 @@ ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahPhaseTimings::Phase p
ShenandoahRootScanner::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) : ShenandoahRootScanner::ShenandoahRootScanner(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase), ShenandoahRootProcessor(phase),
_serial_roots(phase),
_thread_roots(phase, n_workers > 1) { _thread_roots(phase, n_workers > 1) {
nmethod::oops_do_marking_prologue(); nmethod::oops_do_marking_prologue();
} }
@ -207,26 +186,14 @@ void ShenandoahRootScanner::roots_do(uint worker_id, OopClosure* oops, CLDClosur
assert(clds != NULL, "Only possible with CLD closure"); assert(clds != NULL, "Only possible with CLD closure");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
ResourceMark rm; ResourceMark rm;
// Process serial-claiming roots first
_serial_roots.oops_do(oops, worker_id);
// Process heavy-weight/fully parallel roots the last
_thread_roots.threads_do(&tc_cl, worker_id); _thread_roots.threads_do(&tc_cl, worker_id);
} }
void ShenandoahRootScanner::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) { void ShenandoahRootScanner::strong_roots_do(uint worker_id, OopClosure* oops, CLDClosure* clds, CodeBlobClosure* code, ThreadClosure* tc) {
assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading"); assert(ShenandoahHeap::heap()->unload_classes(), "Should be used during class unloading");
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc); ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
ResourceMark rm; ResourceMark rm;
// Process serial-claiming roots first
_serial_roots.oops_do(oops, worker_id);
// Process heavy-weight/fully parallel roots the last
_thread_roots.threads_do(&tc_cl, worker_id); _thread_roots.threads_do(&tc_cl, worker_id);
} }
@ -235,7 +202,6 @@ ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers,
bool stw_roots_processing, bool stw_roots_processing,
bool stw_class_unloading) : bool stw_class_unloading) :
ShenandoahRootProcessor(phase), ShenandoahRootProcessor(phase),
_serial_roots(phase),
_vm_roots(phase), _vm_roots(phase),
_cld_roots(phase, n_workers), _cld_roots(phase, n_workers),
_thread_roots(phase, n_workers > 1), _thread_roots(phase, n_workers > 1),
@ -256,7 +222,6 @@ void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
AlwaysTrueClosure always_true; AlwaysTrueClosure always_true;
// Process serial-claiming roots first // Process serial-claiming roots first
_serial_roots.oops_do(oops, worker_id);
_serial_weak_roots.weak_oops_do(oops, worker_id); _serial_weak_roots.weak_oops_do(oops, worker_id);
// Process light-weight/limited parallel roots then // Process light-weight/limited parallel roots then
@ -281,7 +246,6 @@ void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) : ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase), ShenandoahRootProcessor(phase),
_serial_roots(phase),
_vm_roots(phase), _vm_roots(phase),
_cld_roots(phase, n_workers), _cld_roots(phase, n_workers),
_thread_roots(phase, n_workers > 1), _thread_roots(phase, n_workers > 1),
@ -293,7 +257,6 @@ ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimi
ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) : ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
ShenandoahRootProcessor(phase), ShenandoahRootProcessor(phase),
_serial_roots(phase),
_vm_roots(phase), _vm_roots(phase),
_cld_roots(phase, n_workers), _cld_roots(phase, n_workers),
_thread_roots(phase, n_workers > 1), _thread_roots(phase, n_workers > 1),
@ -314,7 +277,6 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
AlwaysTrueClosure always_true; AlwaysTrueClosure always_true;
// Process serial-claiming roots first // Process serial-claiming roots first
_serial_roots.oops_do(oops, worker_id);
_serial_weak_roots.weak_oops_do(oops, worker_id); _serial_weak_roots.weak_oops_do(oops, worker_id);
// Process light-weight/limited parallel roots then // Process light-weight/limited parallel roots then
@ -330,7 +292,6 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() : ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
ShenandoahRootProcessor(ShenandoahPhaseTimings::heap_iteration_roots), ShenandoahRootProcessor(ShenandoahPhaseTimings::heap_iteration_roots),
_serial_roots(ShenandoahPhaseTimings::heap_iteration_roots),
_thread_roots(ShenandoahPhaseTimings::heap_iteration_roots, false /*is par*/), _thread_roots(ShenandoahPhaseTimings::heap_iteration_roots, false /*is par*/),
_vm_roots(ShenandoahPhaseTimings::heap_iteration_roots), _vm_roots(ShenandoahPhaseTimings::heap_iteration_roots),
_cld_roots(ShenandoahPhaseTimings::heap_iteration_roots, 1), _cld_roots(ShenandoahPhaseTimings::heap_iteration_roots, 1),
@ -351,7 +312,6 @@ ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
ResourceMark rm; ResourceMark rm;
// Process serial-claiming roots first // Process serial-claiming roots first
_serial_roots.oops_do(oops, 0);
_serial_weak_roots.weak_oops_do(oops, 0); _serial_weak_roots.weak_oops_do(oops, 0);
// Process light-weight/limited parallel roots then // Process light-weight/limited parallel roots then

View file

@ -49,14 +49,6 @@ public:
void oops_do(OopClosure* cl, uint worker_id); void oops_do(OopClosure* cl, uint worker_id);
}; };
class ShenandoahSerialRoots {
private:
ShenandoahSerialRoot _object_synchronizer_root;
public:
ShenandoahSerialRoots(ShenandoahPhaseTimings::Phase phase);
void oops_do(OopClosure* cl, uint worker_id);
};
class ShenandoahWeakSerialRoot { class ShenandoahWeakSerialRoot {
typedef void (*WeakOopsDo)(BoolObjectClosure*, OopClosure*); typedef void (*WeakOopsDo)(BoolObjectClosure*, OopClosure*);
private: private:
@ -199,7 +191,6 @@ public:
class ShenandoahRootScanner : public ShenandoahRootProcessor { class ShenandoahRootScanner : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots;
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
public: public:
@ -238,7 +229,6 @@ public:
// root scanning // root scanning
class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor { class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots;
ShenandoahThreadRoots _thread_roots; ShenandoahThreadRoots _thread_roots;
ShenandoahVMRoots<false /*concurrent*/> _vm_roots; ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/> ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
@ -257,7 +247,6 @@ public:
// Evacuate all roots at a safepoint // Evacuate all roots at a safepoint
class ShenandoahRootEvacuator : public ShenandoahRootProcessor { class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots;
ShenandoahVMRoots<false /*concurrent*/> _vm_roots; ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots; _cld_roots;
@ -278,7 +267,6 @@ public:
// Update all roots at a safepoint // Update all roots at a safepoint
class ShenandoahRootUpdater : public ShenandoahRootProcessor { class ShenandoahRootUpdater : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots;
ShenandoahVMRoots<false /*concurrent*/> _vm_roots; ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots; _cld_roots;
@ -298,7 +286,6 @@ public:
// Adjuster all roots at a safepoint during full gc // Adjuster all roots at a safepoint during full gc
class ShenandoahRootAdjuster : public ShenandoahRootProcessor { class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
private: private:
ShenandoahSerialRoots _serial_roots;
ShenandoahVMRoots<false /*concurrent*/> _vm_roots; ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/> ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
_cld_roots; _cld_roots;

View file

@ -195,7 +195,6 @@ void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAliv
CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong); CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong);
// Process serial-claiming roots first // Process serial-claiming roots first
_serial_roots.oops_do(keep_alive, worker_id);
_serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id); _serial_weak_roots.weak_oops_do(is_alive, keep_alive, worker_id);
// Process light-weight/limited parallel roots then // Process light-weight/limited parallel roots then

View file

@ -74,7 +74,6 @@ void ShenandoahRootVerifier::oops_do(OopClosure* oops) {
if (verify(SerialRoots)) { if (verify(SerialRoots)) {
shenandoah_assert_safepoint(); shenandoah_assert_safepoint();
ObjectSynchronizer::oops_do(oops);
} }
if (verify(JNIHandleRoots)) { if (verify(JNIHandleRoots)) {
@ -118,7 +117,6 @@ void ShenandoahRootVerifier::roots_do(OopClosure* oops) {
ClassLoaderDataGraph::cld_do(&clds); ClassLoaderDataGraph::cld_do(&clds);
JNIHandles::oops_do(oops); JNIHandles::oops_do(oops);
ObjectSynchronizer::oops_do(oops);
Universe::vm_global()->oops_do(oops); Universe::vm_global()->oops_do(oops);
AlwaysTrueClosure always_true; AlwaysTrueClosure always_true;
@ -143,7 +141,6 @@ void ShenandoahRootVerifier::strong_roots_do(OopClosure* oops) {
ClassLoaderDataGraph::roots_cld_do(&clds, NULL); ClassLoaderDataGraph::roots_cld_do(&clds, NULL);
JNIHandles::oops_do(oops); JNIHandles::oops_do(oops);
ObjectSynchronizer::oops_do(oops);
Universe::vm_global()->oops_do(oops); Universe::vm_global()->oops_do(oops);
// Do thread roots the last. This allows verification code to find // Do thread roots the last. This allows verification code to find

View file

@ -54,7 +54,6 @@
static const ZStatSubPhase ZSubPhasePauseRootsSetup("Pause Roots Setup"); static const ZStatSubPhase ZSubPhasePauseRootsSetup("Pause Roots Setup");
static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots"); static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots");
static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown"); static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown");
static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer");
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport"); static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport");
static const ZStatSubPhase ZSubPhasePauseRootsVMThread("Pause Roots VM Thread"); static const ZStatSubPhase ZSubPhasePauseRootsVMThread("Pause Roots VM Thread");
static const ZStatSubPhase ZSubPhasePauseRootsJavaThreads("Pause Roots Java Threads"); static const ZStatSubPhase ZSubPhasePauseRootsJavaThreads("Pause Roots Java Threads");
@ -184,7 +183,6 @@ void ZJavaThreadsIterator::threads_do(ThreadClosure* cl) {
ZRootsIterator::ZRootsIterator(bool visit_jvmti_weak_export) : ZRootsIterator::ZRootsIterator(bool visit_jvmti_weak_export) :
_visit_jvmti_weak_export(visit_jvmti_weak_export), _visit_jvmti_weak_export(visit_jvmti_weak_export),
_java_threads_iter(), _java_threads_iter(),
_object_synchronizer(this),
_jvmti_weak_export(this), _jvmti_weak_export(this),
_vm_thread(this), _vm_thread(this),
_java_threads(this), _java_threads(this),
@ -211,11 +209,6 @@ ZRootsIterator::~ZRootsIterator() {
COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::update_pointers()); COMPILER2_OR_JVMCI_PRESENT(DerivedPointerTable::update_pointers());
} }
void ZRootsIterator::do_object_synchronizer(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhasePauseRootsObjectSynchronizer);
ObjectSynchronizer::oops_do(cl);
}
void ZRootsIterator::do_jvmti_weak_export(ZRootsIteratorClosure* cl) { void ZRootsIterator::do_jvmti_weak_export(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhasePauseRootsJVMTIWeakExport); ZStatTimer timer(ZSubPhasePauseRootsJVMTIWeakExport);
AlwaysTrueClosure always_alive; AlwaysTrueClosure always_alive;
@ -241,7 +234,6 @@ void ZRootsIterator::do_code_cache(ZRootsIteratorClosure* cl) {
void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl) { void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
ZStatTimer timer(ZSubPhasePauseRoots); ZStatTimer timer(ZSubPhasePauseRoots);
_object_synchronizer.oops_do(cl);
_vm_thread.oops_do(cl); _vm_thread.oops_do(cl);
_java_threads.oops_do(cl); _java_threads.oops_do(cl);
if (!ClassUnloading) { if (!ClassUnloading) {

View file

@ -110,13 +110,11 @@ private:
const bool _visit_jvmti_weak_export; const bool _visit_jvmti_weak_export;
ZJavaThreadsIterator _java_threads_iter; ZJavaThreadsIterator _java_threads_iter;
void do_object_synchronizer(ZRootsIteratorClosure* cl);
void do_jvmti_weak_export(ZRootsIteratorClosure* cl); void do_jvmti_weak_export(ZRootsIteratorClosure* cl);
void do_vm_thread(ZRootsIteratorClosure* cl); void do_vm_thread(ZRootsIteratorClosure* cl);
void do_java_threads(ZRootsIteratorClosure* cl); void do_java_threads(ZRootsIteratorClosure* cl);
void do_code_cache(ZRootsIteratorClosure* cl); void do_code_cache(ZRootsIteratorClosure* cl);
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_object_synchronizer> _object_synchronizer;
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export; ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_jvmti_weak_export> _jvmti_weak_export;
ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_vm_thread> _vm_thread; ZSerialOopsDo<ZRootsIterator, &ZRootsIterator::do_vm_thread> _vm_thread;
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_java_threads> _java_threads; ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_java_threads> _java_threads;

View file

@ -71,7 +71,6 @@ void RootSetClosure<Delegate>::process() {
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure); ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
// We don't follow code blob oops, because they have misaligned oops. // We don't follow code blob oops, because they have misaligned oops.
Threads::oops_do(this, NULL); Threads::oops_do(this, NULL);
ObjectSynchronizer::oops_do(this);
OopStorageSet::strong_oops_do(this); OopStorageSet::strong_oops_do(this);
AOTLoader::oops_do(this); AOTLoader::oops_do(this);
} }

View file

@ -95,7 +95,6 @@ class ReferenceToRootClosure : public StackObj {
bool _complete; bool _complete;
bool do_cldg_roots(); bool do_cldg_roots();
bool do_object_synchronizer_roots();
bool do_oop_storage_roots(); bool do_oop_storage_roots();
bool do_string_table_roots(); bool do_string_table_roots();
bool do_aot_loader_roots(); bool do_aot_loader_roots();
@ -129,13 +128,6 @@ bool ReferenceToRootClosure::do_cldg_roots() {
return rlc.complete(); return rlc.complete();
} }
bool ReferenceToRootClosure::do_object_synchronizer_roots() {
assert(!complete(), "invariant");
ReferenceLocateClosure rlc(_callback, OldObjectRoot::_object_synchronizer, OldObjectRoot::_type_undetermined, NULL);
ObjectSynchronizer::oops_do(&rlc);
return rlc.complete();
}
bool ReferenceToRootClosure::do_oop_storage_roots() { bool ReferenceToRootClosure::do_oop_storage_roots() {
int i = 0; int i = 0;
for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) { for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) {
@ -171,11 +163,6 @@ bool ReferenceToRootClosure::do_roots() {
return true; return true;
} }
if (do_object_synchronizer_roots()) {
_complete = true;
return true;
}
if (do_oop_storage_roots()) { if (do_oop_storage_roots()) {
_complete = true; _complete = true;
return true; return true;

View file

@ -54,8 +54,6 @@ const char* OldObjectRoot::system_description(System system) {
return "Universe"; return "Universe";
case _threads: case _threads:
return "Threads"; return "Threads";
case _object_synchronizer:
return "Object Monitor";
case _class_loader_data: case _class_loader_data:
return "Class Loader Data"; return "Class Loader Data";
case _code_cache: case _code_cache:

View file

@ -36,7 +36,6 @@ class OldObjectRoot : public AllStatic {
_threads, _threads,
_strong_oop_storage_set_first, _strong_oop_storage_set_first,
_strong_oop_storage_set_last = _strong_oop_storage_set_first + OopStorageSet::strong_count - 1, _strong_oop_storage_set_last = _strong_oop_storage_set_first + OopStorageSet::strong_count - 1,
_object_synchronizer,
_class_loader_data, _class_loader_data,
_code_cache, _code_cache,
_aot, _aot,

View file

@ -31,8 +31,11 @@
#include "utilities/ostream.hpp" #include "utilities/ostream.hpp"
WeakHandle::WeakHandle(OopStorage* storage, Handle obj) : WeakHandle::WeakHandle(OopStorage* storage, Handle obj) :
WeakHandle(storage, obj()) {}
WeakHandle::WeakHandle(OopStorage* storage, oop obj) :
_obj(storage->allocate()) { _obj(storage->allocate()) {
assert(obj() != NULL, "no need to create weak null oop"); assert(obj != NULL, "no need to create weak null oop");
if (_obj == NULL) { if (_obj == NULL) {
vm_exit_out_of_memory(sizeof(oop*), OOM_MALLOC_ERROR, vm_exit_out_of_memory(sizeof(oop*), OOM_MALLOC_ERROR,
@ -40,7 +43,7 @@ WeakHandle::WeakHandle(OopStorage* storage, Handle obj) :
storage->name()); storage->name());
} }
NativeAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, obj()); NativeAccess<ON_PHANTOM_OOP_REF>::oop_store(_obj, obj);
} }
void WeakHandle::release(OopStorage* storage) const { void WeakHandle::release(OopStorage* storage) const {

View file

@ -48,6 +48,7 @@ class WeakHandle {
public: public:
WeakHandle() : _obj(NULL) {} // needed for init WeakHandle() : _obj(NULL) {} // needed for init
WeakHandle(OopStorage* storage, Handle obj); WeakHandle(OopStorage* storage, Handle obj);
WeakHandle(OopStorage* storage, oop obj);
inline oop resolve() const; inline oop resolve() const;
inline oop peek() const; inline oop peek() const;

View file

@ -1751,7 +1751,6 @@ static jvmtiHeapRootKind toJvmtiHeapRootKind(jvmtiHeapReferenceKind kind) {
switch (kind) { switch (kind) {
case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: return JVMTI_HEAP_ROOT_JNI_GLOBAL; case JVMTI_HEAP_REFERENCE_JNI_GLOBAL: return JVMTI_HEAP_ROOT_JNI_GLOBAL;
case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: return JVMTI_HEAP_ROOT_SYSTEM_CLASS; case JVMTI_HEAP_REFERENCE_SYSTEM_CLASS: return JVMTI_HEAP_ROOT_SYSTEM_CLASS;
case JVMTI_HEAP_REFERENCE_MONITOR: return JVMTI_HEAP_ROOT_MONITOR;
case JVMTI_HEAP_REFERENCE_STACK_LOCAL: return JVMTI_HEAP_ROOT_STACK_LOCAL; case JVMTI_HEAP_REFERENCE_STACK_LOCAL: return JVMTI_HEAP_ROOT_STACK_LOCAL;
case JVMTI_HEAP_REFERENCE_JNI_LOCAL: return JVMTI_HEAP_ROOT_JNI_LOCAL; case JVMTI_HEAP_REFERENCE_JNI_LOCAL: return JVMTI_HEAP_ROOT_JNI_LOCAL;
case JVMTI_HEAP_REFERENCE_THREAD: return JVMTI_HEAP_ROOT_THREAD; case JVMTI_HEAP_REFERENCE_THREAD: return JVMTI_HEAP_ROOT_THREAD;
@ -3017,13 +3016,6 @@ inline bool VM_HeapWalkOperation::collect_simple_roots() {
return false; return false;
} }
// Inflated monitors
blk.set_kind(JVMTI_HEAP_REFERENCE_MONITOR);
ObjectSynchronizer::oops_do(&blk);
if (blk.stopped()) {
return false;
}
// threads are now handled in collect_stack_roots() // threads are now handled in collect_stack_roots()
// Other kinds of roots maintained by HotSpot // Other kinds of roots maintained by HotSpot

View file

@ -24,6 +24,8 @@
#include "precompiled.hpp" #include "precompiled.hpp"
#include "classfile/vmSymbols.hpp" #include "classfile/vmSymbols.hpp"
#include "gc/shared/oopStorage.hpp"
#include "gc/shared/oopStorageSet.hpp"
#include "jfr/jfrEvents.hpp" #include "jfr/jfrEvents.hpp"
#include "jfr/support/jfrThreadId.hpp" #include "jfr/support/jfrThreadId.hpp"
#include "logging/log.hpp" #include "logging/log.hpp"
@ -114,6 +116,8 @@ static int Knob_PreSpin = 10; // 20-100 likely better
DEBUG_ONLY(static volatile bool InitDone = false;) DEBUG_ONLY(static volatile bool InitDone = false;)
OopStorage* ObjectMonitor::_oop_storage = NULL;
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Theory of operations -- Monitors lists, thread residency, etc: // Theory of operations -- Monitors lists, thread residency, etc:
// //
@ -237,6 +241,53 @@ void ObjectMonitor::operator delete[] (void *p) {
operator delete(p); operator delete(p);
} }
// Check that object() and set_object() are called from the right context:
static void check_object_context() {
#ifdef ASSERT
Thread* self = Thread::current();
if (self->is_Java_thread()) {
// Mostly called from JavaThreads so sanity check the thread state.
JavaThread* jt = self->as_Java_thread();
switch (jt->thread_state()) {
case _thread_in_vm: // the usual case
case _thread_in_Java: // during deopt
break;
default:
fatal("called from an unsafe thread state");
}
assert(jt->is_active_Java_thread(), "must be active JavaThread");
} else {
// However, ThreadService::get_current_contended_monitor()
// can call here via the VMThread so sanity check it.
assert(self->is_VM_thread(), "must be");
}
#endif // ASSERT
}
oop ObjectMonitor::object() const {
check_object_context();
if (_object.is_null()) {
return NULL;
}
return _object.resolve();
}
oop ObjectMonitor::object_peek() const {
if (_object.is_null()) {
return NULL;
}
return _object.peek();
}
void ObjectMonitor::set_object(oop obj) {
check_object_context();
if (_object.is_null()) {
_object = WeakHandle(_oop_storage, obj);
} else {
_object.replace(obj);
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Enter support // Enter support
@ -446,10 +497,10 @@ void ObjectMonitor::install_displaced_markword_in_object(const oop obj) {
OrderAccess::loadload(); OrderAccess::loadload();
} }
const oop l_object = object(); const oop l_object = object_peek();
if (l_object == NULL) { if (l_object == NULL) {
// ObjectMonitor's object ref has already been cleared by async // ObjectMonitor's object ref has already been cleared by async
// deflation so we're done here. // deflation or GC so we're done here.
return; return;
} }
assert(l_object == obj, "object=" INTPTR_FORMAT " must equal obj=" assert(l_object == obj, "object=" INTPTR_FORMAT " must equal obj="
@ -703,7 +754,6 @@ void ObjectMonitor::EnterI(TRAPS) {
// In addition, Self.TState is stable. // In addition, Self.TState is stable.
assert(_owner == Self, "invariant"); assert(_owner == Self, "invariant");
assert(object() != NULL, "invariant");
UnlinkAfterAcquire(Self, &node); UnlinkAfterAcquire(Self, &node);
if (_succ == Self) _succ = NULL; if (_succ == Self) _succ = NULL;
@ -2055,6 +2105,8 @@ void ObjectMonitor::Initialize() {
#undef NEWPERFVARIABLE #undef NEWPERFVARIABLE
} }
_oop_storage = OopStorageSet::create_weak("ObjectSynchronizer Weak");
DEBUG_ONLY(InitDone = true;) DEBUG_ONLY(InitDone = true;)
} }
@ -2103,7 +2155,7 @@ void ObjectMonitor::print() const { print_on(tty); }
void ObjectMonitor::print_debug_style_on(outputStream* st) const { void ObjectMonitor::print_debug_style_on(outputStream* st) const {
st->print_cr("(ObjectMonitor*) " INTPTR_FORMAT " = {", p2i(this)); st->print_cr("(ObjectMonitor*) " INTPTR_FORMAT " = {", p2i(this));
st->print_cr(" _header = " INTPTR_FORMAT, header().value()); st->print_cr(" _header = " INTPTR_FORMAT, header().value());
st->print_cr(" _object = " INTPTR_FORMAT, p2i(object())); st->print_cr(" _object = " INTPTR_FORMAT, p2i(object_peek()));
st->print(" _allocation_state = "); st->print(" _allocation_state = ");
if (is_free()) { if (is_free()) {
st->print("Free"); st->print("Free");

View file

@ -28,6 +28,7 @@
#include "memory/allocation.hpp" #include "memory/allocation.hpp"
#include "memory/padded.hpp" #include "memory/padded.hpp"
#include "oops/markWord.hpp" #include "oops/markWord.hpp"
#include "oops/weakHandle.hpp"
#include "runtime/os.hpp" #include "runtime/os.hpp"
#include "runtime/park.hpp" #include "runtime/park.hpp"
#include "runtime/perfData.hpp" #include "runtime/perfData.hpp"
@ -132,14 +133,17 @@ class ObjectMonitor {
friend class VMStructs; friend class VMStructs;
JVMCI_ONLY(friend class JVMCIVMStructs;) JVMCI_ONLY(friend class JVMCIVMStructs;)
static OopStorage* _oop_storage;
// The sync code expects the header field to be at offset zero (0). // The sync code expects the header field to be at offset zero (0).
// Enforced by the assert() in header_addr(). // Enforced by the assert() in header_addr().
volatile markWord _header; // displaced object header word - mark volatile markWord _header; // displaced object header word - mark
void* volatile _object; // backward object pointer - strong root WeakHandle _object; // backward object pointer
typedef enum { typedef enum {
Free = 0, // Free must be 0 for monitor to be free after memset(..,0,..). Free = 0, // Free must be 0 for monitor to be free after memset(..,0,..).
New, New,
Old Old,
ChainMarker
} AllocationState; } AllocationState;
AllocationState _allocation_state; AllocationState _allocation_state;
// Separate _header and _owner on different cache lines since both can // Separate _header and _owner on different cache lines since both can
@ -148,7 +152,7 @@ class ObjectMonitor {
// change until deflation so _object and _allocation_state are good // change until deflation so _object and _allocation_state are good
// choices to share the cache line with _header. // choices to share the cache line with _header.
DEFINE_PAD_MINUS_SIZE(0, OM_CACHE_LINE_SIZE, sizeof(volatile markWord) + DEFINE_PAD_MINUS_SIZE(0, OM_CACHE_LINE_SIZE, sizeof(volatile markWord) +
sizeof(void* volatile) + sizeof(AllocationState)); sizeof(WeakHandle) + sizeof(AllocationState));
// Used by async deflation as a marker in the _owner field: // Used by async deflation as a marker in the _owner field:
#define DEFLATER_MARKER reinterpret_cast<void*>(-1) #define DEFLATER_MARKER reinterpret_cast<void*>(-1)
void* volatile _owner; // pointer to owning thread OR BasicLock void* volatile _owner; // pointer to owning thread OR BasicLock
@ -329,6 +333,7 @@ class ObjectMonitor {
public: public:
oop object() const; oop object() const;
oop object_peek() const;
oop* object_addr(); oop* object_addr();
void set_object(oop obj); void set_object(oop obj);
void release_set_allocation_state(AllocationState s); void release_set_allocation_state(AllocationState s);
@ -338,6 +343,7 @@ class ObjectMonitor {
bool is_free() const; bool is_free() const;
bool is_old() const; bool is_old() const;
bool is_new() const; bool is_new() const;
bool is_chainmarker() const;
// Returns true if the specified thread owns the ObjectMonitor. Otherwise // Returns true if the specified thread owns the ObjectMonitor. Otherwise
// returns false and throws IllegalMonitorStateException (IMSE). // returns false and throws IllegalMonitorStateException (IMSE).

View file

@ -92,24 +92,15 @@ inline void ObjectMonitor::clear_common() {
assert(contentions() <= 0, "must not be positive: contentions=%d", contentions()); assert(contentions() <= 0, "must not be positive: contentions=%d", contentions());
assert(_waiters == 0, "must be 0: waiters=%d", _waiters); assert(_waiters == 0, "must be 0: waiters=%d", _waiters);
assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions); assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions);
assert(object() != NULL, "must be non-NULL");
set_allocation_state(Free); set_allocation_state(Free);
set_object(NULL); set_object(NULL);
} }
inline oop ObjectMonitor::object() const {
return (oop)_object;
}
inline oop* ObjectMonitor::object_addr() { inline oop* ObjectMonitor::object_addr() {
return (oop*)&_object; return (oop*)&_object;
} }
inline void ObjectMonitor::set_object(oop obj) {
_object = (void*)obj;
}
// Return number of threads contending for this monitor. // Return number of threads contending for this monitor.
inline jint ObjectMonitor::contentions() const { inline jint ObjectMonitor::contentions() const {
return Atomic::load(&_contentions); return Atomic::load(&_contentions);
@ -223,6 +214,10 @@ inline bool ObjectMonitor::is_new() const {
return _allocation_state == New; return _allocation_state == New;
} }
inline bool ObjectMonitor::is_chainmarker() const {
return _allocation_state == ChainMarker;
}
// The _next_om field can be concurrently read and modified so we // The _next_om field can be concurrently read and modified so we
// use Atomic operations to disable compiler optimizations that // use Atomic operations to disable compiler optimizations that
// might try to elide loading and/or storing this field. // might try to elide loading and/or storing this field.

View file

@ -159,8 +159,6 @@ struct ObjectMonitorListGlobals {
}; };
static ObjectMonitorListGlobals om_list_globals; static ObjectMonitorListGlobals om_list_globals;
#define CHAINMARKER (cast_to_oop<intptr_t>(-1))
// =====================> Spin-lock functions // =====================> Spin-lock functions
@ -510,10 +508,10 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
if (mark.has_monitor()) { if (mark.has_monitor()) {
ObjectMonitor* const m = mark.monitor(); ObjectMonitor* const m = mark.monitor();
// An async deflation can race us before we manage to make the // An async deflation or GC can race us before we manage to make
// ObjectMonitor busy by setting the owner below. If we detect // the ObjectMonitor busy by setting the owner below. If we detect
// that race we just bail out to the slow-path here. // that race we just bail out to the slow-path here.
if (m->object() == NULL) { if (m->object_peek() == NULL) {
return false; return false;
} }
Thread* const owner = (Thread *) m->_owner; Thread* const owner = (Thread *) m->_owner;
@ -1314,10 +1312,10 @@ JavaThread* ObjectSynchronizer::get_lock_owner(ThreadsList * t_list, Handle h_ob
void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) { void ObjectSynchronizer::monitors_iterate(MonitorClosure* closure) {
PaddedObjectMonitor* block = Atomic::load(&g_block_list); PaddedObjectMonitor* block = Atomic::load(&g_block_list);
while (block != NULL) { while (block != NULL) {
assert(block->object() == CHAINMARKER, "must be a block header"); assert(block->is_chainmarker(), "must be a block header");
for (int i = _BLOCKSIZE - 1; i > 0; i--) { for (int i = _BLOCKSIZE - 1; i > 0; i--) {
ObjectMonitor* mid = (ObjectMonitor *)(block + i); ObjectMonitor* mid = (ObjectMonitor *)(block + i);
if (mid->object() != NULL) { if (mid->object_peek() != NULL) {
// Only process with closure if the object is set. // Only process with closure if the object is set.
// monitors_iterate() is only called at a safepoint or when the // monitors_iterate() is only called at a safepoint or when the
@ -1402,34 +1400,6 @@ jlong ObjectSynchronizer::time_since_last_async_deflation_ms() {
return (os::javaTimeNanos() - last_async_deflation_time_ns()) / (NANOUNITS / MILLIUNITS); return (os::javaTimeNanos() - last_async_deflation_time_ns()) / (NANOUNITS / MILLIUNITS);
} }
void ObjectSynchronizer::oops_do(OopClosure* f) {
// We only scan the global used list here (for moribund threads), and
// the thread-local monitors in Thread::oops_do().
global_used_oops_do(f);
}
void ObjectSynchronizer::global_used_oops_do(OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
// Acquire semantics not needed since we're at a safepoint.
list_oops_do(Atomic::load(&om_list_globals._in_use_list), f);
}
void ObjectSynchronizer::thread_local_used_oops_do(Thread* thread, OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
list_oops_do(thread->om_in_use_list, f);
}
void ObjectSynchronizer::list_oops_do(ObjectMonitor* list, OopClosure* f) {
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
// The oops_do() phase does not overlap with monitor deflation
// so no need to lock ObjectMonitors for the list traversal.
for (ObjectMonitor* mid = list; mid != NULL; mid = unmarked_next(mid)) {
if (mid->object() != NULL) {
f->do_oop(mid->object_addr());
}
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// ObjectMonitor Lifecycle // ObjectMonitor Lifecycle
@ -1467,7 +1437,7 @@ ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
// on the shared global list. // on the shared global list.
m = take_from_start_of_om_free_list(self); m = take_from_start_of_om_free_list(self);
if (m != NULL) { if (m != NULL) {
guarantee(m->object() == NULL, "invariant"); guarantee(m->object_peek() == NULL, "invariant");
m->set_allocation_state(ObjectMonitor::New); m->set_allocation_state(ObjectMonitor::New);
prepend_to_om_in_use_list(self, m); prepend_to_om_in_use_list(self, m);
return m; return m;
@ -1488,7 +1458,7 @@ ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
if (take == NULL) { if (take == NULL) {
break; // No more are available. break; // No more are available.
} }
guarantee(take->object() == NULL, "invariant"); guarantee(take->object_peek() == NULL, "invariant");
// We allowed 3 field values to linger during async deflation. // We allowed 3 field values to linger during async deflation.
// Clear or restore them as appropriate. // Clear or restore them as appropriate.
take->set_header(markWord::zero()); take->set_header(markWord::zero());
@ -1550,7 +1520,7 @@ ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
temp[_BLOCKSIZE - 1].set_next_om((ObjectMonitor*)NULL); temp[_BLOCKSIZE - 1].set_next_om((ObjectMonitor*)NULL);
// Element [0] is reserved for global list linkage // Element [0] is reserved for global list linkage
temp[0].set_object(CHAINMARKER); temp[0].set_allocation_state(ObjectMonitor::ChainMarker);
// Consider carving out this thread's current request from the // Consider carving out this thread's current request from the
// block in hand. This avoids some lock traffic and redundant // block in hand. This avoids some lock traffic and redundant
@ -1575,7 +1545,7 @@ ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
void ObjectSynchronizer::om_release(Thread* self, ObjectMonitor* m, void ObjectSynchronizer::om_release(Thread* self, ObjectMonitor* m,
bool from_per_thread_alloc) { bool from_per_thread_alloc) {
guarantee(m->header().value() == 0, "invariant"); guarantee(m->header().value() == 0, "invariant");
guarantee(m->object() == NULL, "invariant"); guarantee(m->object_peek() == NULL, "invariant");
NoSafepointVerifier nsv; NoSafepointVerifier nsv;
if ((m->is_busy() | m->_recursions) != 0) { if ((m->is_busy() | m->_recursions) != 0) {
@ -1686,10 +1656,7 @@ void ObjectSynchronizer::om_release(Thread* self, ObjectMonitor* m,
// //
// We currently call om_flush() from Threads::remove() before the // We currently call om_flush() from Threads::remove() before the
// thread has been excised from the thread list and is no longer a // thread has been excised from the thread list and is no longer a
// mutator. In particular, this ensures that the thread's in-use // mutator.
// monitors are scanned by a GC safepoint, either via Thread::oops_do()
// (before om_flush() is called) or via ObjectSynchronizer::oops_do()
// (after om_flush() is called).
// //
// deflate_global_idle_monitors_using_JT() and // deflate_global_idle_monitors_using_JT() and
// deflate_per_thread_idle_monitors_using_JT() (in another thread) can // deflate_per_thread_idle_monitors_using_JT() (in another thread) can
@ -1733,14 +1700,25 @@ void ObjectSynchronizer::om_flush(Thread* self) {
cur_om = unmarked_next(in_use_tail); cur_om = unmarked_next(in_use_tail);
continue; continue;
} }
if (cur_om->object() == NULL) { if (cur_om->object_peek() == NULL) {
// cur_om was deflated and the object ref was cleared while it // Two reasons for object() to be NULL here:
// 1) cur_om was deflated and the object ref was cleared while it
// was locked. We happened to see it just after it was unlocked // was locked. We happened to see it just after it was unlocked
// (and added to the free list). Refetch the possibly changed // (and added to the free list).
// next field and try again. // 2) The object has been GC'ed so the association with object is
cur_om = unmarked_next(in_use_tail); // already broken, but we don't want to do the deflation work now.
// Refetch the possibly changed next field:
ObjectMonitor* in_use_next = unmarked_next(in_use_tail);
if (cur_om != in_use_next) {
// The NULL is because of async deflation so try again:
cur_om = in_use_next;
continue; continue;
} }
// Implied else: The NULL is because of GC, but we leave the
// node on the in-use list to be deflated after it has been
// moved to the global in-use list.
}
in_use_tail = cur_om; in_use_tail = cur_om;
in_use_count++; in_use_count++;
cur_om = unmarked_next(cur_om); cur_om = unmarked_next(cur_om);
@ -1785,7 +1763,7 @@ void ObjectSynchronizer::om_flush(Thread* self) {
} }
free_tail = s; free_tail = s;
free_count++; free_count++;
guarantee(s->object() == NULL, "invariant"); guarantee(s->object_peek() == NULL, "invariant");
if (s->is_busy()) { if (s->is_busy()) {
stringStream ss; stringStream ss;
fatal("must be !is_busy: %s", s->is_busy_to_string(&ss)); fatal("must be !is_busy: %s", s->is_busy_to_string(&ss));
@ -2101,6 +2079,14 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid,
return false; return false;
} }
const oop obj = mid->object_peek();
if (obj == NULL) {
// If the object died, we can recycle the monitor without racing with
// Java threads. The GC already broke the association with the object.
mid->set_owner_from(NULL, DEFLATER_MARKER);
mid->_contentions = -max_jint;
} else {
// Set a NULL owner to DEFLATER_MARKER to force any contending thread // Set a NULL owner to DEFLATER_MARKER to force any contending thread
// through the slow path. This is just the first part of the async // through the slow path. This is just the first part of the async
// deflation dance. // deflation dance.
@ -2134,6 +2120,7 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid,
} }
return false; return false;
} }
}
// Sanity checks for the races: // Sanity checks for the races:
guarantee(mid->owner_is_DEFLATER_MARKER(), "must be deflater marker"); guarantee(mid->owner_is_DEFLATER_MARKER(), "must be deflater marker");
@ -2146,7 +2133,7 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid,
"must be no entering threads: EntryList=" INTPTR_FORMAT, "must be no entering threads: EntryList=" INTPTR_FORMAT,
p2i(mid->_EntryList)); p2i(mid->_EntryList));
const oop obj = mid->object(); if (obj != NULL) {
if (log_is_enabled(Trace, monitorinflation)) { if (log_is_enabled(Trace, monitorinflation)) {
ResourceMark rm; ResourceMark rm;
log_trace(monitorinflation)("deflate_monitor_using_JT: " log_trace(monitorinflation)("deflate_monitor_using_JT: "
@ -2158,10 +2145,11 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid,
// Install the old mark word if nobody else has already done it. // Install the old mark word if nobody else has already done it.
mid->install_displaced_markword_in_object(obj); mid->install_displaced_markword_in_object(obj);
}
mid->clear_common(); mid->clear_common();
assert(mid->object() == NULL, "must be NULL: object=" INTPTR_FORMAT, assert(mid->object_peek() == NULL, "must be NULL: object=" INTPTR_FORMAT,
p2i(mid->object())); p2i(mid->object_peek()));
assert(mid->is_free(), "must be free: allocation_state=%d", assert(mid->is_free(), "must be free: allocation_state=%d",
(int)mid->allocation_state()); (int)mid->allocation_state());
@ -2256,10 +2244,9 @@ int ObjectSynchronizer::deflate_monitor_list_using_JT(ObjectMonitor** list_p,
next_next = unmarked_next(next); next_next = unmarked_next(next);
} }
// Only try to deflate if there is an associated Java object and if // Only try to deflate if mid is old (is not newly allocated and
// mid is old (is not newly allocated and is not newly freed). // is not newly freed).
if (mid->object() != NULL && mid->is_old() && if (mid->is_old() && deflate_monitor_using_JT(mid, free_head_p, free_tail_p)) {
deflate_monitor_using_JT(mid, free_head_p, free_tail_p)) {
// Deflation succeeded and already updated free_head_p and // Deflation succeeded and already updated free_head_p and
// free_tail_p as needed. Finish the move to the local free list // free_tail_p as needed. Finish the move to the local free list
// by unlinking mid from the global or per-thread in-use list. // by unlinking mid from the global or per-thread in-use list.
@ -2290,9 +2277,8 @@ int ObjectSynchronizer::deflate_monitor_list_using_JT(ObjectMonitor** list_p,
mid = next; // mid keeps non-NULL next's locked state mid = next; // mid keeps non-NULL next's locked state
next = next_next; next = next_next;
} else { } else {
// mid is considered in-use if it does not have an associated // mid is considered in-use if mid is not old or deflation did not
// Java object or mid is not old or deflation did not succeed. // succeed. A mid->is_new() node can be seen here when it is freshly
// A mid->is_new() node can be seen here when it is freshly
// returned by om_alloc() (and skips the deflation code path). // returned by om_alloc() (and skips the deflation code path).
// A mid->is_old() node can be seen here when deflation failed. // A mid->is_old() node can be seen here when deflation failed.
// A mid->is_free() node can be seen here when a fresh node from // A mid->is_free() node can be seen here when a fresh node from
@ -2717,16 +2703,16 @@ void ObjectSynchronizer::chk_free_entry(JavaThread* jt, ObjectMonitor* n,
*error_cnt_p = *error_cnt_p + 1; *error_cnt_p = *error_cnt_p + 1;
} }
} }
if (n->object() != NULL) { if (n->object_peek() != NULL) {
if (jt != NULL) { if (jt != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": free per-thread monitor must have NULL _object " ": free per-thread monitor must have NULL _object "
"field: _object=" INTPTR_FORMAT, p2i(jt), p2i(n), "field: _object=" INTPTR_FORMAT, p2i(jt), p2i(n),
p2i(n->object())); p2i(n->object_peek()));
} else { } else {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor " out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor "
"must have NULL _object field: _object=" INTPTR_FORMAT, "must have NULL _object field: _object=" INTPTR_FORMAT,
p2i(n), p2i(n->object())); p2i(n), p2i(n->object_peek()));
} }
*error_cnt_p = *error_cnt_p + 1; *error_cnt_p = *error_cnt_p + 1;
} }
@ -2856,18 +2842,8 @@ void ObjectSynchronizer::chk_in_use_entry(JavaThread* jt, ObjectMonitor* n,
} }
*error_cnt_p = *error_cnt_p + 1; *error_cnt_p = *error_cnt_p + 1;
} }
if (n->object() == NULL) { const oop obj = n->object_peek();
if (jt != NULL) { if (obj != NULL) {
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
": in-use per-thread monitor must have non-NULL _object "
"field.", p2i(jt), p2i(n));
} else {
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global monitor "
"must have non-NULL _object field.", p2i(n));
}
*error_cnt_p = *error_cnt_p + 1;
}
const oop obj = n->object();
const markWord mark = obj->mark(); const markWord mark = obj->mark();
if (!mark.has_monitor()) { if (!mark.has_monitor()) {
if (jt != NULL) { if (jt != NULL) {
@ -2899,6 +2875,7 @@ void ObjectSynchronizer::chk_in_use_entry(JavaThread* jt, ObjectMonitor* n,
} }
*error_cnt_p = *error_cnt_p + 1; *error_cnt_p = *error_cnt_p + 1;
} }
}
} }
// Check the thread's free list and count; log the results of the checks. // Check the thread's free list and count; log the results of the checks.
@ -2977,12 +2954,12 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out) {
if ((cur = get_list_head_locked(&om_list_globals._in_use_list)) != NULL) { if ((cur = get_list_head_locked(&om_list_globals._in_use_list)) != NULL) {
// Marked the global in-use list head so process the list. // Marked the global in-use list head so process the list.
while (true) { while (true) {
const oop obj = cur->object(); const oop obj = cur->object_peek();
const markWord mark = cur->header(); const markWord mark = cur->header();
ResourceMark rm; ResourceMark rm;
out->print(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(cur), out->print(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(cur),
cur->is_busy() != 0, mark.hash() != 0, cur->owner() != NULL, cur->is_busy() != 0, mark.hash() != 0, cur->owner() != NULL,
p2i(obj), obj->klass()->external_name()); p2i(obj), obj == NULL ? "" : obj->klass()->external_name());
if (cur->is_busy() != 0) { if (cur->is_busy() != 0) {
out->print(" (%s)", cur->is_busy_to_string(&ss)); out->print(" (%s)", cur->is_busy_to_string(&ss));
ss.reset(); ss.reset();
@ -3007,13 +2984,13 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream * out) {
if ((cur = get_list_head_locked(&jt->om_in_use_list)) != NULL) { if ((cur = get_list_head_locked(&jt->om_in_use_list)) != NULL) {
// Marked the global in-use list head so process the list. // Marked the global in-use list head so process the list.
while (true) { while (true) {
const oop obj = cur->object(); const oop obj = cur->object_peek();
const markWord mark = cur->header(); const markWord mark = cur->header();
ResourceMark rm; ResourceMark rm;
out->print(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT out->print(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT
" %s", p2i(jt), p2i(cur), cur->is_busy() != 0, " %s", p2i(jt), p2i(cur), cur->is_busy() != 0,
mark.hash() != 0, cur->owner() != NULL, p2i(obj), mark.hash() != 0, cur->owner() != NULL, p2i(obj),
obj->klass()->external_name()); obj == NULL ? "" : obj->klass()->external_name());
if (cur->is_busy() != 0) { if (cur->is_busy() != 0) {
out->print(" (%s)", cur->is_busy_to_string(&ss)); out->print(" (%s)", cur->is_busy_to_string(&ss));
ss.reset(); ss.reset();
@ -3069,7 +3046,7 @@ int ObjectSynchronizer::log_monitor_list_counts(outputStream * out) {
int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) { int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) {
PaddedObjectMonitor* block = Atomic::load(&g_block_list); PaddedObjectMonitor* block = Atomic::load(&g_block_list);
while (block != NULL) { while (block != NULL) {
assert(block->object() == CHAINMARKER, "must be a block header"); assert(block->is_chainmarker(), "must be a block header");
if (monitor > &block[0] && monitor < &block[_BLOCKSIZE]) { if (monitor > &block[0] && monitor < &block[_BLOCKSIZE]) {
address mon = (address)monitor; address mon = (address)monitor;
address blk = (address)block; address blk = (address)block;

View file

@ -150,9 +150,6 @@ class ObjectSynchronizer : AllStatic {
static bool request_deflate_idle_monitors(); // for whitebox test support and VM exit logging static bool request_deflate_idle_monitors(); // for whitebox test support and VM exit logging
static void set_is_async_deflation_requested(bool new_value) { _is_async_deflation_requested = new_value; } static void set_is_async_deflation_requested(bool new_value) { _is_async_deflation_requested = new_value; }
static jlong time_since_last_async_deflation_ms(); static jlong time_since_last_async_deflation_ms();
static void oops_do(OopClosure* f);
// Process oops in thread local used monitors
static void thread_local_used_oops_do(Thread* thread, OopClosure* f);
// debugging // debugging
static void audit_and_print_stats(bool on_exit); static void audit_and_print_stats(bool on_exit);
@ -190,11 +187,6 @@ class ObjectSynchronizer : AllStatic {
// Function to prepend new blocks to the appropriate lists: // Function to prepend new blocks to the appropriate lists:
static void prepend_block_to_lists(PaddedObjectMonitor* new_blk); static void prepend_block_to_lists(PaddedObjectMonitor* new_blk);
// Process oops in all global used monitors (i.e. moribund thread's monitors)
static void global_used_oops_do(OopClosure* f);
// Process oops in monitors on the given list
static void list_oops_do(ObjectMonitor* list, OopClosure* f);
// Support for SynchronizerTest access to GVars fields: // Support for SynchronizerTest access to GVars fields:
static u_char* get_gvars_addr(); static u_char* get_gvars_addr();
static u_char* get_gvars_hc_sequence_addr(); static u_char* get_gvars_hc_sequence_addr();

View file

@ -889,10 +889,6 @@ void Thread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
// Do oop for ThreadShadow // Do oop for ThreadShadow
f->do_oop((oop*)&_pending_exception); f->do_oop((oop*)&_pending_exception);
handle_area()->oops_do(f); handle_area()->oops_do(f);
// We scan thread local monitor lists here, and the remaining global
// monitors in ObjectSynchronizer::oops_do().
ObjectSynchronizer::thread_local_used_oops_do(this, f);
} }
void Thread::metadata_handles_do(void f(Metadata*)) { void Thread::metadata_handles_do(void f(Metadata*)) {
@ -2217,11 +2213,6 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
thread_name = os::strdup(get_thread_name()); thread_name = os::strdup(get_thread_name());
} }
// We must flush any deferred card marks and other various GC barrier
// related buffers (e.g. G1 SATB buffer and G1 dirty card queue buffer)
// before removing a thread from the list of active threads.
BarrierSet::barrier_set()->on_thread_detach(this);
log_info(os, thread)("JavaThread %s (tid: " UINTX_FORMAT ").", log_info(os, thread)("JavaThread %s (tid: " UINTX_FORMAT ").",
exit_type == JavaThread::normal_exit ? "exiting" : "detaching", exit_type == JavaThread::normal_exit ? "exiting" : "detaching",
os::current_thread_id()); os::current_thread_id());
@ -2269,8 +2260,6 @@ void JavaThread::cleanup_failed_attach_current_thread(bool is_daemon) {
tlab().retire(); tlab().retire();
} }
BarrierSet::barrier_set()->on_thread_detach(this);
Threads::remove(this, is_daemon); Threads::remove(this, is_daemon);
this->smr_delete(); this->smr_delete();
} }
@ -4598,6 +4587,13 @@ void Threads::remove(JavaThread* p, bool is_daemon) {
// Reclaim the ObjectMonitors from the om_in_use_list and om_free_list of the moribund thread. // Reclaim the ObjectMonitors from the om_in_use_list and om_free_list of the moribund thread.
ObjectSynchronizer::om_flush(p); ObjectSynchronizer::om_flush(p);
// We must flush any deferred card marks and other various GC barrier
// related buffers (e.g. G1 SATB buffer and G1 dirty card queue buffer)
// before removing a thread from the list of active threads.
// This must be done after ObjectSynchronizer::om_flush(), as GC barriers
// are used in om_flush().
BarrierSet::barrier_set()->on_thread_detach(p);
// Extra scope needed for Thread_lock, so we can check // Extra scope needed for Thread_lock, so we can check
// that we do not remove thread without safepoint code notice // that we do not remove thread without safepoint code notice
{ MonitorLocker ml(Threads_lock); { MonitorLocker ml(Threads_lock);

View file

@ -1379,27 +1379,6 @@ void JNIGlobalsDumper::do_oop(oop* obj_p) {
} }
}; };
// Support class used to generate HPROF_GC_ROOT_MONITOR_USED records
class MonitorUsedDumper : public OopClosure {
private:
DumpWriter* _writer;
DumpWriter* writer() const { return _writer; }
public:
MonitorUsedDumper(DumpWriter* writer) {
_writer = writer;
}
void do_oop(oop* obj_p) {
u4 size = 1 + sizeof(address);
writer()->start_sub_record(HPROF_GC_ROOT_MONITOR_USED, size);
writer()->write_objectID(*obj_p);
writer()->end_sub_record();
}
void do_oop(narrowOop* obj_p) { ShouldNotReachHere(); }
};
// Support class used to generate HPROF_GC_ROOT_STICKY_CLASS records // Support class used to generate HPROF_GC_ROOT_STICKY_CLASS records
class StickyClassDumper : public KlassClosure { class StickyClassDumper : public KlassClosure {
@ -1852,10 +1831,6 @@ void VM_HeapDumper::work(uint worker_id) {
// HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals // HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals
do_threads(); do_threads();
// HPROF_GC_ROOT_MONITOR_USED
MonitorUsedDumper mon_dumper(writer());
ObjectSynchronizer::oops_do(&mon_dumper);
// HPROF_GC_ROOT_JNI_GLOBAL // HPROF_GC_ROOT_JNI_GLOBAL
JNIGlobalsDumper jni_dumper(writer()); JNIGlobalsDumper jni_dumper(writer());
JNIHandles::oops_do(&jni_dumper); JNIHandles::oops_do(&jni_dumper);

View file

@ -92,7 +92,11 @@ public class ObjectMonitor extends VMObject {
public long recursions() { return recursionsField.getValue(addr); } public long recursions() { return recursionsField.getValue(addr); }
public OopHandle object() { public OopHandle object() {
return addr.getOopHandleAt(objectFieldOffset); Address objAddr = addr.getAddressAt(objectFieldOffset);
if (objAddr == null) {
return null;
}
return objAddr.getOopHandleAt(0);
} }
public int contentions() { public int contentions() {

View file

@ -121,7 +121,6 @@ public class TestGCLogMessages {
new LogMessageWithLevel("LAB Undo Waste", Level.DEBUG), new LogMessageWithLevel("LAB Undo Waste", Level.DEBUG),
// Ext Root Scan // Ext Root Scan
new LogMessageWithLevel("Thread Roots", Level.TRACE), new LogMessageWithLevel("Thread Roots", Level.TRACE),
new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE),
new LogMessageWithLevel("CLDG Roots", Level.TRACE), new LogMessageWithLevel("CLDG Roots", Level.TRACE),
new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE),
new LogMessageWithLevel("JNI Global Roots", Level.TRACE), new LogMessageWithLevel("JNI Global Roots", Level.TRACE),

View file

@ -203,10 +203,6 @@ public class TestHumongousClassLoader {
gc.provoke(); gc.provoke();
boolean did_deflation = WB.deflateIdleMonitors();
Asserts.assertEQ(did_deflation, true,
"deflateIdleMonitors() should have worked.");
// Test checks // Test checks
Asserts.assertEquals(WB.isClassAlive(HUMONGOUS_CLASSLOADER_NAME), false, Asserts.assertEquals(WB.isClassAlive(HUMONGOUS_CLASSLOADER_NAME), false,
String.format("Classloader class %s is loaded after we forget all references to it", String.format("Classloader class %s is loaded after we forget all references to it",

View file

@ -91,7 +91,6 @@ public class TestG1ParallelPhases {
Set<String> allPhases = of( Set<String> allPhases = of(
"ExtRootScan", "ExtRootScan",
"ThreadRoots", "ThreadRoots",
"ObjectSynchronizerRoots",
"VM Global", "VM Global",
"JNI Global", "JNI Global",
"Thread OopStorage", "Thread OopStorage",