Repository: dotnet/runtime
File: src/coreclr/jit/codegenwasm.cpp (C++)

Code before:
{
    GenTree*  dstAddr     = cpObjNode->Addr();
    GenTree*  source      = cpObjNode->Data();
    var_types srcAddrType = TYP_BYREF;
    regNumber dstReg      = GetMultiUseOperandReg(dstAddr);
    unsigned  dstOffset   = 0;
    regNumber srcReg;
    unsigned  srcOffset;

    // Identify the register containing our source base address, either a multi-use
    //  reg representing the operand of a GT_IND, or the frame pointer for LCL_VAR/LCL_FLD.
    if (source->OperIs(GT_IND))
    {
        source = source->gtGetOp1();
        assert(!source->isContained());
        srcAddrType = source->TypeGet();
        srcReg      = GetMultiUseOperandReg(source);
        srcOffset   = 0;
    }
    else
    {
        noway_assert(source->OperIs(GT_LCL_FLD, GT_LCL_VAR));
        GenTreeLclVarCommon* lclVar = source->AsLclVarCommon();
        bool                 fpBased;
        srcOffset = m_compiler->lvaFrameAddress(lclVar->GetLclNum(), &fpBased) + lclVar->GetLclOffs();
        noway_assert(fpBased);
        srcReg = GetFramePointerReg();
    }

    // If the destination is on the stack we don't need the write barrier.
    bool dstOnStack = cpObjNode->IsAddressNotOnHeap(m_compiler);
    // We should have generated a memory.copy for this scenario in lowering.
    assert(!dstOnStack);

#ifdef DEBUG
    assert(!dstAddr->isContained());

    // This GenTree node has data about GC pointers, this means we're dealing
    // with CpObj.
    assert(cpObjNode->GetLayout()->HasGCPtr());
#endif // DEBUG

    genConsumeOperands(cpObjNode);

    emitter* emit = GetEmitter();

    // TODO-WASM: Implicit null check

    // TODO-WASM: Remove the need to do this somehow
    // The dst and src may be on the evaluation stack, but we can't reliably use them, so drop them.
    emit->emitIns(INS_drop);

Review comment (suggestion):
```suggestion
        assert(fpBased);
```
It is rare that you need a `noway_assert`.

`noway_assert` is a Release-mode assert. You only should need for cases where you suspect it may not be hit in our extensive testing.

Code after:
//------------------------------------------------------------------------
// genCodeForCpObj: Produce code for a GT_STORE_BLK node that represents a cpobj operation.
//
// Arguments:
//    cpObjNode - the node
//
void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode)
{
    GenTree*  dstAddr     = cpObjNode->Addr();
    GenTree*  source      = cpObjNode->Data();
    var_types srcAddrType = TYP_BYREF;
    regNumber dstReg      = GetMultiUseOperandReg(dstAddr);
    unsigned  dstOffset   = 0;
    regNumber srcReg;
    unsigned  srcOffset;

    // Identify the register containing our source base address, either a multi-use
    //  reg representing the operand of a GT_IND, or the frame pointer for LCL_VAR/LCL_FLD.
    if (source->OperIs(GT_IND))
    {
        source = source->gtGetOp1();
        assert(!source->isContained());
        srcAddrType = source->TypeGet();
        srcReg      = GetMultiUseOperandReg(source);
        srcOffset   = 0;

        genEmitNullCheck(srcReg);
    }
    else
    {
        assert(source->OperIs(GT_LCL_FLD, GT_LCL_VAR));
        GenTreeLclVarCommon* lclVar = source->AsLclVarCommon();
        bool                 fpBased;
        srcOffset = m_compiler->lvaFrameAddress(lclVar->GetLclNum(), &fpBased) + lclVar->GetLclOffs();
        assert(fpBased);
        srcReg = GetFramePointerReg();
    }

    // If the destination is on the stack we don't need the write barrier.
    bool dstOnStack = cpObjNode->IsAddressNotOnHeap(m_compiler);
    // We should have generated a memory.copy for this scenario in lowering.
    assert(!dstOnStack);

#ifdef DEBUG
    assert(!dstAddr->isContained());

    // This GenTree node has data about GC pointers, this means we're dealing
    // with CpObj.
    assert(cpObjNode->GetLayout()->HasGCPtr());
#endif // DEBUG