예제 #1
0
/*
 * ProfileArgIterator::GetHiddenArgValue
 *
 * Called after initialization, any number of times, to retrieve any
 * hidden argument, so that resolution for Generics can be done.
 *
 * Parameters:
 *    None.
 *
 * Returns:
 *    Value of the hidden parameter, or NULL if none exists.
 */
LPVOID ProfileArgIterator::GetHiddenArgValue(void)
{
    //
    // It would be really nice to contract this, but the underlying functions are convolutedly
    // contracted.  Basically everything should be loaded by the time the profiler gets a call
    // back, so everything is NOTHROW/NOTRIGGER, but there is not mechanism for saying that the
    // contracts in called functions should be for the best case, not the worst case, now.
    //
    WRAPPER_NO_CONTRACT;

    PROFILE_PLATFORM_SPECIFIC_DATA *pData = (PROFILE_PLATFORM_SPECIFIC_DATA *)m_handle;

    MethodDesc *pMethodDesc = FunctionIdToMethodDesc(pData->functionId);

    if (!pMethodDesc->RequiresInstArg())
    {
        return NULL;
    }

    //
    // The ArgIterator::GetParamTypeOffset() can only be called after calling GetNextOffset until the
    // entire signature has been walked, but *before* GetNextOffset returns TransitionBlock::InvalidOffset
    // - indicating the end.
    //

    //
    // Get the offset of the hidden arg
    //
    int argOffset = m_argIterator.GetParamTypeArgOffset();

    //
    // If this is not enregistered, return the value
    //
    if (TransitionBlock::IsStackArgumentOffset(argOffset))
    {
        return *(LPVOID *)(((LPBYTE)pData->esp) + (argOffset - TransitionBlock::GetOffsetOfArgs()));
    }

    switch (argOffset - TransitionBlock::GetOffsetOfArgumentRegisters())
    {
    case offsetof(ArgumentRegisters, ECX):
        return (LPVOID)(pData->ecx);
    case offsetof(ArgumentRegisters, EDX):
        return (LPVOID)(pData->edx);
    }

    _ASSERTE(!"Arg is an unsaved register!");
    return NULL;
}
예제 #2
0
/*
 * ProfileArgIterator::ProfileArgIterator
 *
 * Constructor. Initializes for arg iteration.
 *
 * Parameters:
 *    pMetaSig - The signature of the method we are going iterate over
 *    platformSpecificHandle - the value passed to ProfileEnter/Leave/Tailcall
 *
 * Returns:
 *    None.
 */
ProfileArgIterator::ProfileArgIterator(MetaSig * pSig, void * platformSpecificHandle) :
    m_argIterator(pSig)
{
    WRAPPER_NO_CONTRACT;

    _ASSERTE(pSig != NULL);
    _ASSERTE(platformSpecificHandle != NULL);

    m_handle = platformSpecificHandle;
    PROFILE_PLATFORM_SPECIFIC_DATA* pData = (PROFILE_PLATFORM_SPECIFIC_DATA*)m_handle;

    // unwind a frame and get the Rsp for the profiled method to make sure it matches
    // what the JIT gave us
#ifdef _DEBUG
    {
        // setup the context to represent the frame that called ProfileEnterNaked
        CONTEXT ctx;
        memset(&ctx, 0, sizeof(CONTEXT));
        ctx.Rsp = (UINT64)pData->probeRsp;
        ctx.Rbp = (UINT64)pData->rbp;
        ctx.Rip = (UINT64)pData->ip;

        // walk up a frame to the caller frame (called the managed method which
        // called ProfileEnterNaked)
        Thread::VirtualUnwindCallFrame(&ctx);

        _ASSERTE(pData->profiledRsp == (void*)ctx.Rsp);
    }
#endif // _DEBUG
    
    // Get the hidden arg if there is one
    MethodDesc * pMD = FunctionIdToMethodDesc(pData->functionId);

    if ( (pData->hiddenArg == NULL)                                         &&
         (pMD->RequiresInstArg() || pMD->AcquiresInstMethodTableFromThis()) )
    {
        // In the enter probe, the JIT may not have pushed the generics token onto the stack yet.
        // Luckily, we can inspect the registers reliably at this point.
        if (pData->flags & PROFILE_ENTER)
        {
            _ASSERTE(!((pData->flags & PROFILE_LEAVE) || (pData->flags & PROFILE_TAILCALL)));

            if (pMD->AcquiresInstMethodTableFromThis())
            {
                pData->hiddenArg = GetThis();
            }
            else
            {
                // The param type arg comes after the return buffer argument and the "this" pointer.
                int     index = 0;

                if (m_argIterator.HasThis())
                {
                    index++;
                }

                if (m_argIterator.HasRetBuffArg())
                {
                    index++;
                }

                pData->hiddenArg = *(LPVOID*)((LPBYTE)pData->profiledRsp + (index * sizeof(SIZE_T)));
            }
        }
        else
        {
            EECodeInfo codeInfo((PCODE)pData->ip);

            // We want to pass the caller SP here.
            pData->hiddenArg = EECodeManager::GetExactGenericsToken((SIZE_T)(pData->profiledRsp), &codeInfo);
        }
    }
}