RFR: 8189871: Refactor GC barriers to use declarative semantics
Kim Barrett
kim.barrett at oracle.com
Thu Nov 16 19:43:35 UTC 2017
> On Nov 15, 2017, at 11:55 AM, Erik Österlund <erik.osterlund at oracle.com> wrote:
>> http://cr.openjdk.java.net/~eosterlund/8189871/webrev.00/src/hotspot/share/runtime/access.hpp.html
>>
>> 240 template <typename T>
>> 241 struct OopOrNarrowOopInternal: AllStatic {
>> 242 typedef oop type;
>> 243 };
>> 244
>> 245 template <>
>> 246 struct OopOrNarrowOopInternal<narrowOop>: AllStatic {
>> 247 typedef narrowOop type;
>> 248 };
>> 249
>>
>> Kim and I agree that we should not have the default template definition for oop and have two specializations instead. Mostly I agree because this is confusing.
>>
>> 240 template <typename T>
>> 241 struct OopOrNarrowOopInternal;
>>
>> 240 template <>
>> 241 struct OopOrNarrowOopInternal<oop>: AllStatic {
>> 242 typedef oop type;
>> 243 };
>> 244
>> 245 template <>
>> 246 struct OopOrNarrowOopInternal<narrowOop>: AllStatic {
>> 247 typedef narrowOop type;
>> 248 };
>> 249
>>
>
> This choice is actually deliberate. The reason is that we pass in things that is-an oop but is not exactly oop, like for example arrayOop or oopDesc* and the whole subclass tree if oop. An earlier incarnation of the Access API used a new IsDerived<X, Y> metafunction to determine whether a type is-an oop.
> However, in order to keep the solution simpler and introduce less type dependencies, I instead use this OopOrNarrowOop thing to pass oop-like things through it and narrow it down to oop or narrowOop. If a narrowOop is passed in, then it becomes narrowOop, if you pass in oopDesc*, arrayOop, oop, instanceOop, or whatever, then it results in an oop, and tries to implicitly convert whatever was passed in to oop. That will act as if the overload was "oop" in the way that you can pass in anything that is implicitly convertible to exactly oop or narrowOop, and once you make it past that layer, it will be treated only as oop or narrowOop.
>
> Sorry for any resulting confusion.
Thanks for the explanation. That wasn’t at all obvious. It might be useful to add a comment that the default case handles all variants of oop and treats them all as oop.
>> We were also trying to figure out how the runtime would know whether to use IN_CONCURRENT_ROOT vs IN_ROOT decorator, since it probably varies for GCs. And requires runtime code to know whether the root is scanned concurrently or not, which we don't know.
>>
>
> The Access API needs to know whether this is scanned concurrently or not (because we *have* to perform different barriers then). So whatever data structure the access is performed on, needs to make sure this is known.
The person writing the access call cannot be expected to accurately
know whether or not the associated location will be scanned
concurrently. Even ignoring some of those people not being GC
experts, there is the problem that the answer might not be knowable
until runtime, because it may (will) depend on which GC is selected,
and possibly other considerations as well.
Does IN_CONCURRENT_ROOT really mean the location *might* be
concurrently processed, and using that tag is a conservative choice
that won't actually be wrong, but may be suboptimal? (E.g. it should
really be called IS_POSSIBLY_CONCURRENT_ROOT?) Or are the choices
between these really exclusive? I'm guessing the former, but I'm not
certain of that, and the descriptions are no help. Nor do I know how
bad such suboptimal behavior might be. (If they really are exclusive,
then I don't see how to use these at all.)
When we discussed this problem previously, we talked about having
specific names associated with categories of off-heap references that
might be handled differently by different collectors. Some specific
examples that came up in that discussion were JNI global (and weak)
handles, and interned strings. Even if we really expect all of our
concurrent collectors to eventually process all of these concurrently,
such features might be added on different schedules for different
collectors.
Without such a naming scheme, e.g. with only a generic
IS_CONCURRENT_ROOT, different collectors may pay the cost for being
conservative for different categories. That might be acceptable if
being conservative is cheap. But then I would expect the possibly
concurrent case to be pretty much the default, to be used nearly
everywhere, since it is unreasonable to expect non-GC experts to stay
up to date on which roots are never ever scanned concurrently by any
collector.
More information about the hotspot-dev
mailing list