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.22 2.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 ByRef; + ref object ByRef; } public struct NotByRefLike diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs index ac8b380d19416..886f7aa791fd6 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/CoreTestAssembly/Platform.cs @@ -48,7 +48,7 @@ public struct Double { } public abstract class ValueType { } public abstract class Enum : ValueType { } public struct Nullable where T : struct { } - + public sealed class String { } public abstract class Array : System.Collections.IList { } public abstract class Delegate { } @@ -68,11 +68,9 @@ public class Exception { } public ref struct TypedReference { - private readonly ByReference _value; + private readonly ref byte _value; private readonly RuntimeTypeHandle _typeHandle; } - - public ref struct ByReference { } } namespace System.Collections diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/InstanceFieldLayout.il b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/InstanceFieldLayout.il index 83906647e842c..35bf1dd165fff 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/InstanceFieldLayout.il +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILTestAssembly/InstanceFieldLayout.il @@ -4,18 +4,18 @@ .class public sequential ansi sealed beforefieldinit IsByRefLike.InvalidStruct extends [CoreTestAssembly]System.ValueType { - .field private valuetype [CoreTestAssembly]System.ByReference`1 ByRef + .field private object& ByRef } .class public auto ansi beforefieldinit IsByRefLike.InvalidClass1 extends [CoreTestAssembly]System.Object { - .field private valuetype [CoreTestAssembly]System.ByReference`1 ByRef + .field private object& ByRef } .class public auto ansi beforefieldinit IsByRefLike.InvalidClass2 extends [CoreTestAssembly]System.Object { - .custom instance void [CoreTestAssembly]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( 01 00 00 00 ) - .field private valuetype [CoreTestAssembly]System.ByReference`1 ByRef + .custom instance void [CoreTestAssembly]System.Runtime.CompilerServices.IsByRefLikeAttribute::.ctor() = ( 01 00 00 00 ) + .field private object& ByRef } diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs index e92749b5ab272..0a60a72a4a640 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/InstanceFieldLayoutTests.cs @@ -31,7 +31,7 @@ public void TestExplicitLayout() MetadataType t = _testModule.GetType("Explicit", "Class1"); // With 64bit, there should be 8 bytes for the System.Object EE data pointer + - // 10 bytes up until the offset of the char field + the char size of 2 + we + // 10 bytes up until the offset of the char field + the char size of 2 + we // round up the whole instance size to the next pointer size (+4) = 24 Assert.Equal(24, t.InstanceByteCount.AsInt); @@ -95,7 +95,7 @@ public void TestExplicitTypeLayoutWithInheritance() if (f.Name == "Lol") { - // First field after base class, with offset 0 so it should lie on the byte count of + // First field after base class, with offset 0 so it should lie on the byte count of // the base class = 20 Assert.Equal(20, f.Offset.AsInt); } @@ -821,11 +821,6 @@ public void TestByRefLikeTypes() Assert.True(type.IsByRefLike); } - { - DefType type = _context.GetWellKnownType(WellKnownType.ByReferenceOfT); - Assert.True(type.IsByRefLike); - } - { DefType type = _testModule.GetType("IsByRefLike", "ByRefLikeStruct"); Assert.True(type.IsByRefLike); diff --git a/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj b/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj index 14a99e98aad28..ab5cc92e42435 100644 --- a/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj +++ b/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj @@ -21,6 +21,9 @@ $(Description) Microsoft.Diagnostics.Tools.Pgo Major + + 10 diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index d679c69a24592..6b80b79d18c9b 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -1362,12 +1362,6 @@ void SystemDomain::LoadBaseSystemClasses() // the SZArrayHelper class here. g_pSZArrayHelperClass = CoreLibBinder::GetClass(CLASS__SZARRAYHELPER); - // Load ByReference class - // - // NOTE: ByReference must be the first by-ref-like system type to be loaded, - // because MethodTable::ClassifyEightBytesWithManagedLayout depends on it. - g_pByReferenceClass = CoreLibBinder::GetClass(CLASS__BYREFERENCE); - // Load Nullable class g_pNullableClass = CoreLibBinder::GetClass(CLASS__NULLABLE); diff --git a/src/coreclr/vm/classnames.h b/src/coreclr/vm/classnames.h index dee85ad23b160..9a4d4e35845af 100644 --- a/src/coreclr/vm/classnames.h +++ b/src/coreclr/vm/classnames.h @@ -15,7 +15,6 @@ #define g_ArrayClassName "System.Array" #define g_NullableName "Nullable`1" -#define g_ByReferenceName "ByReference`1" #define g_CollectionsEnumerableItfName "System.Collections.IEnumerable" #define g_CollectionsEnumeratorClassName "System.Collections.IEnumerator" diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index cd4995aa32141..cd9b127b8f9af 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -575,9 +575,9 @@ DEFINE_FIELD(NULL, VALUE, Value) DEFINE_CLASS(NULLABLE, System, Nullable`1) -DEFINE_CLASS(BYREFERENCE, System, ByReference`1) +DEFINE_CLASS(BYREFERENCE, System, ByReference) DEFINE_METHOD(BYREFERENCE, CTOR, .ctor, NoSig) -DEFINE_METHOD(BYREFERENCE, GET_VALUE, get_Value, NoSig) +DEFINE_FIELD(BYREFERENCE, VALUE, Value) DEFINE_CLASS(SPAN, System, Span`1) DEFINE_METHOD(SPAN, CTOR_PTR_INT, .ctor, IM_VoidPtr_Int_RetVoid) DEFINE_METHOD(SPAN, GET_ITEM, get_Item, IM_Int_RetRefT) diff --git a/src/coreclr/vm/interpreter.cpp b/src/coreclr/vm/interpreter.cpp index 0200c71a4887b..5e6d3e9f85cac 100644 --- a/src/coreclr/vm/interpreter.cpp +++ b/src/coreclr/vm/interpreter.cpp @@ -9177,14 +9177,6 @@ void Interpreter::DoCallWork(bool virtualCall, void* thisArg, CORINFO_RESOLVED_T { switch (intrinsicId) { - case NI_System_ByReference_ctor: - DoByReferenceCtor(); - didIntrinsic = true; - break; - case NI_System_ByReference_get_Value: - DoByReferenceValue(); - didIntrinsic = true; - break; #if INTERP_ILSTUBS case NI_System_StubHelpers_GetStubContext: OpStackSet(m_curStackHt, GetStubContext()); @@ -10752,74 +10744,6 @@ void Interpreter::DoGetTypeFromHandle() OpStackTypeSet(ind, InterpreterType(CORINFO_TYPE_CLASS)); } -void Interpreter::DoByReferenceCtor() -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } CONTRACTL_END; - - // Note 'this' is not passed on the operand stack... - _ASSERTE(m_curStackHt > 0); - _ASSERTE(m_callThisArg != NULL); - unsigned valInd = m_curStackHt - 1; - CorInfoType valCit = OpStackTypeGet(valInd).ToCorInfoType(); - -#ifdef _DEBUG - if (valCit != CORINFO_TYPE_BYREF) - { - VerificationError("ByReference.ctor called with non-byref value."); - } -#endif // _DEBUG - -#if INTERP_TRACING - if (s_TraceInterpreterILFlag.val(CLRConfig::INTERNAL_TraceInterpreterIL)) - { - fprintf(GetLogFile(), " ByReference.ctor -- intrinsic\n"); - } -#endif // INTERP_TRACING - - GCX_FORBID(); - void** thisPtr = reinterpret_cast(m_callThisArg); - void* val = OpStackGet(valInd); - *thisPtr = val; - m_curStackHt--; -} - -void Interpreter::DoByReferenceValue() -{ - CONTRACTL { - THROWS; - GC_TRIGGERS; - MODE_COOPERATIVE; - } CONTRACTL_END; - - _ASSERTE(m_curStackHt > 0); - unsigned slot = m_curStackHt - 1; - CorInfoType thisCit = OpStackTypeGet(slot).ToCorInfoType(); - -#ifdef _DEBUG - if (thisCit != CORINFO_TYPE_BYREF) - { - VerificationError("ByReference.get_Value called with non-byref this"); - } -#endif // _DEBUG - -#if INTERP_TRACING - if (s_TraceInterpreterILFlag.val(CLRConfig::INTERNAL_TraceInterpreterIL)) - { - fprintf(GetLogFile(), " ByReference.getValue -- intrinsic\n"); - } -#endif // INTERP_TRACING - - GCX_FORBID(); - void** thisPtr = OpStackGet(slot); - void* value = *thisPtr; - OpStackSet(slot, value); - OpStackTypeSet(slot, InterpreterType(CORINFO_TYPE_BYREF)); -} - void Interpreter::DoSIMDHwAccelerated() { CONTRACTL { diff --git a/src/coreclr/vm/interpreter.h b/src/coreclr/vm/interpreter.h index 7856f97fbeba8..517cb554bd3ed 100644 --- a/src/coreclr/vm/interpreter.h +++ b/src/coreclr/vm/interpreter.h @@ -1774,8 +1774,6 @@ class Interpreter void DoStringLength(); void DoStringGetChar(); void DoGetTypeFromHandle(); - void DoByReferenceCtor(); - void DoByReferenceValue(); void DoSIMDHwAccelerated(); void DoGetIsSupported(); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 84fbd5a279c57..ea91727f15023 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -2067,9 +2067,6 @@ static unsigned ComputeGCLayout(MethodTable * pMT, BYTE* gcPtrs) _ASSERTE(pMT->IsValueType()); - if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) - return MarkGCField(gcPtrs, TYPE_GC_BYREF); - unsigned result = 0; ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) @@ -9214,17 +9211,6 @@ CorInfoType CEEInfo::getFieldTypeInternal (CORINFO_FIELD_HANDLE fieldHnd, TypeHandle clsHnd = TypeHandle(); FieldDesc* field = (FieldDesc*) fieldHnd; CorElementType type = field->GetFieldType(); - - if (type == ELEMENT_TYPE_I) - { - PTR_MethodTable enclosingMethodTable = field->GetApproxEnclosingMethodTable(); - if (enclosingMethodTable->IsByRefLike() && enclosingMethodTable->HasSameTypeDefAs(g_pByReferenceClass)) - { - _ASSERTE(field->GetOffset() == 0); - return CORINFO_TYPE_BYREF; - } - } - if (!CorTypeInfo::IsPrimitiveType(type)) { PCCOR_SIGNATURE sig; diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index c3f40ee29ff65..98c3d6fd0c193 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -2285,12 +2285,6 @@ bool MethodTable::ClassifyEightBytesWithManagedLayout(SystemVStructRegisterPassi numIntroducedFields = GetNumInstanceFieldBytes() / pFieldStart->GetSize(); } - // System types are loaded before others, so ByReference would be loaded before Span or any other type that has a - // ByReference field. ByReference is the first by-ref-like system type to be loaded (see - // SystemDomain::LoadBaseSystemClasses), so if the current method table is marked as by-ref-like and g_pByReferenceClass is - // null, it must be the initial load of ByReference. - bool isThisByReferenceOfT = IsByRefLike() && (g_pByReferenceClass == nullptr || HasSameTypeDefAs(g_pByReferenceClass)); - for (unsigned int fieldIndex = 0; fieldIndex < numIntroducedFields; fieldIndex++) { FieldDesc* pField; @@ -2320,20 +2314,7 @@ bool MethodTable::ClassifyEightBytesWithManagedLayout(SystemVStructRegisterPassi } CorElementType fieldType = pField->GetFieldType(); - - SystemVClassificationType fieldClassificationType; - if (isThisByReferenceOfT) - { - // 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 - _ASSERTE(numIntroducedFields == 1); - _ASSERTE(fieldType == CorElementType::ELEMENT_TYPE_I); - fieldClassificationType = SystemVClassificationTypeIntegerByRef; - } - else - { - fieldClassificationType = CorInfoType2UnixAmd64Classification(fieldType); - } + SystemVClassificationType fieldClassificationType = CorInfoType2UnixAmd64Classification(fieldType); #ifdef _DEBUG LPCUTF8 fieldName; diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 57089d293765c..0bc8773845f4c 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -8803,10 +8803,6 @@ MethodTableBuilder::HandleExplicitLayout( STANDARD_VM_CONTRACT; _ASSERTE(pMT->IsByRefLike()); - // ByReference is an indication for a byref field, treat it as such. - if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) - return MarkTagType(pFieldLayout, TARGET_POINTER_SIZE, byref); - ExplicitClassTrust explicitClassTrust; ExplicitFieldTrust::TrustLevel trust; @@ -9902,9 +9898,6 @@ void MethodTableBuilder::CheckForSystemTypes() if (g_pNullableClass != NULL) { - _ASSERTE(g_pByReferenceClass != NULL); - _ASSERTE(g_pByReferenceClass->IsByRefLike()); - _ASSERTE(g_pNullableClass->IsNullable()); // Pre-compute whether the class is a Nullable so that code:Nullable::IsNullableType is efficient diff --git a/src/coreclr/vm/mlinfo.cpp b/src/coreclr/vm/mlinfo.cpp index 93922dd32665c..2665a46d12f0a 100644 --- a/src/coreclr/vm/mlinfo.cpp +++ b/src/coreclr/vm/mlinfo.cpp @@ -2262,7 +2262,6 @@ MarshalInfo::MarshalInfo(Module* pModule, break; // 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 @@ -2272,7 +2271,6 @@ MarshalInfo::MarshalInfo(Module* pModule, if (m_pMT->HasInstantiation() && !IsFieldScenario() && (!m_pMT->IsBlittable() || (m_pMT->HasSameTypeDefAs(g_pNullableClass) - || m_pMT->HasSameTypeDefAs(g_pByReferenceClass) || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__SPAN)) || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__READONLY_SPAN)) || m_pMT->HasSameTypeDefAs(CoreLibBinder::GetClass(CLASS__VECTOR64T)) diff --git a/src/coreclr/vm/siginfo.cpp b/src/coreclr/vm/siginfo.cpp index 14766c118dac8..a8d18ec63a293 100644 --- a/src/coreclr/vm/siginfo.cpp +++ b/src/coreclr/vm/siginfo.cpp @@ -4950,12 +4950,6 @@ class ByRefPointerOffsetsReporter _ASSERTE(pMT != nullptr); _ASSERTE(pMT->IsByRefLike()); - if (pMT->HasSameTypeDefAs(g_pByReferenceClass)) - { - Report(baseOffset); - return; - } - ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS); for (FieldDesc* pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next()) { diff --git a/src/coreclr/vm/tailcallhelp.cpp b/src/coreclr/vm/tailcallhelp.cpp index caa6cf4e6f64e..522528a0ee3e1 100644 --- a/src/coreclr/vm/tailcallhelp.cpp +++ b/src/coreclr/vm/tailcallhelp.cpp @@ -630,49 +630,28 @@ void TailCallHelp::CreateCallTargetStubSig(const TailCallInfo& info, SigBuilder* #endif // _DEBUG } -// Get TypeHandle for ByReference -static TypeHandle GetByReferenceOfByteType() +static TypeHandle GetByReferenceType() { - TypeHandle byteTH(CoreLibBinder::GetElementType(ELEMENT_TYPE_U1)); - Instantiation byteInst(&byteTH, 1); - TypeHandle th = TypeHandle(CoreLibBinder::GetClass(CLASS__BYREFERENCE)).Instantiate(byteInst); + TypeHandle th = TypeHandle(CoreLibBinder::GetClass(CLASS__BYREFERENCE)); return th; } -// Get MethodDesc* for ByReference::get_Value -static MethodDesc* GetByReferenceOfByteValueGetter() +static FieldDesc* GetByReferenceValueField() { - MethodDesc* getter = CoreLibBinder::GetMethod(METHOD__BYREFERENCE__GET_VALUE); - getter = - MethodDesc::FindOrCreateAssociatedMethodDesc( - getter, - GetByReferenceOfByteType().GetMethodTable(), - false, - Instantiation(), - TRUE); - - return getter; + FieldDesc* pFD = CoreLibBinder::GetField(FIELD__BYREFERENCE__VALUE); + return pFD; } -// Get MethodDesc* for ByReference::.ctor -static MethodDesc* GetByReferenceOfByteCtor() +static MethodDesc* GetByReferenceOfCtor() { - MethodDesc* ctor = CoreLibBinder::GetMethod(METHOD__BYREFERENCE__CTOR); - ctor = - MethodDesc::FindOrCreateAssociatedMethodDesc( - ctor, - GetByReferenceOfByteType().GetMethodTable(), - false, - Instantiation(), - TRUE); - - return ctor; + MethodDesc* pMD = CoreLibBinder::GetMethod(METHOD__BYREFERENCE__CTOR); + return pMD; } void TailCallHelp::EmitLoadTyHnd(ILCodeStream* stream, TypeHandle tyHnd) { if (tyHnd.IsByRef()) - stream->EmitCALL(stream->GetToken(GetByReferenceOfByteValueGetter()), 1, 1); + stream->EmitLDFLD(stream->GetToken(GetByReferenceValueField())); else stream->EmitLDOBJ(stream->GetToken(tyHnd)); } @@ -681,8 +660,8 @@ void TailCallHelp::EmitStoreTyHnd(ILCodeStream* stream, TypeHandle tyHnd) { if (tyHnd.IsByRef()) { - stream->EmitNEWOBJ(stream->GetToken(GetByReferenceOfByteCtor()), 1); - stream->EmitSTOBJ(stream->GetToken(GetByReferenceOfByteType())); + stream->EmitNEWOBJ(stream->GetToken(GetByReferenceOfCtor()), 1); + stream->EmitSTOBJ(stream->GetToken(GetByReferenceType())); } else { diff --git a/src/coreclr/vm/vars.cpp b/src/coreclr/vm/vars.cpp index a796d58ef99a5..d725b6f4c4f06 100644 --- a/src/coreclr/vm/vars.cpp +++ b/src/coreclr/vm/vars.cpp @@ -57,7 +57,6 @@ GPTR_IMPL(MethodTable, g_pStringClass); GPTR_IMPL(MethodTable, g_pArrayClass); GPTR_IMPL(MethodTable, g_pSZArrayHelperClass); GPTR_IMPL(MethodTable, g_pNullableClass); -GPTR_IMPL(MethodTable, g_pByReferenceClass); GPTR_IMPL(MethodTable, g_pExceptionClass); GPTR_IMPL(MethodTable, g_pThreadAbortExceptionClass); GPTR_IMPL(MethodTable, g_pOutOfMemoryExceptionClass); diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index c1de60729ea91..d6f8022940281 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -363,7 +363,6 @@ GPTR_DECL(MethodTable, g_pStringClass); GPTR_DECL(MethodTable, g_pArrayClass); GPTR_DECL(MethodTable, g_pSZArrayHelperClass); GPTR_DECL(MethodTable, g_pNullableClass); -GPTR_DECL(MethodTable, g_pByReferenceClass); GPTR_DECL(MethodTable, g_pExceptionClass); GPTR_DECL(MethodTable, g_pThreadAbortExceptionClass); GPTR_DECL(MethodTable, g_pOutOfMemoryExceptionClass); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj index fabda09091ab6..b8f3b225c7207 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System.Diagnostics.DiagnosticSource.csproj @@ -6,6 +6,8 @@ $(NoWarn);SA1205;CA1845 false true + + 10 Provides Classes that allow you to decouple code logging rich (unserializable) diagnostics/telemetry (e.g. framework) from code that consumes it (e.g. tools) Commonly Used Types: diff --git a/src/libraries/System.Memory/ref/System.Memory.cs b/src/libraries/System.Memory/ref/System.Memory.cs index c96b01b0f7f2f..c2eca9be38bc0 100644 --- a/src/libraries/System.Memory/ref/System.Memory.cs +++ b/src/libraries/System.Memory/ref/System.Memory.cs @@ -530,17 +530,7 @@ public static partial class Utf8Parser public static bool TryParse(System.ReadOnlySpan source, out ulong value, out int bytesConsumed, char standardFormat = '\0') { throw null; } } } -namespace System.Runtime.CompilerServices -{ - // 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; } } - } -} + namespace System.Runtime.InteropServices { public static partial class MemoryMarshal @@ -553,16 +543,16 @@ public static partial class MemoryMarshal public static System.ReadOnlySpan Cast(System.ReadOnlySpan span) where TFrom : struct where TTo : struct { throw null; } public static System.Span Cast(System.Span span) where TFrom : struct where TTo : struct { throw null; } public static System.Memory CreateFromPinnedArray(T[]? array, int start, int length) { throw null; } - public static System.ReadOnlySpan CreateReadOnlySpan([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] ref T reference, int length) { throw null; } + public static System.ReadOnlySpan CreateReadOnlySpan(scoped ref T reference, int length) { throw null; } [System.CLSCompliant(false)] public static unsafe ReadOnlySpan CreateReadOnlySpanFromNullTerminated(byte* value) { throw null; } [System.CLSCompliant(false)] public static unsafe ReadOnlySpan CreateReadOnlySpanFromNullTerminated(char* value) { throw null; } - public static System.Span CreateSpan([System.Runtime.CompilerServices.LifetimeAnnotation(true, false)] ref T reference, int length) { throw null; } + public static System.Span CreateSpan(scoped ref T reference, int length) { throw null; } public static ref T GetArrayDataReference(T[] array) { throw null; } public static ref byte GetArrayDataReference(System.Array array) { throw null; } - public static ref T GetReference([System.Runtime.CompilerServices.LifetimeAnnotation(false, true)] System.ReadOnlySpan span) { throw null; } - public static ref T GetReference([System.Runtime.CompilerServices.LifetimeAnnotation(false, true)] System.Span span) { throw null; } + public static ref T GetReference(System.ReadOnlySpan span) { throw null; } + public static ref T GetReference(System.Span span) { throw null; } public static T Read(System.ReadOnlySpan source) where T : struct { throw null; } public static System.Collections.Generic.IEnumerable ToEnumerable(System.ReadOnlyMemory memory) { throw null; } public static bool TryGetArray(System.ReadOnlyMemory memory, out System.ArraySegment segment) { throw null; } diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index 93eab8cdde985..a079ceb5f11ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -758,7 +758,6 @@ - diff --git a/src/libraries/System.Private.CoreLib/src/System/ByReference.cs b/src/libraries/System.Private.CoreLib/src/System/ByReference.cs index bb58fc3579a45..230a854d6d1f3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ByReference.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ByReference.cs @@ -6,36 +6,14 @@ namespace System { - // ByReference is meant to be used to represent "ref T" fields. It is working - // around lack of first class support for byref fields in C# and IL. The JIT and - // type loader has special handling for it that turns it into a thin wrapper around ref T. + // ByReference is meant to be used to represent a tracked reference in cases where C# + // proves difficult. See use in Reflection. [NonVersionable] - internal readonly ref struct ByReference + internal readonly ref struct ByReference { -#pragma warning disable CA1823, 169 // private field '{blah}' is never used - private readonly IntPtr _value; -#pragma warning restore CA1823, 169 + public readonly ref byte Value; + public ByReference(ref byte value) => Value = ref value; -#pragma warning disable IDE0060 - [Intrinsic] - public ByReference(ref T value) - { - // Implemented as a JIT intrinsic - This default implementation is for - // completeness and to provide a concrete error if called via reflection - // or if intrinsic is missed. - throw new PlatformNotSupportedException(); - } -#pragma warning restore IDE0060 - -#pragma warning disable CA1822 // Mark members as static - public ref T Value - { - // Implemented as a JIT intrinsic - This default implementation is for - // completeness and to provide a concrete error if called via reflection - // or if the intrinsic is missed. - [Intrinsic] - get => throw new PlatformNotSupportedException(); - } -#pragma warning restore CA1822 + public static ByReference Create(ref T p) => new ByReference(ref Unsafe.As(ref p)); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs index cfdbe719b8d79..bb5917a06fd13 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormat.cs @@ -299,7 +299,7 @@ private static string FormatHebrewMonthName(DateTime time, int month, int repeat // The pos should point to a quote character. This method will // append to the result StringBuilder the string enclosed by the quote character. // - internal static int ParseQuoteString(ReadOnlySpan format, int pos, ref ValueStringBuilder result) + internal static int ParseQuoteString(scoped ReadOnlySpan format, int pos, ref ValueStringBuilder result) { // // NOTE : pos will be the index of the quote character in the 'format' string. @@ -444,7 +444,7 @@ private static bool IsUseGenitiveForm(ReadOnlySpan format, int index, int // Actions: Format the DateTime instance using the specified format. // private static void FormatCustomized( - DateTime dateTime, ReadOnlySpan format, DateTimeFormatInfo dtfi, TimeSpan offset, ref ValueStringBuilder result) + DateTime dateTime, scoped ReadOnlySpan format, DateTimeFormatInfo dtfi, TimeSpan offset, ref ValueStringBuilder result) { Calendar cal = dtfi.Calendar; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs index 8695e9b9beac1..f66e5482c36d9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs @@ -300,7 +300,7 @@ private static void WriteDigits(uint value, Span buffer) } /// Format the TimeSpan instance using the specified format. - private static void FormatCustomized(TimeSpan value, ReadOnlySpan format, DateTimeFormatInfo dtfi, ref ValueStringBuilder result) + private static void FormatCustomized(TimeSpan value, scoped ReadOnlySpan format, DateTimeFormatInfo dtfi, ref ValueStringBuilder result) { Debug.Assert(dtfi != null); diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs index 68b2cbc0c2c25..aca4b4f3fec9e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs @@ -23,7 +23,7 @@ namespace System public readonly ref struct ReadOnlySpan { /// A byref or a native ptr. - internal readonly ByReference _reference; + internal readonly ref T _reference; /// The number of elements this ReadOnlySpan contains. private readonly int _length; @@ -41,7 +41,7 @@ public ReadOnlySpan(T[]? array) return; // returns default } - _reference = new ByReference(ref MemoryMarshal.GetArrayDataReference(array)); + _reference = ref MemoryMarshal.GetArrayDataReference(array); _length = array.Length; } @@ -75,7 +75,7 @@ public ReadOnlySpan(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; } @@ -102,7 +102,7 @@ public unsafe ReadOnlySpan(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; } @@ -112,7 +112,7 @@ public unsafe ReadOnlySpan(void* pointer, int length) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal ReadOnlySpan(in T reference) { - _reference = new ByReference(ref Unsafe.AsRef(in reference)); + _reference = ref Unsafe.AsRef(in reference); _length = 1; } @@ -122,7 +122,7 @@ internal ReadOnlySpan(ref T reference, int length) { Debug.Assert(length >= 0); - _reference = new ByReference(ref reference); + _reference = ref reference; _length = length; } @@ -143,7 +143,7 @@ public ref readonly 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 */); } } @@ -261,7 +261,7 @@ public ref readonly 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; } @@ -284,7 +284,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 { @@ -305,7 +305,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; @@ -317,7 +317,7 @@ public bool TryCopyTo(Span destination) /// 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;