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

Code before:
    OBJECTREF* pObjRef = NULL;

    if( GC_SP_REL == spBase )
    {
        _ASSERTE(!"GC_SP_REL is invalid for interpreter frames");
    }
    else if( GC_CALLER_SP_REL == spBase )
    {
        _ASSERTE(!"GC_CALLER_SP_REL is invalid for interpreter frames");
    }
    else
    {
        // Interpreter-TODO: Enhance GcInfoEncoder/Decoder to allow omitting the stack slot base register for interpreted
        //  methods, since only one base (fp) is ever used for interpreter locals. See Interpreter-TODO in DecodeSlotTable.
        _ASSERTE( GC_FRAMEREG_REL == spBase );
        uint8_t* fp = (uint8_t *)GetFP(pRD->pCurrentContext);
        _ASSERTE(fp);
        pObjRef = (OBJECTREF*)(fp + spOffset);
    }
    InterpMethodContextFrame* pFrame = (InterpMethodContextFrame*)GetSP(pRD->pCurrentContext);
    _ASSERTE(pFrame->pStack == (int8_t *)GetFP(pRD->pCurrentContext));
    InterpMethodContextFrame* pFrameCallee = pFrame->pNext;

    // If the stack slot is in a callee's frame, then we do not actually need to report it. This should ONLY happen if the
    // stack slot is in the argument area of the caller. As a double check, we validate that we only return this address if
    // the 
    if (pFrameCallee != NULL)
    {
        if (pFrameCallee->ip != 0)
        {
            _ASSERTE(pFrameCallee->pStack > pFrame->pStack); // Since only the last funclet is GC reported, we shouldn't have any cases where the stack doesn't grow
            if (pFrameCallee->pStack <= (int8_t*)pObjRef)
            {
                // The stack slot is in the callee's frame, not the caller's frame.
                pObjRef = (OBJECTREF*)&ZeroValue;
            }
        }
    }
    return pObjRef;
}
#endif


template <typename GcInfoEncoding> OBJECTREF* TGcInfoDecoder<GcInfoEncoding>::GetStackSlot(
                        INT32           spOffset,
                        GcStackSlotBase spBase,
                        PREGDISPLAY     pRD
                        )
{
    OBJECTREF* pObjRef;


Review comment (suggestion):
The comment is incomplete and ends abruptly with "if the". Please complete this sentence to clarify the validation condition being described.
```suggestion
    // the stack location is within the current frame's argument area and not in the callee's frame.
```

Code after:
    OBJECTREF* pObjRef = NULL;

    if( GC_SP_REL == spBase )
    {
        _ASSERTE(!"GC_SP_REL is invalid for interpreter frames");
    }
    else if( GC_CALLER_SP_REL == spBase )
    {
        _ASSERTE(!"GC_CALLER_SP_REL is invalid for interpreter frames");
    }
    else
    {
        // Interpreter-TODO: Enhance GcInfoEncoder/Decoder to allow omitting the stack slot base register for interpreted
        //  methods, since only one base (fp) is ever used for interpreter locals. See Interpreter-TODO in DecodeSlotTable.
        _ASSERTE( GC_FRAMEREG_REL == spBase );
        uint8_t* fp = (uint8_t *)GetFP(pRD->pCurrentContext);
        _ASSERTE(fp);
        pObjRef = (OBJECTREF*)(fp + spOffset);
    }
    InterpMethodContextFrame* pFrame = (InterpMethodContextFrame*)GetSP(pRD->pCurrentContext);
    _ASSERTE(pFrame->pStack == (int8_t *)GetFP(pRD->pCurrentContext));
    InterpMethodContextFrame* pFrameCallee = pFrame->pNext;

    // If the stack slot is in a callee's frame, then we do not actually need to report it. This should ONLY happen if the
    // stack slot is in the argument area of the caller. As a double check, we validate in the caller of this function that
    // the stack slot in question is a interior pinned slot (which when FEATURE_INTERPRETER is defined indicates a conservatively reported stack slot).
    if (pFrameCallee != NULL)
    {
        if (pFrameCallee->ip != 0)
        {
            _ASSERTE(pFrameCallee->pStack > pFrame->pStack); // Since only the last funclet is GC reported, we shouldn't have any cases where the stack doesn't grow
            if (pFrameCallee->pStack <= (int8_t*)pObjRef)
            {
                // The stack slot is in the callee's frame, not the caller's frame.
                // Return as a sentinel to indicate nothing is reported here.
                pObjRef = NULL;
            }
        }
    }
    return pObjRef;
}
#endif


template <typename GcInfoEncoding> OBJECTREF* TGcInfoDecoder<GcInfoEncoding>::GetStackSlot(
                        INT32           spOffset,
                        GcStackSlotBase spBase,
                        PREGDISPLAY     pRD
                        )
{
    OBJECTREF* pObjRef;