//
[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());
[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);
using System.Runtime;
using System.Runtime.CompilerServices;
-using Internal.Runtime.Augments;
+using Internal.Runtime;
using Debug = System.Diagnostics.Debug;
// 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;
// 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);
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++)
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<byte, float>(ref fieldData).GetHashCode();
}
- else if (fieldType.ElementType == Internal.Runtime.EETypeElementType.Double)
+ else if (fieldType->ElementType == EETypeElementType.Double)
{
hashCode = Unsafe.As<byte, double>(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
namespace Internal.IL.Stubs
{
/// <summary>
- /// 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.
/// </summary>
{
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,
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();
// 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));