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