summaryrefslogtreecommitdiff
path: root/src/vm/rejit.h
blob: b417851d133d85a2f7b9035ec672b84788c7dfa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// 
// ===========================================================================
// File: REJIT.H
//

// 
// REJIT.H defines the class and structures used to store info about rejitted
// methods.  See comment at top of rejit.cpp for more information on how
// rejit works.
// 
// ===========================================================================
#ifndef _REJIT_H_
#define _REJIT_H_

#include "common.h"
#include "contractimpl.h"
#include "shash.h"
#include "corprof.h"
#include "codeversion.h"

class ReJitManager;
class MethodDesc;
class ClrDataAccess;

#ifdef FEATURE_REJIT

//---------------------------------------------------------------------------------------
// The CLR's implementation of ICorProfilerFunctionControl, which is passed
// to the profiler.  The profiler calls methods on this to specify the IL and
// codegen flags for a given rejit request.
// 
class ProfilerFunctionControl : public ICorProfilerFunctionControl
{
public:
    ProfilerFunctionControl(LoaderHeap * pHeap);
    virtual ~ProfilerFunctionControl();

    // IUnknown functions
    virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, void** pInterface);
    virtual ULONG STDMETHODCALLTYPE AddRef();
    virtual ULONG STDMETHODCALLTYPE Release();

    // ICorProfilerFunctionControl functions
    virtual HRESULT STDMETHODCALLTYPE SetCodegenFlags(DWORD flags);
    virtual HRESULT STDMETHODCALLTYPE SetILFunctionBody(ULONG cbNewILMethodHeader, LPCBYTE pbNewILMethodHeader);
    virtual HRESULT STDMETHODCALLTYPE SetILInstrumentedCodeMap(ULONG cILMapEntries, COR_IL_MAP * rgILMapEntries);

    // Accessors
    DWORD GetCodegenFlags();
    LPBYTE GetIL();
    ULONG GetInstrumentedMapEntryCount();
    COR_IL_MAP* GetInstrumentedMapEntries();


protected:
    Volatile<LONG> m_refCount;
    LoaderHeap * m_pHeap;
    DWORD m_dwCodegenFlags;
    ULONG m_cbIL;

    // This pointer will get copied into SharedReJitInfo::m_pbIL and owned there.
    LPBYTE m_pbIL;
    ULONG m_cInstrumentedMapEntries;
    COR_IL_MAP * m_rgInstrumentedMapEntries;
};

#endif  // FEATURE_REJIT

#ifndef DACCESS_COMPILE
// Used to walk the NGEN/R2R inlining data
class NativeImageInliningIterator
{
public:
    NativeImageInliningIterator();

    HRESULT Reset(Module *pInlineeModule, MethodDesc *pInlinee);
    BOOL Next();
    MethodDesc *GetMethodDesc();

private:
    Module *m_pModule;
    MethodDesc *m_pInlinee;
    NewArrayHolder<MethodInModule> m_dynamicBuffer;
    COUNT_T m_dynamicBufferSize;
    COUNT_T m_currentPos;

    const COUNT_T s_bufferSize = 10;
};
#endif // DACCESS_COMPILE

//---------------------------------------------------------------------------------------
// The big honcho.  One of these per AppDomain, plus one for the
// SharedDomain.  Contains the hash table of ReJitInfo structures to manage
// every rejit and revert request for its owning domain.
// 
class ReJitManager
{
    friend class ClrDataAccess;
    friend class DacDbiInterfaceImpl;
    friend class CEEInfo;

private:

#ifdef FEATURE_REJIT

    // One global crst (for the entire CLR instance) to synchronize
    // cross-ReJitManager operations, such as batch calls to RequestRejit and
    // RequestRevert (which modify multiple ReJitManager instances).
    static CrstStatic s_csGlobalRequest;

#endif //FEATURE_REJIT

public:

    static void InitStatic();

    static BOOL IsReJITEnabled();

