A couple of questions for G1 developers

Thomas Schatzl thomas.schatzl at oracle.com
Mon Jun 3 13:52:29 UTC 2019


On Mon, 2019-06-03 at 11:42 +0100, Andrew Haley wrote:
> I'm debugging a crash that may have nothing to do with G1. However:
> 1. What is the structure of the G1BlockOffsetTable? It looks like an
>    offset (in HeapWords?) for each chunk, from the start of the chunk
>    to the start of the object which begins that chunk. So, if an
>    object straddles a chunk binary, the offset is subtracted from the
>    start of the chunk to give an oop.

It's an array of bytes, for every card containing the (backwards-
)offset to a valid (presumably next) object boundary. Note that this is
not necessarily a direct offset, but may contain an offset to another,
previous BOT entry, forming a slide.

E.g. the comment in
G1BlockOffsetTablePart::set_remainder_to_point_to_start contains some

I.e. the block offset table as mentioned in literature. The main
difference between this and the standard (serial, ...) implementation
is that it keeps a "finger" for every region that contains information
up to which the BOT has already been updated.

Briefly looking at the code I could imagine that there could be some
problems with synchronization and memory visibility of the finger. In
essence, this is very old code people are reluctant to touch.

Can you share more details about your G1 crash?

> A supplementary question: how are TLABs handled by this?

Not sure about the question. Maybe below answer answers this as well.

> 2. Why does G1BlockOffsetTablePart::forward_to_block_containing_addr
>    need an acquiring load on
>   if (oop(q)->klass_or_null_acquire() == NULL) {
>     return q;
> I guess it must be because of a race, but what is it racing with?

The racing components are on the one hand the allocating mutator
thread, and on the other hand refinement. While the card table contains
a special "is-young" value for newly allocated regions, this setting
the "is-young" value is racy with the mutators. So you might end up
with refinement looking at not fully initialized contents of the klass
value, where a NULL klass serves as indicator for that situation (and
refinement should give up refining that card for now).

(There is a similar race with allocating/initializing humongous objects
in old gen).


More information about the hotspot-gc-dev mailing list