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

Code before:
void ExecuteInterpretedMethodWithArgs(TADDR targetIp, int8_t* args, size_t argSize, void* retBuff, PCODE callerIp);

#define SPECIAL_ARG_ADDR(pos) (((int8_t*)pCallDescrData->pSrc) + ((pos)*INTERP_STACK_SLOT_SIZE))

extern "C" void STDCALL CallDescrWorkerInternal(CallDescrData* pCallDescrData)
{
    _ASSERTE(pCallDescrData != NULL);
    _ASSERTE(pCallDescrData->pTarget != (PCODE)NULL);

    // WASM-TODO: This path has a flaw. The DoPrestub call may trigger a GC, and there is no
    // explicit protection for the arguments. All platforms assume part of the call is
    // a no GC trigger region, but DoPrestub may trigger a GC. Therefore this needs to be
    // revisited to ensure correctness.

    MethodDesc* pMethod = PortableEntryPoint::GetMethodDesc(pCallDescrData->pTarget);
    InterpByteCodeStart* targetIp = pMethod->GetInterpreterCode();
    if (targetIp == NULL)
    {
        GCX_PREEMP();
        (void)pMethod->DoPrestub(NULL /* MethodTable */, CallerGCMode::Coop);
        targetIp = pMethod->GetInterpreterCode();
    }

    size_t argsSize = pCallDescrData->nArgsSize;
    if (pCallDescrData->hasRetBuff) {
        argsSize -= TARGET_REGISTER_SIZE;
    }

    ExecuteInterpretedMethodWithArgs((TADDR)targetIp, SPECIAL_ARG_ADDR(pCallDescrData->hasRetBuff ? 1 : 0), argsSize, pCallDescrData->hasRetBuff ? *(int8_t**)SPECIAL_ARG_ADDR(0) : (int8_t*)pCallDescrData->returnValue, (PCODE)&CallDescrWorkerInternal);
}


Review comment (bug):
CallDescrWorkerInternal subtracts TARGET_REGISTER_SIZE, but this file only includes interpexec.h; TARGET_REGISTER_SIZE is defined in callingconvention.h, so this risks failing to compile depending on include order/forced includes. Consider using INTERP_STACK_SLOT_SIZE here (since this code is working in interpreter stack slots) or explicitly including the header that defines TARGET_REGISTER_SIZE.
```suggestion
        argsSize -= INTERP_STACK_SLOT_SIZE;
```

Code after:
void ExecuteInterpretedMethodWithArgs(TADDR targetIp, int8_t* args, size_t argSize, void* retBuff, PCODE callerIp);

#define SPECIAL_ARG_ADDR(pos) (void**)(((int8_t*)pCallDescrData->pSrc) + ((pos)*INTERP_STACK_SLOT_SIZE))

extern "C" void STDCALL CallDescrWorkerInternal(CallDescrData* pCallDescrData)
{
    _ASSERTE(pCallDescrData != NULL);
    _ASSERTE(pCallDescrData->pTarget != (PCODE)NULL);

    // WASM-TODO: This path has a flaw. The DoPrestub call may trigger a GC, and there is no
    // explicit protection for the arguments. All platforms assume part of the call is
    // a no GC trigger region, but DoPrestub may trigger a GC. Therefore this needs to be
    // revisited to ensure correctness.

    MethodDesc* pMethod = PortableEntryPoint::GetMethodDesc(pCallDescrData->pTarget);
    InterpByteCodeStart* targetIp = pMethod->GetInterpreterCode();
    if (targetIp == NULL)
    {
        GCX_PREEMP();
        (void)pMethod->DoPrestub(NULL /* MethodTable */, CallerGCMode::Coop);
        targetIp = pMethod->GetInterpreterCode();
    }

    size_t argsSize = pCallDescrData->nArgsSize;
    void* retBuff;
    int8_t* args;
    if (pCallDescrData->hasRetBuff)
    {
        argsSize -= INTERP_STACK_SLOT_SIZE;
        if (pCallDescrData->hasThis)
        {
            retBuff = *SPECIAL_ARG_ADDR(1);
            *SPECIAL_ARG_ADDR(1) = *SPECIAL_ARG_ADDR(0);
        }
        else
        {
            retBuff = *SPECIAL_ARG_ADDR(0);
        }
        args = (int8_t*)SPECIAL_ARG_ADDR(1);
    }
    else
    {
        args = (int8_t*)pCallDescrData->pSrc;
        retBuff = pCallDescrData->returnValue;
    }

    ExecuteInterpretedMethodWithArgs((TADDR)targetIp, args, argsSize, retBuff, (PCODE)&CallDescrWorkerInternal);
}