RFR: 8209437: Mechanism for decoupling consumers and providers of behaviours

Andrew Dinn adinn at redhat.com
Tue Aug 14 10:27:32 UTC 2018


On 13/08/18 18:05, Erik Österlund wrote:
> Sometimes we find ourselves passing around context information about how
> to perform a certain operation (e.g. check if an oop is alive, logging
> or tracing, etc). Sometimes such behaviours are provided globally by a
> GC, and sometimes only in local scopes known by the GC. Sometimes it is
> even accessed from mutators.
> 
> It would be great to have a general mechanism for decoupling how
> behaviours are provided, from the code that uses them.
> 
> In particular, I will need this mechanism to build a new nmethod
> unloading mechanism for concurrent class unloading. Today we have a
> single threaded and a parallel nmethod unloading mechanism. Rather than
> introducing a third concurrent way of doing this, I would like to unify
> these mechanism into one mechanism that can be used in all three
> contexts. In order to get there, I need these utilities in order to not
> make a mess. I have a bunch of other use cases down the road as well.
> 
> The ideas behind this mechanism are pretty straight forward. Behaviours
> are provided in different ways by "behaviour providers". The providers
> may be global and local, but come in a strict layering (each provider
> has a parent). So from a given callsite, there is a chain of
> responsibility with behaviour providers. You can use BehaviourMark to
> provide a behaviour locally in a certain scope. There are also global
> behaviours to which a GC at bootstrapping time can add behaviours. If no
> local behaviour was found, the global behaviours are checked as plan B.
> In order to speed up the walk, the scoped behaviour providers also come
> with a lazily populated behaviour provider cache that will take you
> straight to a given provider, effectively skipping through the search
> through the chain of responsibility.
The really nice thing about this is that it makes context values appear
out of thin air without having to explicitly plumb dataflow paths
through call parameter chains.

The really nasty thing about this is that it makes context values appear
out of thin air without having to explicitly plumb dataflow paths
through call parameter chains.

So, is this nice or nasty? I automatically veer towards making plumbing
visible/explicit rather than hidden. Some context overrides using this
mechanism may clearly be local and highly visible but for any use
without an immediately local override it will be very hard to track back
from the point where a context value is used to /every/ point where it
might be configured/set. It is critical not to render code opaque to
those who did not write it (or even to those who did and then took a 2
month break from looking at it).

Of course, sometimes -- in complex cases -- you can't see the plumbing
for the pipes (plumbing /is/ pipes just as a wood /is/ trees) and I have
observed that the GC code does already include such cases (all those
families of closures that are passed around). So, yes, the current
alternative is not without its problems. However, at least there is a
clear marker for what to look at i.e. visible parameterization of the
call chains.

So, my default response is 'ooooh, nasty' but I can see your point.

regards,


Andrew Dinn
-----------
Senior Principal Software Engineer
Red Hat UK Ltd
Registered in England and Wales under Company Registration No. 03798903
Directors: Michael Cunningham, Michael ("Mike") O'Neill, Eric Shander


More information about the hotspot-runtime-dev mailing list