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

Code before:
        pCode = ECall::GetFCallImpl(this, true /* throwForInvalidFCall */, &hasManagedImpl);

#ifdef FEATURE_PORTABLE_ENTRYPOINTS
        if (!hasManagedImpl)
        {
            // Update the PortableEntryPoint to point to the actual code for the FCall implementation.
            // Return the PortableEntryPoint as the PCODE.
            PCODE entryPoint = GetPortableEntryPoint();
            PortableEntryPoint::SetActualCode(entryPoint, pCode);
            pCode = entryPoint;
        }
        else
        {
            MethodDesc* helperMD = PortableEntryPoint::GetMethodDesc(pCode);
            // If the FCall implementation is managed, then we need to potentially set up the interpreter code for it as well.
            // This is because the FCall may have been compiled to an IL stub that needs to be interpreted.
            if (helperMD->ShouldCallPrestub())
                (void)helperMD->DoPrestub(NULL /* MethodTable */, CallerGCMode::Coop);
            void* ilStubInterpData = helperMD->GetInterpreterCode();
            SetInterpreterCode((InterpByteCodeStart*)ilStubInterpData);

            // Use this method's own PortableEntryPoint rather than the helper's.
            // Setting pCode to the helper's PortableEntryPoint would write a foreign
            // MethodDesc pointer into this method's slot, breaking MethodDesc lookups
            // and access checks (e.g. private Delegate.DelegateConstruct exposed on
            // delegate ctor slots causes MethodAccessException).
            PCODE entryPoint = GetPortableEntryPoint();
            if (ilStubInterpData != NULL)
            {
                PortableEntryPoint::SetInterpreterData(entryPoint, (PCODE)(TADDR)ilStubInterpData);
            }
            pCode = entryPoint;
        }
#else // !FEATURE_PORTABLE_ENTRYPOINTS
        // FCalls are always wrapped in a precode to enable mapping of the entrypoint back to MethodDesc
        GetOrCreatePrecode();
#endif // FEATURE_PORTABLE_ENTRYPOINTS
    }
    else if (IsArray())
    {
        pStub = GenerateArrayOpStub((ArrayMethodDesc*)this);
    }
    else if (IsEEImpl())
    {
        _ASSERTE(GetMethodTable()->IsDelegate());
        pStub = COMDelegate::GetInvokeMethodStub((EEImplMethodDesc*)this);
    }
    else
    {
        // This is a method type we don't handle yet
        _ASSERTE(!"Unknown Method Type");

Review comment (bug):
```suggestion
            // It is required to maintain 1:1 mapping between MethodDesc and its entrypoint.
```
There are multiple places where we depend on 1:1 mapping between MethodDesc and entrypoint. It is well-known invariant documented in https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/method-descriptor.md . We do not need to comment on what all may be broken if this invariant does not hold.

Code after:
        pCode = ECall::GetFCallImpl(this, true /* throwForInvalidFCall */, &hasManagedImpl);

#ifdef FEATURE_PORTABLE_ENTRYPOINTS
        if (!hasManagedImpl)
        {
            // Update the PortableEntryPoint to point to the actual code for the FCall implementation.
            // Return the PortableEntryPoint as the PCODE.
            PCODE entryPoint = GetPortableEntryPoint();
            PortableEntryPoint::SetActualCode(entryPoint, pCode);
            pCode = entryPoint;
        }
        else
        {
            MethodDesc* helperMD = PortableEntryPoint::GetMethodDesc(pCode);
            // If the FCall implementation is managed, then we need to potentially set up the interpreter code for it as well.
            // This is because the FCall may have been compiled to an IL stub that needs to be interpreted.
            if (helperMD->ShouldCallPrestub())
                (void)helperMD->DoPrestub(NULL /* MethodTable */, CallerGCMode::Coop);
            void* ilStubInterpData = helperMD->GetInterpreterCode();
            // WASM-TODO: update this when we will have codegen
            _ASSERTE(ilStubInterpData != NULL);
            SetInterpreterCode((InterpByteCodeStart*)ilStubInterpData);

            // Use this method's own PortableEntryPoint rather than the helper's.
            // It is required to maintain 1:1 mapping between MethodDesc and its entrypoint.
            PCODE entryPoint = GetPortableEntryPoint();
            PortableEntryPoint::SetInterpreterData(entryPoint, (PCODE)(TADDR)ilStubInterpData);
            pCode = entryPoint;
        }
#else // !FEATURE_PORTABLE_ENTRYPOINTS
        // FCalls are always wrapped in a precode to enable mapping of the entrypoint back to MethodDesc
        GetOrCreatePrecode();
#endif // FEATURE_PORTABLE_ENTRYPOINTS
    }
    else if (IsArray())
    {
        pStub = GenerateArrayOpStub((ArrayMethodDesc*)this);
    }
    else if (IsEEImpl())
    {
        _ASSERTE(GetMethodTable()->IsDelegate());
        pStub = COMDelegate::GetInvokeMethodStub((EEImplMethodDesc*)this);
    }
    else
    {
        // This is a method type we don't handle yet
        _ASSERTE(!"Unknown Method Type");
    }

    /**************************   POSTJIT *************************/
    _ASSERTE(pCode == (PCODE)NULL || GetNativeCode() == (PCODE)NULL || pCode == GetNativeCode());