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

Code before:
                        //  required to be followed by a ret, so we know nothing is going to read from stack[returnOffset] after the call.
                        pFrame->ReInit(pFrame->pParent, targetIp, pFrame->pRetVal, pFrame->pStack);
                    }
                    else
                    {
                        // Save current execution state for when we return from called method
                        pFrame->ip = ip;

                        // Allocate child frame.
                        {
                            InterpMethodContextFrame *pChildFrame = pFrame->pNext;
                            if (!pChildFrame)
                            {
                                pChildFrame = (InterpMethodContextFrame*)alloca(sizeof(InterpMethodContextFrame));
                                pChildFrame->pNext = NULL;
                                pFrame->pNext = pChildFrame;
                                // Save the lowest SP in the current method so that we can identify it by that during stackwalk
                                pInterpreterFrame->SetInterpExecMethodSP((TADDR)GetCurrentSP());
                            }
                            pChildFrame->ReInit(pFrame, targetIp, stack + returnOffset, stack + callArgsOffset);
                            pFrame = pChildFrame;
                        }
                        assert (((size_t)pFrame->pStack % INTERP_STACK_ALIGNMENT) == 0);
                    }

                    // Set execution state for the new frame
                    pMethod = pFrame->startIp->Method;
                    assert(pMethod->CheckIntegrity());
                    stack = pFrame->pStack;
                    ip = pFrame->startIp->GetByteCodes();
                    pThreadContext->pStackPointer = stack + pMethod->allocaSize;
                    break;
                }
                case INTOP_NEWOBJ_GENERIC:
                {
                    isTailcall = false;
                    returnOffset = ip[1];
                    callArgsOffset = ip[2];
                    methodSlot = ip[4];
                    InterpGenericLookup *pLookup = (InterpGenericLookup*)&pMethod->pDataItems[ip[5]];
                    MethodTable *pMTNewObj = (MethodTable*)DoGenericLookup(LOCAL_VAR(ip[3], void*), pLookup);

                    OBJECTREF objRef = AllocateObject(pMTNewObj);

                    // This is return value
                    LOCAL_VAR(returnOffset, OBJECTREF) = objRef;
                    // Set `this` arg for ctor call
                    LOCAL_VAR (callArgsOffset, OBJECTREF) = objRef;
                    ip += 6;

                    goto CALL_INTERP_SLOT;

Review comment (suggestion):
The magic number 5 for the isPInvoke parameter index and the increment of 6 for the instruction pointer make the code harder to maintain. Consider defining named constants for these values to improve readability.

Code after:

                    MethodDesc *pMD = (MethodDesc*)pMethod->pDataItems[methodSlot];

                    OBJECTREF *pThisArg = LOCAL_VAR_ADDR(callArgsOffset, OBJECTREF);
                    NULL_CHECK(*pThisArg);

                    // Interpreter-TODO
                    // This needs to be optimized, not operating at MethodDesc level, rather with ftnptr
                    // slots containing the interpreter IR pointer
                    targetMethod = pMD->GetMethodDescOfVirtualizedCode(pThisArg, pMD->GetMethodTable());
                    ip += 4;
                    goto CALL_INTERP_METHOD;
                }

                case INTOP_CALLI_TAIL:
                case INTOP_CALLI:
                {
                    isTailcall = (*ip == INTOP_CALLI_TAIL);
                    returnOffset = ip[1];
                    callArgsOffset = ip[2];
                    int32_t calliFunctionPointerVar = ip[3];
                    int32_t calliCookie = ip[4];
                    int32_t flags = ip[5];

                    void* cookie = pMethod->pDataItems[calliCookie];
                    ip += 6;

                    // Save current execution state for when we return from called method
                    pFrame->ip = ip;

                    // Interpreter-FIXME: isTailcall
                    if (flags & (int32_t)CalliFlags::PInvoke)
                    {
                        if (flags & (int32_t)CalliFlags::SuppressGCTransition)
                        {
                            InvokeUnmanagedCalli(LOCAL_VAR(calliFunctionPointerVar, PCODE), cookie, stack + callArgsOffset, stack + returnOffset);
                        }
                        else
                        {
                            InvokeUnmanagedCalliWithTransition(LOCAL_VAR(calliFunctionPointerVar, PCODE), cookie, stack, pFrame, stack + callArgsOffset, stack + returnOffset);
                        }
                    }
                    else
                    {
                        InvokeCalliStub(LOCAL_VAR(calliFunctionPointerVar, PCODE), cookie, stack + callArgsOffset, stack + returnOffset);
                    }

                    break;
                }

                case INTOP_CALL_PINVOKE: