ronantakizawa/codereview-bench huggingface dataset:
Repository: dotnet/runtime
File: src/libraries/System.IO.Hashing/src/System/IO/Hashing/Adler32.cs (C#)

Code before:
            => Update(InitialState, source);

        private const uint Base = 65521; // largest prime smaller than 65536
        private const int NMax = 5552;   // NMax is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1

        private static uint Update(uint adler, ReadOnlySpan<byte> buf)
        {
            if (buf.IsEmpty)
            {
                return 1u;
            }

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            while (buf.Length > 0)
            {
                int k = buf.Length < NMax ? buf.Length : NMax;
                for (int i = 0; i < k; i++)
                {
                    s1 += buf[i];
                    s2 += s1;
                }
                s1 %= Base;
                s2 %= Base;
                buf = buf.Slice(k);
            }

            return (s2 << 16) | s1;
        }
    }
}


Review comment (suggestion):
I'd have to check, but I think it's likely this is incurring a bounds check on every buf[i] access. You could avoid that by first slicing and then iterating the slice, e.g.
```csharp
int k = buf.Length < NMax ? buf.Length : NMax;
foreach (byte b in buf.Slice(0, k))
{
    s1 += b;
    s2 += s1;
}
```
cc: @EgorBo 

Code after:

        private static uint Update(uint adler, ReadOnlySpan<byte> buf)
        {
            if (buf.IsEmpty)
            {
                return adler;
            }

            return UpdateScalar(adler, buf);
        }

        private static uint UpdateScalar(uint adler, ReadOnlySpan<byte> buf)
        {
            const uint Base = 65521; // largest prime smaller than 65536
            const int NMax = 5552; // NMax is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1

            uint s1 = adler & 0xFFFF;
            uint s2 = (adler >> 16) & 0xFFFF;
            while (buf.Length > 0)
            {
                int k = buf.Length < NMax ? buf.Length : NMax;
                foreach (byte b in buf.Slice(0, k))
                {
                    s1 += b;
                    s2 += s1;
                }
                s1 %= Base;
                s2 %= Base;
                buf = buf.Slice(k);
            }

            return (s2 << 16) | s1;
        }
    }
}
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
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()
    {
        FinalizerThread::FinalizerThreadWorkerRound();
    }
}

#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):
I need help with the transition to correct GC mode here. This is single-threaded and it would not be interrupted.

Code after:
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;

#ifndef TARGET_WASM
    hEventFinalizer->Set();
#else  // !TARGET_WASM
#ifdef TARGET_BROWSER
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;
            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();

Review comment (suggestion):
```suggestion
            FinalizerThread::FinalizerThreadWorkerIteration();
```

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:
            if (g_TriggerHeapDump)
            {
                return;
            }

            break;
#endif
        default:
            //what's wrong?
            _ASSERTE (!"Bad return code from WaitForMultipleObjects");
            return;
        }
    }
}

static BOOL s_FinalizerThreadOK = FALSE;
static BOOL s_InitializedFinalizerThreadForPlatform = FALSE;
static BOOL s_PriorityBoosted = FALSE;

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    s_PriorityBoosted = FALSE;

    while (!fQuitFinalizer)
    {
        FinalizerThread::FinalizerThreadWorkerRound();
    }

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

VOID FinalizerThread::FinalizerThreadWorkerRound()
{
#ifndef TARGET_WASM
    // Wait for work to do...

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

Review comment (suggestion):
```suggestion
        FinalizerThread::FinalizerThreadWorkerIteration();
```

Code after:
        }
    }
}

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

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    CONTRACTL
    {
        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
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
        default:
            //what's wrong?
            _ASSERTE (!"Bad return code from WaitForMultipleObjects");
            return;
        }
    }
}

static BOOL s_FinalizerThreadOK = FALSE;
static BOOL s_InitializedFinalizerThreadForPlatform = FALSE;
static BOOL s_PriorityBoosted = FALSE;

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    s_PriorityBoosted = FALSE;

    while (!fQuitFinalizer)
    {
        FinalizerThread::FinalizerThreadWorkerRound();
    }

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

VOID FinalizerThread::FinalizerThreadWorkerRound()
{
#ifndef TARGET_WASM
    // Wait for work to do...

    _ASSERTE(GetFinalizerThread()->PreemptiveGCDisabled());
#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
    }
#endif
    GetFinalizerThread()->EnablePreemptiveGC();
#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


Review comment (suggestion):
```suggestion
VOID FinalizerThread::FinalizerThreadWorkerIteration()
```

