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:
parent
f800af978c
commit
d8921ed573
src
hotspot/share
gc
g1
parallel
shared
shenandoah
shenandoahConcurrentMark.cppshenandoahPhaseTimings.hppshenandoahRootProcessor.cppshenandoahRootProcessor.hppshenandoahRootProcessor.inline.hppshenandoahRootVerifier.cpp
z
jfr/leakprofiler
oops
prims
runtime
objectMonitor.cppobjectMonitor.hppobjectMonitor.inline.hppsynchronizer.cppsynchronizer.hppthread.cpp
services
jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime
test
hotspot/jtreg/gc/g1
jdk/jdk/jfr/event/gc/collection
@ -58,7 +58,6 @@ G1GCPhaseTimes::G1GCPhaseTimes(STWGCTimer* gc_timer, uint max_gc_threads) :
|
||||
|
||||
// Root scanning phases
|
||||
_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);
|
||||
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);
|
||||
|
@ -48,7 +48,6 @@ class G1GCPhaseTimes : public CHeapObj<mtGC> {
|
||||
GCWorkerStart,
|
||||
ExtRootScan,
|
||||
ThreadRoots,
|
||||
ObjectSynchronizerRoots,
|
||||
CLDGRoots,
|
||||
AOT_ONLY(AOTCodeRoots COMMA)
|
||||
CMRefRoots,
|
||||
|
@ -180,13 +180,6 @@ void G1RootProcessor::process_vm_roots(G1RootClosures* closures,
|
||||
uint worker_id) {
|
||||
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 (UseAOT) {
|
||||
G1GCParPhaseTimesTracker x(phase_times, G1GCPhaseTimes::AOTCodeRoots, worker_id);
|
||||
|
@ -54,7 +54,6 @@ class G1RootProcessor : public StackObj {
|
||||
|
||||
enum G1H_process_roots_tasks {
|
||||
G1RP_PS_Universe_oops_do,
|
||||
G1RP_PS_ObjectSynchronizer_oops_do,
|
||||
G1RP_PS_Management_oops_do,
|
||||
G1RP_PS_ClassLoaderDataGraph_oops_do,
|
||||
G1RP_PS_jvmti_oops_do,
|
||||
|
@ -2010,10 +2010,6 @@ static void mark_from_roots_work(ParallelRootType::Value root_type, uint worker_
|
||||
PCMarkAndPushClosure mark_and_push_closure(cm);
|
||||
|
||||
switch (root_type) {
|
||||
case ParallelRootType::object_synchronizer:
|
||||
ObjectSynchronizer::oops_do(&mark_and_push_closure);
|
||||
break;
|
||||
|
||||
case ParallelRootType::class_loader_data:
|
||||
{
|
||||
CLDToOopClosure cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_strong);
|
||||
@ -2224,7 +2220,6 @@ void PSParallelCompact::adjust_roots(ParCompactionManager* cm) {
|
||||
|
||||
// General strong roots.
|
||||
Threads::oops_do(&oop_closure, NULL);
|
||||
ObjectSynchronizer::oops_do(&oop_closure);
|
||||
OopStorageSet::strong_oops_do(&oop_closure);
|
||||
CLDToOopClosure cld_closure(&oop_closure, ClassLoaderData::_claim_strong);
|
||||
ClassLoaderDataGraph::cld_do(&cld_closure);
|
||||
|
@ -34,7 +34,6 @@ public:
|
||||
// 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.
|
||||
enum Value {
|
||||
object_synchronizer,
|
||||
class_loader_data,
|
||||
code_cache,
|
||||
//"threads" are handled in parallel as a special case
|
||||
|
@ -92,10 +92,6 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i
|
||||
PSPromoteRootsClosure roots_to_old_closure(pm);
|
||||
|
||||
switch (root_type) {
|
||||
case ParallelRootType::object_synchronizer:
|
||||
ObjectSynchronizer::oops_do(&roots_closure);
|
||||
break;
|
||||
|
||||
case ParallelRootType::class_loader_data:
|
||||
{
|
||||
PSScavengeCLDClosure cld_closure(pm);
|
||||
|
@ -817,9 +817,6 @@ void GenCollectedHeap::process_roots(StrongRootsScope* scope,
|
||||
bool is_par = scope->n_threads() > 1;
|
||||
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 (UseAOT && _process_strong_tasks->try_claim_task(GCH_PS_aot_oops_do)) {
|
||||
AOTLoader::oops_do(strong_roots);
|
||||
|
@ -105,7 +105,6 @@ protected:
|
||||
|
||||
// The set of potentially parallel tasks in root scanning.
|
||||
enum GCH_strong_roots_tasks {
|
||||
GCH_PS_ObjectSynchronizer_oops_do,
|
||||
GCH_PS_OopStorageSet_oops_do,
|
||||
GCH_PS_ClassLoaderDataGraph_oops_do,
|
||||
GCH_PS_CodeCache_oops_do,
|
||||
|
@ -38,7 +38,7 @@ class OopStorageSet : public AllStatic {
|
||||
public:
|
||||
// Must be updated when new OopStorages are introduced
|
||||
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;
|
||||
|
||||
private:
|
||||
|
@ -163,10 +163,6 @@ inline void CompactibleSpace::scan_and_forward(SpaceType* space, CompactPoint* c
|
||||
HeapWord* scan_limit = space->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()) {
|
||||
// prefetch beyond cur_obj
|
||||
Prefetch::write(cur_obj, interval);
|
||||
|
@ -256,7 +256,6 @@ private:
|
||||
ShenandoahConcurrentMark* _cm;
|
||||
TaskTerminator* _terminator;
|
||||
bool _dedup_string;
|
||||
ShenandoahSharedFlag _claimed_syncroots;
|
||||
|
||||
public:
|
||||
ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) :
|
||||
@ -294,9 +293,6 @@ public:
|
||||
ShenandoahStoreValEnqueueBarrier ? &resolve_mark_cl : NULL,
|
||||
do_nmethods ? &blobsCl : NULL);
|
||||
Threads::threads_do(&tc);
|
||||
if (ShenandoahStoreValEnqueueBarrier && _claimed_syncroots.try_set()) {
|
||||
ObjectSynchronizer::oops_do(&resolve_mark_cl);
|
||||
}
|
||||
} else {
|
||||
ShenandoahMarkRefsClosure mark_cl(q, rp);
|
||||
MarkingCodeBlobClosure blobsCl(&mark_cl, !CodeBlobToOopClosure::FixRelocations);
|
||||
@ -304,9 +300,6 @@ public:
|
||||
ShenandoahStoreValEnqueueBarrier ? &mark_cl : NULL,
|
||||
do_nmethods ? &blobsCl : NULL);
|
||||
Threads::threads_do(&tc);
|
||||
if (ShenandoahStoreValEnqueueBarrier && _claimed_syncroots.try_set()) {
|
||||
ObjectSynchronizer::oops_do(&mark_cl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,6 @@ class outputStream;
|
||||
f(CNT_PREFIX ## CodeCacheRoots, DESC_PREFIX "Code Cache Roots") \
|
||||
f(CNT_PREFIX ## VMStrongRoots, DESC_PREFIX "VM Strong 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 ## JVMTIWeakRoots, DESC_PREFIX "JVMTI Weak Roots") \
|
||||
f(CNT_PREFIX ## StringDedupTableRoots, DESC_PREFIX "Dedup Table Roots") \
|
||||
|
@ -36,26 +36,6 @@
|
||||
#include "memory/resourceArea.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,
|
||||
ShenandoahPhaseTimings::Phase phase, ShenandoahPhaseTimings::ParPhase 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) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_serial_roots(phase),
|
||||
_thread_roots(phase, n_workers > 1) {
|
||||
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");
|
||||
|
||||
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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");
|
||||
ShenandoahParallelOopsDoThreadClosure tc_cl(oops, code, tc);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -235,7 +202,6 @@ ShenandoahRootEvacuator::ShenandoahRootEvacuator(uint n_workers,
|
||||
bool stw_roots_processing,
|
||||
bool stw_class_unloading) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_serial_roots(phase),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, n_workers),
|
||||
_thread_roots(phase, n_workers > 1),
|
||||
@ -256,7 +222,6 @@ void ShenandoahRootEvacuator::roots_do(uint worker_id, OopClosure* oops) {
|
||||
AlwaysTrueClosure always_true;
|
||||
|
||||
// Process serial-claiming roots first
|
||||
_serial_roots.oops_do(oops, worker_id);
|
||||
_serial_weak_roots.weak_oops_do(oops, worker_id);
|
||||
|
||||
// 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) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_serial_roots(phase),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, n_workers),
|
||||
_thread_roots(phase, n_workers > 1),
|
||||
@ -293,7 +257,6 @@ ShenandoahRootUpdater::ShenandoahRootUpdater(uint n_workers, ShenandoahPhaseTimi
|
||||
|
||||
ShenandoahRootAdjuster::ShenandoahRootAdjuster(uint n_workers, ShenandoahPhaseTimings::Phase phase) :
|
||||
ShenandoahRootProcessor(phase),
|
||||
_serial_roots(phase),
|
||||
_vm_roots(phase),
|
||||
_cld_roots(phase, n_workers),
|
||||
_thread_roots(phase, n_workers > 1),
|
||||
@ -314,7 +277,6 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
|
||||
AlwaysTrueClosure always_true;
|
||||
|
||||
// Process serial-claiming roots first
|
||||
_serial_roots.oops_do(oops, worker_id);
|
||||
_serial_weak_roots.weak_oops_do(oops, worker_id);
|
||||
|
||||
// Process light-weight/limited parallel roots then
|
||||
@ -330,7 +292,6 @@ void ShenandoahRootAdjuster::roots_do(uint worker_id, OopClosure* oops) {
|
||||
|
||||
ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
|
||||
ShenandoahRootProcessor(ShenandoahPhaseTimings::heap_iteration_roots),
|
||||
_serial_roots(ShenandoahPhaseTimings::heap_iteration_roots),
|
||||
_thread_roots(ShenandoahPhaseTimings::heap_iteration_roots, false /*is par*/),
|
||||
_vm_roots(ShenandoahPhaseTimings::heap_iteration_roots),
|
||||
_cld_roots(ShenandoahPhaseTimings::heap_iteration_roots, 1),
|
||||
@ -351,7 +312,6 @@ ShenandoahHeapIterationRootScanner::ShenandoahHeapIterationRootScanner() :
|
||||
ResourceMark rm;
|
||||
|
||||
// Process serial-claiming roots first
|
||||
_serial_roots.oops_do(oops, 0);
|
||||
_serial_weak_roots.weak_oops_do(oops, 0);
|
||||
|
||||
// Process light-weight/limited parallel roots then
|
||||
|
@ -49,14 +49,6 @@ public:
|
||||
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 {
|
||||
typedef void (*WeakOopsDo)(BoolObjectClosure*, OopClosure*);
|
||||
private:
|
||||
@ -199,7 +191,6 @@ public:
|
||||
|
||||
class ShenandoahRootScanner : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
|
||||
public:
|
||||
@ -238,7 +229,6 @@ public:
|
||||
// root scanning
|
||||
class ShenandoahHeapIterationRootScanner : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahThreadRoots _thread_roots;
|
||||
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, true /*single threaded*/>
|
||||
@ -257,7 +247,6 @@ public:
|
||||
// Evacuate all roots at a safepoint
|
||||
class ShenandoahRootEvacuator : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
|
||||
_cld_roots;
|
||||
@ -278,7 +267,6 @@ public:
|
||||
// Update all roots at a safepoint
|
||||
class ShenandoahRootUpdater : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
|
||||
_cld_roots;
|
||||
@ -298,7 +286,6 @@ public:
|
||||
// Adjuster all roots at a safepoint during full gc
|
||||
class ShenandoahRootAdjuster : public ShenandoahRootProcessor {
|
||||
private:
|
||||
ShenandoahSerialRoots _serial_roots;
|
||||
ShenandoahVMRoots<false /*concurrent*/> _vm_roots;
|
||||
ShenandoahClassLoaderDataRoots<false /*concurrent*/, false /*single threaded*/>
|
||||
_cld_roots;
|
||||
|
@ -195,7 +195,6 @@ void ShenandoahRootUpdater::roots_do(uint worker_id, IsAlive* is_alive, KeepAliv
|
||||
CLDToOopClosure clds(keep_alive, ClassLoaderData::_claim_strong);
|
||||
|
||||
// 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);
|
||||
|
||||
// Process light-weight/limited parallel roots then
|
||||
|
@ -74,7 +74,6 @@ void ShenandoahRootVerifier::oops_do(OopClosure* oops) {
|
||||
|
||||
if (verify(SerialRoots)) {
|
||||
shenandoah_assert_safepoint();
|
||||
ObjectSynchronizer::oops_do(oops);
|
||||
}
|
||||
|
||||
if (verify(JNIHandleRoots)) {
|
||||
@ -118,7 +117,6 @@ void ShenandoahRootVerifier::roots_do(OopClosure* oops) {
|
||||
ClassLoaderDataGraph::cld_do(&clds);
|
||||
|
||||
JNIHandles::oops_do(oops);
|
||||
ObjectSynchronizer::oops_do(oops);
|
||||
Universe::vm_global()->oops_do(oops);
|
||||
|
||||
AlwaysTrueClosure always_true;
|
||||
@ -143,7 +141,6 @@ void ShenandoahRootVerifier::strong_roots_do(OopClosure* oops) {
|
||||
ClassLoaderDataGraph::roots_cld_do(&clds, NULL);
|
||||
|
||||
JNIHandles::oops_do(oops);
|
||||
ObjectSynchronizer::oops_do(oops);
|
||||
Universe::vm_global()->oops_do(oops);
|
||||
|
||||
// Do thread roots the last. This allows verification code to find
|
||||
|
@ -54,7 +54,6 @@
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsSetup("Pause Roots Setup");
|
||||
static const ZStatSubPhase ZSubPhasePauseRoots("Pause Roots");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsTeardown("Pause Roots Teardown");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsObjectSynchronizer("Pause Roots ObjectSynchronizer");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsJVMTIWeakExport("Pause Roots JVMTIWeakExport");
|
||||
static const ZStatSubPhase ZSubPhasePauseRootsVMThread("Pause Roots VM Thread");
|
||||
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) :
|
||||
_visit_jvmti_weak_export(visit_jvmti_weak_export),
|
||||
_java_threads_iter(),
|
||||
_object_synchronizer(this),
|
||||
_jvmti_weak_export(this),
|
||||
_vm_thread(this),
|
||||
_java_threads(this),
|
||||
@ -211,11 +209,6 @@ ZRootsIterator::~ZRootsIterator() {
|
||||
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) {
|
||||
ZStatTimer timer(ZSubPhasePauseRootsJVMTIWeakExport);
|
||||
AlwaysTrueClosure always_alive;
|
||||
@ -241,7 +234,6 @@ void ZRootsIterator::do_code_cache(ZRootsIteratorClosure* cl) {
|
||||
|
||||
void ZRootsIterator::oops_do(ZRootsIteratorClosure* cl) {
|
||||
ZStatTimer timer(ZSubPhasePauseRoots);
|
||||
_object_synchronizer.oops_do(cl);
|
||||
_vm_thread.oops_do(cl);
|
||||
_java_threads.oops_do(cl);
|
||||
if (!ClassUnloading) {
|
||||
|
@ -110,13 +110,11 @@ private:
|
||||
const bool _visit_jvmti_weak_export;
|
||||
ZJavaThreadsIterator _java_threads_iter;
|
||||
|
||||
void do_object_synchronizer(ZRootsIteratorClosure* cl);
|
||||
void do_jvmti_weak_export(ZRootsIteratorClosure* cl);
|
||||
void do_vm_thread(ZRootsIteratorClosure* cl);
|
||||
void do_java_threads(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_vm_thread> _vm_thread;
|
||||
ZParallelOopsDo<ZRootsIterator, &ZRootsIterator::do_java_threads> _java_threads;
|
||||
|
@ -71,7 +71,6 @@ void RootSetClosure<Delegate>::process() {
|
||||
ClassLoaderDataGraph::always_strong_cld_do(&cldt_closure);
|
||||
// We don't follow code blob oops, because they have misaligned oops.
|
||||
Threads::oops_do(this, NULL);
|
||||
ObjectSynchronizer::oops_do(this);
|
||||
OopStorageSet::strong_oops_do(this);
|
||||
AOTLoader::oops_do(this);
|
||||
}
|
||||
|
@ -95,7 +95,6 @@ class ReferenceToRootClosure : public StackObj {
|
||||
bool _complete;
|
||||
|
||||
bool do_cldg_roots();
|
||||
bool do_object_synchronizer_roots();
|
||||
bool do_oop_storage_roots();
|
||||
bool do_string_table_roots();
|
||||
bool do_aot_loader_roots();
|
||||
@ -129,13 +128,6 @@ bool ReferenceToRootClosure::do_cldg_roots() {
|
||||
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() {
|
||||
int i = 0;
|
||||
for (OopStorageSet::Iterator it = OopStorageSet::strong_iterator(); !it.is_end(); ++it, ++i) {
|
||||
@ -171,11 +163,6 @@ bool ReferenceToRootClosure::do_roots() {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (do_object_synchronizer_roots()) {
|
||||
_complete = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (do_oop_storage_roots()) {
|
||||
_complete = true;
|
||||
return true;
|
||||
|
@ -54,8 +54,6 @@ const char* OldObjectRoot::system_description(System system) {
|
||||
return "Universe";
|
||||
case _threads:
|
||||
return "Threads";
|
||||
case _object_synchronizer:
|
||||
return "Object Monitor";
|
||||
case _class_loader_data:
|
||||
return "Class Loader Data";
|
||||
case _code_cache:
|
||||
|
@ -36,7 +36,6 @@ class OldObjectRoot : public AllStatic {
|
||||
_threads,
|
||||
_strong_oop_storage_set_first,
|
||||
_strong_oop_storage_set_last = _strong_oop_storage_set_first + OopStorageSet::strong_count - 1,
|
||||
_object_synchronizer,
|
||||
_class_loader_data,
|
||||
_code_cache,
|
||||
_aot,
|
||||
|
@ -31,8 +31,11 @@
|
||||
#include "utilities/ostream.hpp"
|
||||
|
||||
WeakHandle::WeakHandle(OopStorage* storage, Handle obj) :
|
||||
WeakHandle(storage, obj()) {}
|
||||
|
||||
WeakHandle::WeakHandle(OopStorage* storage, oop obj) :
|
||||
_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) {
|
||||
vm_exit_out_of_memory(sizeof(oop*), OOM_MALLOC_ERROR,
|
||||
@ -40,7 +43,7 @@ WeakHandle::WeakHandle(OopStorage* storage, Handle obj) :
|
||||
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 {
|
||||
|
@ -48,6 +48,7 @@ class WeakHandle {
|
||||
public:
|
||||
WeakHandle() : _obj(NULL) {} // needed for init
|
||||
WeakHandle(OopStorage* storage, Handle obj);
|
||||
WeakHandle(OopStorage* storage, oop obj);
|
||||
|
||||
inline oop resolve() const;
|
||||
inline oop peek() const;
|
||||
|
@ -1751,7 +1751,6 @@ static jvmtiHeapRootKind toJvmtiHeapRootKind(jvmtiHeapReferenceKind kind) {
|
||||
switch (kind) {
|
||||
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_MONITOR: return JVMTI_HEAP_ROOT_MONITOR;
|
||||
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_THREAD: return JVMTI_HEAP_ROOT_THREAD;
|
||||
@ -3017,13 +3016,6 @@ inline bool VM_HeapWalkOperation::collect_simple_roots() {
|
||||
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()
|
||||
|
||||
// Other kinds of roots maintained by HotSpot
|
||||
|
@ -24,6 +24,8 @@
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
#include "gc/shared/oopStorage.hpp"
|
||||
#include "gc/shared/oopStorageSet.hpp"
|
||||
#include "jfr/jfrEvents.hpp"
|
||||
#include "jfr/support/jfrThreadId.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;)
|
||||
|
||||
OopStorage* ObjectMonitor::_oop_storage = NULL;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Theory of operations -- Monitors lists, thread residency, etc:
|
||||
//
|
||||
@ -237,6 +241,53 @@ void ObjectMonitor::operator delete[] (void *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
|
||||
|
||||
@ -446,10 +497,10 @@ void ObjectMonitor::install_displaced_markword_in_object(const oop obj) {
|
||||
OrderAccess::loadload();
|
||||
}
|
||||
|
||||
const oop l_object = object();
|
||||
const oop l_object = object_peek();
|
||||
if (l_object == NULL) {
|
||||
// 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;
|
||||
}
|
||||
assert(l_object == obj, "object=" INTPTR_FORMAT " must equal obj="
|
||||
@ -703,7 +754,6 @@ void ObjectMonitor::EnterI(TRAPS) {
|
||||
// In addition, Self.TState is stable.
|
||||
|
||||
assert(_owner == Self, "invariant");
|
||||
assert(object() != NULL, "invariant");
|
||||
|
||||
UnlinkAfterAcquire(Self, &node);
|
||||
if (_succ == Self) _succ = NULL;
|
||||
@ -2055,6 +2105,8 @@ void ObjectMonitor::Initialize() {
|
||||
#undef NEWPERFVARIABLE
|
||||
}
|
||||
|
||||
_oop_storage = OopStorageSet::create_weak("ObjectSynchronizer Weak");
|
||||
|
||||
DEBUG_ONLY(InitDone = true;)
|
||||
}
|
||||
|
||||
@ -2103,7 +2155,7 @@ void ObjectMonitor::print() const { print_on(tty); }
|
||||
void ObjectMonitor::print_debug_style_on(outputStream* st) const {
|
||||
st->print_cr("(ObjectMonitor*) " INTPTR_FORMAT " = {", p2i(this));
|
||||
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 = ");
|
||||
if (is_free()) {
|
||||
st->print("Free");
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "memory/allocation.hpp"
|
||||
#include "memory/padded.hpp"
|
||||
#include "oops/markWord.hpp"
|
||||
#include "oops/weakHandle.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include "runtime/park.hpp"
|
||||
#include "runtime/perfData.hpp"
|
||||
@ -132,14 +133,17 @@ class ObjectMonitor {
|
||||
friend class VMStructs;
|
||||
JVMCI_ONLY(friend class JVMCIVMStructs;)
|
||||
|
||||
static OopStorage* _oop_storage;
|
||||
|
||||
// The sync code expects the header field to be at offset zero (0).
|
||||
// Enforced by the assert() in header_addr().
|
||||
volatile markWord _header; // displaced object header word - mark
|
||||
void* volatile _object; // backward object pointer - strong root
|
||||
WeakHandle _object; // backward object pointer
|
||||
typedef enum {
|
||||
Free = 0, // Free must be 0 for monitor to be free after memset(..,0,..).
|
||||
New,
|
||||
Old
|
||||
Old,
|
||||
ChainMarker
|
||||
} AllocationState;
|
||||
AllocationState _allocation_state;
|
||||
// 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
|
||||
// choices to share the cache line with _header.
|
||||
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:
|
||||
#define DEFLATER_MARKER reinterpret_cast<void*>(-1)
|
||||
void* volatile _owner; // pointer to owning thread OR BasicLock
|
||||
@ -329,6 +333,7 @@ class ObjectMonitor {
|
||||
public:
|
||||
|
||||
oop object() const;
|
||||
oop object_peek() const;
|
||||
oop* object_addr();
|
||||
void set_object(oop obj);
|
||||
void release_set_allocation_state(AllocationState s);
|
||||
@ -338,6 +343,7 @@ class ObjectMonitor {
|
||||
bool is_free() const;
|
||||
bool is_old() const;
|
||||
bool is_new() const;
|
||||
bool is_chainmarker() const;
|
||||
|
||||
// Returns true if the specified thread owns the ObjectMonitor. Otherwise
|
||||
// returns false and throws IllegalMonitorStateException (IMSE).
|
||||
|
@ -92,24 +92,15 @@ inline void ObjectMonitor::clear_common() {
|
||||
assert(contentions() <= 0, "must not be positive: contentions=%d", contentions());
|
||||
assert(_waiters == 0, "must be 0: waiters=%d", _waiters);
|
||||
assert(_recursions == 0, "must be 0: recursions=" INTX_FORMAT, _recursions);
|
||||
assert(object() != NULL, "must be non-NULL");
|
||||
|
||||
set_allocation_state(Free);
|
||||
set_object(NULL);
|
||||
}
|
||||
|
||||
inline oop ObjectMonitor::object() const {
|
||||
return (oop)_object;
|
||||
}
|
||||
|
||||
inline oop* ObjectMonitor::object_addr() {
|
||||
return (oop*)&_object;
|
||||
}
|
||||
|
||||
inline void ObjectMonitor::set_object(oop obj) {
|
||||
_object = (void*)obj;
|
||||
}
|
||||
|
||||
// Return number of threads contending for this monitor.
|
||||
inline jint ObjectMonitor::contentions() const {
|
||||
return Atomic::load(&_contentions);
|
||||
@ -223,6 +214,10 @@ inline bool ObjectMonitor::is_new() const {
|
||||
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
|
||||
// use Atomic operations to disable compiler optimizations that
|
||||
// might try to elide loading and/or storing this field.
|
||||
|
@ -159,8 +159,6 @@ struct ObjectMonitorListGlobals {
|
||||
};
|
||||
static ObjectMonitorListGlobals om_list_globals;
|
||||
|
||||
#define CHAINMARKER (cast_to_oop<intptr_t>(-1))
|
||||
|
||||
|
||||
// =====================> Spin-lock functions
|
||||
|
||||
@ -510,10 +508,10 @@ bool ObjectSynchronizer::quick_enter(oop obj, Thread* self,
|
||||
|
||||
if (mark.has_monitor()) {
|
||||
ObjectMonitor* const m = mark.monitor();
|
||||
// An async deflation can race us before we manage to make the
|
||||
// ObjectMonitor busy by setting the owner below. If we detect
|
||||
// An async deflation or GC can race us before we manage to make
|
||||
// the ObjectMonitor busy by setting the owner below. If we detect
|
||||
// that race we just bail out to the slow-path here.
|
||||
if (m->object() == NULL) {
|
||||
if (m->object_peek() == NULL) {
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
PaddedObjectMonitor* block = Atomic::load(&g_block_list);
|
||||
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--) {
|
||||
ObjectMonitor* mid = (ObjectMonitor *)(block + i);
|
||||
if (mid->object() != NULL) {
|
||||
if (mid->object_peek() != NULL) {
|
||||
// Only process with closure if the object is set.
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
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
|
||||
@ -1467,7 +1437,7 @@ ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
|
||||
// on the shared global list.
|
||||
m = take_from_start_of_om_free_list(self);
|
||||
if (m != NULL) {
|
||||
guarantee(m->object() == NULL, "invariant");
|
||||
guarantee(m->object_peek() == NULL, "invariant");
|
||||
m->set_allocation_state(ObjectMonitor::New);
|
||||
prepend_to_om_in_use_list(self, m);
|
||||
return m;
|
||||
@ -1488,7 +1458,7 @@ ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
|
||||
if (take == NULL) {
|
||||
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.
|
||||
// Clear or restore them as appropriate.
|
||||
take->set_header(markWord::zero());
|
||||
@ -1550,7 +1520,7 @@ ObjectMonitor* ObjectSynchronizer::om_alloc(Thread* self) {
|
||||
temp[_BLOCKSIZE - 1].set_next_om((ObjectMonitor*)NULL);
|
||||
|
||||
// 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
|
||||
// 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,
|
||||
bool from_per_thread_alloc) {
|
||||
guarantee(m->header().value() == 0, "invariant");
|
||||
guarantee(m->object() == NULL, "invariant");
|
||||
guarantee(m->object_peek() == NULL, "invariant");
|
||||
NoSafepointVerifier nsv;
|
||||
|
||||
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
|
||||
// thread has been excised from the thread list and is no longer a
|
||||
// mutator. In particular, this ensures that the thread's in-use
|
||||
// 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).
|
||||
// mutator.
|
||||
//
|
||||
// deflate_global_idle_monitors_using_JT() and
|
||||
// deflate_per_thread_idle_monitors_using_JT() (in another thread) can
|
||||
@ -1733,13 +1700,24 @@ void ObjectSynchronizer::om_flush(Thread* self) {
|
||||
cur_om = unmarked_next(in_use_tail);
|
||||
continue;
|
||||
}
|
||||
if (cur_om->object() == NULL) {
|
||||
// cur_om was deflated and the object ref was cleared while it
|
||||
if (cur_om->object_peek() == NULL) {
|
||||
// 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
|
||||
// (and added to the free list). Refetch the possibly changed
|
||||
// next field and try again.
|
||||
cur_om = unmarked_next(in_use_tail);
|
||||
continue;
|
||||
// (and added to the free list).
|
||||
// 2) The object has been GC'ed so the association with object is
|
||||
// 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;
|
||||
}
|
||||
// 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_count++;
|
||||
@ -1785,7 +1763,7 @@ void ObjectSynchronizer::om_flush(Thread* self) {
|
||||
}
|
||||
free_tail = s;
|
||||
free_count++;
|
||||
guarantee(s->object() == NULL, "invariant");
|
||||
guarantee(s->object_peek() == NULL, "invariant");
|
||||
if (s->is_busy()) {
|
||||
stringStream ss;
|
||||
fatal("must be !is_busy: %s", s->is_busy_to_string(&ss));
|
||||
@ -2101,38 +2079,47 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid,
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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
|
||||
// deflation dance.
|
||||
if (mid->try_set_owner_from(NULL, DEFLATER_MARKER) != NULL) {
|
||||
// The owner field is no longer NULL so we lost the race since the
|
||||
// ObjectMonitor is now busy.
|
||||
return false;
|
||||
}
|
||||
const oop obj = mid->object_peek();
|
||||
|
||||
if (mid->contentions() > 0 || mid->_waiters != 0) {
|
||||
// Another thread has raced to enter the ObjectMonitor after
|
||||
// mid->is_busy() above or has already entered and waited on
|
||||
// it which makes it busy so no deflation. Restore owner to
|
||||
// NULL if it is still DEFLATER_MARKER.
|
||||
if (mid->try_set_owner_from(DEFLATER_MARKER, NULL) != DEFLATER_MARKER) {
|
||||
// Deferred decrement for the JT EnterI() that cancelled the async deflation.
|
||||
mid->add_to_contentions(-1);
|
||||
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
|
||||
// through the slow path. This is just the first part of the async
|
||||
// deflation dance.
|
||||
if (mid->try_set_owner_from(NULL, DEFLATER_MARKER) != NULL) {
|
||||
// The owner field is no longer NULL so we lost the race since the
|
||||
// ObjectMonitor is now busy.
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make a zero contentions field negative to force any contending threads
|
||||
// to retry. This is the second part of the async deflation dance.
|
||||
if (Atomic::cmpxchg(&mid->_contentions, (jint)0, -max_jint) != 0) {
|
||||
// Contentions was no longer 0 so we lost the race since the
|
||||
// ObjectMonitor is now busy. Restore owner to NULL if it is
|
||||
// still DEFLATER_MARKER:
|
||||
if (mid->try_set_owner_from(DEFLATER_MARKER, NULL) != DEFLATER_MARKER) {
|
||||
// Deferred decrement for the JT EnterI() that cancelled the async deflation.
|
||||
mid->add_to_contentions(-1);
|
||||
if (mid->contentions() > 0 || mid->_waiters != 0) {
|
||||
// Another thread has raced to enter the ObjectMonitor after
|
||||
// mid->is_busy() above or has already entered and waited on
|
||||
// it which makes it busy so no deflation. Restore owner to
|
||||
// NULL if it is still DEFLATER_MARKER.
|
||||
if (mid->try_set_owner_from(DEFLATER_MARKER, NULL) != DEFLATER_MARKER) {
|
||||
// Deferred decrement for the JT EnterI() that cancelled the async deflation.
|
||||
mid->add_to_contentions(-1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make a zero contentions field negative to force any contending threads
|
||||
// to retry. This is the second part of the async deflation dance.
|
||||
if (Atomic::cmpxchg(&mid->_contentions, (jint)0, -max_jint) != 0) {
|
||||
// Contentions was no longer 0 so we lost the race since the
|
||||
// ObjectMonitor is now busy. Restore owner to NULL if it is
|
||||
// still DEFLATER_MARKER:
|
||||
if (mid->try_set_owner_from(DEFLATER_MARKER, NULL) != DEFLATER_MARKER) {
|
||||
// Deferred decrement for the JT EnterI() that cancelled the async deflation.
|
||||
mid->add_to_contentions(-1);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity checks for the races:
|
||||
@ -2146,22 +2133,23 @@ bool ObjectSynchronizer::deflate_monitor_using_JT(ObjectMonitor* mid,
|
||||
"must be no entering threads: EntryList=" INTPTR_FORMAT,
|
||||
p2i(mid->_EntryList));
|
||||
|
||||
const oop obj = mid->object();
|
||||
if (log_is_enabled(Trace, monitorinflation)) {
|
||||
ResourceMark rm;
|
||||
log_trace(monitorinflation)("deflate_monitor_using_JT: "
|
||||
"object=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT ", type='%s'",
|
||||
p2i(obj), obj->mark().value(),
|
||||
obj->klass()->external_name());
|
||||
}
|
||||
if (obj != NULL) {
|
||||
if (log_is_enabled(Trace, monitorinflation)) {
|
||||
ResourceMark rm;
|
||||
log_trace(monitorinflation)("deflate_monitor_using_JT: "
|
||||
"object=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT ", type='%s'",
|
||||
p2i(obj), obj->mark().value(),
|
||||
obj->klass()->external_name());
|
||||
}
|
||||
|
||||
// Install the old mark word if nobody else has already done it.
|
||||
mid->install_displaced_markword_in_object(obj);
|
||||
// Install the old mark word if nobody else has already done it.
|
||||
mid->install_displaced_markword_in_object(obj);
|
||||
}
|
||||
mid->clear_common();
|
||||
|
||||
assert(mid->object() == NULL, "must be NULL: object=" INTPTR_FORMAT,
|
||||
p2i(mid->object()));
|
||||
assert(mid->object_peek() == NULL, "must be NULL: object=" INTPTR_FORMAT,
|
||||
p2i(mid->object_peek()));
|
||||
assert(mid->is_free(), "must be free: allocation_state=%d",
|
||||
(int)mid->allocation_state());
|
||||
|
||||
@ -2256,10 +2244,9 @@ int ObjectSynchronizer::deflate_monitor_list_using_JT(ObjectMonitor** list_p,
|
||||
next_next = unmarked_next(next);
|
||||
}
|
||||
|
||||
// Only try to deflate if there is an associated Java object and if
|
||||
// mid is old (is not newly allocated and is not newly freed).
|
||||
if (mid->object() != NULL && mid->is_old() &&
|
||||
deflate_monitor_using_JT(mid, free_head_p, free_tail_p)) {
|
||||
// Only try to deflate if mid is old (is not newly allocated and
|
||||
// is not newly freed).
|
||||
if (mid->is_old() && deflate_monitor_using_JT(mid, free_head_p, free_tail_p)) {
|
||||
// Deflation succeeded and already updated free_head_p and
|
||||
// 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.
|
||||
@ -2290,9 +2277,8 @@ int ObjectSynchronizer::deflate_monitor_list_using_JT(ObjectMonitor** list_p,
|
||||
mid = next; // mid keeps non-NULL next's locked state
|
||||
next = next_next;
|
||||
} else {
|
||||
// mid is considered in-use if it does not have an associated
|
||||
// Java object or mid is not old or deflation did not succeed.
|
||||
// A mid->is_new() node can be seen here when it is freshly
|
||||
// mid is considered in-use if mid is not old or deflation did not
|
||||
// succeed. A mid->is_new() node can be seen here when it is freshly
|
||||
// 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_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;
|
||||
}
|
||||
}
|
||||
if (n->object() != NULL) {
|
||||
if (n->object_peek() != NULL) {
|
||||
if (jt != NULL) {
|
||||
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
|
||||
": free per-thread monitor must have NULL _object "
|
||||
"field: _object=" INTPTR_FORMAT, p2i(jt), p2i(n),
|
||||
p2i(n->object()));
|
||||
p2i(n->object_peek()));
|
||||
} else {
|
||||
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": free global monitor "
|
||||
"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;
|
||||
}
|
||||
@ -2856,48 +2842,39 @@ void ObjectSynchronizer::chk_in_use_entry(JavaThread* jt, ObjectMonitor* n,
|
||||
}
|
||||
*error_cnt_p = *error_cnt_p + 1;
|
||||
}
|
||||
if (n->object() == NULL) {
|
||||
if (jt != 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));
|
||||
const oop obj = n->object_peek();
|
||||
if (obj != NULL) {
|
||||
const markWord mark = obj->mark();
|
||||
if (!mark.has_monitor()) {
|
||||
if (jt != NULL) {
|
||||
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
|
||||
": in-use per-thread monitor's object does not think "
|
||||
"it has a monitor: obj=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT, p2i(jt), p2i(n), p2i(obj), mark.value());
|
||||
} else {
|
||||
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
|
||||
"monitor's object does not think it has a monitor: obj="
|
||||
INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n),
|
||||
p2i(obj), mark.value());
|
||||
}
|
||||
*error_cnt_p = *error_cnt_p + 1;
|
||||
}
|
||||
*error_cnt_p = *error_cnt_p + 1;
|
||||
}
|
||||
const oop obj = n->object();
|
||||
const markWord mark = obj->mark();
|
||||
if (!mark.has_monitor()) {
|
||||
if (jt != NULL) {
|
||||
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
|
||||
": in-use per-thread monitor's object does not think "
|
||||
"it has a monitor: obj=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT, p2i(jt), p2i(n), p2i(obj), mark.value());
|
||||
} else {
|
||||
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
|
||||
"monitor's object does not think it has a monitor: obj="
|
||||
INTPTR_FORMAT ", mark=" INTPTR_FORMAT, p2i(n),
|
||||
p2i(obj), mark.value());
|
||||
ObjectMonitor* const obj_mon = mark.monitor();
|
||||
if (n != obj_mon) {
|
||||
if (jt != NULL) {
|
||||
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
|
||||
": in-use per-thread monitor's object does not refer "
|
||||
"to the same monitor: obj=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT ", obj_mon=" INTPTR_FORMAT, p2i(jt),
|
||||
p2i(n), p2i(obj), mark.value(), p2i(obj_mon));
|
||||
} else {
|
||||
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
|
||||
"monitor's object does not refer to the same monitor: obj="
|
||||
INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon="
|
||||
INTPTR_FORMAT, p2i(n), p2i(obj), mark.value(), p2i(obj_mon));
|
||||
}
|
||||
*error_cnt_p = *error_cnt_p + 1;
|
||||
}
|
||||
*error_cnt_p = *error_cnt_p + 1;
|
||||
}
|
||||
ObjectMonitor* const obj_mon = mark.monitor();
|
||||
if (n != obj_mon) {
|
||||
if (jt != NULL) {
|
||||
out->print_cr("ERROR: jt=" INTPTR_FORMAT ", monitor=" INTPTR_FORMAT
|
||||
": in-use per-thread monitor's object does not refer "
|
||||
"to the same monitor: obj=" INTPTR_FORMAT ", mark="
|
||||
INTPTR_FORMAT ", obj_mon=" INTPTR_FORMAT, p2i(jt),
|
||||
p2i(n), p2i(obj), mark.value(), p2i(obj_mon));
|
||||
} else {
|
||||
out->print_cr("ERROR: monitor=" INTPTR_FORMAT ": in-use global "
|
||||
"monitor's object does not refer to the same monitor: obj="
|
||||
INTPTR_FORMAT ", mark=" INTPTR_FORMAT ", obj_mon="
|
||||
INTPTR_FORMAT, p2i(n), p2i(obj), mark.value(), p2i(obj_mon));
|
||||
}
|
||||
*error_cnt_p = *error_cnt_p + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
// Marked the global in-use list head so process the list.
|
||||
while (true) {
|
||||
const oop obj = cur->object();
|
||||
const oop obj = cur->object_peek();
|
||||
const markWord mark = cur->header();
|
||||
ResourceMark rm;
|
||||
out->print(INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT " %s", p2i(cur),
|
||||
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) {
|
||||
out->print(" (%s)", cur->is_busy_to_string(&ss));
|
||||
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) {
|
||||
// Marked the global in-use list head so process the list.
|
||||
while (true) {
|
||||
const oop obj = cur->object();
|
||||
const oop obj = cur->object_peek();
|
||||
const markWord mark = cur->header();
|
||||
ResourceMark rm;
|
||||
out->print(INTPTR_FORMAT " " INTPTR_FORMAT " %d%d%d " INTPTR_FORMAT
|
||||
" %s", p2i(jt), p2i(cur), cur->is_busy() != 0,
|
||||
mark.hash() != 0, cur->owner() != NULL, p2i(obj),
|
||||
obj->klass()->external_name());
|
||||
obj == NULL ? "" : obj->klass()->external_name());
|
||||
if (cur->is_busy() != 0) {
|
||||
out->print(" (%s)", cur->is_busy_to_string(&ss));
|
||||
ss.reset();
|
||||
@ -3069,7 +3046,7 @@ int ObjectSynchronizer::log_monitor_list_counts(outputStream * out) {
|
||||
int ObjectSynchronizer::verify_objmon_isinpool(ObjectMonitor *monitor) {
|
||||
PaddedObjectMonitor* block = Atomic::load(&g_block_list);
|
||||
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]) {
|
||||
address mon = (address)monitor;
|
||||
address blk = (address)block;
|
||||
|
@ -150,9 +150,6 @@ class ObjectSynchronizer : AllStatic {
|
||||
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 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
|
||||
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:
|
||||
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:
|
||||
static u_char* get_gvars_addr();
|
||||
static u_char* get_gvars_hc_sequence_addr();
|
||||
|
@ -889,10 +889,6 @@ void Thread::oops_do(OopClosure* f, CodeBlobClosure* cf) {
|
||||
// Do oop for ThreadShadow
|
||||
f->do_oop((oop*)&_pending_exception);
|
||||
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*)) {
|
||||
@ -2217,11 +2213,6 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) {
|
||||
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 ").",
|
||||
exit_type == JavaThread::normal_exit ? "exiting" : "detaching",
|
||||
os::current_thread_id());
|
||||
@ -2269,8 +2260,6 @@ void JavaThread::cleanup_failed_attach_current_thread(bool is_daemon) {
|
||||
tlab().retire();
|
||||
}
|
||||
|
||||
BarrierSet::barrier_set()->on_thread_detach(this);
|
||||
|
||||
Threads::remove(this, is_daemon);
|
||||
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.
|
||||
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
|
||||
// that we do not remove thread without safepoint code notice
|
||||
{ MonitorLocker ml(Threads_lock);
|
||||
|
@ -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
|
||||
|
||||
class StickyClassDumper : public KlassClosure {
|
||||
@ -1852,10 +1831,6 @@ void VM_HeapDumper::work(uint worker_id) {
|
||||
// HPROF_GC_ROOT_THREAD_OBJ + frames + jni locals
|
||||
do_threads();
|
||||
|
||||
// HPROF_GC_ROOT_MONITOR_USED
|
||||
MonitorUsedDumper mon_dumper(writer());
|
||||
ObjectSynchronizer::oops_do(&mon_dumper);
|
||||
|
||||
// HPROF_GC_ROOT_JNI_GLOBAL
|
||||
JNIGlobalsDumper jni_dumper(writer());
|
||||
JNIHandles::oops_do(&jni_dumper);
|
||||
|
@ -92,7 +92,11 @@ public class ObjectMonitor extends VMObject {
|
||||
public long recursions() { return recursionsField.getValue(addr); }
|
||||
|
||||
public OopHandle object() {
|
||||
return addr.getOopHandleAt(objectFieldOffset);
|
||||
Address objAddr = addr.getAddressAt(objectFieldOffset);
|
||||
if (objAddr == null) {
|
||||
return null;
|
||||
}
|
||||
return objAddr.getOopHandleAt(0);
|
||||
}
|
||||
|
||||
public int contentions() {
|
||||
|
@ -121,7 +121,6 @@ public class TestGCLogMessages {
|
||||
new LogMessageWithLevel("LAB Undo Waste", Level.DEBUG),
|
||||
// Ext Root Scan
|
||||
new LogMessageWithLevel("Thread Roots", Level.TRACE),
|
||||
new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE),
|
||||
new LogMessageWithLevel("CLDG Roots", Level.TRACE),
|
||||
new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE),
|
||||
new LogMessageWithLevel("JNI Global Roots", Level.TRACE),
|
||||
|
@ -203,10 +203,6 @@ public class TestHumongousClassLoader {
|
||||
|
||||
gc.provoke();
|
||||
|
||||
boolean did_deflation = WB.deflateIdleMonitors();
|
||||
Asserts.assertEQ(did_deflation, true,
|
||||
"deflateIdleMonitors() should have worked.");
|
||||
|
||||
// Test checks
|
||||
Asserts.assertEquals(WB.isClassAlive(HUMONGOUS_CLASSLOADER_NAME), false,
|
||||
String.format("Classloader class %s is loaded after we forget all references to it",
|
||||
|
@ -91,7 +91,6 @@ public class TestG1ParallelPhases {
|
||||
Set<String> allPhases = of(
|
||||
"ExtRootScan",
|
||||
"ThreadRoots",
|
||||
"ObjectSynchronizerRoots",
|
||||
"VM Global",
|
||||
"JNI Global",
|
||||
"Thread OopStorage",
|
||||
|
Loading…
x
Reference in New Issue
Block a user