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

Code before:
{
    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;
    }

    if ((dwExpectedSize % TARGET_POINTER_SIZE) != 0)
    {
        COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
    }

    LoaderAllocator* allocator = currentModule->GetLoaderAllocator();
    AsyncContinuationsManager* asyncConts = allocator->GetAsyncContinuationsManager();

    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++)
            {
                objRefs[byteIndex * 8 + bit] = (b & (1 << bit)) != 0;
            }
        }
        return ::getContinuationType(dwExpectedSize, objRefs, objRefsSize, currentModule);
    }
}



Review comment (suggestion):
The variable 'asyncConts' is declared but never used. It can be safely removed since 'getContinuationType' internally accesses the AsyncContinuationsManager through the LoaderAllocator.
```suggestion

```

Code after:
    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++)
            {
                objRefs[byteIndex * 8 + bit] = (b & (1 << bit)) != 0;
            }
        }
        return ::getContinuationType(dwExpectedSize, objRefs, objRefsSize, currentModule);
    }
}


//
// Type layout check verifies that there was no incompatible change in the value type layout.
// If there was one, we will fall back to JIT instead of using the pre-generated code from the ready to run image.
// This should be rare situation. Changes in value type layout not common.
//
// The following properties of the value type layout are checked:
// - Size