RFR: Traveral GC heuristics
Roman Kennke
rkennke at redhat.com
Wed Jan 17 21:58:52 UTC 2018
>> 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) {
Done.
> *) 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?
Done.
> *) 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?
It's the same set of regs that need to be saved+restored in the write
barrier, a few lines above.
> *) ShenandoahStoreValReadBarrier, ShenandoahStoreValWriteBarrier, ShenandoahStoreValReadBarrier
> exclusion tests
ShStoreValWB and ShStoreValEnq are not exclusive. I need them both in
tandem. I added exclusion test for ShStoreValEnq against ShStoreValRB in
shenandoahCollectorPolicy.cpp, but don't know how to 'encode' that in
TestSelectiveBarrierFlags.java
> *) 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 }
Done.
> shenandoahCollectorPolicy.cpp
>
> *) Stray debugging lines:
>
> 1367 // tty->print_cr("CSET regions:");
> 1376 // r->print_on(tty);
Removed.
> *) 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
Yes, but we need degenerate GC for traversal first :-)
> 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.
Done.
> *) This is not needed anymore:
>
> 207 // TODO: Call this properly with Shenandoah*CycleMark
> 208 heap->set_used_at_last_gc();
Removed.
> 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);
> }
Done.
> shenandoahVerifier.cpp:
>
> *) Why are we testing for "next" bitmap here?
Because traversal uses the next bitmap, and only this, and I don't care
to swap with complete, but I want to verify it. Good?
> _verify_liveness_complete and the comment seem to
> disagree? Comments still mention "partial"?
Fixed.
> 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)") \
>
>
Fixed.
> 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?
>
I only implemented this sketchy MWF thing in C2 for now. This definitely
needs more work, and I don't even know if it is correct.
> Other C2:
>
> *) Roland should take a look, but I find it uncomfortable to change do_unswitching,
> find_unswitching_candidate with new arguements...
This was actually done by Roland to get the new barriers to work and
optimize well enough.
> sharedRuntime.cpp:
>
> *) Bug due to bad indentation and braces?
>
> 215 if (UseShenandoahGC) { ShenandoahBarrierSet::enqueue(orig); }
> 216 return;
Yeah, this is not needed. I removed it.
> 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?
Yes, maybe. But for the start, I did not want it to interfere with
existing code if I can avoid it. For this reason, this looks like a
copy+paste job from conc-mark and partial for some parts.
Thanks for reviewing and spotting all the issues. I could not really
make a diff webrev, because I first had to pull -u your latest work, and
this messed up my differential webrev... sorry. Only full webrev now:
http://cr.openjdk.java.net/~rkennke/traversal/webrev.03/
More information about the shenandoah-dev
mailing list