Simpler cmpxchg-oop?

Roman Kennke rkennke at redhat.com
Thu Aug 30 09:40:19 UTC 2018


Ok, I guess the assumption is not exactly correct: there are in-fact
stores that store from-space refs. This happens during obj-arraycopy:
there we first bulk-transfer the array elements (potentially from-space)
to the target array, and only then scan + update the target array
elements. Too bad: this means we really need the loop for now.

(I wonder how much more efficient a single-loop for obj-arraycopy would
be: we currently scan the array 3x: once for loading+enqueing the
pre-vals, once for actual copy (bulk-transfer), and once for updating
therefs. Since the benefit of bulk-transfer is out of the window anyway,
we could just make it one loop to do everything, and seems with some
likelyhood more efficient than what we do now.)

Roman


> as we're currently discussing cmpxchg-oop for upstream GC interface, I
> wonder if we can come up with a simpler cmpxchg-oop routine.
> 
> We currently do something like this:
> 
> oop cmpxchg_oop(oop newval, oop* addr, oop cmpval) {
> 
>   oop res = cmpxchg(newval, addr, cmpval);
>   while (res != cmpval && rb(res) == rb(cmpval)) { // false failure path
>     cmpval = res;
>     res = cmpxchg(newval, addr, cmpval);
>   }
>   return res;
> }
> 
> We even unroll this a little bit in assembly.
> 
> However, since we're only interested in false-negatives, and because
> there are limited number of states for cmpval and field-val, and because
> state in fieldval can only go from fromspace -> tospace, I believe it is
> enough to try at most two more times:
> 
> oop cmpxchg_oop(oop newval, oop* addr, oop cmpval) {
> 
>   oop res = cmpxchg(newval, addr, cmpval);
>   if (res != cmpval && rb(res) == rb(cmpval)) { // false failure path
>     // Here we can have either cmpval or res in fromspace, but not both
>     // A second false-negative can only occur if another thread
>     // updates the field concurrently. Any such field update can only
>     // store to-space values. That means the 2nd false-negative can
>     // only happen if the field was from-space and cmpval was to-space
>     // in the first attempt.
>     cmpval = res;
>     res = cmpxchg(newval, addr, cmpval);
>     if (res != cmpval && rb(res) == rb(cmpval)) { // false failure path
>       // We can falsely fail a 2nd time only if field has been updated
>       // to to-space, and cmpval was from-space before. At this point
>       // no more false negatives can occur.
>       cmpval = res;
>       res = cmpxchg(newval, addr, cmpval);
>     }
>   }
>   return res;
> }
> 
> Is that right? Can somebody come up with a case where a 3rd or more
> false failures can occur?
> 
> I am asking because two chained if-else branches may be simpler to
> construct in C2 ideal graph (and even C1 LIR?) than a loop. And we could
> drop the loop-backedge in assembly too (we already have two unrolled
> retries in assembly iirc.)
> 
> Roman
> 




More information about the shenandoah-dev mailing list