229 assert(!region_attr.is_humongous_candidate(),
230 "Obj " PTR_FORMAT " should not refer to humongous region %u from " PTR_FORMAT,
231 p2i(obj), _g1h->addr_to_region(obj), p2i(p));
232
233 if (!region_attr.is_in_cset()) {
234 // In this case somebody else already did all the work.
235 return;
236 }
237
238 markWord m = obj->mark();
239 if (m.is_forwarded()) {
240 obj = obj->forwardee(m);
241 } else {
242 obj = do_copy_to_survivor_space(region_attr, obj, m);
243 }
244 RawAccess<IS_NOT_NULL>::oop_store(p, obj);
245
246 write_ref_field_post(p, obj);
247 }
248
249 MAYBE_INLINE_EVACUATION
250 void G1ParScanThreadState::do_partial_array(PartialArrayState* state, bool stolen) {
251 // Access state before release by claim().
252 objArrayOop to_array = objArrayOop(state->destination());
253 PartialArraySplitter::Claim claim =
254 _partial_array_splitter.claim(state, _task_queue, stolen);
255 G1HeapRegionAttr dest_attr = _g1h->region_attr(to_array);
256 G1SkipCardMarkSetter x(&_scanner, dest_attr.is_new_survivor());
257 // Process claimed task.
258 to_array->oop_iterate_elements_range(&_scanner,
259 checked_cast<int>(claim._start),
260 checked_cast<int>(claim._end));
261 }
262
263 MAYBE_INLINE_EVACUATION
264 void G1ParScanThreadState::start_partial_objarray(oop from_obj,
265 oop to_obj) {
266 assert(from_obj->is_forwarded(), "precondition");
267 assert(from_obj->forwardee() == to_obj, "precondition");
268 assert(to_obj->is_objArray(), "precondition");
269
270 objArrayOop to_array = objArrayOop(to_obj);
271 size_t array_length = to_array->length();
272 size_t initial_chunk_size =
273 // The source array is unused when processing states.
274 _partial_array_splitter.start(_task_queue, nullptr, to_array, array_length, ParGCArrayScanChunk);
275
276 assert(_scanner.skip_card_mark_set(), "must be");
277 // Process the initial chunk. No need to process the type in the
278 // klass, as it will already be handled by processing the built-in
279 // module.
280 to_array->oop_iterate_elements_range(&_scanner, 0, checked_cast<int>(initial_chunk_size));
281 }
282
283 MAYBE_INLINE_EVACUATION
284 void G1ParScanThreadState::dispatch_task(ScannerTask task, bool stolen) {
285 verify_task(task);
286 if (task.is_narrow_oop_ptr()) {
287 do_oop_evac(task.to_narrow_oop_ptr());
288 } else if (task.is_oop_ptr()) {
289 do_oop_evac(task.to_oop_ptr());
290 } else {
291 do_partial_array(task.to_partial_array_state(), stolen);
292 }
293 }
294
295 // Process tasks until overflow queue is empty and local queue
296 // contains no more than threshold entries. NOINLINE to prevent
297 // inlining into steal_and_trim_queue.
298 ATTRIBUTE_FLATTEN NOINLINE
299 void G1ParScanThreadState::trim_queue_to_threshold(uint threshold) {
300 ScannerTask task;
|
229 assert(!region_attr.is_humongous_candidate(),
230 "Obj " PTR_FORMAT " should not refer to humongous region %u from " PTR_FORMAT,
231 p2i(obj), _g1h->addr_to_region(obj), p2i(p));
232
233 if (!region_attr.is_in_cset()) {
234 // In this case somebody else already did all the work.
235 return;
236 }
237
238 markWord m = obj->mark();
239 if (m.is_forwarded()) {
240 obj = obj->forwardee(m);
241 } else {
242 obj = do_copy_to_survivor_space(region_attr, obj, m);
243 }
244 RawAccess<IS_NOT_NULL>::oop_store(p, obj);
245
246 write_ref_field_post(p, obj);
247 }
248
249 ALWAYSINLINE
250 void G1ParScanThreadState::process_array_chunk(objArrayOop obj, size_t start, size_t end) {
251 obj->oop_iterate_elements_range(&_scanner,
252 checked_cast<int>(start),
253 checked_cast<int>(end));
254 }
255
256 MAYBE_INLINE_EVACUATION
257 void G1ParScanThreadState::do_partial_array(PartialArrayState* state, bool stolen) {
258 // Access state before release by claim().
259 objArrayOop to_array = objArrayOop(state->destination());
260 PartialArraySplitter::Claim claim =
261 _partial_array_splitter.claim(state, _task_queue, stolen);
262 G1HeapRegionAttr dest_attr = _g1h->region_attr(to_array);
263 G1SkipCardMarkSetter x(&_scanner, dest_attr.is_new_survivor());
264 // Process claimed task.
265 assert(to_array->is_objArray(), "Must be");
266 process_array_chunk(to_array, claim._start, claim._end);
267 }
268
269 MAYBE_INLINE_EVACUATION
270 void G1ParScanThreadState::start_partial_objarray(oop from_obj,
271 oop to_obj) {
272 assert(from_obj->is_forwarded(), "precondition");
273 assert(from_obj->forwardee() == to_obj, "precondition");
274 assert(to_obj->is_objArray(), "precondition");
275 assert(!_scanner.do_metadata(), "precondition");
276 assert(_scanner.skip_card_mark_set(), "precondition");
277
278 objArrayOop to_array = objArrayOop(to_obj);
279 size_t array_length = to_array->length();
280 size_t initial_chunk_size =
281 // The source array is unused when processing states.
282 _partial_array_splitter.start(_task_queue, nullptr, to_array, array_length, ParGCArrayScanChunk);
283
284 process_array_chunk(to_array, 0, initial_chunk_size);
285 }
286
287 MAYBE_INLINE_EVACUATION
288 void G1ParScanThreadState::dispatch_task(ScannerTask task, bool stolen) {
289 verify_task(task);
290 if (task.is_narrow_oop_ptr()) {
291 do_oop_evac(task.to_narrow_oop_ptr());
292 } else if (task.is_oop_ptr()) {
293 do_oop_evac(task.to_oop_ptr());
294 } else {
295 do_partial_array(task.to_partial_array_state(), stolen);
296 }
297 }
298
299 // Process tasks until overflow queue is empty and local queue
300 // contains no more than threshold entries. NOINLINE to prevent
301 // inlining into steal_and_trim_queue.
302 ATTRIBUTE_FLATTEN NOINLINE
303 void G1ParScanThreadState::trim_queue_to_threshold(uint threshold) {
304 ScannerTask task;
|