Repository: dotnet/runtime
File: src/coreclr/vm/jitinterface.cpp (C++)

Code before:
    } while (cur >= last);
}


MethodTable* GetContinuationTypeFromLayout(PCCOR_SIGNATURE pBlob)
{
    STANDARD_VM_CONTRACT;

    SigPointer p(pBlob);
    // Skip Continuation type signature
    IfFailThrow(p.SkipExactlyOne());

    uint32_t dwFlags;
    IfFailThrow(p.GetData(&dwFlags));

    uint32_t dwExpectedSize;
    IfFailThrow(p.GetData(&dwExpectedSize));

    if (!(dwFlags & READYTORUN_LAYOUT_GCLayout))
    {
        return nullptr;
    }

    // Use the global loader allocator (System module's allocator) for R2R fixups
    LoaderAllocator* allocator = SystemDomain::GetGlobalLoaderAllocator();
    AsyncContinuationsManager* asyncConts = allocator->GetAsyncContinuationsManager();

    if (!(dwFlags & READYTORUN_LAYOUT_GCLayout_Empty))
    {
        uint8_t* pGCRefMapBlob = (uint8_t*)p.GetPtr();
        size_t objRefsSize = (dwExpectedSize / TARGET_POINTER_SIZE);
        bool* objRefs = (bool*)_alloca(objRefsSize * sizeof(bool));
        size_t bytesInBlob = (objRefsSize + 7) / 8;
        // Read bitmap from blob
        for(size_t byteIndex = 0; byteIndex < bytesInBlob; byteIndex++)
        {
            uint8_t b = pGCRefMapBlob[byteIndex];
            for (int bit = 0; bit < 8 && byteIndex * 8 + bit < objRefsSize; bit++)
            {
                objRefs[byteIndex * 8 + bit] = (b & (1 << bit)) != 0;
            }
        }
        return asyncConts->LookupOrCreateContinuationMethodTableFromLayout(
            (unsigned)dwExpectedSize,
            objRefs
        );
    }
    else
    {
        return asyncConts->LookupOrCreateContinuationMethodTableFromLayout(
            (unsigned)dwExpectedSize,

Review comment (suggestion):
The PR description states "Include OwningMethod to associate the Continuation type with the correct loader allocator at runtime", but the implementation uses the global loader allocator (SystemDomain::GetGlobalLoaderAllocator()) and System module instead of the owning method's loader allocator. This discrepancy should be clarified - either the description needs to be updated, or the implementation should encode and use the owning method information to determine the correct loader allocator.

Code after:
        while (offset < offsetStop)
        {
            size_t bit = offset / TARGET_POINTER_SIZE;

            size_t index = bit / 8;
            _ASSERTE(index < cbGCRefMap);
            pGCRefMap[index] |= (1 << (bit & 7));

            offset += TARGET_POINTER_SIZE;
        }
        cur--;
    } while (cur >= last);
}

MethodTable* GetContinuationTypeFromLayout(PCCOR_SIGNATURE pBlob, Module* currentModule)
{
    STANDARD_VM_CONTRACT;

    SigPointer p(pBlob);
    // Skip Continuation type signature
    IfFailThrow(p.SkipExactlyOne());

    uint32_t dwFlags;
    IfFailThrow(p.GetData(&dwFlags));

    uint32_t dwExpectedSize;
    IfFailThrow(p.GetData(&dwExpectedSize));

    if (((dwFlags & READYTORUN_LAYOUT_GCLayout) == 0)
        || ((dwFlags & READYTORUN_LAYOUT_Alignment_Native) == 0)
        || ((dwExpectedSize % TARGET_POINTER_SIZE) != 0))
    {
        return nullptr;
    }

    if (dwFlags & READYTORUN_LAYOUT_GCLayout_Empty)
    {
        // No GC references, don't read a bitmap
        return ::getContinuationType(dwExpectedSize, nullptr, 0, currentModule);
    }
    else
    {
        uint8_t* pGCRefMapBlob = (uint8_t*)p.GetPtr();
        size_t objRefsSize = (dwExpectedSize / TARGET_POINTER_SIZE);
        bool* objRefs = (bool*)_alloca(objRefsSize * sizeof(bool));
        size_t bytesInBlob = (objRefsSize + 7) / 8;
        // Expand bitmap to bool array for use with getContinuationType
        for (size_t byteIndex = 0; byteIndex < bytesInBlob; byteIndex++)
        {
            uint8_t b = pGCRefMapBlob[byteIndex];
            for (int bit = 0; bit < 8 && byteIndex * 8 + bit < objRefsSize; bit++)