Skip to content

JIT should optimize away the cast that occurs after Array.Clone #45302

@GrabYourPitchforks

Description

@GrabYourPitchforks

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

Metadata

Metadata

Assignees

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions