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