    static BOOL IsReJITInlineTrackingEnabled();

    static HRESULT RequestReJIT(
        ULONG                   cFunctions,
        ModuleID                rgModuleIDs[],
        mdMethodDef             rgMethodDefs[],
        COR_PRF_REJIT_FLAGS   flags);
    
    static HRESULT RequestRevert(
        ULONG       cFunctions,
        ModuleID    rgModuleIDs[],
        mdMethodDef rgMethodDefs[],
        HRESULT     rgHrStatuses[]);

    static HRESULT ConfigureILCodeVersion(ILCodeVersion ilCodeVersion);
    static CORJIT_FLAGS JitFlagsFromProfCodegenFlags(DWORD dwCodegenFlags);

    static ReJITID GetReJitId(PTR_MethodDesc pMD, PCODE pCodeStart);
    static ReJITID GetReJitIdNoLock(PTR_MethodDesc pMD, PCODE pCodeStart);
    static HRESULT GetReJITIDs(PTR_MethodDesc pMD, ULONG cReJitIds, ULONG * pcReJitIds, ReJITID reJitIds[]);

#ifdef FEATURE_REJIT

#ifndef DACCESS_COMPILE
    static void ReportReJITError(CodeVersionManager::CodePublishError* pErrorRecord);
    static void ReportReJITError(Module* pModule, mdMethodDef methodDef, MethodDesc* pMD, HRESULT hrStatus);
#endif

private:

    static HRESULT UpdateActiveILVersions(
        ULONG               cFunctions,
        ModuleID            rgModuleIDs[],
        mdMethodDef         rgMethodDefs[],
        HRESULT             rgHrStatuses[],
        BOOL                fIsRevert,
        COR_PRF_REJIT_FLAGS flags);

    struct CodeActivationBatch
    {
        CodeActivationBatch(CodeVersionManager * pCodeVersionManager) :
            m_pCodeVersionManager(pCodeVersionManager)
        {}
        CodeVersionManager* m_pCodeVersionManager;
        CDynArray<ILCodeVersion> m_methodsToActivate;
    };

    class CodeActivationBatchTraits : public DefaultSHashTraits<CodeActivationBatch *>
    {
    public:
        typedef DefaultSHashTraits<CodeActivationBatch *> PARENT;
        typedef PARENT::element_t element_t;
        typedef PARENT::count_t count_t;
        typedef CodeVersionManager * key_t;
        static key_t GetKey(const element_t &e) { return e->m_pCodeVersionManager; }
        static BOOL Equals(key_t k1, key_t k2) { return (k1 == k2); }
        static count_t Hash(key_t k) { return (count_t)(SIZE_T)k; }
        static bool IsNull(const element_t &e) { return (e == NULL); }
    };

    static HRESULT UpdateActiveILVersion(
        SHash<CodeActivationBatchTraits> *pMgrToCodeActivationBatch,
        Module *            pModule,
        mdMethodDef         methodDef,
        BOOL                fIsRevert,
        COR_PRF_REJIT_FLAGS flags);

    static HRESULT UpdateNativeInlinerActiveILVersions(
        SHash<CodeActivationBatchTraits> *pMgrToCodeActivationBatch,
        MethodDesc         *pInlinee,
        BOOL                fIsRevert,
        COR_PRF_REJIT_FLAGS flags);
    
    static HRESULT UpdateJitInlinerActiveILVersions(
        SHash<CodeActivationBatchTraits> *pMgrToCodeActivationBatch,
        MethodDesc         *pInlinee,
        BOOL                fIsRevert,
        COR_PRF_REJIT_FLAGS flags);

    static HRESULT BindILVersion(
        CodeVersionManager *pCodeVersionManager,
        PTR_Module          pModule,
        mdMethodDef         methodDef,
        ILCodeVersion      *pILCodeVersion,
        COR_PRF_REJIT_FLAGS flags);

#endif // FEATURE_REJIT

};

#include "rejit.inl"

#endif // _REJIT_H_