Skip to content

Commit

Permalink
First exclude InternalSetValue
Browse files Browse the repository at this point in the history
  • Loading branch information
huoyaoyuan committed Jun 5, 2024
1 parent 94acf75 commit 272883f
Showing 1 changed file with 2 additions and 94 deletions.
96 changes: 2 additions & 94 deletions src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -633,100 +633,8 @@ private unsafe nint GetFlattenedIndex(ReadOnlySpan<int> indices)
return result;
}

private unsafe void InternalSetValue(object? value, nint flattenedIndex)
{
MethodTable* pMethodTable = RuntimeHelpers.GetMethodTable(this);

TypeHandle arrayElementTypeHandle = pMethodTable->GetArrayElementTypeHandle();

// Legacy behavior (this handles pointers and function pointers)
if (arrayElementTypeHandle.IsTypeDesc)
{
ThrowHelper.ThrowNotSupportedException(ExceptionResource.Arg_TypeNotSupported);
}

Debug.Assert((nuint)flattenedIndex < NativeLength);

ref byte arrayDataRef = ref MemoryMarshal.GetArrayDataReference(this);

MethodTable* pElementMethodTable = arrayElementTypeHandle.AsMethodTable();

if (value == null)
{
// Null is the universal zero...
if (pElementMethodTable->IsValueType)
{
ref byte offsetDataRef = ref Unsafe.Add(ref arrayDataRef, flattenedIndex * pMethodTable->ComponentSize);
if (pElementMethodTable->ContainsGCPointers)
SpanHelpers.ClearWithReferences(ref Unsafe.As<byte, nint>(ref offsetDataRef), pElementMethodTable->GetNumInstanceFieldBytes());
else
SpanHelpers.ClearWithoutReferences(ref offsetDataRef, pElementMethodTable->GetNumInstanceFieldBytes());
}
else
{
ref object? elementRef = ref Unsafe.As<byte, object?>(ref arrayDataRef);
ref object? offsetElementRef = ref Unsafe.Add(ref elementRef, (nuint)flattenedIndex);
offsetElementRef = null;
}
}
else if (TypeHandle.AreSameType(arrayElementTypeHandle, TypeHandle.TypeHandleOf<object>()))
{
// Everything is compatible with Object
ref object? elementRef = ref Unsafe.As<byte, object?>(ref arrayDataRef);
ref object? offsetElementRef = ref Unsafe.Add(ref elementRef, (nuint)flattenedIndex);
offsetElementRef = value;
}
else if (!pElementMethodTable->IsValueType)
{
if (CastHelpers.IsInstanceOfAny(pElementMethodTable, value) == null)
{
ThrowHelper.ThrowInvalidCastException_StoreArrayElement();
}

ref object? elementRef = ref Unsafe.As<byte, object?>(ref arrayDataRef);
ref object? offsetElementRef = ref Unsafe.Add(ref elementRef, (nuint)flattenedIndex);
offsetElementRef = value;
}
else
{
// value class or primitive type

ref byte offsetDataRef = ref Unsafe.Add(ref arrayDataRef, flattenedIndex * pMethodTable->ComponentSize);
if (CastHelpers.IsInstanceOfAny(pElementMethodTable, value) != null)
{
if (pElementMethodTable->IsNullable)
{
RuntimeHelpers.Unbox_Nullable(ref offsetDataRef, pElementMethodTable, value);
}
else if (pElementMethodTable->ContainsGCPointers)
{
Buffer.BulkMoveWithWriteBarrier(ref offsetDataRef, ref value.GetRawData(), pElementMethodTable->GetNumInstanceFieldBytes());
}
else
{
SpanHelpers.Memmove(ref offsetDataRef, ref value.GetRawData(), pElementMethodTable->GetNumInstanceFieldBytes());
}
}
else
{
// Allow enum -> primitive conversion, disallow primitive -> enum conversion
MethodTable* thSrc = RuntimeHelpers.GetMethodTable(value);
CorElementType srcType = thSrc->GetVerifierCorElementType();
CorElementType targetType = pElementMethodTable->GetVerifierCorElementType();

if (!srcType.IsPrimitiveType() || !targetType.IsPrimitiveType() || !pElementMethodTable->IsTruePrimitive)
ThrowHelper.ThrowInvalidCastException_StoreArrayElement();

// Get a properly widened type
if (!RuntimeHelpers.CanPrimitiveWiden(srcType, targetType))
ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_PrimitiveWiden);

PrimitiveWiden(ref value.GetRawData(), ref offsetDataRef, srcType, targetType);
}
}

GC.KeepAlive(this); // Keep the method table alive
}
[MethodImpl(MethodImplOptions.InternalCall)]
private extern void InternalSetValue(object? value, nint flattenedIndex);

public int Length => checked((int)Unsafe.As<RawArrayData>(this).Length);

Expand Down

0 comments on commit 272883f

Please sign in to comment.