RFR: 8189871: Refactor GC barriers to use declarative semantics
Erik Osterlund
erik.osterlund at oracle.com
Fri Nov 17 18:03:57 UTC 2017
Hi Coleen,
Thanks for the review.
/Erik
> On 17 Nov 2017, at 16:58, coleen.phillimore at oracle.com wrote:
>
>
>
>> On 11/17/17 9:39 AM, Erik Österlund wrote:
>> Hi Coleen,
>>
>>> On 2017-11-17 00:59, coleen.phillimore at oracle.com wrote:
>>>
>>> Hi Erik,
>>>
>>> I believe that the access API belongs in the "oops" directory, as that is where the code uses them primarily. Other than the location of the access* files, I've read through much of the code and don't have anything specific to add that would improve this change. It's a bit big, ie. the Access class is large but separating out the implementations into access.inline.hpp doesn't seem like that useful of an improvement. The template heavy code starts to look like boilerplate after a while.
>>
>> I moved the Access API to the oops directory as you wished.
>
> Thanks!
>>
>>> The Access<decorator>::verify_decorators() could be made out-of-line in access.inline.hpp file to make the class more readable but it's not a strong request.
>>
>> Fixed.
>
> Thanks, that helps a bit with readability.
>>
>>> The IN_CONCURRENT_ROOT decorator looks like something that can't be used or is the default from the runtime perspective, but can be removed or sorted out later.
>>
>> I would like to defer the default discussion until later if that is okay. We definitely need the ability to have non-concurrent roots, they definitely are the norm and not the exception today, but eventually we might want to change that. But I don't know if we are quite there yet.
>>
>
> I agree with you. Let's see how these are used and adjust accordingly.
>
>>> I'd found a typo on first reading but now I don't know where it was.
>>
>> If you find it again, I will happily remove it.
>>
>>> Nice work!
>>
>> Thanks! And thank you for the review.
>>
>> The latest full webrev can be found here:
>> http://cr.openjdk.java.net/~eosterlund/8189871/webrev.02/
>>
>> The latest incremental webrev can be found here:
>> http://cr.openjdk.java.net/~eosterlund/8189871/webrev.01_02/
>
> Looks good!!
>
> Coleen
>
>>
>> Thanks,
>> /Erik
>>
>>> Coleen
>>>
>>>> On 11/14/17 7:37 PM, coleen.phillimore at oracle.com wrote:
>>>>
>>>> Hi, Meta-comment: I think the access API should be in oops rather than the runtime directory. This API is for accessing objects in the heap from other objects in the heap or in runtime code. So that seems like it belongs in the oops directory to me (even though metadata is there for historical reasons). The memory directory would be my second choice, and runtime third.
>>>>
>>>> I've been reading through much of the code with help and explanation of what these templates do from Kim. They are pretty tricky but I can see why they are there and what they do. I'm going to suggest some comments in places when I've gotten through more of this.
>>>>
>>>> Thanks,
>>>> Coleen
>>>>
>>>>> On 11/9/17 12:00 PM, Erik Österlund wrote:
>>>>> Hi,
>>>>>
>>>>> In an effort to remove explicit calls to GC barriers (and other orthogonal forms of barriers, like encoding/decoding oops for compressed oops and fencing for memory ordering), I have built an API that I call "Access". Its purpose is to perform accesses with declarative semantics, to handle multiple orthogonal concerns that affect how an access is performed, including memory ordering, compressed oops, GC barriers for marking, reference strength, etc, and as a result making GCs more modular, and as a result allow new concurrently compacting GC schemes utilizing load barriers to live in harmony in hotspot without everyone going crazy manually inserting barriers if UseBlahGC is enabled.
>>>>>
>>>>> CR:
>>>>> https://bugs.openjdk.java.net/browse/JDK-8189871
>>>>>
>>>>> Webrev:
>>>>> http://cr.openjdk.java.net/~eosterlund/8189871/webrev.00/
>>>>>
>>>>> So there are three views of this I suppose:
>>>>>
>>>>> 1) The frontend: how this is actually used in shared code
>>>>> 2) The backends: how anyone writing a GC sticks their required barriers in there
>>>>> 3) The internals: how accesses find their way from the frontend to the corresponding backend
>>>>>
>>>>> == Frontend ==
>>>>>
>>>>> Let's start with the frontend. I hope I made this fairly simple! You can find it in runtime/access.hpp
>>>>> Each access annotates its declarative semantics with a set of "decorators", which is the name of the attributes/properties affecting how an access is performed.
>>>>> There is an Access<decorator> API that makes the declarative semantics possible.
>>>>>
>>>>> For example, if I want to perform a load acquire of an oop in the heap that has "weak" strength, I would do something like:
>>>>> oop result = Access<MO_ACQUIRE | IN_HEAP | ON_WEAK_OOP_REF>::oop_load_at(obj, offset);
>>>>>
>>>>> The Access API would then send the access through some GC backend, that overrides the whole access and tells it to perform a "raw" load acquire, and then possibly keep it alive if necessary (G1 SATB enqueue barriers).
>>>>>
>>>>> To make life easier, there are some helpers for the most common access patterns that merely add some default decorator for the involved type of access. For example, there is a RawAccess for performing AS_RAW accesses (that bypasses runtime checks and GC barriers), HeapAccess sets the IN_HEAP decorator and RootAccess sets the IN_ROOT decorator for accessing root oops. So for the previous call, I could simply do:
>>>>>
>>>>> oop result = HeapAccess<MO_ACQUIRE | ON_WEAK_OOP_REF>::oop_load_at(obj, offset);
>>>>>
>>>>> The access.hpp file introduces each decorator (belonging to some category) with an explanation what it is for. It also introduces all operations you can make with access (loads, stores, cmpxchg, xchg, arraycopy and clone).
>>>>>
>>>>> This changeset mostly introduces the Access API but is not complete in annotating the code more than where it gets very awkward if I don't.
>>>>>
>>>>> == Backend ==
>>>>>
>>>>> For a GC maintainer, the BarrierSet::AccessBarrier is the top level backend that provides basic accesses that may be overridden. By default, it just performs raw accesses without any GC barriers, that handle things like compressed oops and memory ordering only. The ModRef barrier set introduces the notion of pre/post write barriers, that can be overridden for each GC. The CardTableModRef barrier set overrides the post write barrier to mark cards, and G1 overrides it to mark cards slightly differently and do some SATB enqueueing. G1 also overrides loads to see if we need to perform SATB enqueue on weak references.
>>>>>
>>>>> The raw accesses go to the RawAccessBarrier (living in accessBackend.hpp) that performs the actual accesses. It connects to Atomic and OrderAccess for accesses that require that.
>>>>>
>>>>> == Internals ==
>>>>>
>>>>> Internally, the accesses go through a number of stages in access.inline.hpp as documented at the top.
>>>>>
>>>>> 1) set default decorators and get rid of CV qualifiers etc. Sanity checking also happens here: we check that the decorators make sense for the access being performed, and that the passed in types are not bogus.
>>>>> 2) reduce types so if we have a different type of the address and value, then either it is not allowed or it implies we use compressed oops and remember that we know something about whether compressed oops are used or not, before erasing address type
>>>>> 3) pre-runtime dispatch: figure out if all runtime checks can be bypassed into a raw access
>>>>> 4) runtime dispatch: send the access through a function pointer that upon the first invocation resolves the intended GC AccessBarrier accessor on the BarrierSet that handles this access, as well as figures out whether we are using compressed oops or not while we are at it, and then calls it through the post-runtime dispatch
>>>>> 5) post-runtime dispatch: fix some erased types that were not known at compile time such as whether the address is a narrowOop* or oop* depending on whether compressed oops was selected at runtime or not, and call the resolved BarrierSet::AccessBarrier accessor (load/store/etc) with all the call-site build-time and run-time resolved decorators and type information that describes the access.
>>>>>
>>>>> Testing: mach5 tier1-5
>>>>>
>>>>> Thanks,
>>>>> /Erik
>>>>
>>>
>>
>
More information about the hotspot-dev
mailing list