Speed up Array.Reverse by using ref reassignment by GrabYourPitchforks · Pull Request #17891 · dotnet/coreclr (original) (raw)

Quick question to reviewers who are more familiar with the JIT and GC:

I played around with two different patterns here. The first, Unsafe.Add(ref first, length - 1), generates this bytecode:

dec length movsxd length64, length lea last, [first + length * stride]

The second, Unsafe.Add(ref Unsafe.Add(ref first, length), -1), generates this bytecode:

movsxd length64, length lea last, [first + length64 * stride - stride]

Is it possible in theory for the JIT to generate something like the below in the second case?

movsxd length64, length lea last, [first + length64 * stride] add last, -stride

And if it does generate this, is it possible that immediately after the lea instruction but before the add, first and last technically point to different objects, which could allow the GC to relocate first but not last, causing the final add instruction to get last to point to garbage?

FYI, the reason I asked the above question is that this same pattern of "get a ref to just past the end of the array then back up" also appears in Buffer.Memmove(ref byte, ref byte, ...). I don't recall that particular code pattern being mentioned in the review, so not sure if it just slipped under the radar during review or if it's actually safe.