class __declspec()

in src/InstrumentationEngine/MethodInfo.h [25:288]


    class __declspec(uuid("CDD3824F-B876-4450-9459-885BA1C21540"))
    CMethodInfo : public IMethodInfo2, public CDataContainer
    {
    private:
        // Non-addref'd back pointer the profiler manager.
        CProfilerManager* m_pProfilerManager;

        // True if this method info is not shared across calls and therefore not stored in s_methodInfos or within the containing module info
        // This ensures unrelated calls do not stomp on the lifetime of methodinfos.
        bool m_bIsStandaloneMethodInfo;

        FunctionID m_functionId;
        mdToken m_tkFunction;

        ClassID m_classId;
        CComPtr<CModuleInfo> m_pModuleInfo;

        // Clr callback for rejit scenarios. Not set for non-rejit.
        CComPtr<ICorProfilerFunctionControl> m_pFunctionControl;

        // metadata token of the containing class
        mdTypeDef m_tkTypeDef;

        // declaring type
        CComPtr<IType> m_pDeclaringType;

        // return value type
        CComPtr<IType> m_pReturnType;

        // NOTE: Not initialized until a call to GetName is made.
        // then the value is cached
        CComBSTR m_bstrMethodName;

        // NOTE: Not initialized until a call to GetFullName is made.
        // then the value is cached
        CComBSTR m_bstrMethodFullName;

        CorMethodAttr m_methodAttr;
        CorMethodImpl m_implFlags;
        ULONG m_rva;

        // method signatures
        PCOR_SIGNATURE m_pSig;
        ULONG m_cbSigBlob;
        bool m_bDeleteCorSig;

        // method parameters
        std::vector<CComPtr<IMethodParameter>> m_parameters;
        std::vector<CComPtr<IType>> m_genericParameters;

        CComPtr<CInstructionGraph> m_pInstructionGraph;

        // All instrumented methods are converted to fat header
        COR_ILMETHOD_FAT m_newCorHeader;
        bool m_bIsHeaderInitialized;

        // Do not use CComPtr here! Local variables are tied to the lifetime of MethodInfo.
        // Local vars
        CLocalVariableCollection* m_localVariables;

        // Read-only original local vars.
        CLocalVariableCollection* m_origLocalVariables;

        // Raw IL stream. Set after instrumentation methods are finished, but before raw profiler callbacks.
        // This does not include method headers or exception handlers
        vector<BYTE> m_pILStream;

        // map of old offsets to new offsets. Originally set when instrumentation methods have finished.
        // Updated if raw callbacks modify il. Note, this is a CSharedArray because it is also cached by this
        // method's ModuleInfo
        CSharedArray<COR_IL_MAP> m_pCorILMap;

        // The rendered method body including headers and exception handlers after instrumenation methods have finished, but before
        // raw profilers execute. This includes the updated core header, the il body, the exception ranges etc...
        vector<BYTE> m_pIntermediateRenderedMethod;

        // The final rendered method body after all instrumenation methods and raw profiler hooks have instrumented
        // NOTE: a seperate copy is needed because the clr requires a callee destroyed buffer in the rejit cases, and
        // some hosts, including MMA, will try to consume the buffer after the set to calculate the cor il map.
        vector<BYTE> m_pFinalRenderedMethod;

        //There are raw profiler hook situations where we will not be in control of the buffer passed to SetILFunctionBody:
        // - The user allocates the buffer, skipping GetILFunctionBodyAllocator (in newer runtimes, RVA's do not have any specific memory location requirements)
        // - Raw profiler hook calls SetILFunctionBody right after DefineMethod
        LPCBYTE m_userDefinedBuffer;

        // Set to true if any client has instrumented the method.
        bool m_bIsInstrumented;

        CComPtr<CExceptionSection> m_pExceptionSection;

        CComPtr<CInstructionFactory> m_pInstructionFactory;

        // Code gen flags used during a rejit
        DWORD m_dwRejitCodeGenFlags;

        bool m_bMethodSignatureInitialized;

        bool m_bCorAttributesInitialized;

        bool m_bGenericParametersInitialized;

        // Set to false after the before instrumentation pass to ensure instrumentation methods
        // do not set the baseline at incorrect times.
        bool m_bIsCreateBaselineEnabled;

        bool m_bIsRejit;

    public:
        DEFINE_DELEGATED_REFCOUNT_ADDREF(CMethodInfo);
        DEFINE_DELEGATED_REFCOUNT_RELEASE(CMethodInfo);
        STDMETHOD(QueryInterface)(_In_ REFIID riid, _Out_ void **ppvObject) override
        {
            return ImplQueryInterface(
                static_cast<IMethodInfo2*>(this),
                static_cast<IMethodInfo*>(this),
                static_cast<IDataContainer*>(static_cast<CDataContainer*>(this)),
                riid,
                ppvObject
                );
        }
    public:
        CMethodInfo(
            _In_ CProfilerManager* pProfilerManager,
            _In_ FunctionID functionId,
            _In_ mdToken functionToken,
            _In_ ClassID classId,
            _In_ CModuleInfo* pModuleInfo,
            _In_opt_ ICorProfilerFunctionControl* pFunctionControl
            );

        ~CMethodInfo();

        HRESULT Initialize(_In_ bool bAddToMethodInfoMap, _In_ bool isRejit);

        // Called after instrumentation is finished with the method. This removes it from the
        // static map. Only used for the non-rejit instrumentation code path. Not for any other
        // scenario.
        HRESULT Cleanup();

        HRESULT ApplyIntermediateMethodInstrumentation();

        HRESULT CreateILFunctionBody();

        HRESULT GetIntermediateRenderedFunctionBody(
            _Out_opt_ LPCBYTE* ppMethodHeader,
            _Out_opt_ ULONG* pcbMethodSize
            );

        // Called after the raw profiler hook has instrumented the function. Sets the IL transformation
        // status of this method to true.
        HRESULT SetFinalRenderedFunctionBody(
            _In_reads_bytes_(cbMethodSize) LPCBYTE pMethodHeader,
            _In_ ULONG cbMethodSize);

         bool IsInstrumented() const
         {
             return m_bIsInstrumented;
         }

         // Applys all IL transformations and sets the IL cached transformation status of this method to true.
         HRESULT ApplyFinalInstrumentation();

         HRESULT MergeILInstrumentedCodeMap(_In_ ULONG cILMapEntries, _In_reads_(cILMapEntries) COR_IL_MAP* rgILMapEntries);

        // Recreate the instruction graph, exception section, and cor_il_map from the
        // raw results. This is used by the diagnostic logging engine.
        HRESULT GetInstrumentationResults(
            _Out_ CInstructionGraph** ppInstructionGraph,
            _Out_ CExceptionSection** ppExceptionSection,
            _Out_ COR_IL_MAP** ppCorILMap,
            _Out_ DWORD* dwCorILMapmLen
            );

        void LogMethodInfo();
        void LogInstructionGraph(_In_ CInstructionGraph* pInstructionGraph);
        void LogExceptionSection(_In_ CExceptionSection* pExceptionSection);
        void LogCorIlMap(_In_reads_(dwCorILMapmLen) const COR_IL_MAP* pCorIlMap, _In_ DWORD dwCorILMapmLen);
        tstring GetCorElementTypeString(_In_ IType* pType);


        CModuleInfo* GetModuleInfo();

        bool IsCreateBaselineEnabled() const;
        void DisableCreateBaseline();
        bool IsRejit() const
        {
            return m_bIsRejit;
        }

        // IMethodInfo methods
    public:
        virtual HRESULT __stdcall GetModuleInfo(_Out_ IModuleInfo** ppModuleInfo) override;

        virtual HRESULT __stdcall GetName(_Out_ BSTR* pbstrName) override;
        virtual HRESULT __stdcall GetFullName(_Out_ BSTR* pbstrFullName) override;

        // Obtain the graph of instructions.  Manipulating this graph will result in changes to the code
        // a the end of jit or rejit.
        virtual HRESULT __stdcall GetInstructions(_Out_ IInstructionGraph** ppInstructionGraph) override;

        // Obtain the collection of local variables
        virtual HRESULT __stdcall GetLocalVariables(_Out_ ILocalVariableCollection** ppLocalVariables) override;

        virtual HRESULT __stdcall GetClassId(_Out_ ClassID* pClassId) override;
        virtual HRESULT __stdcall GetFunctionId(_Out_ FunctionID* pFunctionID) override;
        virtual HRESULT __stdcall GetMethodToken(_Out_ mdToken* pToken) override;
        virtual HRESULT __stdcall GetGenericParameterCount(_Out_ DWORD* pCount) override;
        virtual HRESULT __stdcall GetIsStatic(_Out_ BOOL* pbValue) override;
        virtual HRESULT __stdcall GetIsPublic(_Out_ BOOL* pbValue) override;
        virtual HRESULT __stdcall GetIsPrivate(_Out_ BOOL* pbValue) override;
        virtual HRESULT __stdcall GetIsPropertyGetter(_Out_ BOOL* pbValue) override;
        virtual HRESULT __stdcall GetIsPropertySetter(_Out_ BOOL* pbValue) override;
        virtual HRESULT __stdcall GetIsFinalizer(_Out_ BOOL* pbValue) override;
        virtual HRESULT __stdcall GetIsConstructor(_Out_ BOOL* pbValue) override;
        virtual HRESULT __stdcall GetIsStaticConstructor(_Out_ BOOL* pbValue) override;

        virtual HRESULT __stdcall GetParameters(_Out_ IEnumMethodParameters** ppMethodArgs) override;
        virtual HRESULT __stdcall GetDeclaringType(_Out_ IType** ppType) override;
        virtual HRESULT __stdcall GetReturnType(_Out_ IType** ppType) override;

        virtual HRESULT __stdcall GetCorSignature(_In_ DWORD cbBuffer, _Out_opt_ BYTE* corSignature, _Out_ DWORD* pcbSignature) override;

        virtual HRESULT __stdcall GetLocalVarSigToken(_Out_ mdToken* pToken) override;
        virtual HRESULT __stdcall SetLocalVarSigToken(_In_ mdToken token) override;

        virtual HRESULT __stdcall GetAttributes(_Out_ /*CorMethodAttr*/ DWORD* pCorMethodAttr) override;
        virtual HRESULT __stdcall GetRejitCodeGenFlags(_Out_ DWORD* pRefitFlags) override;
        virtual HRESULT __stdcall GetCodeRva(_Out_ DWORD* pRva) override;
        virtual HRESULT __stdcall MethodImplFlags(_Out_ /*CorMethodImpl*/ UINT* pCorMethodImpl) override;

        // Allow callers to adjust optimizations during a rejit. For instance, disable all optimizations against a method
        virtual HRESULT __stdcall SetRejitCodeGenFlags(_In_ DWORD dwFlags) override;

        virtual HRESULT __stdcall GetExceptionSection(_Out_ IExceptionSection** ppExceptionSection) override;

        virtual HRESULT __stdcall GetInstructionFactory(_Out_ IInstructionFactory** ppInstructionFactory) override;

        // Return the running count of the number of rejits for this methodinfo
        virtual HRESULT __stdcall GetRejitCount(_Out_ DWORD* pdwRejitCount) override;

        virtual HRESULT __stdcall GetMaxStack(_Out_ DWORD* pMaxStack) override;

        virtual HRESULT __stdcall GetSingleRetDefaultInstrumentation(_Out_ ISingleRetDefaultInstrumentation** ppSingleRetDefaultInstrumentation) override;

    // IMethodInfo2 methods
    public:
        virtual HRESULT __stdcall GetOriginalLocalVariables(_Out_ ILocalVariableCollection** ppLocalVariables) override;

    private:
        HRESULT InitializeName(_In_ mdToken tkFunction);
        HRESULT InitializeCorAttributes(_In_ mdToken tkFunction);
        HRESULT InitializeMethodSignature(_In_ mdToken tkFunction);
        HRESULT InitializeHeader(
            _Out_opt_ IMAGE_COR_ILMETHOD** ppMethodHeader = nullptr,
            _Out_opt_ ULONG* pcbMethodSize = 0);
        HRESULT InitializeInstructionsAndExceptions();
        HRESULT InitializeGenericParameters(mdToken tkFunction);

        HRESULT GetFinalInstrumentation(_Out_ DWORD* pcbMethodBody, _Out_ LPCBYTE* ppMethodBody);

        HRESULT InitializeFullName();

    };