278 log_trace(gc, promotion)(" (%d: promotion failure size = " SIZE_FORMAT ") ", |
278 log_trace(gc, promotion)(" (%d: promotion failure size = " SIZE_FORMAT ") ", |
279 _thread_num, _promotion_failed_info.first_size()); |
279 _thread_num, _promotion_failed_info.first_size()); |
280 } |
280 } |
281 } |
281 } |
282 |
282 |
283 class ParScanThreadStateSet: private ResourceArray { |
283 class ParScanThreadStateSet: StackObj { |
284 public: |
284 public: |
285 // Initializes states for the specified number of threads; |
285 // Initializes states for the specified number of threads; |
286 ParScanThreadStateSet(int num_threads, |
286 ParScanThreadStateSet(int num_threads, |
287 Space& to_space, |
287 Space& to_space, |
288 ParNewGeneration& young_gen, |
288 ParNewGeneration& young_gen, |
327 ObjToScanQueueSet& queue_set, |
329 ObjToScanQueueSet& queue_set, |
328 Stack<oop, mtGC>* overflow_stacks, |
330 Stack<oop, mtGC>* overflow_stacks, |
329 PreservedMarksSet& preserved_marks_set, |
331 PreservedMarksSet& preserved_marks_set, |
330 size_t desired_plab_sz, |
332 size_t desired_plab_sz, |
331 ParallelTaskTerminator& term) |
333 ParallelTaskTerminator& term) |
332 : ResourceArray(sizeof(ParScanThreadState), num_threads), |
334 : _young_gen(young_gen), |
333 _young_gen(young_gen), |
|
334 _old_gen(old_gen), |
335 _old_gen(old_gen), |
335 _term(term) |
336 _term(term), |
|
337 _per_thread_states(NEW_RESOURCE_ARRAY(ParScanThreadState, num_threads)), |
|
338 _num_threads(num_threads) |
336 { |
339 { |
337 assert(num_threads > 0, "sanity check!"); |
340 assert(num_threads > 0, "sanity check!"); |
338 assert(ParGCUseLocalOverflow == (overflow_stacks != NULL), |
341 assert(ParGCUseLocalOverflow == (overflow_stacks != NULL), |
339 "overflow_stack allocation mismatch"); |
342 "overflow_stack allocation mismatch"); |
340 // Initialize states. |
343 // Initialize states. |
341 for (int i = 0; i < num_threads; ++i) { |
344 for (int i = 0; i < num_threads; ++i) { |
342 new ((ParScanThreadState*)_data + i) |
345 new(_per_thread_states + i) |
343 ParScanThreadState(&to_space, &young_gen, &old_gen, i, &queue_set, |
346 ParScanThreadState(&to_space, &young_gen, &old_gen, i, &queue_set, |
344 overflow_stacks, preserved_marks_set.get(i), |
347 overflow_stacks, preserved_marks_set.get(i), |
345 desired_plab_sz, term); |
348 desired_plab_sz, term); |
346 } |
349 } |
347 } |
350 } |
348 |
351 |
349 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) { |
352 inline ParScanThreadState& ParScanThreadStateSet::thread_state(int i) { |
350 assert(i >= 0 && i < length(), "sanity check!"); |
353 assert(i >= 0 && i < _num_threads, "sanity check!"); |
351 return ((ParScanThreadState*)_data)[i]; |
354 return _per_thread_states[i]; |
352 } |
355 } |
353 |
356 |
354 void ParScanThreadStateSet::trace_promotion_failed(const YoungGCTracer* gc_tracer) { |
357 void ParScanThreadStateSet::trace_promotion_failed(const YoungGCTracer* gc_tracer) { |
355 for (int i = 0; i < length(); ++i) { |
358 for (int i = 0; i < _num_threads; ++i) { |
356 if (thread_state(i).promotion_failed()) { |
359 if (thread_state(i).promotion_failed()) { |
357 gc_tracer->report_promotion_failed(thread_state(i).promotion_failed_info()); |
360 gc_tracer->report_promotion_failed(thread_state(i).promotion_failed_info()); |
358 thread_state(i).promotion_failed_info().reset(); |
361 thread_state(i).promotion_failed_info().reset(); |
359 } |
362 } |
360 } |
363 } |
361 } |
364 } |
362 |
365 |
363 void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed) { |
366 void ParScanThreadStateSet::reset(uint active_threads, bool promotion_failed) { |
364 _term.reset_for_reuse(active_threads); |
367 _term.reset_for_reuse(active_threads); |
365 if (promotion_failed) { |
368 if (promotion_failed) { |
366 for (int i = 0; i < length(); ++i) { |
369 for (int i = 0; i < _num_threads; ++i) { |
367 thread_state(i).print_promotion_failure_size(); |
370 thread_state(i).print_promotion_failure_size(); |
368 } |
371 } |
369 } |
372 } |
370 } |
373 } |
371 |
374 |
399 ResourceMark rm; |
402 ResourceMark rm; |
400 outputStream* st = log.debug_stream(); |
403 outputStream* st = log.debug_stream(); |
401 |
404 |
402 print_termination_stats_hdr(st); |
405 print_termination_stats_hdr(st); |
403 |
406 |
404 for (int i = 0; i < length(); ++i) { |
407 for (int i = 0; i < _num_threads; ++i) { |
405 const ParScanThreadState & pss = thread_state(i); |
408 const ParScanThreadState & pss = thread_state(i); |
406 const double elapsed_ms = pss.elapsed_time() * 1000.0; |
409 const double elapsed_ms = pss.elapsed_time() * 1000.0; |
407 const double s_roots_ms = pss.strong_roots_time() * 1000.0; |
410 const double s_roots_ms = pss.strong_roots_time() * 1000.0; |
408 const double term_ms = pss.term_time() * 1000.0; |
411 const double term_ms = pss.term_time() * 1000.0; |
409 st->print_cr("%3d %9.2f %9.2f %6.2f %9.2f %6.2f " SIZE_FORMAT_W(8), |
412 st->print_cr("%3d %9.2f %9.2f %6.2f %9.2f %6.2f " SIZE_FORMAT_W(8), |
450 void ParScanThreadStateSet::flush() { |
453 void ParScanThreadStateSet::flush() { |
451 // Work in this loop should be kept as lightweight as |
454 // Work in this loop should be kept as lightweight as |
452 // possible since this might otherwise become a bottleneck |
455 // possible since this might otherwise become a bottleneck |
453 // to scaling. Should we add heavy-weight work into this |
456 // to scaling. Should we add heavy-weight work into this |
454 // loop, consider parallelizing the loop into the worker threads. |
457 // loop, consider parallelizing the loop into the worker threads. |
455 for (int i = 0; i < length(); ++i) { |
458 for (int i = 0; i < _num_threads; ++i) { |
456 ParScanThreadState& par_scan_state = thread_state(i); |
459 ParScanThreadState& par_scan_state = thread_state(i); |
457 |
460 |
458 // Flush stats related to To-space PLAB activity and |
461 // Flush stats related to To-space PLAB activity and |
459 // retire the last buffer. |
462 // retire the last buffer. |
460 par_scan_state.to_space_alloc_buffer()->flush_and_retire_stats(_young_gen.plab_stats()); |
463 par_scan_state.to_space_alloc_buffer()->flush_and_retire_stats(_young_gen.plab_stats()); |