RFR: 8189871: Refactor GC barriers to use declarative semantics
Roman Kennke
rkennke at redhat.com
Mon Nov 13 17:10:06 UTC 2017
Hi Erik,
> Hi Roman,
>
> On 2017-11-10 16:01, Roman Kennke wrote:
>> Hi Erik,
>>
>> This looks very good to me. It is likely that we'll need to extend it
>> a little bit for Shenandoah, but I haven't got around to try that out
>> yet, and will propose it when this patch percolated down to the
>> Shenandoah project.
>
> Yes. The framework should be quite flexible, and of course I will work
> with you on anything that needs to be updated.
Perfect!
>> Questions (I know I've asked some of it before in private discussions):
>> - A BarrierSet needs to declare an AccessBarrier inner class. How
>> does this get 'registered' with the Access dispatcher?
>
> Good question. Each new GC is tied together at one single point. The
> Access API picks up GCs from the gc/shared/barrierSetConfig.hpp and
> .inline.hpp files.
>
> So to register a new GC, such as Shenandoah, you have to:
>
> 1) Make sure you have a BarrierSet enum value which is added to the
> list of FOR_EACH_BARRIER_SET_DO as well as
> FOR_EACH_CONCRETE_BARRIER_SET_DO in barrierSetConfig.hpp.
>
> The first of said lists contains all barrier sets that are known to
> exist at build time, and the second of said lists crucially contains
> concrete barrier sets that have an AccessBarrier to resolve.
>
> 2) You also need to make sure in the barrierSetConfig.inline.hpp file
> that you #include your shenandoah BarrierSet inline.hpp file.
>
> 3) You have to provide a specialization for the BarrierSet::GetName
> and BarrierSet::GetType metafunctions that provide an enum value for a
> barrier set type, and vice versa.
>
> 4) Since you probably want primitive accesses in the heap to also
> resolve into the barrier set in a build that includes Shenandoah, you
> should #define SUPPORT_BARRIER_ON_PRIMITIVES in the
> barrierSetConfig.hpp file when building with Shenandoah. This will
> flick on the INTERNAL_BT_BARRIER_ON_PRIMITIVES decorator to each
> access so that the Access framework understands that even primitive
> accesses must be resolved at run-time in the barrier set. So this is a
> build-time switch for turning on run-time resolution of primitive
> accesses in the heap.
>
> And now you should be set: your new
> ShenandoahBarrierSet::AccessBarrier will be called for each access,
> including primitives.
>
> It works the following way:
>
> 1) The barrier resolver loads the current barrier set, and checks the
> "name" of it (the enum value).
> 2) Each "name" for concrete barriers that you listed in
> barrierSetConfig.hpp is asked for...
> 3) ...the BarrierSet::GetType of that enum "name", and...
> 4) The AccessBarrier of that resulting BarrierSet (your
> ShenandoahBarrierSet) will be called.
>
> Hope that makes sense.
>
It is ok. But just so. ;-)
The problem is that it is a bit mystical how stuff is set up, and I'd
prefer a more explicit way to do it.
Maybe add the above explanations (how to make new GC barriers) in a
comment somewhere?
>> - I see you use namespace. I haven't seen them anywhere else in
>> Hotspot, so this looks quite unusual :-) Not that I am against it (I
>> would probably advocate for using more of it), but have you
>> considered alternatives that look more common Hotspot-style (e.g.
>> declaring an all-static AccessInternal class)?
>
> We do not have any platform that has problems with namespaces. So I
> would prefer this basic namespace usage to a bunch of AllStatic
> classes. I hope nobody minds that.
>
I am ok with it.
>> - The dispatching machinery looks a bit over the top, and from the
>> outskirts like a manual re-invention of virtual method dispatch.
>> Couldn't we do the same stuff with the usual public interface /
>> concrete implementation idioms? I am worried that adding just one
>> method to the interface turns into a nightmare of wiring up stuff and
>> adding tons of boilerplate to get it going. Not to mention the
>> learning curve involved trying to make sense of what goes where.
>
> It's not quite like a normal virtual call though. It's a virtual
> dispatch that carries template parameters through the runtime
> dispatch. The template parameters are required for 1) remembering the
> decorators (semantics of the access), and 2) the type information of
> the operands for the access.
>
> In my experience, when you need to drag template parameters through
> some form of virtual dispatch, it is easiest to use function pointers
> and not virtual calls.
> I understand it might look a bit complicated, but I hope that is okay.
Right. Templates and virtual doesn't play well (or at all) together.
I've seen that the GC interface JEP just went to 'targeted' so I guess
you can push it (probably needs more review?)
Roman
More information about the hotspot-dev
mailing list