Write barrier for G1GC SATB wasn't atomic?
igor.veresov at oracle.com
Wed Mar 23 07:00:43 UTC 2011
That's ok. The goal of SATB is to snapshot the object graph and track
the changes to it. So, in your example, obj0 was the contents of the
field before the snapshot. It doesn't matter if we capture it multiple
times or values that were stored to the field after the snapshot - all
of this will be filtered later. The important part is that we captured
the value that was before the snapshot at least once.
On 3/22/11 11:11 PM, Narihiro Nakamura wrote:
> Hi, all.
> I read G1GC by a hobby.
> I have one question about write barrier for SATB.
> I think that satb write barrier is defined in the following points:
> - cpu/sparc/vm/assembler_sparc.cpp: MacroAssembler::g1_write_barrier_pre()
> - cpu/x86/vm/assembler_x86.cpp: MacroAssembler::g1_write_barrier_pre()
> - share/vm/opto/graphKit.cpp: GraphKit::g1_write_barrier_pre()
There are also C1 versions in c1_LIRGeneration.cpp, c1_CodeStubs_*.cpp,
> I read their code.
> I think that the pseudo-cord of "satb write barrier" is as follows:
> 1: def satb_write_barrier(field, newobj):
> 2: oldobj = *field // (a)
> 3: if $gc_phase == GC_CONCURRENT_MARK and oldobj != Null:
> 4: enqueue($current_thread.stab_mark_queue, oldobj) // (b)
> 5: *field = newobj // (c)
It actually checks if marking is in progress first, then loads the
previous value. More importantly, the the marking flag can be set only
during a safepoint, so from that point of view, barriers are "atomic"
with respect to safepoints, a thread won't enter a safepoint while in
> This code doesn't look like in atomic operation from (a) to (b).
> In that case, when mutator more than 2 try to write *field at the
> same time, the reference that should record may leak out to satb
> mark queue.
> For example.
> 1. *field == obj0 address
> 2. t1(Thread1) try to write obj1 address to *field.
> 3. t2(Thread2) try to write obj2 address to *field.
> 4. t1 at (a): oldobj = obj0
> 5. t2 at (a): oldobj = obj0
> 6. t1 at (b): enqueue obj0 to satb mark queue
> 7. t2 at (b): enqueue obj0 to satb mark queue
> 8. t1 at (c): *field = obj1
> 9. t2 at (c): *field = obj2
> In this example, obj1 that should enqueue satb mark queue is leaked.
Yes, we're not interested in obj1 at all. We're only interested in the
contents of the field that were there before the marking started.
> Is this intended behavior? Or, Is it my misunderstanding?
More information about the hotspot-gc-dev