HRESULT AddExitProbe()

in ProfilingAPI/ReJITEnterLeaveHooks/ILRewriter.cpp [766:817]


HRESULT AddExitProbe(
    ILRewriter * pilr,
    FunctionID functionId,
    UINT_PTR methodAddress,
    ULONG32 methodSignature)
{
    HRESULT hr;
    BOOL fAtLeastOneProbeAdded = FALSE;

    // Find all RETs, and insert a call to the exit probe before each one.
    for (ILInstr * pInstr = pilr->GetILList()->m_pNext; pInstr != pilr->GetILList(); pInstr = pInstr->m_pNext)
    {
        switch (pInstr->m_opcode)
        {
        case CEE_RET:
        {
            // We want any branches or leaves that targeted the RET instruction to
            // actually target the epilog instructions we're adding. So turn the "RET"
            // into ["NOP", "RET"], and THEN add the epilog between the NOP & RET. That
            // ensures that any branches that went to the RET will now go to the NOP and
            // then execute our epilog.

            // NOTE: The NOP is not strictly required, but is a simplification of the implementation.
            // RET->NOP
            pInstr->m_opcode = CEE_NOP;

            // Add the new RET after
            ILInstr * pNewRet = pilr->NewILInstr();
            pNewRet->m_opcode = CEE_RET;
            pilr->InsertAfter(pInstr, pNewRet);

            // Add now insert the epilog before the new RET
            hr = AddProbe(pilr, functionId, methodAddress, methodSignature, pNewRet);
            if (FAILED(hr))
                return hr;
            fAtLeastOneProbeAdded = TRUE;

            // Advance pInstr after all this gunk so the for loop continues properly
            pInstr = pNewRet;
            break;
        }

        default:
            break;
        }
    }

    if (!fAtLeastOneProbeAdded)
        return E_FAIL;

    return S_OK;
}