ronantakizawa/codereview-bench huggingface dataset:
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
    void SystemJS_ExecuteFinalizationCallback()
    {
        CONTRACTL
        {
            NOTHROW;
            GC_TRIGGERS;
            ENTRY_POINT;  // This is called by a host.
        }
        CONTRACTL_END;

        HRESULT hr=S_OK;

        BEGIN_EXTERNAL_ENTRYPOINT(&hr);
        
        EX_TRY
        {
            GCX_COOP();
            FinalizerThread::FinalizerThreadWorkerRound();
        }
        EX_HOOK
        {
            Exception *ex = GET_EXCEPTION();
            SString err;
            ex->GetMessage(err);
            LogErrorToHost("Error message: %s", err.GetUTF8());
            abort();
        }
        EX_END_HOOK;
        
        END_EXTERNAL_ENTRYPOINT;
    }
}

#endif // !TARGET_WASM

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
    SystemJS_ScheduleFinalization();
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.

Review comment (suggestion):
I don't think calling `abort()` here is what we want. See `FinalizerThread::FinalizerThreadStart` where we will continue to loop.

Code after:
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_BROWSER

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
#ifdef TARGET_BROWSER
    SystemJS_ScheduleFinalization();
#else
    // WASI is not implemented yet
#endif // TARGET_BROWSER
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.
    VolatilePtr<LCGMethodResolver> s_delayDestroyDynamicMethod = nullptr;

    bool HasDelayedDynamicMethod()
    {
        LIMITED_METHOD_CONTRACT;
        return s_delayDestroyDynamicMethod != nullptr;
    }

    void AddDelayedDynamicMethod(DynamicMethodDesc* pDMD)
    {
        STANDARD_VM_CONTRACT;
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
    }
}

static bool s_FinalizerThreadOK = false;
static bool s_InitializedFinalizerThreadForPlatform = false;
static bool s_PriorityBoosted = false;

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    while (!fQuitFinalizer)
    {
        FinalizerThread::FinalizerThreadWorkerIteration();
    }

    if (s_InitializedFinalizerThreadForPlatform)
        Thread::CleanUpForManagedThreadInNative(GetFinalizerThread());
}

VOID FinalizerThread::FinalizerThreadWorkerIteration()
{
    GetFinalizerThread()->EnablePreemptiveGC();
#ifndef TARGET_WASM
    // Wait for work to do...

#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
    }
#endif
#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = TRUE;
    }
#endif
#if 0
    // Setting the event here, instead of at the bottom of the loop, could
    // cause us to skip draining the Q, if the request is made as soon as
    // the app starts running.
    SignalFinalizationDone();
#endif //0

    WaitForFinalizerEvent (hEventFinalizer);

    // Process pending finalizer work items from the GC first.
    FinalizerWorkItem* pWork = GCHeapUtilities::GetGCHeap()->GetExtraWorkForFinalization();
    while (pWork != NULL)
    {
        FinalizerWorkItem* pNext = pWork->next;
        pWork->callback(pWork);

Review comment (suggestion):
These `GetFinalizerThread()->m_GCOnTransitionsOK = FALSE/TRUE` should be moved up as well. It is important that the call to `EnablePreemptiveGC` is enclosed by these calls - it is a perf optimization for GC stress.

Code after:
        THROWS;
        GC_TRIGGERS;
        MODE_COOPERATIVE;
    }
    CONTRACTL_END;

    while (!fQuitFinalizer)
    {
        FinalizerThread::FinalizerThreadWorkerIteration(nullptr);
    }

    if (s_InitializedFinalizerThreadForPlatform)
        Thread::CleanUpForManagedThreadInNative(GetFinalizerThread());
}

VOID FinalizerThread::FinalizerThreadWorkerIteration(void *args)
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_COOPERATIVE;
    }
    CONTRACTL_END;

#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
    }
#endif
    GetFinalizerThread()->EnablePreemptiveGC();
#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = TRUE;
    }
#endif

#ifndef TARGET_WASM
#if 0
    // Setting the event here, instead of at the bottom of the loop, could
    // cause us to skip draining the Q, if the request is made as soon as
    // the app starts running.
    SignalFinalizationDone();
#endif //0

    // Wait for work to do...
    WaitForFinalizerEvent (hEventFinalizer);

#endif // !TARGET_WASM
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:

