diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index bb203368d6dbb..650d992c5b910 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -344,7 +344,7 @@ internal static unsafe object IsInstanceOfInterface(EETypePtr pTargetType, objec // [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhBoxAny")] - private static extern unsafe object RhBoxAny(ref byte pData, MethodTable* pEEType); + internal static extern unsafe object RhBoxAny(ref byte pData, MethodTable* pEEType); internal static unsafe object RhBoxAny(ref byte pData, EETypePtr pEEType) => RhBoxAny(ref pData, pEEType.ToPointer()); @@ -372,7 +372,7 @@ internal static unsafe string RhNewString(EETypePtr pEEType, int length) [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhBox")] - private static extern unsafe object RhBox(MethodTable* pEEType, ref byte data); + internal static extern unsafe object RhBox(MethodTable* pEEType, ref byte data); internal static unsafe object RhBox(EETypePtr pEEType, ref byte data) => RhBox(pEEType.ToPointer(), ref data); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ValueType.cs index f51c4b333991e..a445c6db621ce 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/ValueType.cs @@ -14,7 +14,7 @@ using System.Runtime; using System.Runtime.CompilerServices; -using Internal.Runtime.Augments; +using Internal.Runtime; using Debug = System.Diagnostics.Debug; @@ -39,15 +39,15 @@ public abstract class ValueType // This API is a bit awkward because we want to avoid burning more than one vtable slot on this. // When index == GetNumFields, this method is expected to return the number of fields of this // valuetype. Otherwise, it returns the offset and type handle of the index-th field on this type. - internal virtual int __GetFieldHelper(int index, out EETypePtr eeType) + internal virtual unsafe int __GetFieldHelper(int index, out MethodTable* mt) { // Value types that don't override this method will use the fast path that looks at bytes, not fields. Debug.Assert(index == GetNumFields); - eeType = default; + mt = default; return UseFastHelper; } - public override bool Equals([NotNullWhen(true)] object? obj) + public override unsafe bool Equals([NotNullWhen(true)] object? obj) { if (obj == null || obj.GetEETypePtr() != this.GetEETypePtr()) return false; @@ -71,7 +71,7 @@ public override bool Equals([NotNullWhen(true)] object? obj) // Foreach field, box and call the Equals method. for (int i = 0; i < numFields; i++) { - int fieldOffset = __GetFieldHelper(i, out EETypePtr fieldType); + int fieldOffset = __GetFieldHelper(i, out MethodTable* fieldType); // Fetch the value of the field on both types object thisField = RuntimeImports.RhBoxAny(ref Unsafe.Add(ref thisRawData, fieldOffset), fieldType); @@ -102,22 +102,22 @@ public override int GetHashCode() return hashCode; } - private int GetHashCodeImpl() + private unsafe int GetHashCodeImpl() { int numFields = __GetFieldHelper(GetNumFields, out _); if (numFields == UseFastHelper) - return FastGetValueTypeHashCodeHelper(this.GetEETypePtr(), ref this.GetRawData()); + return FastGetValueTypeHashCodeHelper(this.GetMethodTable(), ref this.GetRawData()); return RegularGetValueTypeHashCode(ref this.GetRawData(), numFields); } - private static int FastGetValueTypeHashCodeHelper(EETypePtr type, ref byte data) + private static unsafe int FastGetValueTypeHashCodeHelper(MethodTable* type, ref byte data) { // Sanity check - if there are GC references, we should not be hashing bytes - Debug.Assert(!type.HasPointers); + Debug.Assert(!type->HasGCPointers); - int size = (int)type.ValueTypeSize; + int size = (int)type->ValueTypeSize; int hashCode = 0; for (int i = 0; i < size / 4; i++) @@ -128,31 +128,31 @@ private static int FastGetValueTypeHashCodeHelper(EETypePtr type, ref byte data) return hashCode; } - private int RegularGetValueTypeHashCode(ref byte data, int numFields) + private unsafe int RegularGetValueTypeHashCode(ref byte data, int numFields) { int hashCode = 0; // We only take the hashcode for the first non-null field. That's what the CLR does. for (int i = 0; i < numFields; i++) { - int fieldOffset = __GetFieldHelper(i, out EETypePtr fieldType); + int fieldOffset = __GetFieldHelper(i, out MethodTable* fieldType); ref byte fieldData = ref Unsafe.Add(ref data, fieldOffset); - Debug.Assert(!fieldType.IsPointer); + Debug.Assert(!fieldType->IsPointerType); - if (fieldType.ElementType == Internal.Runtime.EETypeElementType.Single) + if (fieldType->ElementType == EETypeElementType.Single) { hashCode = Unsafe.As(ref fieldData).GetHashCode(); } - else if (fieldType.ElementType == Internal.Runtime.EETypeElementType.Double) + else if (fieldType->ElementType == EETypeElementType.Double) { hashCode = Unsafe.As(ref fieldData).GetHashCode(); } - else if (fieldType.IsPrimitive) + else if (fieldType->IsPrimitive) { hashCode = FastGetValueTypeHashCodeHelper(fieldType, ref fieldData); } - else if (fieldType.IsValueType) + else if (fieldType->IsValueType) { // We have no option but to box since this value type could have // GC pointers (we could find out if we want though), or fields of type Double/Single (we can't diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs index 9bb60e317e249..532087549e237 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/ValueTypeGetFieldHelperMethodOverride.cs @@ -8,7 +8,7 @@ namespace Internal.IL.Stubs { /// - /// Synthetic method override of "int ValueType.__GetFieldHelper(Int32, out EETypePtr)". This method is injected + /// Synthetic method override of "int ValueType.__GetFieldHelper(Int32, out MethodTable*)". This method is injected /// into all value types that cannot have their Equals(object) and GetHashCode() methods operate on individual /// bytes. The purpose of the override is to provide access to the value types' fields and their types. /// @@ -46,7 +46,7 @@ public override MethodSignature Signature { TypeSystemContext context = _owningType.Context; TypeDesc int32Type = context.GetWellKnownType(WellKnownType.Int32); - TypeDesc eeTypePtrType = context.SystemModule.GetKnownType("System", "EETypePtr"); + TypeDesc eeTypePtrType = context.SystemModule.GetKnownType("Internal.Runtime", "MethodTable").MakePointerType(); _signature = new MethodSignature(0, 0, int32Type, new[] { int32Type, @@ -64,9 +64,8 @@ public override MethodIL EmitIL() ILEmitter emitter = new ILEmitter(); - TypeDesc eeTypePtrType = Context.SystemModule.GetKnownType("System", "EETypePtr"); - MethodDesc eeTypePtrOfMethod = eeTypePtrType.GetKnownMethod("EETypePtrOf", null); - ILToken eeTypePtrToken = emitter.NewToken(eeTypePtrType); + TypeDesc methodTableType = Context.SystemModule.GetKnownType("Internal.Runtime", "MethodTable"); + MethodDesc methodTableOfMethod = methodTableType.GetKnownMethod("Of", null); var switchStream = emitter.NewCodeStream(); var getFieldStream = emitter.NewCodeStream(); @@ -98,10 +97,10 @@ public override MethodIL EmitIL() // Don't unnecessarily create an MethodTable for the enum. boxableFieldType = boxableFieldType.UnderlyingType; - MethodDesc ptrOfField = eeTypePtrOfMethod.MakeInstantiatedMethod(boxableFieldType); - getFieldStream.Emit(ILOpcode.call, emitter.NewToken(ptrOfField)); + MethodDesc mtOfFieldMethod = methodTableOfMethod.MakeInstantiatedMethod(boxableFieldType); + getFieldStream.Emit(ILOpcode.call, emitter.NewToken(mtOfFieldMethod)); - getFieldStream.Emit(ILOpcode.stobj, eeTypePtrToken); + getFieldStream.Emit(ILOpcode.stind_i); getFieldStream.EmitLdArg(0); getFieldStream.Emit(ILOpcode.ldflda, emitter.NewToken(field));