1

I have a java code which looks like this:

private volatile boolean myWriteActionPending;
void startWrite() {
  boolean prev = myWriteActionPending;
  myWriteActionPending = true;
  try {
    // acquire write lock here + do some other stuff
  } finally {
    myWriteActionPending = prev;
  }
}

C1 in java-11.0.14.1 generates following code for myWriteActionPending = true:

mov    eax,0x1
mov    BYTE PTR [rsi+0x5a],al
lock add DWORD PTR [rsp-0x40],0x0

And this for myWriteActionPending = prev:

mov    edi,DWORD PTR [rsp+0xf8]
and    edi,0x1
mov    BYTE PTR [rsi+0x5a],dil
lock add DWORD PTR [rsp-0x40],0x0

C2 generates this for myWriteActionPending = prev:

mov    rbx,QWORD PTR [rsp+0x8]
mov    BYTE PTR [rbx+0x5a],r12b
lock add DWORD PTR [rsp-0x40],0x0

Since I use compressed oops r12 contains the HeapBase. What is the meaning of mov BYTE PTR [rbx+0x5a],r12b? How it restores the field to the original value?

phuclv
  • 37,963
  • 15
  • 156
  • 475
neverov
  • 1,283
  • 8
  • 11
  • 2
    A bit of context (code before these fragments) would be helpful. One possible optimization: if `myWriteActionPending` is already `true` prior to the operation, both writes are obsolete and can be omitted. Otherwise, the first write has to write `1` and the second has to write `0`, where every register whose lowest byte contains zero would be usable. – Holger Feb 21 '22 at 09:00
  • It seems like compiler indeed transformed finally block to `myWriteActionPending = true`. I thought it would emit immediate `0x0` instead of using the register with 0 lower byte. Doesn't such a transformation change semantics? The `prev` was saved because potentially there might be a recursive call to `startWrite` and in this case value of `myWriteActionPending` will be preserved. In practice it never happened. Can jit detect that? – neverov Feb 21 '22 at 18:26
  • @Holger: interesting idea that it might be using `r12b` as a convenient zero register. In this case that wouldn't actually save any bytes of code-size, though, since `mov BYTE PTR [rbx+0x5a], 0` with an immediate 0 is the same size: no REX prefix since no regs from r8..15 are involved, but an immediate zero byte. It *would* help if the pointer had been in any of R8..15 though, and it's not worse (except on P6-family for register-read stalls), so it would make sense for the compiler to always replace immediate zero with R12B without checking if it saved code-size or not, if it's 256-aligned – Peter Cordes Feb 21 '22 at 21:59
  • 1
    Whether the JIT can preclude recursive operations, depends on the actual contents of the `try` block and whether contained method invocations have been inlined. As said, it would be helpful to see the code of the entire method. – Holger Feb 22 '22 at 08:31
  • Generated code for the method is 2500 lines long with a lot of inlined functions. Unfortunately I cannot share the java source of it. Anyway your comment answered the original question about r12 use. Thank you! – neverov Feb 22 '22 at 17:55

0 Answers0