1188 // There are two reasons to retire all plabs between old-gen evacuation passes.
1189 // 1. We need to make the plab memory parsable by remembered-set scanning.
1190 // 2. We need to establish a trustworthy UpdateWaterMark value within each old-gen heap region
1191 shenandoah_plab->retire();
1192
1193 // Re-enable promotions for the next evacuation phase.
1194 shenandoah_plab->enable_promotions();
1195
1196 // Reset the fill size for next evacuation phase.
1197 if (_resize && shenandoah_plab->desired_size() > 0) {
1198 shenandoah_plab->set_desired_size(0);
1199 }
1200 }
1201 }
1202 };
1203
1204 class ShenandoahGCStatePropagatorHandshakeClosure : public HandshakeClosure {
1205 public:
1206 explicit ShenandoahGCStatePropagatorHandshakeClosure(char gc_state) :
1207 HandshakeClosure("Shenandoah GC State Change"),
1208 _gc_state(gc_state) {}
1209
1210 void do_thread(Thread* thread) override {
1211 ShenandoahThreadLocalData::set_gc_state(thread, _gc_state);
1212 }
1213 private:
1214 char _gc_state;
1215 };
1216
1217 class ShenandoahPrepareForUpdateRefsHandshakeClosure : public HandshakeClosure {
1218 public:
1219 explicit ShenandoahPrepareForUpdateRefsHandshakeClosure(char gc_state) :
1220 HandshakeClosure("Shenandoah Prepare for Update Refs"),
1221 _retire(ResizeTLAB), _propagator(gc_state) {}
1222
1223 void do_thread(Thread* thread) override {
1224 _propagator.do_thread(thread);
1225 if (ShenandoahThreadLocalData::gclab(thread) != nullptr) {
1226 _retire.do_thread(thread);
1227 }
1228 }
1229 private:
1230 ShenandoahRetireGCLABClosure _retire;
1231 ShenandoahGCStatePropagatorHandshakeClosure _propagator;
1232 };
1233
1234 void ShenandoahHeap::evacuate_collection_set(ShenandoahGeneration* generation, bool concurrent) {
1235 assert(generation->is_global(), "Only global generation expected here");
1236 ShenandoahEvacuationTask task(this, _collection_set, concurrent);
1237 workers()->run_task(&task);
1238 }
1239
1240 void ShenandoahHeap::concurrent_prepare_for_update_refs() {
1241 {
1242 // Java threads take this lock while they are being attached and added to the list of threads.
1243 // If another thread holds this lock before we update the gc state, it will receive a stale
1244 // gc state, but they will have been added to the list of java threads and so will be corrected
1245 // by the following handshake.
1246 MutexLocker lock(Threads_lock);
1247
1248 // A cancellation at this point means the degenerated cycle must resume from update-refs.
1249 set_gc_state_concurrent(EVACUATION, false);
1250 set_gc_state_concurrent(WEAK_ROOTS, false);
1251 set_gc_state_concurrent(UPDATE_REFS, true);
1252 }
1253
1254 // This will propagate the gc state and retire gclabs and plabs for threads that require it.
1255 ShenandoahPrepareForUpdateRefsHandshakeClosure prepare_for_update_refs(_gc_state.raw_value());
1256
1257 // The handshake won't touch worker threads (or control thread, or VM thread), so do those separately.
1258 Threads::non_java_threads_do(&prepare_for_update_refs);
1259
1260 // Now retire gclabs and plabs and propagate gc_state for mutator threads
1261 Handshake::execute(&prepare_for_update_refs);
1262
1263 _update_refs_iterator.reset();
1264 }
1265
1266 class ShenandoahCompositeHandshakeClosure : public HandshakeClosure {
1267 HandshakeClosure* _handshake_1;
1268 HandshakeClosure* _handshake_2;
1269 public:
1270 ShenandoahCompositeHandshakeClosure(HandshakeClosure* handshake_1, HandshakeClosure* handshake_2) :
1271 HandshakeClosure(handshake_2->name()),
|
1188 // There are two reasons to retire all plabs between old-gen evacuation passes.
1189 // 1. We need to make the plab memory parsable by remembered-set scanning.
1190 // 2. We need to establish a trustworthy UpdateWaterMark value within each old-gen heap region
1191 shenandoah_plab->retire();
1192
1193 // Re-enable promotions for the next evacuation phase.
1194 shenandoah_plab->enable_promotions();
1195
1196 // Reset the fill size for next evacuation phase.
1197 if (_resize && shenandoah_plab->desired_size() > 0) {
1198 shenandoah_plab->set_desired_size(0);
1199 }
1200 }
1201 }
1202 };
1203
1204 class ShenandoahGCStatePropagatorHandshakeClosure : public HandshakeClosure {
1205 public:
1206 explicit ShenandoahGCStatePropagatorHandshakeClosure(char gc_state) :
1207 HandshakeClosure("Shenandoah GC State Change"),
1208 _gc_state(gc_state), _gc_state_fast(ShenandoahThreadLocalData::compute_gc_state_fast(gc_state)) {}
1209
1210 void do_thread(Thread* thread) override {
1211 ShenandoahThreadLocalData::set_gc_state(thread, _gc_state, _gc_state_fast);
1212 }
1213 private:
1214 char _gc_state;
1215 char _gc_state_fast;
1216 };
1217
1218 class ShenandoahPrepareForUpdateRefsHandshakeClosure : public HandshakeClosure {
1219 public:
1220 explicit ShenandoahPrepareForUpdateRefsHandshakeClosure(char gc_state) :
1221 HandshakeClosure("Shenandoah Prepare for Update Refs"),
1222 _retire(ResizeTLAB), _propagator(gc_state) {}
1223
1224 void do_thread(Thread* thread) override {
1225 _propagator.do_thread(thread);
1226 if (ShenandoahThreadLocalData::gclab(thread) != nullptr) {
1227 _retire.do_thread(thread);
1228 }
1229 }
1230 private:
1231 ShenandoahRetireGCLABClosure _retire;
1232 ShenandoahGCStatePropagatorHandshakeClosure _propagator;
1233 };
1234
1235 void ShenandoahHeap::evacuate_collection_set(ShenandoahGeneration* generation, bool concurrent) {
1236 if (concurrent && ShenandoahWeakRootsEarly) {
1237 // Turn weak roots off now, so that weak barriers do not go slow.
1238 {
1239 MutexLocker lock(Threads_lock);
1240 set_gc_state_concurrent(WEAK_ROOTS, false);
1241 }
1242
1243 ShenandoahGCStatePropagatorHandshakeClosure propagate_gc_state(_gc_state.raw_value());
1244 Threads::non_java_threads_do(&propagate_gc_state);
1245 Handshake::execute(&propagate_gc_state);
1246 }
1247
1248 assert(generation->is_global(), "Only global generation expected here");
1249 ShenandoahEvacuationTask task(this, _collection_set, concurrent);
1250 workers()->run_task(&task);
1251 }
1252
1253 void ShenandoahHeap::concurrent_prepare_for_update_refs() {
1254 {
1255 // Java threads take this lock while they are being attached and added to the list of threads.
1256 // If another thread holds this lock before we update the gc state, it will receive a stale
1257 // gc state, but they will have been added to the list of java threads and so will be corrected
1258 // by the following handshake.
1259 MutexLocker lock(Threads_lock);
1260
1261 // A cancellation at this point means the degenerated cycle must resume from update-refs.
1262 set_gc_state_concurrent(EVACUATION, false);
1263 set_gc_state_concurrent(UPDATE_REFS, true);
1264 if (!ShenandoahWeakRootsEarly) {
1265 set_gc_state_concurrent(WEAK_ROOTS, false);
1266 }
1267 }
1268
1269 // This will propagate the gc state and retire gclabs and plabs for threads that require it.
1270 ShenandoahPrepareForUpdateRefsHandshakeClosure prepare_for_update_refs(_gc_state.raw_value());
1271
1272 // The handshake won't touch worker threads (or control thread, or VM thread), so do those separately.
1273 Threads::non_java_threads_do(&prepare_for_update_refs);
1274
1275 // Now retire gclabs and plabs and propagate gc_state for mutator threads
1276 Handshake::execute(&prepare_for_update_refs);
1277
1278 _update_refs_iterator.reset();
1279 }
1280
1281 class ShenandoahCompositeHandshakeClosure : public HandshakeClosure {
1282 HandshakeClosure* _handshake_1;
1283 HandshakeClosure* _handshake_2;
1284 public:
1285 ShenandoahCompositeHandshakeClosure(HandshakeClosure* handshake_1, HandshakeClosure* handshake_2) :
1286 HandshakeClosure(handshake_2->name()),
|