Code after:

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    CONTRACTL
    {
        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
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.h (C/C++)

Code before:
        _ASSERTE(g_pFinalizerThread != 0);
        return g_pFinalizerThread;
    }

    static bool IsCurrentThreadFinalizer();

    static void EnableFinalization();

    static void DelayDestroyDynamicMethodDesc(DynamicMethodDesc* pDMD);

    // returns if there is some extra work for the finalizer thread.
    static bool HaveExtraWorkForFinalizer();

    static OBJECTREF GetNextFinalizableObject();

    static void RaiseShutdownEvents();

    static void WaitForFinalizerThreadStart();

    static void FinalizerThreadWait();

    static void SignalFinalizationDone(int observedFullGcCount);

    static VOID FinalizerThreadWorker(void *args);

    static VOID FinalizerThreadWorkerRound();

    static DWORD WINAPI FinalizerThreadStart(void *args);

    static void FinalizerThreadCreate();
};

#endif // _FINALIZER_THREAD_H_


Review comment (suggestion):
```suggestion
    static VOID FinalizerThreadWorkerIteration();
```

Code after:
        _ASSERTE(g_pFinalizerThread != 0);
        return g_pFinalizerThread;
    }

    static bool IsCurrentThreadFinalizer();

    static void EnableFinalization();

    static void DelayDestroyDynamicMethodDesc(DynamicMethodDesc* pDMD);

    // returns if there is some extra work for the finalizer thread.
    static bool HaveExtraWorkForFinalizer();

    static OBJECTREF GetNextFinalizableObject();

    static void RaiseShutdownEvents();

    static void WaitForFinalizerThreadStart();

    static void FinalizerThreadWait();

    static void SignalFinalizationDone(int observedFullGcCount);

    static VOID FinalizerThreadWorker(void *args);

    static VOID FinalizerThreadWorkerIteration(void *args);

    static DWORD WINAPI FinalizerThreadStart(void *args);

    static void FinalizerThreadCreate();
};

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

Code before:
            return;
#if defined(__linux__) && defined(FEATURE_EVENT_TRACE)
        case (WAIT_TIMEOUT + kLowMemoryNotification):
        case (WAIT_TIMEOUT + kFinalizer):
            if (g_TriggerHeapDump)
            {
                return;
            }

            break;
#endif
        default:
            //what's wrong?
            _ASSERTE (!"Bad return code from WaitForMultipleObjects");
            return;
        }
    }
}

static BOOL s_FinalizerThreadOK = FALSE;
static BOOL s_InitializedFinalizerThreadForPlatform = FALSE;
static BOOL s_PriorityBoosted = FALSE;

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    s_PriorityBoosted = FALSE;

    while (!fQuitFinalizer)
    {
        FinalizerThread::FinalizerThreadWorkerRound();
    }

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

VOID FinalizerThread::FinalizerThreadWorkerRound()
{
#ifndef TARGET_WASM
    // Wait for work to do...

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

Review comment (suggestion):
```suggestion
```
Unnecessary. Also, you can change the variable to lower-case `bool` while you are on it

Code after:
        default:
            //what's wrong?
            _ASSERTE (!"Bad return code from WaitForMultipleObjects");
            return;
        }
    }
}

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

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    CONTRACTL
    {
        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())
    {
Repository: dotnet/runtime
File: src/coreclr/vm/finalizerthread.cpp (C++)

Code before:
            }

            break;
#endif
        default:
            //what's wrong?
            _ASSERTE (!"Bad return code from WaitForMultipleObjects");
            return;
        }
    }
}

static BOOL s_FinalizerThreadOK = FALSE;
static BOOL s_InitializedFinalizerThreadForPlatform = FALSE;
static BOOL s_PriorityBoosted = FALSE;

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    s_PriorityBoosted = FALSE;

    while (!fQuitFinalizer)
    {
        FinalizerThread::FinalizerThreadWorkerRound();
    }

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

VOID FinalizerThread::FinalizerThreadWorkerRound()
{
#ifndef TARGET_WASM
    // Wait for work to do...

    _ASSERTE(GetFinalizerThread()->PreemptiveGCDisabled());
#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
    }
#endif
    GetFinalizerThread()->EnablePreemptiveGC();
#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

Review comment (suggestion):
```suggestion
{
    CONTRACTL
    {
        THROWS;
        GC_TRIGGERS;
        MODE_COOPERATIVE;
    }
    CONTRACTL_END;

```
This seems to be the expected contract

Code after:

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

VOID FinalizerThread::FinalizerThreadWorker(void *args)
{
    CONTRACTL
    {
        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
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)
{
    s_PriorityBoosted = FALSE;

    while (!fQuitFinalizer)
    {
        FinalizerThread::FinalizerThreadWorkerRound();
    }

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

VOID FinalizerThread::FinalizerThreadWorkerRound()
{
#ifndef TARGET_WASM
    // Wait for work to do...

    _ASSERTE(GetFinalizerThread()->PreemptiveGCDisabled());
#ifdef _DEBUG
    if (g_pConfig->FastGCStressLevel())
    {
        GetFinalizerThread()->m_GCOnTransitionsOK = FALSE;
    }
#endif
    GetFinalizerThread()->EnablePreemptiveGC();
#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)

Review comment (suggestion):
```suggestion
```
Unnecessary (redundant with the contract annotation)

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