diff --git a/eng/Versions.props b/eng/Versions.props
index 6586408c0a394..26772fc07ff54 100644
--- a/eng/Versions.props
+++ b/eng/Versions.props
@@ -49,7 +49,7 @@
- 4.4.0-1.22315.13
+ 4.4.0-1.22328.222.0.0-preview.4.22252.4
diff --git a/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs
index 6e44ec163dfce..dc7e3ee58693f 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs
@@ -12,7 +12,7 @@ namespace System
[System.Runtime.Versioning.NonVersionable] // This only applies to field layout
public ref partial struct TypedReference
{
- private readonly ByReference _value;
+ private readonly ref byte _value;
private readonly IntPtr _type;
public static unsafe object? ToObject(TypedReference value)
@@ -38,11 +38,11 @@ public ref partial struct TypedReference
if (pMethodTable->IsValueType)
{
- result = RuntimeHelpers.Box(pMethodTable, ref value._value.Value);
+ result = RuntimeHelpers.Box(pMethodTable, ref value._value);
}
else
{
- result = Unsafe.As(ref value._value.Value);
+ result = Unsafe.As(ref value._value);
}
return result;
diff --git a/src/coreclr/inc/dacvars.h b/src/coreclr/inc/dacvars.h
index 68ec3af418f00..5ce668353c4fb 100644
--- a/src/coreclr/inc/dacvars.h
+++ b/src/coreclr/inc/dacvars.h
@@ -163,7 +163,6 @@ DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pStringClass, ::g_pStringClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pArrayClass, ::g_pArrayClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pSZArrayHelperClass, ::g_pSZArrayHelperClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pNullableClass, ::g_pNullableClass)
-DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pByReferenceClass, ::g_pByReferenceClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pExceptionClass, ::g_pExceptionClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pThreadAbortExceptionClass, ::g_pThreadAbortExceptionClass)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_pOutOfMemoryExceptionClass, ::g_pOutOfMemoryExceptionClass)
diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp
index 3caad0781ac9d..f01b80ffd3b5b 100644
--- a/src/coreclr/jit/importer.cpp
+++ b/src/coreclr/jit/importer.cpp
@@ -3791,8 +3791,6 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
break;
case NI_Internal_Runtime_MethodTable_Of:
- case NI_System_ByReference_ctor:
- case NI_System_ByReference_get_Value:
case NI_System_Activator_AllocatorOf:
case NI_System_Activator_DefaultConstructorOf:
case NI_System_EETypePtr_EETypePtrOf:
@@ -3899,35 +3897,6 @@ GenTree* Compiler::impIntrinsic(GenTree* newobjThis,
break;
}
- // Implement ByReference Ctor. This wraps the assignment of the ref into a byref-like field
- // in a value type. The canonical example of this is Span. In effect this is just a
- // substitution. The parameter byref will be assigned into the newly allocated object.
- case NI_System_ByReference_ctor:
- {
- // Remove call to constructor and directly assign the byref passed
- // to the call to the first slot of the ByReference struct.
- GenTree* op1 = impPopStack().val;
- GenTree* thisptr = newobjThis;
- CORINFO_FIELD_HANDLE fldHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
- GenTree* field = gtNewFieldRef(TYP_BYREF, fldHnd, thisptr, 0);
- GenTree* assign = gtNewAssignNode(field, op1);
- GenTree* byReferenceStruct = gtCloneExpr(thisptr->gtGetOp1());
- assert(byReferenceStruct != nullptr);
- impPushOnStack(byReferenceStruct, typeInfo(TI_STRUCT, clsHnd));
- retNode = assign;
- break;
- }
-
- // Implement ptr value getter for ByReference struct.
- case NI_System_ByReference_get_Value:
- {
- GenTree* op1 = impPopStack().val;
- CORINFO_FIELD_HANDLE fldHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
- GenTree* field = gtNewFieldRef(TYP_BYREF, fldHnd, op1, 0);
- retNode = field;
- break;
- }
-
case NI_System_Runtime_CompilerServices_RuntimeHelpers_CreateSpan:
{
retNode = impCreateSpanIntrinsic(sig);
@@ -5549,17 +5518,6 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method)
result = NI_System_Activator_DefaultConstructorOf;
}
}
- else if (strcmp(className, "ByReference`1") == 0)
- {
- if (strcmp(methodName, ".ctor") == 0)
- {
- result = NI_System_ByReference_ctor;
- }
- else if (strcmp(methodName, "get_Value") == 0)
- {
- result = NI_System_ByReference_get_Value;
- }
- }
else if (strcmp(className, "Math") == 0 || strcmp(className, "MathF") == 0)
{
if (strcmp(methodName, "Abs") == 0)
diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h
index c206a8c90cc7e..ca812ab66e311 100644
--- a/src/coreclr/jit/namedintrinsiclist.h
+++ b/src/coreclr/jit/namedintrinsiclist.h
@@ -76,8 +76,6 @@ enum NamedIntrinsic : unsigned short
NI_Array_Get,
NI_Array_Set,
- NI_System_ByReference_ctor,
- NI_System_ByReference_get_Value,
NI_System_Activator_AllocatorOf,
NI_System_Activator_DefaultConstructorOf,
NI_System_EETypePtr_EETypePtrOf,
diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypedReference.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypedReference.cs
index cb0878884a8ee..5385e5e58c58b 100644
--- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypedReference.cs
+++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/TypedReference.cs
@@ -16,12 +16,12 @@ namespace System
public ref struct TypedReference
{
// Do not change the ordering of these fields. The JIT has a dependency on this layout.
- private readonly ByReference _value;
+ private readonly ref byte _value;
private readonly RuntimeTypeHandle _typeHandle;
private TypedReference(object target, int offset, RuntimeTypeHandle typeHandle)
{
- _value = new ByReference(ref Unsafe.Add(ref target.GetRawData(), offset));
+ _value = ref Unsafe.Add(ref target.GetRawData(), offset);
_typeHandle = typeHandle;
}
@@ -81,7 +81,7 @@ internal ref byte Value
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
- return ref _value.Value;
+ return ref _value;
}
}
}
diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
index fca3a102d34a5..486ef40732481 100644
--- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
+++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
@@ -2330,11 +2330,6 @@ private int GatherClassGCLayout(TypeDesc type, byte* gcPtrs)
{
int result = 0;
- if (type.IsByReferenceOfT)
- {
- return MarkGcField(gcPtrs, CorInfoGCType.TYPE_GC_BYREF);
- }
-
foreach (var field in type.GetFields())
{
if (field.IsStatic)
@@ -2952,15 +2947,6 @@ private CorInfoType getFieldType(CORINFO_FIELD_STRUCT_* field, CORINFO_CLASS_STR
type = asCorInfoType(fieldType);
}
- Debug.Assert(!fieldDesc.OwningType.IsByReferenceOfT ||
- fieldDesc.OwningType.GetKnownField("_value").FieldType.Category == TypeFlags.IntPtr);
- if (type == CorInfoType.CORINFO_TYPE_NATIVEINT && fieldDesc.OwningType.IsByReferenceOfT)
- {
- Debug.Assert(structType == null || *structType == null);
- Debug.Assert(fieldDesc.Offset.AsInt == 0);
- type = CorInfoType.CORINFO_TYPE_BYREF;
- }
-
return type;
}
diff --git a/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs b/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs
index 0c331f9017dbc..1237cdb3dd34e 100644
--- a/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs
+++ b/src/coreclr/tools/Common/JitInterface/SystemVStructClassificator.cs
@@ -295,21 +295,7 @@ private static bool ClassifyEightBytes(TypeDesc typeDesc,
return false;
}
- SystemVClassificationType fieldClassificationType;
- if (typeDesc.IsByReferenceOfT)
- {
- // ByReference is a special type whose single IntPtr field holds a by-ref potentially interior pointer to GC
- // memory, so classify its field as such
- Debug.Assert(numIntroducedFields == 1);
- Debug.Assert(field.FieldType.IsWellKnownType(WellKnownType.IntPtr));
-
- fieldClassificationType = SystemVClassificationTypeIntegerByRef;
- }
- else
- {
- fieldClassificationType = TypeDef2SystemVClassification(field.FieldType);
- }
-
+ SystemVClassificationType fieldClassificationType = TypeDef2SystemVClassification(field.FieldType);
if (fieldClassificationType == SystemVClassificationTypeStruct)
{
bool inEmbeddedStructPrev = helper.InEmbeddedStruct;
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs b/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs
index 838dd7038d33b..cb4755c5af306 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/ExplicitLayoutValidator.cs
@@ -157,7 +157,7 @@ private void MarkByRefAndORefLocations(MetadataType type, List WellKnownTypeNames => s_wellKnownTypeNames;
@@ -71,7 +70,7 @@ public virtual void SetSystemModule(ModuleDesc systemModule)
// Initialize all well known types - it will save us from checking the name for each loaded type
for (int typeIndex = 0; typeIndex < _wellKnownTypes.Length; typeIndex++)
{
- // Require System.Object to be present as a minimal sanity check.
+ // Require System.Object to be present as a minimal sanity check.
// The set of required well-known types is not strictly defined since different .NET profiles implement different subsets.
MetadataType type = systemModule.GetType("System", s_wellKnownTypeNames[typeIndex], throwIfNotFound: typeIndex == (int)WellKnownType.Object);
if (type != null)
@@ -88,7 +87,7 @@ public override DefType GetWellKnownType(WellKnownType wellKnownType, bool throw
int typeIndex = (int)wellKnownType - 1;
DefType type = _wellKnownTypes[typeIndex];
- if (type == null && throwIfNotFound)
+ if (type == null && throwIfNotFound)
ThrowHelper.ThrowTypeLoadException("System", s_wellKnownTypeNames[typeIndex], SystemModule);
return type;
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs b/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs
index 160dac047db44..d9d2907c53f42 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/TypeDesc.cs
@@ -117,7 +117,6 @@ internal void SetWellKnownType(WellKnownType wellKnownType)
case WellKnownType.RuntimeMethodHandle:
case WellKnownType.RuntimeFieldHandle:
case WellKnownType.TypedReference:
- case WellKnownType.ByReferenceOfT:
flags = TypeFlags.ValueType;
break;
@@ -306,18 +305,6 @@ public bool IsNullable
}
}
- ///
- /// Gets a value indicating whether this is a generic definition, or
- /// an instance of System.ByReference`1.
- ///
- public bool IsByReferenceOfT
- {
- get
- {
- return this.GetTypeDefinition().IsWellKnownType(WellKnownType.ByReferenceOfT);
- }
- }
-
///
/// Gets a value indicating whether this is an array type ().
/// Note this will return true for both multidimensional array types and vector types.
diff --git a/src/coreclr/tools/Common/TypeSystem/Common/WellKnownType.cs b/src/coreclr/tools/Common/TypeSystem/Common/WellKnownType.cs
index cc3e5636058f7..b16257f21697e 100644
--- a/src/coreclr/tools/Common/TypeSystem/Common/WellKnownType.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Common/WellKnownType.cs
@@ -46,6 +46,5 @@ public enum WellKnownType
Exception,
TypedReference,
- ByReferenceOfT,
}
}
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
index 4c11c0570637d..01b82b84027f8 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs
@@ -411,7 +411,6 @@ internal static MarshallerKind GetMarshallerKind(
bool isBlittable = MarshalUtils.IsBlittableType(type);
// Blittable generics are allowed to be marshalled with the following exceptions:
- // * ByReference: This represents an interior pointer and is not actually blittable
// * Nullable: We don't want to be locked into the default behavior as we may want special handling later
// * Vector64: Represents the __m64 ABI primitive which requires currently unimplemented handling
// * Vector128: Represents the __m128 ABI primitive which requires currently unimplemented handling
@@ -420,7 +419,6 @@ internal static MarshallerKind GetMarshallerKind(
// We can't block these types for field scenarios for back-compat reasons.
if (type.HasInstantiation && !isField && (!isBlittable
- || InteropTypes.IsSystemByReference(context, type)
|| InteropTypes.IsSystemSpan(context, type)
|| InteropTypes.IsSystemReadOnlySpan(context, type)
|| InteropTypes.IsSystemNullable(context, type)
diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs
index d78b275f49e96..f69879a10ee15 100644
--- a/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs
+++ b/src/coreclr/tools/Common/TypeSystem/Interop/InteropTypes.cs
@@ -117,11 +117,6 @@ public static bool IsSystemArgIterator(TypeSystemContext context, TypeDesc type)
return IsCoreNamedType(context, type, "System", "ArgIterator");
}
- public static bool IsSystemByReference(TypeSystemContext context, TypeDesc type)
- {
- return IsCoreNamedType(context, type, "System", "ByReference`1");
- }
-
public static bool IsSystemSpan(TypeSystemContext context, TypeDesc type)
{
return IsCoreNamedType(context, type, "System", "Span`1");
diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs
index 0f4dded3fe585..acaa1a0ca859d 100644
--- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs
+++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs
@@ -372,11 +372,6 @@ private void ImportCall(ILOpcode opcode, int token)
return;
}
- if (method.OwningType.IsByReferenceOfT && (method.IsConstructor || method.Name == "get_Value"))
- {
- return;
- }
-
if (IsEETypePtrOf(method))
{
if (runtimeDeterminedMethod.IsRuntimeDeterminedExactMethod)
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs
index ad294d7227d46..3963a30ea7b1f 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/GCRefMapBuilder.cs
@@ -7,15 +7,15 @@
using Internal.TypeSystem;
-// The GCRef map is used to encode GC type of arguments for callsites. Logically, it is sequence where pos is
+// The GCRef map is used to encode GC type of arguments for callsites. Logically, it is sequence where pos is
// position of the reference in the stack frame and token is type of GC reference (one of GCREFMAP_XXX values).
//
-// - The encoding always starts at the byte boundary. The high order bit of each byte is used to signal end of the encoding
+// - The encoding always starts at the byte boundary. The high order bit of each byte is used to signal end of the encoding
// stream. The last byte has the high order bit zero. It means that there are 7 useful bits in each byte.
// - "pos" is always encoded as delta from previous pos.
-// - The basic encoding unit is two bits. Values 0, 1 and 2 are the common constructs (skip single slot, GC reference, interior
-// pointer). Value 3 means that extended encoding follows.
-// - The extended information is integer encoded in one or more four bit blocks. The high order bit of the four bit block is
+// - The basic encoding unit is two bits. Values 0, 1 and 2 are the common constructs (skip single slot, GC reference, interior
+// pointer). Value 3 means that extended encoding follows.
+// - The extended information is integer encoded in one or more four bit blocks. The high order bit of the four bit block is
// used to signal the end.
// - For x86, the encoding starts by size of the callee poped stack. The size is encoded using the same mechanism as above (two bit
// basic encoding, with extended encoding for large values).
@@ -35,7 +35,7 @@ public class GCRefMapBuilder
private int _pendingByte;
///
- /// Number of bits in pending byte. Note that the trailing zero bits are not written out,
+ /// Number of bits in pending byte. Note that the trailing zero bits are not written out,
/// so this can be more than 7.
///
private int _bits;
@@ -293,7 +293,7 @@ private void GcScanValueType(TypeDesc type, ArgDestination argDest, int delta, C
private void FindByRefPointerOffsetsInByRefLikeObject(TypeDesc type, ArgDestination argDest, int delta, CORCOMPILE_GCREFMAP_TOKENS[] frame)
{
- if (type.IsByReferenceOfT || type.IsByRef)
+ if (type.IsByRef)
{
argDest.GcMark(frame, delta, interior: true);
return;
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
index f507cabb4d3e3..62725929b8100 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunMetadataFieldLayoutAlgorithm.cs
@@ -253,7 +253,7 @@ private void GetElementTypeInfoGeneric(
size = fieldType.GetElementSize().AsInt;
alignment = size;
}
- else if (fieldType.IsByRef || fieldType.IsByRefLike || fieldType.IsByReferenceOfT)
+ else if (fieldType.IsByRef || fieldType.IsByRefLike)
{
ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, fieldDesc.OwningType);
}
diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs
index 266be8710eb0b..a36d77e8fe652 100644
--- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs
+++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/IBCProfileData.cs
@@ -18,13 +18,13 @@ public class MibcConfig
public override string ToString()
{
return
- $"""
- FormatVersion: {FormatVersion}
- Runtime: {Runtime}
- Os: {Os}
- Arch: {Arch}
+$@"
+FormatVersion: {FormatVersion}
+Runtime: {Runtime}
+Os: {Os}
+Arch: {Arch}
- """;
+";
}
public static MibcConfig FromKeyValueMap(Dictionary kvMap)
diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs
index 656d075135228..b49dd4ff72930 100644
--- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs
+++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/InstanceFieldLayout.cs
@@ -296,7 +296,7 @@ namespace IsByRefLike
{
public ref struct ByRefLikeStruct
{
- ByReference
public static bool operator ==(ReadOnlySpan left, ReadOnlySpan right) =>
left._length == right._length &&
- Unsafe.AreSame(ref left._reference.Value, ref right._reference.Value);
+ Unsafe.AreSame(ref left._reference, ref right._reference);
///
/// For , returns a new instance of string that represents the characters pointed to by the span.
@@ -327,7 +327,7 @@ public override string ToString()
{
if (typeof(T) == typeof(char))
{
- return new string(new ReadOnlySpan(ref Unsafe.As(ref _reference.Value), _length));
+ return new string(new ReadOnlySpan(ref Unsafe.As(ref _reference), _length));
}
return $"System.ReadOnlySpan<{typeof(T).Name}>[{_length}]";
}
@@ -345,7 +345,7 @@ public ReadOnlySpan Slice(int start)
if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException();
- return new ReadOnlySpan(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), _length - start);
+ return new ReadOnlySpan(ref Unsafe.Add(ref _reference, (nint)(uint)start /* force zero-extension */), _length - start);
}
///
@@ -368,7 +368,7 @@ public ReadOnlySpan Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#endif
- return new ReadOnlySpan(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), length);
+ return new ReadOnlySpan(ref Unsafe.Add(ref _reference, (nint)(uint)start /* force zero-extension */), length);
}
///
@@ -382,7 +382,7 @@ public T[] ToArray()
return Array.Empty();
var destination = new T[_length];
- Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _reference.Value, (uint)_length);
+ Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _reference, (uint)_length);
return destination;
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs
index 00ff3ce98e59a..4e4bab9aa36fc 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs
@@ -55,7 +55,7 @@ public static unsafe InvokeFunc CreateInvokeDelegate(MethodBase method)
il.Emit(OpCodes.Add);
}
- il.Emit(OpCodes.Call, Methods.ByReferenceOfByte_Value()); // This can be replaced by ldfld once byref fields are available in C#
+ il.Emit(OpCodes.Ldfld, Methods.ByReferenceOfByte_Value());
RuntimeType parameterType = (RuntimeType)parameters[i].ParameterType;
if (!parameterType.IsByRef)
@@ -166,9 +166,9 @@ public static void Throw_NullReference_InvokeNullRefReturned()
private static class Methods
{
- private static MethodInfo? s_ByReferenceOfByte_Value;
- public static MethodInfo ByReferenceOfByte_Value() =>
- s_ByReferenceOfByte_Value ??= typeof(ByReference).GetMethod("get_Value")!;
+ private static FieldInfo? s_ByReferenceOfByte_Value;
+ public static FieldInfo ByReferenceOfByte_Value() =>
+ s_ByReferenceOfByte_Value ??= typeof(ByReference).GetField("Value")!;
private static MethodInfo? s_ThrowHelper_Throw_NullReference_InvokeNullRefReturned;
public static MethodInfo ThrowHelper_Throw_NullReference_InvokeNullRefReturned() =>
diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs
index 36d40f1ce8529..f91ad52a9b454 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/MethodBase.cs
@@ -234,13 +234,13 @@ BindingFlags invokeAttr
(sigType.IsByRef && arg.GetType() == RuntimeTypeHandle.GetElementType(sigType)) ||
((sigType.IsEnum || arg.GetType().IsEnum) && RuntimeType.GetUnderlyingType((RuntimeType)arg.GetType()) == RuntimeType.GetUnderlyingType(sigType)));
#endif
- ByReference valueTypeRef = new(ref copyOfParameters[i]!.GetRawData());
- *(ByReference*)(byrefParameters + i) = valueTypeRef;
+ ByReference valueTypeRef = ByReference.Create(ref copyOfParameters[i]!.GetRawData());
+ *(ByReference*)(byrefParameters + i) = valueTypeRef;
}
else
{
- ByReference objRef = new(ref copyOfParameters[i]);
- *(ByReference*)(byrefParameters + i) = objRef;
+ ByReference objRef = ByReference.Create(ref copyOfParameters[i]);
+ *(ByReference*)(byrefParameters + i) = objRef;
}
}
}
@@ -273,11 +273,11 @@ private protected ref struct StackAllocedArguments
[StructLayout(LayoutKind.Sequential)]
private protected ref struct StackAllocatedByRefs
{
- internal ByReference _arg0;
+ internal ref byte _arg0;
#pragma warning disable CA1823, CS0169, IDE0051 // accessed via 'CheckArguments' ref arithmetic
- private ByReference _arg1;
- private ByReference _arg2;
- private ByReference _arg3;
+ private ref byte _arg1;
+ private ref byte _arg2;
+ private ref byte _arg3;
#pragma warning restore CA1823, CS0169, IDE0051
}
#endif
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/LifetimeAnnotationAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/LifetimeAnnotationAttribute.cs
deleted file mode 100644
index f792a7a8e2248..0000000000000
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/LifetimeAnnotationAttribute.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-
-namespace System.Runtime.CompilerServices
-{
- ///
- /// This type is defined until we consume the C# 11 compiler.
- ///
- ///
- /// Also remove in the reference assemblies.
- ///
- [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
- internal sealed class LifetimeAnnotationAttribute : Attribute
- {
- public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped)
- {
- IsRefScoped = isRefScoped;
- IsValueScoped = isValueScoped;
- }
- public bool IsRefScoped { get; }
- public bool IsValueScoped { get; }
- }
-}
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
index d006bd58cbcde..1f2181b9e176c 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/Unsafe.cs
@@ -665,13 +665,14 @@ public static ref T AsRef(void* source)
///
/// Reinterprets the given location as a reference to a value of type .
///
+ /// The lifetime of the reference will not be validated when using this API.
[Intrinsic]
// CoreCLR:METHOD__UNSAFE__AS_REF_IN
// AOT:AsRef
// Mono:AsRef
[NonVersionable]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ref T AsRef([LifetimeAnnotation(true, false)] in T source)
+ public static ref T AsRef(scoped in T source)
{
throw new PlatformNotSupportedException();
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs
index f089434fa332f..c91aa21b5e7d0 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs
@@ -77,27 +77,27 @@ public static Memory AsMemory(ReadOnlyMemory memory) =>
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
/// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
///
- public static ref T GetReference([LifetimeAnnotation(false, true)] Span span) => ref span._reference.Value;
+ public static ref T GetReference(Span span) => ref span._reference;
///
/// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to the location where the 0th element
/// would have been stored. Such a reference may or may not be null. It can be used for pinning but must never be dereferenced.
///
- public static ref T GetReference([LifetimeAnnotation(false, true)] ReadOnlySpan span) => ref span._reference.Value;
+ public static ref T GetReference(ReadOnlySpan span) => ref span._reference;
///
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to fake non-null pointer. Such a reference can be used
/// for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static unsafe ref T GetNonNullPinnableReference(Span span) => ref (span.Length != 0) ? ref span._reference.Value : ref Unsafe.AsRef((void*)1);
+ internal static unsafe ref T GetNonNullPinnableReference(Span span) => ref (span.Length != 0) ? ref Unsafe.AsRef(in span._reference) : ref Unsafe.AsRef((void*)1);
///
/// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to fake non-null pointer. Such a reference
/// can be used for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- internal static unsafe ref T GetNonNullPinnableReference(ReadOnlySpan span) => ref (span.Length != 0) ? ref span._reference.Value : ref Unsafe.AsRef((void*)1);
+ internal static unsafe ref T GetNonNullPinnableReference(ReadOnlySpan span) => ref (span.Length != 0) ? ref Unsafe.AsRef(in span._reference) : ref Unsafe.AsRef((void*)1);
///
/// Casts a Span of one primitive type to another primitive type .
@@ -150,7 +150,7 @@ public static Span Cast(Span span)
}
return new Span(
- ref Unsafe.As(ref span._reference.Value),
+ ref Unsafe.As(ref span._reference),
toLength);
}
@@ -217,9 +217,14 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)),
/// A reference to data.
/// The number of elements the memory contains.
/// A span representing the specified reference and length.
- /// The lifetime of the returned span will not be validated for safety by span-aware languages.
+ ///
+ /// This method should be used with caution. It is dangerous because the length argument is not checked.
+ /// Even though the ref is annotated as scoped, it will be stored into the returned span, and the lifetime
+ /// of the returned span will not be validated for safety, even by span-aware languages.
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static Span CreateSpan([LifetimeAnnotation(true, false)] ref T reference, int length) => new Span(ref reference, length);
+ public static Span CreateSpan(scoped ref T reference, int length) =>
+ new Span(ref Unsafe.AsRef(in reference), length);
///
/// Creates a new read-only span over a portion of a regular managed object. This can be useful
@@ -229,9 +234,14 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)),
/// A reference to data.
/// The number of elements the memory contains.
/// A read-only span representing the specified reference and length.
- /// The lifetime of the returned span will not be validated for safety by span-aware languages.
+ ///
+ /// This method should be used with caution. It is dangerous because the length argument is not checked.
+ /// Even though the ref is annotated as scoped, it will be stored into the returned span, and the lifetime
+ /// of the returned span will not be validated for safety, even by span-aware languages.
+ ///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ReadOnlySpan CreateReadOnlySpan([LifetimeAnnotation(true, false)] ref T reference, int length) => new ReadOnlySpan(ref reference, length);
+ public static ReadOnlySpan CreateReadOnlySpan(scoped ref T reference, int length) =>
+ new ReadOnlySpan(ref Unsafe.AsRef(in reference), length);
/// Creates a new read-only span for a null-terminated string.
/// The pointer to the null-terminated string of characters.
diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs
index 74c80a8d00132..6ecf1aea753b0 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Span.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs
@@ -22,7 +22,7 @@ namespace System
public readonly ref struct Span
{
/// A byref or a native ptr.
- internal readonly ByReference _reference;
+ internal readonly ref T _reference;
/// The number of elements this Span contains.
private readonly int _length;
@@ -43,7 +43,7 @@ public Span(T[]? array)
if (!typeof(T).IsValueType && array.GetType() != typeof(T[]))
ThrowHelper.ThrowArrayTypeMismatchException();
- _reference = new ByReference(ref MemoryMarshal.GetArrayDataReference(array));
+ _reference = ref MemoryMarshal.GetArrayDataReference(array);
_length = array.Length;
}
@@ -80,7 +80,7 @@ public Span(T[]? array, int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#endif
- _reference = new ByReference(ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */));
+ _reference = ref Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), (nint)(uint)start /* force zero-extension */);
_length = length;
}
@@ -107,7 +107,7 @@ public unsafe Span(void* pointer, int length)
if (length < 0)
ThrowHelper.ThrowArgumentOutOfRangeException();
- _reference = new ByReference(ref Unsafe.As(ref *(byte*)pointer));
+ _reference = ref Unsafe.As(ref *(byte*)pointer);
_length = length;
}
@@ -117,7 +117,7 @@ public unsafe Span(void* pointer, int length)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal Span(ref T reference)
{
- _reference = new ByReference(ref reference);
+ _reference = ref reference;
_length = 1;
}
@@ -127,7 +127,7 @@ internal Span(ref T reference, int length)
{
Debug.Assert(length >= 0);
- _reference = new ByReference(ref reference);
+ _reference = ref reference;
_length = length;
}
@@ -148,7 +148,7 @@ public ref T this[int index]
{
if ((uint)index >= (uint)_length)
ThrowHelper.ThrowIndexOutOfRangeException();
- return ref Unsafe.Add(ref _reference.Value, (nint)(uint)index /* force zero-extension */);
+ return ref Unsafe.Add(ref _reference, (nint)(uint)index /* force zero-extension */);
}
}
@@ -266,7 +266,7 @@ public ref T GetPinnableReference()
{
// Ensure that the native code has just one forward branch that is predicted-not-taken.
ref T ret = ref Unsafe.NullRef();
- if (_length != 0) ret = ref _reference.Value;
+ if (_length != 0) ret = ref _reference;
return ref ret;
}
@@ -278,11 +278,11 @@ public unsafe void Clear()
{
if (RuntimeHelpers.IsReferenceOrContainsReferences())
{
- SpanHelpers.ClearWithReferences(ref Unsafe.As(ref _reference.Value), (uint)_length * (nuint)(Unsafe.SizeOf() / sizeof(nuint)));
+ SpanHelpers.ClearWithReferences(ref Unsafe.As(ref _reference), (uint)_length * (nuint)(Unsafe.SizeOf() / sizeof(nuint)));
}
else
{
- SpanHelpers.ClearWithoutReferences(ref Unsafe.As(ref _reference.Value), (uint)_length * (nuint)Unsafe.SizeOf());
+ SpanHelpers.ClearWithoutReferences(ref Unsafe.As(ref _reference), (uint)_length * (nuint)Unsafe.SizeOf());
}
}
@@ -298,12 +298,12 @@ public void Fill(T value)
// The runtime eventually calls memset, which can efficiently support large buffers.
// We don't need to check IsReferenceOrContainsReferences because no references
// can ever be stored in types this small.
- Unsafe.InitBlockUnaligned(ref Unsafe.As(ref _reference.Value), Unsafe.As(ref value), (uint)_length);
+ Unsafe.InitBlockUnaligned(ref Unsafe.As(ref _reference), Unsafe.As(ref value), (uint)_length);
}
else
{
// Call our optimized workhorse method for all other types.
- SpanHelpers.Fill(ref _reference.Value, (uint)_length, value);
+ SpanHelpers.Fill(ref _reference, (uint)_length, value);
}
}
@@ -325,7 +325,7 @@ public void CopyTo(Span destination)
if ((uint)_length <= (uint)destination.Length)
{
- Buffer.Memmove(ref destination._reference.Value, ref _reference.Value, (uint)_length);
+ Buffer.Memmove(ref destination._reference, ref _reference, (uint)_length);
}
else
{
@@ -346,7 +346,7 @@ public bool TryCopyTo(Span destination)
bool retVal = false;
if ((uint)_length <= (uint)destination.Length)
{
- Buffer.Memmove(ref destination._reference.Value, ref _reference.Value, (uint)_length);
+ Buffer.Memmove(ref destination._reference, ref _reference, (uint)_length);
retVal = true;
}
return retVal;
@@ -358,13 +358,13 @@ public bool TryCopyTo(Span destination)
///
public static bool operator ==(Span left, Span right) =>
left._length == right._length &&
- Unsafe.AreSame(ref left._reference.Value, ref right._reference.Value);
+ Unsafe.AreSame(ref left._reference, ref right._reference);
///
/// Defines an implicit conversion of a to a
///
public static implicit operator ReadOnlySpan(Span span) =>
- new ReadOnlySpan(ref span._reference.Value, span._length);
+ new ReadOnlySpan(ref span._reference, span._length);
///
/// For , returns a new instance of string that represents the characters pointed to by the span.
@@ -374,7 +374,7 @@ public override string ToString()
{
if (typeof(T) == typeof(char))
{
- return new string(new ReadOnlySpan(ref Unsafe.As(ref _reference.Value), _length));
+ return new string(new ReadOnlySpan(ref Unsafe.As(ref _reference), _length));
}
return $"System.Span<{typeof(T).Name}>[{_length}]";
}
@@ -392,7 +392,7 @@ public Span Slice(int start)
if ((uint)start > (uint)_length)
ThrowHelper.ThrowArgumentOutOfRangeException();
- return new Span(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), _length - start);
+ return new Span(ref Unsafe.Add(ref _reference, (nint)(uint)start /* force zero-extension */), _length - start);
}
///
@@ -420,7 +420,7 @@ public Span Slice(int start, int length)
ThrowHelper.ThrowArgumentOutOfRangeException();
#endif
- return new Span(ref Unsafe.Add(ref _reference.Value, (nint)(uint)start /* force zero-extension */), length);
+ return new Span(ref Unsafe.Add(ref _reference, (nint)(uint)start /* force zero-extension */), length);
}
///
@@ -435,7 +435,7 @@ public T[] ToArray()
return Array.Empty();
var destination = new T[_length];
- Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _reference.Value, (uint)_length);
+ Buffer.Memmove(ref MemoryMarshal.GetArrayDataReference(destination), ref _reference, (uint)_length);
return destination;
}
}
diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs
index 0923eb440a99a..9ac73fbdcb548 100644
--- a/src/libraries/System.Private.CoreLib/src/System/String.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/String.cs
@@ -419,7 +419,7 @@ public void CopyTo(Span destination)
{
if ((uint)Length <= (uint)destination.Length)
{
- Buffer.Memmove(ref destination._reference.Value, ref _firstChar, (uint)Length);
+ Buffer.Memmove(ref destination._reference, ref _firstChar, (uint)Length);
}
else
{
@@ -436,7 +436,7 @@ public bool TryCopyTo(Span destination)
bool retVal = false;
if ((uint)Length <= (uint)destination.Length)
{
- Buffer.Memmove(ref destination._reference.Value, ref _firstChar, (uint)Length);
+ Buffer.Memmove(ref destination._reference, ref _firstChar, (uint)Length);
retVal = true;
}
return retVal;
diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
index 99aec155a2942..3e164bc80ff17 100644
--- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.Unix.cs
@@ -1007,7 +1007,7 @@ private static bool TZif_ParsePosixFormat(
return !standardName.IsEmpty && !standardOffset.IsEmpty;
}
- private static ReadOnlySpan TZif_ParsePosixName(ReadOnlySpan posixFormat, ref int index)
+ private static ReadOnlySpan TZif_ParsePosixName(ReadOnlySpan posixFormat, scoped ref int index)
{
bool isBracketEnclosed = index < posixFormat.Length && posixFormat[index] == '<';
if (isBracketEnclosed)
@@ -1034,10 +1034,10 @@ private static ReadOnlySpan TZif_ParsePosixName(ReadOnlySpan posixFo
}
}
- private static ReadOnlySpan TZif_ParsePosixOffset(ReadOnlySpan posixFormat, ref int index) =>
+ private static ReadOnlySpan TZif_ParsePosixOffset(ReadOnlySpan posixFormat, scoped ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => !char.IsDigit(c) && c != '+' && c != '-' && c != ':');
- private static void TZif_ParsePosixDateTime(ReadOnlySpan posixFormat, ref int index, out ReadOnlySpan date, out ReadOnlySpan time)
+ private static void TZif_ParsePosixDateTime(ReadOnlySpan posixFormat, scoped ref int index, out ReadOnlySpan date, out ReadOnlySpan time)
{
time = null;
@@ -1049,13 +1049,13 @@ private static void TZif_ParsePosixDateTime(ReadOnlySpan posixFormat, ref
}
}
- private static ReadOnlySpan TZif_ParsePosixDate(ReadOnlySpan posixFormat, ref int index) =>
+ private static ReadOnlySpan TZif_ParsePosixDate(ReadOnlySpan posixFormat, scoped ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => c == '/' || c == ',');
- private static ReadOnlySpan TZif_ParsePosixTime(ReadOnlySpan posixFormat, ref int index) =>
+ private static ReadOnlySpan TZif_ParsePosixTime(ReadOnlySpan posixFormat, scoped ref int index) =>
TZif_ParsePosixString(posixFormat, ref index, c => c == ',');
- private static ReadOnlySpan TZif_ParsePosixString(ReadOnlySpan posixFormat, ref int index, Func breakCondition)
+ private static ReadOnlySpan TZif_ParsePosixString(ReadOnlySpan posixFormat, scoped ref int index, Func breakCondition)
{
int startIndex = index;
for (; index < posixFormat.Length; index++)
diff --git a/src/libraries/System.Private.CoreLib/src/System/TypedReference.cs b/src/libraries/System.Private.CoreLib/src/System/TypedReference.cs
index dd13bfd894a02..2ff8dc78b9c86 100644
--- a/src/libraries/System.Private.CoreLib/src/System/TypedReference.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/TypedReference.cs
@@ -75,7 +75,7 @@ public override bool Equals(object? o)
throw new NotSupportedException(SR.NotSupported_NYI);
}
- internal bool IsNull => Unsafe.IsNullRef(ref _value.Value) && _type == IntPtr.Zero;
+ internal bool IsNull => Unsafe.IsNullRef(ref _value) && _type == IntPtr.Zero;
public static Type GetTargetType(TypedReference value)
{
diff --git a/src/libraries/System.Runtime.Serialization.Formatters/tests/FormatterServicesTests.cs b/src/libraries/System.Runtime.Serialization.Formatters/tests/FormatterServicesTests.cs
index 0a04f250a3f8a..b1ae8a2294e9e 100644
--- a/src/libraries/System.Runtime.Serialization.Formatters/tests/FormatterServicesTests.cs
+++ b/src/libraries/System.Runtime.Serialization.Formatters/tests/FormatterServicesTests.cs
@@ -133,7 +133,7 @@ private ref struct StructWithSpanField
[Theory]
[MemberData(nameof(GetUninitializedObject_ByRefLikeType_NetCore_TestData))]
- [SkipOnTargetFramework(~TargetFrameworkMonikers.Netcoreapp, "Some runtimes don't support or recognise Span, ReadOnlySpan or ByReference as ref types.")]
+ [SkipOnTargetFramework(~TargetFrameworkMonikers.Netcoreapp, "Some runtimes don't support or recognise Span or ReadOnlySpan as ref types.")]
public void GetUninitializedObject_ByRefLikeType_NetCore_ThrowsNotSupportedException(Type type)
{
Assert.Throws(() => FormatterServices.GetUninitializedObject(type));
diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs
index 16b2ec8009469..62dd38cc8725b 100644
--- a/src/libraries/System.Runtime/ref/System.Runtime.cs
+++ b/src/libraries/System.Runtime/ref/System.Runtime.cs
@@ -12538,14 +12538,6 @@ public partial interface ITuple
object? this[int index] { get; }
int Length { get; }
}
- // See src\libraries\System.Private.CoreLib\src\System\Runtime\CompilerServices\LifetimeAnnotationAttribute.cs
- [System.AttributeUsageAttribute(System.AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)]
- internal sealed class LifetimeAnnotationAttribute : System.Attribute
- {
- public LifetimeAnnotationAttribute(bool isRefScoped, bool isValueScoped) { throw null; }
- public bool IsRefScoped { get { throw null; } }
- public bool IsValueScoped { get { throw null; } }
- }
public enum LoadHint
{
Default = 0,
@@ -12789,7 +12781,7 @@ public static partial class Unsafe
public unsafe static void* AsPointer(ref T value) { throw null; }
[System.CLSCompliantAttribute(false)]
public unsafe static ref T AsRef(void* source) { throw null; }
- public static ref T AsRef([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] in T source) { throw null; }
+ public static ref T AsRef(scoped in T source) { throw null; }
[return: System.Diagnostics.CodeAnalysis.NotNullIfNotNull("o")]
public static T? As(object? o) where T : class? { throw null; }
public static ref TTo As(ref TFrom source) { throw null; }
diff --git a/src/mono/System.Private.CoreLib/src/System/TypedReference.Mono.cs b/src/mono/System.Private.CoreLib/src/System/TypedReference.Mono.cs
index f7a473bb92a00..d9003bfecc6c0 100644
--- a/src/mono/System.Private.CoreLib/src/System/TypedReference.Mono.cs
+++ b/src/mono/System.Private.CoreLib/src/System/TypedReference.Mono.cs
@@ -11,7 +11,7 @@ public ref partial struct TypedReference
#region sync with object-internals.h
#pragma warning disable CA1823 // used by runtime
private readonly RuntimeTypeHandle type;
- private readonly ByReference _value;
+ private readonly ref byte _value;
private readonly IntPtr _type;
#pragma warning restore CA1823
#endregion
diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c
index 7619ebecdc4e3..2e28b81e7c781 100644
--- a/src/mono/mono/metadata/class-init.c
+++ b/src/mono/mono/metadata/class-init.c
@@ -1835,35 +1835,12 @@ class_has_ref_fields (MonoClass *klass)
return klass->has_ref_fields;
}
-static gboolean
-class_is_byreference (MonoClass* klass)
-{
- const char* klass_name_space = m_class_get_name_space (klass);
- const char* klass_name = m_class_get_name (klass);
- MonoImage* klass_image = m_class_get_image (klass);
- gboolean in_corlib = klass_image == mono_defaults.corlib;
-
- if (in_corlib &&
- !strcmp (klass_name_space, "System") &&
- !strcmp (klass_name, "ByReference`1")) {
- return TRUE;
- }
-
- return FALSE;
-}
-
static gboolean
type_has_ref_fields (MonoType *ftype)
{
if (m_type_is_byref (ftype) || (MONO_TYPE_ISSTRUCT (ftype) && class_has_ref_fields (mono_class_from_mono_type_internal (ftype))))
return TRUE;
- /* Check for the ByReference`1 type */
- if (MONO_TYPE_ISSTRUCT (ftype)) {
- MonoClass* klass = mono_class_from_mono_type_internal (ftype);
- return class_is_byreference (klass);
- }
-
return FALSE;
}
@@ -1982,7 +1959,7 @@ validate_struct_fields_overlaps (guint8 *layout_check, int layout_size, MonoClas
} else {
int align = 0;
int size = mono_type_size (field->type, &align);
- guint8 type = type_has_references (klass, ftype) ? 1 : (m_type_is_byref (ftype) || class_is_byreference (klass)) ? 2 : 3;
+ guint8 type = type_has_references (klass, ftype) ? 1 : m_type_is_byref (ftype) ? 2 : 3;
// Mark the bytes used by this fields type based on if it contains references or not.
// Make sure there are no overlaps between object and non-object fields.
diff --git a/src/mono/mono/metadata/marshal-shared.c b/src/mono/mono/metadata/marshal-shared.c
index 9479611e9d57b..74f3672148f31 100644
--- a/src/mono/mono/metadata/marshal-shared.c
+++ b/src/mono/mono/metadata/marshal-shared.c
@@ -830,9 +830,7 @@ mono_marshal_shared_emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *kla
case MONO_MARSHAL_CONV_NONE: {
int t;
- //XXX a byref field!?!? that's not allowed! and worse, it might miss a WB
- g_assert (!m_type_is_byref (ftype));
- if (ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U) {
+ if (m_type_is_byref (ftype) || ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U) {
mono_mb_emit_ldloc (mb, 1);
mono_mb_emit_ldloc (mb, 0);
mono_mb_emit_byte (mb, CEE_LDIND_I);
diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c
index ed3a579523e5a..6f998c81a6e91 100644
--- a/src/mono/mono/mini/interp/interp.c
+++ b/src/mono/mono/mini/interp/interp.c
@@ -3342,10 +3342,8 @@ static long opcode_counts[MINT_LASTOP];
if (tracing > 1) { \
output_indent (); \
char *mn = mono_method_full_name (frame->imethod->method, FALSE); \
- char *disasm = mono_interp_dis_mintop ((gint32)(ip - frame->imethod->code), TRUE, ip + 1, *ip); \
- g_print ("(%p) %s -> %s\n", mono_thread_internal_current (), mn, disasm); \
+ g_print ("(%p) %s -> IL_%04x: %-10s\n", mono_thread_internal_current (), mn, (gint32)(ip - frame->imethod->code), mono_interp_opname (*ip)); \
g_free (mn); \
- g_free (disasm); \
}
#else
#define DUMP_INSTR()
diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c
index bcbc773e0ba2d..a65b355d996df 100644
--- a/src/mono/mono/mini/interp/transform.c
+++ b/src/mono/mono/mini/interp/transform.c
@@ -1862,9 +1862,6 @@ interp_handle_intrinsics (TransformData *td, MonoMethod *target_method, MonoClas
!strcmp (klass_name, "SpanHelpers") &&
!strcmp (tm, "ClearWithReferences")) {
*op = MINT_INTRINS_CLEAR_WITH_REFERENCES;
- } else if (in_corlib && !strcmp (klass_name_space, "System") && !strcmp (klass_name, "ByReference`1")) {
- g_assert (!strcmp (tm, "get_Value"));
- *op = MINT_LDIND_I;
} else if (in_corlib && !strcmp (klass_name_space, "System") && !strcmp (klass_name, "Marvin")) {
if (!strcmp (tm, "Block")) {
InterpInst *ldloca2 = td->last_ins;
@@ -5551,18 +5548,6 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
interp_ins_set_sreg (td->last_ins, MINT_CALL_ARGS_SREG);
td->last_ins->flags |= INTERP_INST_FLAG_CALL;
td->last_ins->info.call_args = call_args;
- } else if (m_class_get_image (klass) == mono_defaults.corlib &&
- !strcmp (m_class_get_name (m->klass), "ByReference`1") &&
- !strcmp (m->name, ".ctor")) {
- /* public ByReference(ref T value) */
- MONO_PROFILER_RAISE (inline_method, (td->rtm->method, m));
- g_assert (csignature->hasthis && csignature->param_count == 1);
- td->sp--;
- /* We already have the vt on top of the stack. Just do a dummy mov that should be optimized out */
- interp_add_ins (td, MINT_MOV_P);
- interp_ins_set_sreg (td->last_ins, td->sp [0].local);
- push_type_vt (td, klass, mono_class_value_size (klass, NULL));
- interp_ins_set_dreg (td->last_ins, td->sp [-1].local);
} else if (m_class_get_image (klass) == mono_defaults.corlib &&
(!strcmp (m_class_get_name (m->klass), "Span`1") ||
!strcmp (m_class_get_name (m->klass), "ReadOnlySpan`1")) &&
@@ -5834,7 +5819,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header,
mono_class_init_internal (klass);
MonoClass *field_klass = mono_class_from_mono_type_internal (ftype);
- mt = mint_type (m_class_get_byval_arg (field_klass));
+ mt = mint_type (ftype);
int field_size = mono_class_value_size (field_klass, NULL);
int obj_size = mono_class_value_size (klass, NULL);
obj_size = ALIGN_TO (obj_size, MINT_VT_ALIGNMENT);
diff --git a/src/mono/mono/mini/intrinsics.c b/src/mono/mono/mini/intrinsics.c
index 17b78eb529462..53ccc077c0783 100644
--- a/src/mono/mono/mini/intrinsics.c
+++ b/src/mono/mono/mini/intrinsics.c
@@ -75,24 +75,12 @@ mono_type_is_native_blittable (MonoType *t)
MonoInst*
mini_emit_inst_for_ctor (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
{
- const char* cmethod_klass_name_space = m_class_get_name_space (cmethod->klass);
- const char* cmethod_klass_name = m_class_get_name (cmethod->klass);
- MonoImage *cmethod_klass_image = m_class_get_image (cmethod->klass);
- gboolean in_corlib = cmethod_klass_image == mono_defaults.corlib;
MonoInst *ins = NULL;
/* Required intrinsics are always used even with -O=-intrins */
- if (in_corlib &&
- !strcmp (cmethod_klass_name_space, "System") &&
- !strcmp (cmethod_klass_name, "ByReference`1")) {
- /* public ByReference(ref T value) */
- g_assert (fsig->hasthis && fsig->param_count == 1);
- EMIT_NEW_STORE_MEMBASE (cfg, ins, OP_STORE_MEMBASE_REG, args [0]->dreg, 0, args [1]->dreg);
- return ins;
- }
if (!(cfg->opt & MONO_OPT_INTRINS))
- return NULL;
+ return ins;
#ifdef MONO_ARCH_SIMD_INTRINSICS
if (cfg->opt & MONO_OPT_SIMD) {
@@ -102,7 +90,7 @@ mini_emit_inst_for_ctor (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignat
}
#endif
- return NULL;
+ return ins;
}
static MonoInst*
@@ -806,15 +794,6 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
gboolean in_corlib = cmethod_klass_image == mono_defaults.corlib;
/* Required intrinsics are always used even with -O=-intrins */
- if (in_corlib &&
- !strcmp (cmethod_klass_name_space, "System") &&
- !strcmp (cmethod_klass_name, "ByReference`1") &&
- !strcmp (cmethod->name, "get_Value")) {
- g_assert (fsig->hasthis && fsig->param_count == 0);
- int dreg = alloc_preg (cfg);
- EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, args [0]->dreg, 0);
- return ins;
- }
if (!(cfg->opt & MONO_OPT_INTRINS))
return NULL;