The typical way to clone an array is to use Array.Clone, which returns an object that needs to be cast back to the original array type.
string[] originalArray = GetArray();
string[] clonedArray = (string[])originalArray.Clone();
After the call to Clone, the JIT emits a call to the ChkCastAny helper to ensure that the cast is legitimate.
public static object[] M(object[] o) {
return (Object[])o.Clone();
}
M(System.Object[])
L0000: sub rsp, 0x28
L0004: mov eax, [rcx]
L0006: call 0x00007ffb1bc0e0c0 ; Array.Clone()
L000b: mov rdx, rax
L000e: mov rcx, 0x7ffabc1af762 ; type handle for object[]
L0018: call 0x00007ffb1bc16750 ; ChkCastAny
L001d: nop
L001e: add rsp, 0x28
L0022: ret
There is an opportunity for improvement here. If the target of the Array.Clone call is known by the JIT to be a local of type T, and if the return value of Clone is immediately cast to T or type U (where reinterpret_cast<U>(T) is legal), then the JIT should no-op the cast. In the sample above, that means labels L000b - L001d would disappear.
Some examples:
string[] stringArray;
string[] clone1 = (string[])stringArray.Clone(); // JIT should elide check
object[] clone2 = (object[])stringArray.Clone(); // JIT should elide check
object[] objectArray;
string[] clone3 = (string[])objectArray.Clone(); // check should take place, could succeed or fail at runtime
object[] clone4 = (object[])objectArray.Clone(); // JIT should elide check
int[] intArray;
int[] clone5 = (int[])intArray.Clone(); // JIT should elide check
uint[] clone6 = (uint[])intArray.Clone(); // JIT should elide check
object[] clone7 = (object[])intArray.Clone(); // check should take place and will fail at runtime
The typical way to clone an array is to use
Array.Clone, which returns an object that needs to be cast back to the original array type.After the call to
Clone, the JIT emits a call to theChkCastAnyhelper to ensure that the cast is legitimate.There is an opportunity for improvement here. If the target of the
Array.Clonecall is known by the JIT to be a local of type T, and if the return value ofCloneis immediately cast to T or type U (where reinterpret_cast<U>(T) is legal), then the JIT should no-op the cast. In the sample above, that means labels L000b - L001d would disappear.Some examples: