diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs index 88e07e8d388ce..229d65dabfebe 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs @@ -436,16 +436,8 @@ internal static unsafe bool ObjectHasComponentSize(object obj) // // GC.KeepAlive(o); // - [MethodImpl(MethodImplOptions.AggressiveInlining)] [Intrinsic] - internal static unsafe MethodTable* GetMethodTable(object obj) - { - // The body of this function will be replaced by the EE with unsafe code - // See getILIntrinsicImplementationForRuntimeHelpers for how this happens. - - return (MethodTable*)Unsafe.Add(ref Unsafe.As(ref obj.GetRawData()), -1); - } - + internal static unsafe MethodTable* GetMethodTable(object obj) => GetMethodTable(obj); [LibraryImport(QCall, EntryPoint = "MethodTable_AreTypesEquivalent")] [return: MarshalAs(UnmanagedType.Bool)] diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 5105ed16a790e..e0fc0e0dbacc7 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -3561,6 +3561,12 @@ GenTree* Compiler::impIntrinsic(CORINFO_CLASS_HANDLE clsHnd, break; } + case NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable: + { + retNode = gtNewMethodTableLookup(impPopStack().val); + break; + } + case NI_System_Runtime_InteropService_MemoryMarshal_GetArrayDataReference: { assert(sig->numArgs == 1); @@ -10410,6 +10416,10 @@ NamedIntrinsic Compiler::lookupNamedIntrinsic(CORINFO_METHOD_HANDLE method) result = NI_System_Runtime_CompilerServices_RuntimeHelpers_IsReferenceOrContainsReferences; } + else if (strcmp(methodName, "GetMethodTable") == 0) + { + result = NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable; + } } else if (strcmp(className, "Unsafe") == 0) { diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index e6c26bb31ec7b..54d4d954abf68 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -114,6 +114,7 @@ enum NamedIntrinsic : unsigned short NI_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray, NI_System_Runtime_CompilerServices_RuntimeHelpers_IsKnownConstant, NI_System_Runtime_CompilerServices_RuntimeHelpers_IsReferenceOrContainsReferences, + NI_System_Runtime_CompilerServices_RuntimeHelpers_GetMethodTable, NI_System_Runtime_InteropService_MemoryMarshal_GetArrayDataReference, diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs index 8da99ebcef655..11025b83e0f70 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.NativeAot.cs @@ -216,8 +216,8 @@ internal static unsafe ushort GetElementSize(this Array array) return array.GetMethodTable()->ComponentSize; } - internal static unsafe MethodTable* GetMethodTable(this object obj) - => obj.m_pEEType; + [Intrinsic] + internal static unsafe MethodTable* GetMethodTable(this object obj) => obj.GetMethodTable(); internal static unsafe ref MethodTable* GetMethodTableRef(this object obj) => ref obj.m_pEEType; diff --git a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/RuntimeHelpersIntrinsics.cs b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/RuntimeHelpersIntrinsics.cs index c0318b02959dc..ebfdf6308fefd 100644 --- a/src/coreclr/tools/Common/TypeSystem/IL/Stubs/RuntimeHelpersIntrinsics.cs +++ b/src/coreclr/tools/Common/TypeSystem/IL/Stubs/RuntimeHelpersIntrinsics.cs @@ -19,19 +19,6 @@ public static MethodIL EmitIL(MethodDesc method) Debug.Assert(((MetadataType)method.OwningType).Name == "RuntimeHelpers"); string methodName = method.Name; - if (methodName == "GetMethodTable") - { - ILEmitter emit = new ILEmitter(); - ILCodeStream codeStream = emit.NewCodeStream(); - codeStream.EmitLdArg(0); - codeStream.Emit(ILOpcode.ldflda, emit.NewToken(method.Context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "RawData").GetField("Data"))); - codeStream.EmitLdc(-method.Context.Target.PointerSize); - codeStream.Emit(ILOpcode.add); - codeStream.Emit(ILOpcode.ldind_i); - codeStream.Emit(ILOpcode.ret); - return emit.Link(method); - } - // All the methods handled below are per-instantiation generic methods if (method.Instantiation.Length != 1 || method.IsTypicalMethodDefinition) return null; diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index 0adc92baf3927..09d887b80a2b5 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -632,7 +632,6 @@ DEFINE_METHOD(RTFIELD, GET_FIELDHANDLE, GetFieldHandle, DEFINE_CLASS(RUNTIME_HELPERS, CompilerServices, RuntimeHelpers) DEFINE_METHOD(RUNTIME_HELPERS, IS_BITWISE_EQUATABLE, IsBitwiseEquatable, NoSig) -DEFINE_METHOD(RUNTIME_HELPERS, GET_METHOD_TABLE, GetMethodTable, NoSig) DEFINE_METHOD(RUNTIME_HELPERS, GET_RAW_DATA, GetRawData, NoSig) DEFINE_METHOD(RUNTIME_HELPERS, GET_UNINITIALIZED_OBJECT, GetUninitializedObject, SM_Type_RetObj) DEFINE_METHOD(RUNTIME_HELPERS, ENUM_EQUALS, EnumEquals, NoSig) diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 9c76cf0e7b08b..11257b5c49623 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -7332,43 +7332,6 @@ bool getILIntrinsicImplementationForRuntimeHelpers(MethodDesc * ftn, return true; } - if (tk == CoreLibBinder::GetMethod(METHOD__RUNTIME_HELPERS__GET_METHOD_TABLE)->GetMemberDef()) - { - mdToken tokRawData = CoreLibBinder::GetField(FIELD__RAW_DATA__DATA)->GetMemberDef(); - - // In the CLR, an object is laid out as follows. - // [ object_header || MethodTable* (64-bit pointer) || instance_data ] - // ^ ^-- ref .firstField points here - // `-- reference (type O) points here - // - // So essentially what we want to do is to turn an object reference (type O) into a - // native int&, then dereference it to get the MethodTable*. (Essentially, an object - // reference is a MethodTable**.) Per ECMA-335, Sec. III.1.5, we can add - // (but not subtract) a & and an int32 to produce a &. So we'll get a reference to - // .firstField (type &), then back up one pointer length to get a value of - // essentially type (MethodTable*)&. Both of these are legal GC-trackable references - // to , regardless of 's actual length. - - static BYTE ilcode[] = { CEE_LDARG_0, // stack contains [ O ] = - CEE_LDFLDA,0,0,0,0, // stack contains [ & ] = ref .firstField - CEE_LDC_I4_S,(BYTE)(-TARGET_POINTER_SIZE), // stack contains [ &, int32 ] = -IntPtr.Size - CEE_ADD, // stack contains [ & ] = ref .methodTablePtr - CEE_LDIND_I, // stack contains [ native int ] = .methodTablePtr - CEE_RET }; - - ilcode[2] = (BYTE)(tokRawData); - ilcode[3] = (BYTE)(tokRawData >> 8); - ilcode[4] = (BYTE)(tokRawData >> 16); - ilcode[5] = (BYTE)(tokRawData >> 24); - - methInfo->ILCode = const_cast(ilcode); - methInfo->ILCodeSize = sizeof(ilcode); - methInfo->maxStack = 2; - methInfo->EHcount = 0; - methInfo->options = (CorInfoOptions)0; - return true; - } - if (tk == CoreLibBinder::GetMethod(METHOD__RUNTIME_HELPERS__ENUM_EQUALS)->GetMemberDef()) { // Normally we would follow the above pattern and unconditionally replace the IL,