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 86f1f7d235609a..7a36f5df28bc42 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
@@ -491,7 +491,7 @@ internal unsafe struct MethodTable
private const uint enum_flag_NonTrivialInterfaceCast = 0x00080000 // enum_flag_Category_Array
| 0x40000000 // enum_flag_ComObject
| 0x00400000 // enum_flag_ICastable;
- | 0x00200000 // enum_flag_IDynamicInterfaceCastable;
+ | 0x10000000 // enum_flag_IDynamicInterfaceCastable;
| 0x00040000; // enum_flag_Category_ValueType
private const int DebugClassNamePtr = // adjust for debug_m_szClassName
diff --git a/src/coreclr/gc/env/gcenv.object.h b/src/coreclr/gc/env/gcenv.object.h
index d04445ea36037c..ff0dbb343ed1dd 100644
--- a/src/coreclr/gc/env/gcenv.object.h
+++ b/src/coreclr/gc/env/gcenv.object.h
@@ -4,6 +4,10 @@
#ifndef __GCENV_OBJECT_H__
#define __GCENV_OBJECT_H__
+#ifdef BUILD_AS_STANDALONE
+extern bool g_oldMethodTableFlags;
+#endif
+
// ARM requires that 64-bit primitive types are aligned at 64-bit boundaries for interlocked-like operations.
// Additionally the platform ABI requires these types and composite type containing them to be similarly
// aligned when passed as arguments.
@@ -42,15 +46,15 @@ class ObjHeader
static_assert(sizeof(ObjHeader) == sizeof(uintptr_t), "this assumption is made by the VM!");
-#define MTFlag_RequireAlign8 0x00001000
-#define MTFlag_Category_ValueType 0x00040000
-#define MTFlag_Category_ValueType_Mask 0x000C0000
-#define MTFlag_ContainsPointers 0x01000000
-#define MTFlag_HasCriticalFinalizer 0x08000000
-#define MTFlag_HasFinalizer 0x00100000
-#define MTFlag_IsArray 0x00080000
-#define MTFlag_Collectible 0x10000000
-#define MTFlag_HasComponentSize 0x80000000
+#define MTFlag_RequiresAlign8 0x00001000 // enum_flag_RequiresAlign8
+#define MTFlag_Category_ValueType 0x00040000 // enum_flag_Category_ValueType
+#define MTFlag_Category_ValueType_Mask 0x000C0000 // enum_flag_Category_ValueType_Mask
+#define MTFlag_ContainsPointers 0x01000000 // enum_flag_ContainsPointers
+#define MTFlag_HasCriticalFinalizer 0x00000002 // enum_flag_HasCriticalFinalizer
+#define MTFlag_HasFinalizer 0x00100000 // enum_flag_HasFinalizer
+#define MTFlag_IsArray 0x00080000 // enum_flag_Category_Array
+#define MTFlag_Collectible 0x00200000 // enum_flag_Collectible
+#define MTFlag_HasComponentSize 0x80000000 // enum_flag_HasComponentSize
class MethodTable
{
@@ -85,6 +89,14 @@ class MethodTable
bool Collectible()
{
+#ifdef BUILD_AS_STANDALONE
+ if (g_oldMethodTableFlags)
+ {
+ // This flag is used for .NET 8 or below
+ const int Old_MTFlag_Collectible = 0x10000000;
+ return (m_flags & Old_MTFlag_Collectible) != 0;
+ }
+#endif
return (m_flags & MTFlag_Collectible) != 0;
}
@@ -100,7 +112,7 @@ class MethodTable
bool RequiresAlign8()
{
- return (m_flags & MTFlag_RequireAlign8) != 0;
+ return (m_flags & MTFlag_RequiresAlign8) != 0;
}
bool IsValueType()
@@ -127,18 +139,15 @@ class MethodTable
bool HasCriticalFinalizer()
{
- return (m_flags & MTFlag_HasCriticalFinalizer) != 0;
- }
-
- bool IsArray()
- {
- return (m_flags & MTFlag_IsArray) != 0;
- }
-
- MethodTable * GetParent()
- {
- _ASSERTE(!IsArray());
- return m_pRelatedType;
+#ifdef BUILD_AS_STANDALONE
+ if (g_oldMethodTableFlags)
+ {
+ // This flag is used for .NET 8 or below
+ const int Old_MTFlag_HasCriticalFinalizer = 0x08000000;
+ return (m_flags & Old_MTFlag_HasCriticalFinalizer) != 0;
+ }
+#endif
+ return !HasComponentSize() && (m_flags & MTFlag_HasCriticalFinalizer);
}
bool SanityCheck()
diff --git a/src/coreclr/gc/gccommon.cpp b/src/coreclr/gc/gccommon.cpp
index 413075246fd5c4..2986ce4c2105d4 100644
--- a/src/coreclr/gc/gccommon.cpp
+++ b/src/coreclr/gc/gccommon.cpp
@@ -19,6 +19,7 @@ IGCHandleManager* g_theGCHandleManager;
#ifdef BUILD_AS_STANDALONE
IGCToCLR* g_theGCToCLR;
VersionInfo g_runtimeSupportedVersion;
+bool g_oldMethodTableFlags;
#endif // BUILD_AS_STANDALONE
#ifdef GC_CONFIG_DRIVEN
diff --git a/src/coreclr/gc/gcenv.ee.standalone.inl b/src/coreclr/gc/gcenv.ee.standalone.inl
index 24ca20f5837bda..1751e069c3e43a 100644
--- a/src/coreclr/gc/gcenv.ee.standalone.inl
+++ b/src/coreclr/gc/gcenv.ee.standalone.inl
@@ -14,6 +14,9 @@ extern IGCToCLR* g_theGCToCLR;
// GC version that the current runtime supports
extern VersionInfo g_runtimeSupportedVersion;
+// Does the runtime use the old method table flags
+extern bool g_oldMethodTableFlags;
+
struct StressLogMsg;
// When we are building the GC in a standalone environment, we
diff --git a/src/coreclr/gc/gcinterface.h b/src/coreclr/gc/gcinterface.h
index e992082b78ff68..3cf40f920ec9b9 100644
--- a/src/coreclr/gc/gcinterface.h
+++ b/src/coreclr/gc/gcinterface.h
@@ -15,7 +15,7 @@
// The major version of the IGCToCLR interface. Breaking changes to this interface
// require bumps in the major version number.
-#define EE_INTERFACE_MAJOR_VERSION 1
+#define EE_INTERFACE_MAJOR_VERSION 2
struct ScanContext;
struct gc_alloc_context;
diff --git a/src/coreclr/gc/gcload.cpp b/src/coreclr/gc/gcload.cpp
index 48c1715020d834..05f297f2cb0ea2 100644
--- a/src/coreclr/gc/gcload.cpp
+++ b/src/coreclr/gc/gcload.cpp
@@ -51,6 +51,7 @@ GC_VersionInfo(/* InOut */ VersionInfo* info)
// For example, GC would only call functions on g_theGCToCLR interface that the runtime
// supports.
g_runtimeSupportedVersion = *info;
+ g_oldMethodTableFlags = g_runtimeSupportedVersion.MajorVersion < 2;
#endif
info->MajorVersion = GC_INTERFACE_MAJOR_VERSION;
info->MinorVersion = GC_INTERFACE_MINOR_VERSION;
diff --git a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp
index 0519a3098d2458..b01339f812031f 100644
--- a/src/coreclr/nativeaot/Runtime/DebugHeader.cpp
+++ b/src/coreclr/nativeaot/Runtime/DebugHeader.cpp
@@ -77,7 +77,7 @@ struct DotNetRuntimeDebugHeader
// This counter can be incremented to indicate breaking changes
// This field must be encoded little endian, regardless of the typical endianness of
// the machine
- const uint16_t MajorVersion = 3;
+ const uint16_t MajorVersion = 4;
// This counter can be incremented to indicate back-compatible changes
// This field must be encoded little endian, regardless of the typical endianness of
@@ -269,7 +269,7 @@ extern "C" void PopulateDebugHeaders()
static_assert(MethodTable::Flags::EETypeKindMask == 0x00030000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Flags::HasFinalizerFlag == 0x00100000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
- static_assert(MethodTable::Flags::HasPointersFlag == 0x00200000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
+ static_assert(MethodTable::Flags::HasPointersFlag == 0x01000000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Flags::GenericVarianceFlag == 0x00800000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Flags::IsGenericFlag == 0x02000000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
static_assert(MethodTable::Flags::ElementTypeMask == 0x7C000000, "The debugging data contract has a hard coded dependency on this value of MethodTable::Flags. If you change this value you must bump major_version_number.");
diff --git a/src/coreclr/nativeaot/Runtime/inc/MethodTable.h b/src/coreclr/nativeaot/Runtime/inc/MethodTable.h
index e77f656f45675d..559f9e3b59036b 100644
--- a/src/coreclr/nativeaot/Runtime/inc/MethodTable.h
+++ b/src/coreclr/nativeaot/Runtime/inc/MethodTable.h
@@ -131,23 +131,24 @@ class MethodTable
// simplified version of MethodTable. See LimitedEEType definition below.
EETypeKindMask = 0x00030000,
- // Unused = 0x00040000,
+ // This type has optional fields present.
+ OptionalFieldsFlag = 0x00040000,
+
+ // GC depends on this bit, this bit must be zero
+ CollectibleFlag = 0x00200000,
IsDynamicTypeFlag = 0x00080000,
- // This MethodTable represents a type which requires finalization
+ // GC depends on this bit, this type requires finalization
HasFinalizerFlag = 0x00100000,
- // This type contain gc pointers
- HasPointersFlag = 0x00200000,
+ // GC depends on this bit, this type contain gc pointers
+ HasPointersFlag = 0x01000000,
// This type is generic and one or more of it's type parameters is co- or contra-variant. This only
// applies to interface and delegate types.
GenericVarianceFlag = 0x00800000,
- // This type has optional fields present.
- OptionalFieldsFlag = 0x01000000,
-
// This type is generic.
IsGenericFlag = 0x02000000,
@@ -162,6 +163,7 @@ class MethodTable
enum ExtendedFlags
{
HasEagerFinalizerFlag = 0x0001,
+ // GC depends on this bit, this type has a critical finalizer
HasCriticalFinalizerFlag = 0x0002,
IsTrackedReferenceWithFinalizerFlag = 0x0004,
};
diff --git a/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs b/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs
index b528195d066b62..4e0d70ab324715 100644
--- a/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs
+++ b/src/coreclr/tools/Common/Internal/Runtime/MethodTable.Constants.cs
@@ -32,9 +32,9 @@ internal enum EETypeFlags : uint
HasFinalizerFlag = 0x00100000,
///
- /// This type contain GC pointers.
+ /// This type has optional fields present.
///
- HasPointersFlag = 0x00200000,
+ OptionalFieldsFlag = 0x00200000,
///
/// This MethodTable has sealed vtable entries
@@ -48,9 +48,9 @@ internal enum EETypeFlags : uint
GenericVarianceFlag = 0x00800000,
///
- /// This type has optional fields present.
+ /// This type contain GC pointers.
///
- OptionalFieldsFlag = 0x01000000,
+ HasPointersFlag = 0x01000000,
///
/// This type is generic.
diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h
index 69f16bec6ebdd4..8a718cc159ceaa 100644
--- a/src/coreclr/vm/methodtable.h
+++ b/src/coreclr/vm/methodtable.h
@@ -2246,6 +2246,7 @@ class MethodTable
void SetHasCriticalFinalizer()
{
LIMITED_METHOD_CONTRACT;
+ _ASSERTE(!HasComponentSize());
SetFlag(enum_flag_HasCriticalFinalizer);
}
// Does this class have non-trivial finalization requirements?
@@ -2259,7 +2260,7 @@ class MethodTable
DWORD HasCriticalFinalizer() const
{
LIMITED_METHOD_CONTRACT;
- return GetFlag(enum_flag_HasCriticalFinalizer);
+ return !HasComponentSize() && GetFlag(enum_flag_HasCriticalFinalizer);
}
//-------------------------------------------------------------------
@@ -3291,15 +3292,15 @@ public :
// apply to Strings / Arrays.
enum_flag_UNUSED_ComponentSize_1 = 0x00000001,
-
- enum_flag_StaticsMask = 0x00000006,
+ // GC depends on this bit
+ enum_flag_HasCriticalFinalizer = 0x00000002, // finalizer must be run on Appdomain Unload
+ enum_flag_StaticsMask = 0x0000000C,
enum_flag_StaticsMask_NonDynamic = 0x00000000,
- enum_flag_StaticsMask_Dynamic = 0x00000002, // dynamic statics (EnC, reflection.emit)
+ enum_flag_StaticsMask_Dynamic = 0x00000008, // dynamic statics (EnC, reflection.emit)
enum_flag_StaticsMask_Generics = 0x00000004, // generics statics
- enum_flag_StaticsMask_CrossModuleGenerics = 0x00000006, // cross module generics statics (NGen)
- enum_flag_StaticsMask_IfGenericsThenCrossModule = 0x00000002, // helper constant to get rid of unnecessary check
+ enum_flag_StaticsMask_CrossModuleGenerics = 0x0000000C, // cross module generics statics (NGen)
+ enum_flag_StaticsMask_IfGenericsThenCrossModule = 0x00000008, // helper constant to get rid of unnecessary check
- enum_flag_NotInPZM = 0x00000008, // True if this type is not in its PreferredZapModule
enum_flag_GenericsMask = 0x00000030,
enum_flag_GenericsMask_NonGeneric = 0x00000000, // no instantiation
@@ -3328,9 +3329,10 @@ public :
enum_flag_IsByRefLike = 0x00001000,
+ enum_flag_NotInPZM = 0x00002000, // True if this type is not in its PreferredZapModule
+
// In a perfect world we would fill these flags using other flags that we already have
// which have a constant value for something which has a component size.
- enum_flag_UNUSED_ComponentSize_5 = 0x00002000,
enum_flag_UNUSED_ComponentSize_6 = 0x00004000,
enum_flag_UNUSED_ComponentSize_7 = 0x00008000,
@@ -3342,7 +3344,8 @@ public :
// As you change the flags in WFLAGS_LOW_ENUM you also need to change this
// to be up to date to reflect the default values of those flags for the
// case where this MethodTable is for a String or Array
- enum_flag_StringArrayValues = SET_TRUE(enum_flag_StaticsMask_NonDynamic) |
+ enum_flag_StringArrayValues = SET_FALSE(enum_flag_HasCriticalFinalizer) |
+ SET_TRUE(enum_flag_StaticsMask_NonDynamic) |
SET_FALSE(enum_flag_NotInPZM) |
SET_TRUE(enum_flag_GenericsMask_NonGeneric) |
SET_FALSE(enum_flag_HasVariance) |
@@ -3387,9 +3390,10 @@ public :
enum_flag_Category_ElementTypeMask = 0x000E0000, // bits that matter for element type mask
+ // GC depends on this bit
enum_flag_HasFinalizer = 0x00100000, // instances require finalization
- enum_flag_IDynamicInterfaceCastable = 0x00200000, // class implements IDynamicInterfaceCastable interface
+ enum_flag_IDynamicInterfaceCastable = 0x10000000, // class implements IDynamicInterfaceCastable interface
enum_flag_ICastable = 0x00400000, // class implements ICastable interface
@@ -3401,8 +3405,8 @@ public :
enum_flag_IsTrackedReferenceWithFinalizer = 0x04000000,
- enum_flag_HasCriticalFinalizer = 0x08000000, // finalizer must be run on Appdomain Unload
- enum_flag_Collectible = 0x10000000,
+ // GC depends on this bit
+ enum_flag_Collectible = 0x00200000,
enum_flag_ContainsGenericVariables = 0x20000000, // we cache this flag to help detect these efficiently and
// to detect this condition when restoring