CLREvent * FinalizerThread::hEventFinalizer = NULL;
CLREvent * FinalizerThread::hEventFinalizerDone = NULL;
CLREvent * FinalizerThread::hEventFinalizerToShutDown = NULL;

HANDLE FinalizerThread::MHandles[kHandleCount];

bool FinalizerThread::IsCurrentThreadFinalizer()
{
    LIMITED_METHOD_CONTRACT;

    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_WASM

extern "C" void SystemJS_ScheduleFinalization();
extern "C"
{
    void SystemJS_ExecuteFinalizationCallback()
    {
        CONTRACTL
        {
            NOTHROW;
            GC_TRIGGERS;
            MODE_COOPERATIVE;
        }
        CONTRACTL_END;

        HRESULT hr=S_OK;

        BEGIN_EXTERNAL_ENTRYPOINT(&hr);
        
        INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
        {
            GCX_COOP();
            ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
        }
        UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
        
        END_EXTERNAL_ENTRYPOINT;
    }
}

#endif // !TARGET_WASM

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM

Review comment (suggestion):
On TARGET_WASM this callback is invoked from JS as an external entrypoint, but the contract specifies MODE_COOPERATIVE. This can trip GC-mode asserts because the thread is typically in preemptive mode on entry (and you explicitly switch modes with GCX_COOP()). Consider using ENTRY_POINT or MODE_PREEMPTIVE (consistent with other BEGIN_EXTERNAL_ENTRYPOINT callers) and only assert cooperative after the GCX_COOP scope begins.
```suggestion
            MODE_PREEMPTIVE;
```

Code after:

CLREvent * FinalizerThread::hEventFinalizer = NULL;
CLREvent * FinalizerThread::hEventFinalizerDone = NULL;
CLREvent * FinalizerThread::hEventFinalizerToShutDown = NULL;

HANDLE FinalizerThread::MHandles[kHandleCount];

bool FinalizerThread::IsCurrentThreadFinalizer()
{
    LIMITED_METHOD_CONTRACT;

    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_BROWSER

extern "C" void SystemJS_ScheduleFinalization();

extern "C" void SystemJS_ExecuteFinalizationCallback()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_BROWSER

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
#ifdef TARGET_BROWSER
    SystemJS_ScheduleFinalization();
#else
    // WASI is not implemented yet
#endif // TARGET_BROWSER
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
    void SystemJS_ExecuteFinalizationCallback()
    {
        CONTRACTL
        {
            NOTHROW;
            GC_TRIGGERS;
            MODE_COOPERATIVE;
        }
        CONTRACTL_END;

        HRESULT hr=S_OK;

        BEGIN_EXTERNAL_ENTRYPOINT(&hr);
        
        INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
        {
            GCX_COOP();
            ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
        }
        UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
        
        END_EXTERNAL_ENTRYPOINT;
    }
}

#endif // !TARGET_WASM

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
    SystemJS_ScheduleFinalization();
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.
    VolatilePtr<LCGMethodResolver> s_delayDestroyDynamicMethod = nullptr;

    bool HasDelayedDynamicMethod()
    {
        LIMITED_METHOD_CONTRACT;
        return s_delayDestroyDynamicMethod != nullptr;
    }


Review comment (suggestion):
The closing comment on this conditional is inverted: this is `#ifdef TARGET_WASM`, so the `#endif` comment should reference TARGET_WASM (not `!TARGET_WASM`) to avoid confusion during future maintenance.

Code after:
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_BROWSER

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
#ifdef TARGET_BROWSER
    SystemJS_ScheduleFinalization();
#else
    // WASI is not implemented yet
#endif // TARGET_BROWSER
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.
    VolatilePtr<LCGMethodResolver> s_delayDestroyDynamicMethod = nullptr;

    bool HasDelayedDynamicMethod()
    {
        LIMITED_METHOD_CONTRACT;
        return s_delayDestroyDynamicMethod != nullptr;
    }

    void AddDelayedDynamicMethod(DynamicMethodDesc* pDMD)
    {
        STANDARD_VM_CONTRACT;
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_WASM

extern "C" void SystemJS_ScheduleFinalization();
extern "C"
{
    void SystemJS_ExecuteFinalizationCallback()
    {
        CONTRACTL
        {
            NOTHROW;
            GC_TRIGGERS;
            MODE_PREEMPTIVE;
        }
        CONTRACTL_END;

        INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
        {
            GCX_COOP();
            ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
        }
        UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    }
}

#endif // TARGET_WASM

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
    SystemJS_ScheduleFinalization();
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.
    VolatilePtr<LCGMethodResolver> s_delayDestroyDynamicMethod = nullptr;

    bool HasDelayedDynamicMethod()
    {
        LIMITED_METHOD_CONTRACT;
        return s_delayDestroyDynamicMethod != nullptr;

Review comment (suggestion):
```suggestion

extern "C" void SystemJS_ExecuteFinalizationCallback()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}
```
Nit: This is typical style used for `extern "C"` methods in CoreCLR

Code after:
    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_BROWSER

extern "C" void SystemJS_ScheduleFinalization();

extern "C" void SystemJS_ExecuteFinalizationCallback()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_BROWSER

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
#ifdef TARGET_BROWSER
    SystemJS_ScheduleFinalization();
#else
    // WASI is not implemented yet
#endif // TARGET_BROWSER
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.
    VolatilePtr<LCGMethodResolver> s_delayDestroyDynamicMethod = nullptr;

    bool HasDelayedDynamicMethod()
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
{
    LIMITED_METHOD_CONTRACT;

    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_WASM

extern "C" void SystemJS_ScheduleFinalization();

extern "C" void SystemJS_ExecuteFinalizationCallback()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_WASM

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
    SystemJS_ScheduleFinalization();
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.
    VolatilePtr<LCGMethodResolver> s_delayDestroyDynamicMethod = nullptr;

    bool HasDelayedDynamicMethod()
    {

Review comment (suggestion):
On TARGET_WASM, SystemJS_ExecuteFinalizationCallback currently doesn't invoke any finalizer work (the only call is commented out). As-is, EnableFinalization() will schedule this callback but no finalizers will run. This should call into the finalizer loop (e.g., FinalizerThreadWorkerIteration) in a way that's safe for running on the browser event loop, or the scheduling should be removed until the implementation is complete.

Code after:
{
    LIMITED_METHOD_CONTRACT;

    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_BROWSER

extern "C" void SystemJS_ScheduleFinalization();

extern "C" void SystemJS_ExecuteFinalizationCallback()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_BROWSER

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
#ifdef TARGET_BROWSER
    SystemJS_ScheduleFinalization();
#else
    // WASI is not implemented yet
#endif // TARGET_BROWSER
#endif // !TARGET_WASM
}

namespace
{
    // This is a linked list of the LCGMethodResolvers that represent DynamicMethodDescs
    // waiting to be destroyed. The resolvers are used since they can be chained together
    // to avoid allocations when destroying multiple DynamicMethodDescs.
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
#include "minipal/time.h"
#define LINUX_HEAP_DUMP_TIME_OUT 10000

extern bool s_forcedGCInProgress;
int64_t FinalizerThread::LastHeapDumpTime = 0;

Volatile<BOOL> g_TriggerHeapDump = FALSE;
#endif // __linux__

CLREvent * FinalizerThread::hEventFinalizer = NULL;
CLREvent * FinalizerThread::hEventFinalizerDone = NULL;
CLREvent * FinalizerThread::hEventFinalizerToShutDown = NULL;

HANDLE FinalizerThread::MHandles[kHandleCount];

bool FinalizerThread::IsCurrentThreadFinalizer()
{
    LIMITED_METHOD_CONTRACT;

    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_WASM

extern "C" void SystemJS_ScheduleFinalization();

extern "C" void SystemJS_ExecuteFinalizationCallback()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_WASM

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;


Review comment (bug):
This code uses `#ifdef TARGET_WASM` for browser-only JS interop (`SystemJS_ScheduleFinalization`). `TARGET_WASM` also applies to WASI builds, and there is no WASI implementation of `SystemJS_ScheduleFinalization` in the repo, so this is likely to introduce an unresolved symbol / link failure for WASI/CoreCLR. Please gate this with `TARGET_BROWSER` (or equivalent) and keep non-browser wasm targets on the existing finalization path.

Code after:
#include "minipal/time.h"
#define LINUX_HEAP_DUMP_TIME_OUT 10000

extern bool s_forcedGCInProgress;
int64_t FinalizerThread::LastHeapDumpTime = 0;

Volatile<BOOL> g_TriggerHeapDump = FALSE;
#endif // __linux__

CLREvent * FinalizerThread::hEventFinalizer = NULL;
CLREvent * FinalizerThread::hEventFinalizerDone = NULL;
CLREvent * FinalizerThread::hEventFinalizerToShutDown = NULL;

HANDLE FinalizerThread::MHandles[kHandleCount];

bool FinalizerThread::IsCurrentThreadFinalizer()
{
    LIMITED_METHOD_CONTRACT;

    return GetThreadNULLOk() == g_pFinalizerThread;
}

#ifdef TARGET_BROWSER

extern "C" void SystemJS_ScheduleFinalization();

extern "C" void SystemJS_ExecuteFinalizationCallback()
{
    CONTRACTL
    {
        NOTHROW;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    }
    CONTRACTL_END;

    INSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
    {
        GCX_COOP();
        // TODO-WASM https://github.com/dotnet/runtime/issues/123712
        // ManagedThreadBase::KickOff(FinalizerThread::FinalizerThreadWorkerIteration, NULL);
    }
    UNINSTALL_UNHANDLED_MANAGED_EXCEPTION_TRAP;
}

#endif // TARGET_BROWSER

void FinalizerThread::EnableFinalization()
{
    WRAPPER_NO_CONTRACT;
Repository: dotnet/runtime
File: src/coreclr/vm/jitinterface.cpp (C++)

Code before:
    MethodTable* mt = asyncConts->LookupOrCreateContinuationMethodTable((unsigned)dataSize, objRefs, loaderModule);

#ifdef DEBUG
    MethodTable* mt2 = asyncConts->LookupOrCreateContinuationMethodTable((unsigned)dataSize, objRefs, loaderModule);
    _ASSERTE(mt2 == mt);
#endif

    return mt;
}

CORINFO_CLASS_HANDLE CEEInfo::getContinuationType(
    size_t dataSize,
    bool* objRefs,
    size_t objRefsSize)
{
    CONTRACTL {
        THROWS;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    } CONTRACTL_END;

    CORINFO_CLASS_HANDLE result = NULL;

    JIT_TO_EE_TRANSITION();

    result = (CORINFO_CLASS_HANDLE)::getContinuationType(dataSize, objRefs, objRefsSize, m_pMethodBeingCompiled->GetModule());

    EE_TO_JIT_TRANSITION();

    return result;
}

// Return details about EE internal data structures
uint32_t CEEInfo::getThreadTLSIndex(void **ppIndirection)
{
    CONTRACTL {
        THROWS;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    } CONTRACTL_END;

    uint32_t result = (uint32_t)-1;

    if (ppIndirection != NULL)
        *ppIndirection = NULL;

    return result;
}


int32_t * CEEInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection)

Review comment (suggestion):
This needs to be `m_pMethodBeingCompiled->GetLoaderModule()`.

(It would be even better to make it `m_pMethodBeingCompiled->GetLoaderAllocator()` since loader allocator represents the lifetime scope. Unfortunately. it looks like we need loader module for auxiliary data, so that's not trivial to do.)

Code after:
    MethodTable* mt = asyncConts->LookupOrCreateContinuationMethodTable((unsigned)dataSize, objRefs, loaderModule);

#ifdef DEBUG
    MethodTable* mt2 = asyncConts->LookupOrCreateContinuationMethodTable((unsigned)dataSize, objRefs, loaderModule);
    _ASSERTE(mt2 == mt);
#endif

    return mt;
}

CORINFO_CLASS_HANDLE CEEInfo::getContinuationType(
    size_t dataSize,
    bool* objRefs,
    size_t objRefsSize)
{
    CONTRACTL {
        THROWS;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    } CONTRACTL_END;

    CORINFO_CLASS_HANDLE result = NULL;

    JIT_TO_EE_TRANSITION();

    result = (CORINFO_CLASS_HANDLE)::getContinuationType(dataSize, objRefs, objRefsSize, m_pMethodBeingCompiled->GetLoaderModule());

    EE_TO_JIT_TRANSITION();

    return result;
}

// Return details about EE internal data structures
uint32_t CEEInfo::getThreadTLSIndex(void **ppIndirection)
{
    CONTRACTL {
        THROWS;
        GC_TRIGGERS;
        MODE_PREEMPTIVE;
    } CONTRACTL_END;

    uint32_t result = (uint32_t)-1;

    if (ppIndirection != NULL)
        *ppIndirection = NULL;

    return result;
}


int32_t * CEEInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection)