Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions src/mscorlib/src/System/Collections/Generic/List.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
**
**
===========================================================*/

using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;

namespace System.Collections.Generic
{
using System;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Collections.ObjectModel;
using Runtime.CompilerServices;

// Implements a variable-size List that uses an array of objects to store the
// elements. A List has a capacity, which is the allocated length
// of the internal array. As elements are added to a List, the capacity
Expand Down Expand Up @@ -292,7 +293,7 @@ public int BinarySearch(T item, IComparer<T> comparer)
// Clears the contents of List.
public void Clear()
{
if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
int size = _size;
_size = 0;
Expand Down Expand Up @@ -863,7 +864,7 @@ public int RemoveAll(Predicate<T> match) {
}
}

if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
Array.Clear(_items, freeIndex, _size - freeIndex); // Clear the elements so that the gc can reclaim the references.
}
Expand All @@ -887,7 +888,7 @@ public void RemoveAt(int index) {
{
Array.Copy(_items, index + 1, _items, index, _size - index);
}
if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
_items[_size] = default(T);
}
Expand Down Expand Up @@ -917,7 +918,7 @@ public void RemoveRange(int index, int count) {
}

_version++;
if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
Array.Clear(_items, _size, count);
}
Expand Down
2 changes: 1 addition & 1 deletion src/mscorlib/src/System/ReadOnlySpan.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public ReadOnlySpan(T[] array, int start, int length)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ReadOnlySpan(void* pointer, int length)
{
if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
if (length < 0)
ThrowHelper.ThrowArgumentOutOfRangeException();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,14 @@ internal static void ExecuteBackoutCodeHelper(Object backoutCode, Object userDat
{
((CleanupCode)backoutCode)(userData, exceptionThrown);
}

/// <returns>true if given type is reference type or value type that contains references</returns>
static public bool IsReferenceOrContainsReferences<T>()
{
// The body of this function will be replaced by the EE with unsafe code!!!
// See getILIntrinsicImplementation for how this happens.
throw new InvalidOperationException();
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -223,14 +223,6 @@ static internal bool ByRefLessThan<T>(ref T refA, ref T refB)
throw new InvalidOperationException();
}

/// <returns>true if given type is reference type or value type that contains references</returns>
static internal bool ContainsReferences<T>()
{
// The body of this function will be replaced by the EE with unsafe code!!!
// See getILIntrinsicImplementation for how this happens.
throw new InvalidOperationException();
}

static internal ref T GetArrayData<T>(T[] array)
{
// The body of this function will be replaced by the EE with unsafe code!!!
Expand Down
16 changes: 8 additions & 8 deletions src/mscorlib/src/System/Span.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public Span(T[] array, int start, int length)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe Span(void* pointer, int length)
{
if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
if (length < 0)
ThrowHelper.ThrowArgumentOutOfRangeException();
Expand Down Expand Up @@ -451,7 +451,7 @@ public static class Span
public static Span<byte> AsBytes<T>(this Span<T> source)
where T : struct
{
if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));

return new Span<byte>(
Expand All @@ -470,7 +470,7 @@ ref Unsafe.As<T, byte>(ref source.DangerousGetPinnableReference()),
public static ReadOnlySpan<byte> AsBytes<T>(this ReadOnlySpan<T> source)
where T : struct
{
if (JitHelpers.ContainsReferences<T>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));

return new ReadOnlySpan<byte>(
Expand All @@ -493,9 +493,9 @@ public static Span<TTo> NonPortableCast<TFrom, TTo>(this Span<TFrom> source)
where TFrom : struct
where TTo : struct
{
if (JitHelpers.ContainsReferences<TFrom>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<TFrom>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TFrom));
if (JitHelpers.ContainsReferences<TTo>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<TTo>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo));

return new Span<TTo>(
Expand All @@ -518,9 +518,9 @@ public static ReadOnlySpan<TTo> NonPortableCast<TFrom, TTo>(this ReadOnlySpan<TF
where TFrom : struct
where TTo : struct
{
if (JitHelpers.ContainsReferences<TFrom>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<TFrom>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TFrom));
if (JitHelpers.ContainsReferences<TTo>())
if (RuntimeHelpers.IsReferenceOrContainsReferences<TTo>())
ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(TTo));

return new ReadOnlySpan<TTo>(
Expand Down Expand Up @@ -597,7 +597,7 @@ internal static unsafe void CopyTo<T>(ref T destination, ref T source, int eleme
if (Unsafe.AreSame(ref destination, ref source))
return;

if (!JitHelpers.ContainsReferences<T>())
if (!RuntimeHelpers.IsReferenceOrContainsReferences<T>())
{
fixed (byte* pDestination = &Unsafe.As<T, byte>(ref destination))
{
Expand Down
72 changes: 45 additions & 27 deletions src/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6992,33 +6992,6 @@ bool getILIntrinsicImplementation(MethodDesc * ftn,
methInfo->options = (CorInfoOptions)0;
return true;
}
else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__CONTAINSREFERENCES)->GetMemberDef())
{
_ASSERTE(ftn->HasMethodInstantiation());
Instantiation inst = ftn->GetMethodInstantiation();

_ASSERTE(ftn->GetNumGenericMethodArgs() == 1);
TypeHandle typeHandle = inst[0];
MethodTable * methodTable = typeHandle.GetMethodTable();

static const BYTE returnTrue[] = { CEE_LDC_I4_1, CEE_RET };
static const BYTE returnFalse[] = { CEE_LDC_I4_0, CEE_RET };

if (!methodTable->IsValueType() || methodTable->ContainsPointers())
{
methInfo->ILCode = const_cast<BYTE*>(returnTrue);
}
else
{
methInfo->ILCode = const_cast<BYTE*>(returnFalse);
}

methInfo->ILCodeSize = sizeof(returnTrue);
methInfo->maxStack = 1;
methInfo->EHcount = 0;
methInfo->options = (CorInfoOptions)0;
return true;
}
#endif // FEATURE_SPAN_OF_T

return false;
Expand Down Expand Up @@ -7272,6 +7245,47 @@ bool getILIntrinsicImplementationForInterlocked(MethodDesc * ftn,
return true;
}

bool getILIntrinsicImplementationForRuntimeHelpers(MethodDesc * ftn,
CORINFO_METHOD_INFO * methInfo)
{
STANDARD_VM_CONTRACT;

// Precondition: ftn is a method in mscorlib
_ASSERTE(ftn->GetModule()->IsSystem());

mdMethodDef tk = ftn->GetMemberDef();

if (tk == MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__IS_REFERENCE_OR_CONTAINS_REFERENCES)->GetMemberDef())
{
_ASSERTE(ftn->HasMethodInstantiation());
Instantiation inst = ftn->GetMethodInstantiation();

_ASSERTE(ftn->GetNumGenericMethodArgs() == 1);
TypeHandle typeHandle = inst[0];
MethodTable * methodTable = typeHandle.GetMethodTable();

static const BYTE returnTrue[] = { CEE_LDC_I4_1, CEE_RET };
static const BYTE returnFalse[] = { CEE_LDC_I4_0, CEE_RET };

if (!methodTable->IsValueType() || methodTable->ContainsPointers())
{
methInfo->ILCode = const_cast<BYTE*>(returnTrue);
}
else
{
methInfo->ILCode = const_cast<BYTE*>(returnFalse);
}

methInfo->ILCodeSize = sizeof(returnTrue);
methInfo->maxStack = 1;
methInfo->EHcount = 0;
methInfo->options = (CorInfoOptions)0;
return true;
}

return false;
}

//---------------------------------------------------------------------------------------
//
//static
Expand Down Expand Up @@ -7323,6 +7337,10 @@ getMethodInfoHelper(
{
fILIntrinsic = getILIntrinsicImplementationForVolatile(ftn, methInfo);
}
else if (MscorlibBinder::IsClass(pMT, CLASS__RUNTIME_HELPERS))
{
fILIntrinsic = getILIntrinsicImplementationForRuntimeHelpers(ftn, methInfo);
}

if (!fILIntrinsic)
{
Expand Down
2 changes: 1 addition & 1 deletion src/vm/mscorlib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1179,6 +1179,7 @@ DEFINE_CLASS(RUNTIME_HELPERS, CompilerServices, RuntimeHelpers)
DEFINE_METHOD(RUNTIME_HELPERS, PREPARE_CONSTRAINED_REGIONS, PrepareConstrainedRegions, SM_RetVoid)
DEFINE_METHOD(RUNTIME_HELPERS, PREPARE_CONSTRAINED_REGIONS_NOOP, PrepareConstrainedRegionsNoOP, SM_RetVoid)
DEFINE_METHOD(RUNTIME_HELPERS, EXECUTE_BACKOUT_CODE_HELPER, ExecuteBackoutCodeHelper, SM_Obj_Obj_Bool_RetVoid)
DEFINE_METHOD(RUNTIME_HELPERS, IS_REFERENCE_OR_CONTAINS_REFERENCES, IsReferenceOrContainsReferences, NoSig)

DEFINE_CLASS(JIT_HELPERS, CompilerServices, JitHelpers)
#ifdef _DEBUG
Expand All @@ -1195,7 +1196,6 @@ DEFINE_METHOD(JIT_HELPERS, UNSAFE_CAST_TO_STACKPTR,UnsafeCastToStackPoi
#ifdef FEATURE_SPAN_OF_T
DEFINE_METHOD(JIT_HELPERS, BYREF_LESSTHAN, ByRefLessThan, NoSig)
DEFINE_METHOD(JIT_HELPERS, GET_ARRAY_DATA, GetArrayData, NoSig)
DEFINE_METHOD(JIT_HELPERS, CONTAINSREFERENCES, ContainsReferences, NoSig)
#endif

#ifdef FEATURE_SPAN_OF_T
Expand Down