as dotnet collection Stack.cs source code
public T Peek()
{
int size = _size - 1;
T[] array = _array;
if ((uint)size >= (uint)array.Length)
{
ThrowForEmptyStack();
}
return array[size];
}
there is a local reference copy of the backing array T[] array = _array; source here
and a lot of similar codes in the Collections codebase.
What's the purpose of this? is it related to thread safety or any other consideration? Why just not use the class field _array instead?
I can't find any clues in google, so expecting some insights here.
It seems to be due to JIT optimization.
While the JIT does have logic to do bounds check elision, in the past it did not work if you refer to the field twice, rather than a local variable.
The function
ThrowForEmptyStackis known to be non-returning:So when the code does the check
the JIT now knows that the array index cannot go out-of-bounds, because the bounds check has already been done. So it can elide the normal array bounds check in the generated machine code.
That linked article mentions
staticfields, not instance fields, so it's not clear, but see this discussion in the runtime repo. So in the past, if you used a field then it can't make that optimization. This seems to have been fixed, so the extra code was later removed.