RFR: 8139800: Remove OopsInGenClosure
Stefan Karlsson
stefan.karlsson at oracle.com
Thu Aug 27 12:12:52 UTC 2020
Thanks for reviewing!
StefanK
On 2020-08-27 14:07, stefan.johansson at oracle.com wrote:
> Hi StefanK,
>
> Looks good, and like Kim I really appreciate the very clear explanation :)
>
> Thanks,
> StefanJ
>
> On 2020-08-25 12:15, Stefan Karlsson wrote:
>> Hi all,
>>
>> Please review this patch to remove OopsInGenClosure.
>>
>> https://cr.openjdk.java.net/~stefank/8139800/webrev.01/
>> https://bugs.openjdk.java.net/browse/JDK-8139800
>>
>> The patch builds upon the cleanup patches that are current out for
>> review: JDK-8252245, JDK-8252289, JDK-8252294.
>>
>> - The preparation patches remove most external usages of
>> OopsInGenClosure. However, there are two usages left:
>> oop_since_save_marks_iterate and young_process_roots. These usages
>> call set_generation before applying the closure, and
>> reset_generation() after. I'll explain below why those calls are not
>> needed anymore:
>>
>> ---
>>
>> After the recent cleanups, FastScanClosure is the only concrete class
>> of OopsInGenClosure. FastScanClosure is used to "scan" the young
>> generation (DefNew). But, it is actually used in two different
>> situations, and require different barrier code depending on where it
>> is used:
>>
>> 1) Scan the old gen for pointers into the young gen, and apply a store
>> barrier.
>> 2) Scan non-old gen parts, including oops in CLDs (and associated
>> Metadata)
>>
>> This can be seen here, where the passed in boolean corresponds to the
>> FastScanClosure::_gc_barrier variable:
>>
>> 573 FastScanClosure fsc_with_no_gc_barrier(this, false);
>> 574 FastScanClosure fsc_with_gc_barrier(this, true);
>>
>> This in turn is used here:
>>
>> 77 template <class T> inline void FastScanClosure::do_oop_work(T* p) {
>> ... < Handling the pointer int young gen >
>> 87 if (is_scanning_a_cld()) {
>> 88 do_cld_barrier();
>> 89 } else if (_gc_barrier) {
>> 90 // Now call parent closure
>> 91 do_barrier(p);
>> 92 }
>>
>> Where line 91 deals with the (1) case above, and 87-88 deals with the
>> (2) case.
>>
>> The do_barrier function called in 91, is provided by OopsInGenClosure.
>> The CLD barrier code is provided by OopsInClassLoaderDataOrGenClosure.
>> This class inherits from OopsInGenClosure, but doesn't use the
>> functionality. It inherits from OopsInGenClosure so that they both can
>> be passed through the same code path.
>>
>> In the patch common code is extracted into a revised FastScanClosure
>> super class, that only performs the young gen scanning code, and
>> delegates the barrier code to the derived classes.
>>
>> Two derived classes are created:
>> - DefNewYoungerGenClosure provides the old-to-young gen write barrier
>> and is used for case (1).
>> - DefNewScanClosure provides the CLD barrier for case (2).
>>
>> After the separation, it's apparent that DefNewScanClosure doesn't use
>> the OopsInGenClosure code, and the only external usages are calls to
>> set_generation/reset_generation. There are no actual usages of the
>> values set by those functions. The set_generation/reset_generation
>> calls that can be removed are here:
>>
>> SerialHeap::young_process_roots:
>> ...
>> if (_process_strong_tasks->try_claim_task(GCH_PS_younger_gens)) {
>> - root_closure->reset_generation();
>> }
>>
>> and template <typename OopClosureType>
>>
>> void DefNewGeneration::oop_since_save_marks_iterate(OopClosureType*
>> cl) {
>> - cl->set_generation(this);
>> eden()->oop_since_save_marks_iterate(cl);
>> to()->oop_since_save_marks_iterate(cl);
>> from()->oop_since_save_marks_iterate(cl);
>> - cl->reset_generation();
>>
>>
>> DefNewYoungerGenClosure does use the variables changed by
>> set_generation/reset_generation, but the only callers always pass in
>> the old generation:
>>
>> void TenuredGeneration::oop_since_save_marks_iterate(OopClosureType*
>> blk) {
>> - blk->set_generation(this);
>> _the_space->oop_since_save_marks_iterate(blk);
>> - blk->reset_generation();
>>
>>
>> and:
>>
>> void SerialHeap::young_process_roots
>> ...
>> - old_gen_closure->set_generation(_old_gen);
>> rem_set()->at_younger_refs_iterate();
>> old_gen()->younger_refs_iterate(old_gen_closure, scope->n_threads());
>> - old_gen_closure->reset_generation();
>>
>> So, instead of doing this over and over again, the code is moved to
>> the constructor. After that, there's no external usages of
>> OopsInGenClosure, and the class can be removed from the class hierarchy.
>>
>> ---
>>
>> - I've renamed some of the variables to make it more apparent what
>> generation the code is dealing with.
>>
>> - Note: The FastScanClosure and its derived classes should be moved to
>> gc/serial, but I've left that for a separate RFE.
>>
>> - Note: GCH_PS_younger_gens should probably be removed, but I've left
>> that cleanup for a separate RFE.
>>
>> Testing: Testing on tier1-tier7 on Linux with forced usages of
>> -XX:+UseSerialGC.
>>
>> Thanks,
>> StefanK
More information about the hotspot-gc-dev
mailing list