Repository: dotnet/runtime
File: src/coreclr/interpreter/compiler.cpp (C++)

Code before:
                // since var's which are passed to call instructions are destroyed (unless
                // they are global, and there is no reason to promote the this arg to a global)
                AddIns(INTOP_MOV_P);
                m_pLastNewIns->SetSVar(callArgs[0]);
                PushInterpType(InterpTypeO, NULL);
                m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
                int thisVarForLdvirtftn = m_pStackPointer[-1].var;
                m_pStackPointer--;

                EmitPushLdvirtftn(thisVarForLdvirtftn, &resolvedCallToken, &callInfo);
                m_pStackPointer--;
                int synthesizedLdvirtftnPtrVar = m_pStackPointer[0].var;

                calliCookie = m_compHnd->GetCookieForInterpreterCalliSig(&callInfo.sig);

                EmitCalli(tailcall, calliCookie, synthesizedLdvirtftnPtrVar, &callInfo.sig);
            }
            else
            {
                AddIns(tailcall ? INTOP_CALLVIRT_TAIL : INTOP_CALLVIRT);
                m_pLastNewIns->data[0] = GetDataItemIndex(callInfo.hMethod);
                m_pLastNewIns->data[1] = GetNewDataItemIndex(nullptr);
                int32_t secondCache = GetNewDataItemIndex(nullptr);
#ifdef DEBUG
                assert(secondCache == (m_pLastNewIns->data[1] + 1));
#endif
            }
            break;

        case CORINFO_VIRTUALCALL_STUB:
            // This case should never happen
            assert(!"Unexpected call kind");
        break;
    }

    m_pLastNewIns->SetDVar(dVar);
    m_pLastNewIns->SetSVar(CALL_ARGS_SVAR);

    m_pLastNewIns->flags |= INTERP_INST_FLAG_CALL;
    m_pLastNewIns->info.pCallInfo = (InterpCallInfo*)AllocMemPool0(sizeof (InterpCallInfo));
    m_pLastNewIns->info.pCallInfo->pCallArgs = callArgs;

    if (injectRet)
    {
        // Jmp to PInvoke was converted to normal pinvoke, so we need to inject a ret after the call
        InterpType retType = GetInterpType(m_methodInfo->args.retType);
        switch (retType)
        {
            case InterpTypeVT:
            {
                AddIns(INTOP_RET_VT);

Review comment (bug):
The variable 'secondCache' is assigned but never used. It appears to exist solely for the DEBUG assertion on line 5227 to verify that consecutive GetNewDataItemIndex calls return sequential indices. Consider using (void)secondCache; or UNUSED(secondCache); to explicitly indicate this is intentional, or remove the variable and directly assert on a second call if the assertion is important.
```suggestion
                int32_t secondCache = GetNewDataItemIndex(nullptr);
                (void)secondCache;
```

Code after:
                // produces a function pointer.

                // We need to copy the this argument to the target function to another var,
                // since var's which are passed to call instructions are destroyed (unless
                // they are global, and there is no reason to promote the this arg to a global)
                AddIns(INTOP_MOV_P);
                m_pLastNewIns->SetSVar(callArgs[0]);
                PushInterpType(InterpTypeO, NULL);
                m_pLastNewIns->SetDVar(m_pStackPointer[-1].var);
                int thisVarForLdvirtftn = m_pStackPointer[-1].var;
                m_pStackPointer--;

                EmitPushLdvirtftn(thisVarForLdvirtftn, &resolvedCallToken, &callInfo);
                m_pStackPointer--;
                int synthesizedLdvirtftnPtrVar = m_pStackPointer[0].var;

                calliCookie = m_compHnd->GetCookieForInterpreterCalliSig(&callInfo.sig);

                EmitCalli(tailcall, calliCookie, synthesizedLdvirtftnPtrVar, &callInfo.sig);
            }
            else
            {
                AddIns(tailcall ? INTOP_CALLVIRT_TAIL : INTOP_CALLVIRT);
                m_pLastNewIns->data[0] = GetDataItemIndex(callInfo.hMethod);
                m_pLastNewIns->data[1] = GetNewDataItemIndex(nullptr);
                int32_t secondCache = GetNewDataItemIndex(nullptr);
#ifdef DEBUG
                assert(secondCache == (m_pLastNewIns->data[1] + 1));
#endif
            }
            break;

        case CORINFO_VIRTUALCALL_STUB:
            // This case should never happen
            assert(!"Unexpected call kind");
        break;
    }

    m_pLastNewIns->SetDVar(dVar);
    m_pLastNewIns->SetSVar(CALL_ARGS_SVAR);

    m_pLastNewIns->flags |= INTERP_INST_FLAG_CALL;
    m_pLastNewIns->info.pCallInfo = (InterpCallInfo*)AllocMemPool0(sizeof (InterpCallInfo));
    m_pLastNewIns->info.pCallInfo->pCallArgs = callArgs;

    if (injectRet)
    {
        // Jmp to PInvoke was converted to normal pinvoke, so we need to inject a ret after the call
        InterpType retType = GetInterpType(m_methodInfo->args.retType);
        switch (retType)
        {