mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-26 14:24:46 +02:00
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
37 changed files with 211 additions and 344 deletions
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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") \
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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).
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue