Skip to content

Commit

Permalink
Convert ReRegisterForFinalize to QCALL (#103211)
Browse files Browse the repository at this point in the history
* Convert ReRegisterForFinalize to QCALL

* Update src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs

---------

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
  • Loading branch information
AustinWise and jkotas authored Jun 10, 2024
1 parent 0b24915 commit e6c2e53
Show file tree
Hide file tree
Showing 6 changed files with 27 additions and 17 deletions.
14 changes: 10 additions & 4 deletions src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs
Original file line number Diff line number Diff line change
Expand Up @@ -328,14 +328,20 @@ public static void SuppressFinalize(object obj)
// for which SuppressFinalize has already been called. The other situation
// where calling ReRegisterForFinalize is useful is inside a finalizer that
// needs to resurrect itself or an object that it references.
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern void _ReRegisterForFinalize(object o);
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "GCInterface_ReRegisterForFinalize")]
private static partial void ReRegisterForFinalize(ObjectHandleOnStack o);

public static void ReRegisterForFinalize(object obj)
public static unsafe void ReRegisterForFinalize(object obj)
{
ArgumentNullException.ThrowIfNull(obj);

_ReRegisterForFinalize(obj);
MethodTable* pMT = RuntimeHelpers.GetMethodTable(obj);
if (pMT->HasFinalizer)
{
ReRegisterForFinalize(ObjectHandleOnStack.Create(ref obj));
}

// GC.KeepAlive(obj) not required. pMT kept alive via ObjectHandleOnStack
}

// Returns the total number of bytes currently in use by live objects in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ internal unsafe struct MethodTable
private const uint enum_flag_ContainsGenericVariables = 0x20000000;
private const uint enum_flag_HasComponentSize = 0x80000000;
private const uint enum_flag_HasTypeEquivalence = 0x02000000;
private const uint enum_flag_HasFinalizer = 0x00100000;
private const uint enum_flag_Category_Mask = 0x000F0000;
private const uint enum_flag_Category_ValueType = 0x00040000;
private const uint enum_flag_Category_Nullable = 0x00050000;
Expand Down Expand Up @@ -614,6 +615,8 @@ internal unsafe struct MethodTable

public bool HasTypeEquivalence => (Flags & enum_flag_HasTypeEquivalence) != 0;

public bool HasFinalizer => (Flags & enum_flag_HasFinalizer) != 0;

internal static bool AreSameType(MethodTable* mt1, MethodTable* mt2) => mt1 == mt2;

public bool HasDefaultConstructor => (Flags & (enum_flag_HasComponentSize | enum_flag_HasDefaultCtor)) == enum_flag_HasDefaultCtor;
Expand Down
22 changes: 11 additions & 11 deletions src/coreclr/vm/comutilnative.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1081,24 +1081,24 @@ FCIMPLEND
**Arguments: Object of interest
**Exceptions: None
==============================================================================*/
FCIMPL1(void, GCInterface::ReRegisterForFinalize, Object *obj)
extern "C" void QCALLTYPE GCInterface_ReRegisterForFinalize(QCall::ObjectHandleOnStack pObj)
{
FCALL_CONTRACT;
QCALL_CONTRACT;

BEGIN_QCALL;

GCX_COOP();

// Checked by the caller
_ASSERTE(obj != NULL);
_ASSERTE(pObj.Get() != NULL);
_ASSERTE(pObj.Get()->GetMethodTable()->HasFinalizer());

if (obj->GetMethodTable()->HasFinalizer())
if (!GCHeapUtilities::GetGCHeap()->RegisterForFinalization(-1, OBJECTREFToObject(pObj.Get())))
{
HELPER_METHOD_FRAME_BEGIN_1(obj);
if (!GCHeapUtilities::GetGCHeap()->RegisterForFinalization(-1, obj))
{
ThrowOutOfMemory();
}
HELPER_METHOD_FRAME_END();
ThrowOutOfMemory();
}
END_QCALL;
}
FCIMPLEND

FORCEINLINE UINT64 GCInterface::InterlockedAdd (UINT64 *pAugend, UINT64 addend) {
WRAPPER_NO_CONTRACT;
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/vm/comutilnative.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ class GCInterface {
static FCDECL0(int, GetMaxGeneration);
static FCDECL1(void, KeepAlive, Object *obj);
static FCDECL1(void, SuppressFinalize, Object *obj);
static FCDECL1(void, ReRegisterForFinalize, Object *obj);
static FCDECL2(int, CollectionCount, INT32 generation, INT32 getSpecialGCCount);

static FCDECL0(INT64, GetAllocatedBytesForCurrentThread);
Expand Down Expand Up @@ -218,6 +217,8 @@ extern "C" void QCALLTYPE GCInterface_AddMemoryPressure(UINT64 bytesAllocated);

extern "C" void QCALLTYPE GCInterface_RemoveMemoryPressure(UINT64 bytesAllocated);

extern "C" void QCALLTYPE GCInterface_ReRegisterForFinalize(QCall::ObjectHandleOnStack pObj);

extern "C" void QCALLTYPE GCInterface_EnumerateConfigurationValues(void* configurationContext, EnumerateConfigurationValuesCallback callback);

extern "C" int QCALLTYPE GCInterface_RefreshMemoryLimit(GCHeapHardLimitInfo heapHardLimitInfo);
Expand Down
1 change: 0 additions & 1 deletion src/coreclr/vm/ecalllist.h
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,6 @@ FCFuncStart(gGCInterfaceFuncs)
FCFuncElement("GetGeneration", GCInterface::GetGeneration)
FCFuncElement("GetMaxGeneration", GCInterface::GetMaxGeneration)
FCFuncElement("_SuppressFinalize", GCInterface::SuppressFinalize)
FCFuncElement("_ReRegisterForFinalize", GCInterface::ReRegisterForFinalize)

FCFuncElement("GetAllocatedBytesForCurrentThread", GCInterface::GetAllocatedBytesForCurrentThread)
FCFuncElement("GetTotalAllocatedBytesApproximate", GCInterface::GetTotalAllocatedBytesApproximate)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/qcallentrypoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,7 @@ static const Entry s_QCall[] =
DllImportEntry(GCInterface_EndNoGCRegion)
DllImportEntry(GCInterface_GetTotalMemory)
DllImportEntry(GCInterface_Collect)
DllImportEntry(GCInterface_ReRegisterForFinalize)
DllImportEntry(GCInterface_WaitForPendingFinalizers)
DllImportEntry(GCInterface_AddMemoryPressure)
DllImportEntry(GCInterface_RemoveMemoryPressure)
Expand Down

0 comments on commit e6c2e53

Please sign in to comment.