RFR: Traveral GC heuristics

Aleksey Shipilev shade at redhat.com
Wed Jan 17 17:54:26 UTC 2018


On 01/17/2018 04:08 PM, Roman Kennke wrote:
> Full:
> http://cr.openjdk.java.net/~rkennke/traversal/webrev.02/

Exciting!

c1_Runtime1_x86.cpp:

*) Let's rewrite this:

   if (bs->kind() == BarrierSet::ShenandoahBarrierSet && !ShenandoahSATBBarrier &&
!ShenandoahConditionalSATBBarrier && !ShenandoahStoreValEnqueueBarrier) {

into:

    if (bs->kind() == BarrierSet::ShenandoahBarrierSet && !(ShenandoahSATBBarrier ||
ShenandoahConditionalSATBBarrier || ShenandoahStoreValEnqueueBarrier) {

*) Re:

1644           __ testb(gc_state, ShenandoahHeap::MARKING | ShenandoahHeap::TRAVERSAL);

So, set_concurrent_traversal_in_progress activates the SATB queues, and this is good. Why don't we
set the ShenandoahHeap::MARKING bit to gc_state there, and avoid "| TRAVERSAL" all around the
arch-specific code?


*) shenandoahBarrierSet_x86.cpp: Pushes/pops around the call to g1_write_barrier_pre seem
suspicious. How do we know we need to caller-save rbx, rcx, rdx, c_rarg1? Deserves a comment, maybe?

*) ShenandoahStoreValReadBarrier, ShenandoahStoreValWriteBarrier, ShenandoahStoreValReadBarrier
exclusion tests

*) shenandoahBarrierSet.cpp: branches are the same, which looks like typo. Should be compound
boolean predicate?

  42       if (ALWAYS_ENQUEUE && !oopDesc::is_null(o)) {
  43         ShenandoahBarrierSet::enqueue(o);
  44       } else if (evac) {
  45         ShenandoahBarrierSet::enqueue(o);
  46       }

shenandoahCollectorPolicy.cpp

 *) Stray debugging lines:

1367     // tty->print_cr("CSET regions:");
1376         // r->print_on(tty);

 *) Heuristics need work: I think it runs into problem that adaptive cset selection solves: it
chooses either too big or too small cset. I wonder if you can actually reuse that in traversal
heuristics

shenandoahConcurrentThread.cpp:

 *) I think you want to introduce ShenandoahHeap::{vmop_entry,entry,op}_traversal family of methods,
and call them, as we do with the rest of VM ops.

 *) This is not needed anymore:

 207   // TODO: Call this properly with Shenandoah*CycleMark
 208   heap->set_used_at_last_gc();

shenandoahHeap.cpp:

 *) As mentioned above, this:

1683 void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) {
1684   set_gc_state_bit(TRAVERSAL_BITPOS, in_progress);
1685   JavaThread::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
1686   set_evacuation_in_progress_at_safepoint(in_progress);
1687   set_has_forwarded_objects(in_progress);
1688 }

is probably just:

 void ShenandoahHeap::set_concurrent_traversal_in_progress(bool in_progress) {
   set_gc_state_bit(TRAVERSAL_BITPOS, in_progress);
   set_gc_state_bit(MARKING_BITPOS, in_progress);
   set_gc_state_bit(HAS_FORWARDED_OBJECTS_BITPOS, in_progress);
   set_gc_state_bit_at_safepoint(_gc_state.raw_value());
   JavaThread::satb_mark_queue_set().set_active_all_threads(in_progress, !in_progress);
 }

shenandoahVerifier.cpp:

*) Why are we testing for "next" bitmap here? _verify_liveness_complete and the comment seem to
disagree? Comments still mention "partial"?

 void ShenandoahVerifier::verify_after_traversal() {
   verify_at_safepoint(
         "After Traversal",
         _verify_forwarded_none,      // cannot have forwarded objects
         _verify_marked_next,         // bitmaps might be stale, but alloc-after-mark should be well
         _verify_matrix_disable,      // matrix is conservatively consistent
         _verify_cset_none,           // no cset references left after partial
         _verify_liveness_complete,   // no reliable liveness data anymore
         _verify_regions_nocset       // no cset regions, trash regions allowed
  );
 }

shenandoah_globals.hpp:

 *) Comment is duplicated:

 316                                                                             \
 317   diagnostic(bool, ShenandoahStoreValEnqueueBarrier, false,                 \
 318           "Turn on/off enqueuing of oops after write barriers (MWF)")       \
 319                                                                             \
 320   diagnostic(bool, ShenandoahMWF, false,                                    \
 321           "Turn on/off enqueuing of oops after write barriers (MWF)")       \


graphKit.cpp:

 *) So we predicate shenandoah_enqueue_barrier with !ShenandoahMWF here:

4887     if (ShenandoahStoreValEnqueueBarrier && !ShenandoahMWF) {
4888       shenandoah_enqueue_barrier(obj);
4889     }

 ...but not around other uses of ShenandoahStoreValEnqueueBarrier, e.g. in c1_LIRGenerator?

Other C2:

 *) Roland should take a look, but I find it uncomfortable to change do_unswitching,
find_unswitching_candidate with new arguements...

sharedRuntime.cpp:

 *) Bug due to bad indentation and braces?

 215 if (UseShenandoahGC) { ShenandoahBarrierSet::enqueue(orig); }
 216 return;

shenandoahTraversalGC*:

 *) Really, really unfortunate to duplicate a lot from shenandoahConcurrentMark. Maybe we should
massage the codebase so that we could reuse significant chunks of the code?

Thanks,
-Aleksey



More information about the shenandoah-dev mailing list