47 ThreadLocalAllocStats& ShenandoahStackWatermark::stats() {
48 return _stats;
49 }
50
51 uint32_t ShenandoahStackWatermark::epoch_id() const {
52 return _epoch_id;
53 }
54
55 void ShenandoahStackWatermark::change_epoch_id() {
56 shenandoah_assert_safepoint();
57 _epoch_id++;
58 if (_epoch_id > MAX_EPOCH_ID) {
59 _epoch_id = MIN_EPOCH_ID;
60 }
61 }
62
63 ShenandoahStackWatermark::ShenandoahStackWatermark(JavaThread* jt) :
64 StackWatermark(jt, StackWatermarkKind::gc, _epoch_id),
65 _heap(ShenandoahHeap::heap()),
66 _stats(),
67 _keep_alive_cl(),
68 _evac_update_oop_cl(),
69 _nm_cl() {
70 assert(StackWatermarkState::epoch(_state) == _epoch_id,
71 "Should be the same: %u != %u", StackWatermarkState::epoch(_state), _epoch_id);
72 }
73
74 OopClosure* ShenandoahStackWatermark::closure_from_context(void* context) {
75 if (context != nullptr) {
76 assert((_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) ||
77 _heap->is_concurrent_mark_in_progress(),
78 "Only these two phases");
79 assert(Thread::current()->is_Worker_thread(), "Unexpected thread passing in context: " PTR_FORMAT, p2i(context));
80 return reinterpret_cast<OopClosure*>(context);
81 } else {
82 if (_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) {
83 return &_evac_update_oop_cl;
84 } else if (_heap->is_concurrent_mark_in_progress()) {
85 return &_keep_alive_cl;
86 } else {
87 ShouldNotReachHere();
88 return nullptr;
89 }
90 }
91 }
92
93 void ShenandoahStackWatermark::start_processing_impl(void* context) {
94 NoSafepointVerifier nsv;
95
96 // Process the non-frame part of the thread
97 if (_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) {
98 // Retire the TLABs, which will force threads to reacquire their TLABs.
99 // This is needed for two reasons. Strong one: new allocations would be with new freeset,
100 // which would be outside the collection set, so no cset writes would happen there.
101 // Weaker one: new allocations would happen past update watermark, and so less work would
102 // be needed for reference updates (would update the large filler instead).
103 retire_tlab();
104
105 _jt->oops_do_no_frames(closure_from_context(context), &_nm_cl);
106 } else if (_heap->is_concurrent_mark_in_progress()) {
107 // We need to reset all TLABs because they might be below the TAMS, and we need to mark
108 // the objects in them. Do not let mutators allocate any new objects in their current TLABs.
109 // It is also a good place to resize the TLAB sizes for future allocations.
110 retire_tlab();
111
112 _jt->oops_do_no_frames(closure_from_context(context), &_nm_cl);
113 } else {
114 ShouldNotReachHere();
115 }
116
117 // Publishes the processing start to concurrent threads
118 StackWatermark::start_processing_impl(context);
119 }
120
121 void ShenandoahStackWatermark::retire_tlab() {
122 // Retire TLAB
123 if (UseTLAB) {
124 _stats.reset();
125 _jt->retire_tlab(&_stats);
126 if (ResizeTLAB) {
127 _jt->tlab().resize();
128 }
129 }
130 }
131
132 void ShenandoahStackWatermark::process(const frame& fr, RegisterMap& register_map, void* context) {
133 OopClosure* oops = closure_from_context(context);
134 assert(oops != nullptr, "Should not get to here");
135 assert((_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) ||
136 _heap->is_concurrent_mark_in_progress(),
137 "Only these two phases");
138 fr.oops_do(oops, &_nm_cl, ®ister_map, DerivedPointerIterationMode::_directly);
139 }
|
47 ThreadLocalAllocStats& ShenandoahStackWatermark::stats() {
48 return _stats;
49 }
50
51 uint32_t ShenandoahStackWatermark::epoch_id() const {
52 return _epoch_id;
53 }
54
55 void ShenandoahStackWatermark::change_epoch_id() {
56 shenandoah_assert_safepoint();
57 _epoch_id++;
58 if (_epoch_id > MAX_EPOCH_ID) {
59 _epoch_id = MIN_EPOCH_ID;
60 }
61 }
62
63 ShenandoahStackWatermark::ShenandoahStackWatermark(JavaThread* jt) :
64 StackWatermark(jt, StackWatermarkKind::gc, _epoch_id),
65 _heap(ShenandoahHeap::heap()),
66 _stats(),
67 _no_op_cl(),
68 _keep_alive_cl(),
69 _evac_update_oop_cl(),
70 _nm_cl() {
71 assert(StackWatermarkState::epoch(_state) == _epoch_id,
72 "Should be the same: %u != %u", StackWatermarkState::epoch(_state), _epoch_id);
73 }
74
75 OopClosure* ShenandoahStackWatermark::closure_from_context(void* context) {
76 if (context != nullptr) {
77 assert(Thread::current()->is_Worker_thread(), "Unexpected thread passing in context: " PTR_FORMAT, p2i(context));
78 return reinterpret_cast<OopClosure*>(context);
79 } else {
80 if (_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) {
81 return &_evac_update_oop_cl;
82 } else if (_heap->is_concurrent_mark_in_progress()) {
83 return &_keep_alive_cl;
84 } else {
85 return &_no_op_cl;
86 }
87 }
88 }
89
90 void ShenandoahStackWatermark::start_processing_impl(void* context) {
91 NoSafepointVerifier nsv;
92
93 if (_heap->is_concurrent_weak_root_in_progress() && _heap->is_evacuation_in_progress()) {
94 // This is needed for two reasons. Strong one: new allocations would be with new freeset,
95 // which would be outside the collection set, so no cset writes would happen there.
96 // Weaker one: new allocations would happen past update watermark, and so less work would
97 // be needed for reference updates (would update the large filler instead).
98 retire_tlab();
99 } else if (_heap->is_concurrent_mark_in_progress()) {
100 // We need to reset all TLABs because they might be below the TAMS, and we need to mark
101 // the objects in them. Do not let mutators allocate any new objects in their current TLABs.
102 // It is also a good place to resize the TLAB sizes for future allocations.
103 retire_tlab();
104 }
105
106 // Process the non-frame part of the thread
107 _jt->oops_do_no_frames(closure_from_context(context), &_nm_cl);
108
109 // Publishes the processing start to concurrent threads
110 StackWatermark::start_processing_impl(context);
111 }
112
113 void ShenandoahStackWatermark::retire_tlab() {
114 // Retire TLAB
115 if (UseTLAB) {
116 _stats.reset();
117 _jt->retire_tlab(&_stats);
118 if (ResizeTLAB) {
119 _jt->tlab().resize();
120 }
121 }
122 }
123
124 void ShenandoahStackWatermark::process(const frame& fr, RegisterMap& register_map, void* context) {
125 OopClosure* oops = closure_from_context(context);
126 assert(oops != nullptr, "Should not get to here");
127 fr.oops_do(oops, &_nm_cl, ®ister_map, DerivedPointerIterationMode::_directly);
128 }
|