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

Code before:
                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);
                assert(secondCache == (m_pLastNewIns->data[1] + 1));
            }
            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);
                m_pLastNewIns->SetSVar(dVar);
                m_pLastNewIns->data[0] = m_pVars[dVar].size;
                break;
            }
            case InterpTypeVoid:
                AddIns(INTOP_RET_VOID);

Review comment (bug):
```suggestion
#ifdef _DEBUG
                int32_t secondCache = GetNewDataItemIndex(nullptr);
                assert(secondCache == (m_pLastNewIns->data[1] + 1));
#endif // _DEBUG
```

Code after:
                // 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)
        {
            case InterpTypeVT:
            {