Add some comments to SpanHelpers.Char IndexOf and LastIndexOf (#17447)
[platform/upstream/coreclr.git] / src / gc / gcinterface.ee.h
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 #ifndef _GCINTERFACE_EE_H_
6 #define _GCINTERFACE_EE_H_
7
8 enum EtwGCRootFlags
9 {
10     kEtwGCRootFlagsPinning =            0x1,
11     kEtwGCRootFlagsWeakRef =            0x2,
12     kEtwGCRootFlagsInterior =           0x4,
13     kEtwGCRootFlagsRefCounted =         0x8,
14 };
15
16 enum EtwGCRootKind
17 {
18     kEtwGCRootKindStack =               0,
19     kEtwGCRootKindFinalizer =           1,
20     kEtwGCRootKindHandle =              2,
21     kEtwGCRootKindOther =               3,
22 };
23
24 // This interface provides functions that the GC can use to fire events.
25 // Events fired on this interface are split into two categories: "known"
26 // events and "dynamic" events. Known events are events that are baked-in
27 // to the hosting runtime's event manifest and are part of the GC/EE interface.
28 // There is one callback on IGCToCLREventSink for each known event.
29 //
30 // Dynamic events are constructed at runtime by the GC and are not known
31 // to the EE. ([LOCALGC TODO dynamic event implementation])
32 class IGCToCLREventSink
33 {
34 public:
35     // Fires a dynamic event with the given event name and payload. Dynamic
36     // events are not known to the EE and are fired as an unschematized event
37     // to the underlying eventing implementation.
38     virtual
39     void FireDynamicEvent(
40         const char* eventName,
41         void* payload,
42         uint32_t payloadSize) = 0;
43     virtual
44     void FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type) = 0;
45
46     virtual
47     void FireGCEnd_V1(uint32_t count, uint32_t depth) = 0;
48
49     virtual
50     void FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength) = 0;
51
52     virtual
53     void FireGCHeapStats_V1(
54         uint64_t generationSize0,
55         uint64_t totalPromotedSize0,
56         uint64_t generationSize1,
57         uint64_t totalPromotedSize1,
58         uint64_t generationSize2,
59         uint64_t totalPromotedSize2,
60         uint64_t generationSize3,
61         uint64_t totalPromotedSize3,
62         uint64_t finalizationPromotedSize,
63         uint64_t finalizationPromotedCount,
64         uint32_t pinnedObjectCount,
65         uint32_t sinkBlockCount,
66         uint32_t gcHandleCount) = 0;
67
68     virtual
69     void FireGCCreateSegment_V1(void* address, size_t size, uint32_t type) = 0;
70
71     virtual
72     void FireGCFreeSegment_V1(void* address) = 0;
73
74     virtual
75     void FireGCCreateConcurrentThread_V1() = 0;
76
77     virtual
78     void FireGCTerminateConcurrentThread_V1() = 0;
79
80     virtual
81     void FireGCTriggered(uint32_t reason) = 0;
82
83     virtual
84     void FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes) = 0;
85
86     virtual
87     void FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId) = 0;
88
89     virtual
90     void FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired,
91         int32_t numHeaps,
92         uint32_t condemnedGeneration,
93         uint32_t gen0reductionCount,
94         uint32_t reason,
95         uint32_t globalMechanisms,
96         uint32_t pauseMode,
97         uint32_t memoryPressure) = 0;
98
99     virtual
100     void FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind) = 0;
101
102     virtual
103     void FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress) = 0;
104
105     virtual
106     void FirePinObjectAtGCTime(void* object, uint8_t** ppObject) = 0;
107
108     virtual
109     void FireGCPerHeapHistory_V3(void *freeListAllocated,
110                                  void *freeListRejected,
111                                  void *endOfSegAllocated,
112                                  void *condemnedAllocated,
113                                  void *pinnedAllocated,
114                                  void *pinnedAllocatedAdvance,
115                                  uint32_t runningFreeListEfficiency,
116                                  uint32_t condemnReasons0,
117                                  uint32_t condemnReasons1,
118                                  uint32_t compactMechanisms,
119                                  uint32_t expandMechanisms,
120                                  uint32_t heapIndex,
121                                  void *extraGen0Commit,
122                                  uint32_t count,
123                                  uint32_t valuesLen,
124                                  void *values) = 0;
125     virtual
126     void FireBGCBegin() = 0;
127     virtual
128     void FireBGC1stNonConEnd() = 0;
129     virtual
130     void FireBGC1stConEnd() = 0;
131     virtual
132     void FireBGC2ndNonConBegin() = 0;
133     virtual
134     void FireBGC2ndNonConEnd() = 0;
135     virtual
136     void FireBGC2ndConBegin() = 0;
137     virtual
138     void FireBGC2ndConEnd() = 0;
139     virtual
140     void FireBGCDrainMark(uint64_t objects) = 0;
141     virtual
142     void FireBGCRevisit(uint64_t pages, uint64_t objects, uint32_t isLarge) = 0;
143     virtual
144     void FireBGCOverflow(uint64_t min, uint64_t max, uint64_t objects, uint32_t isLarge) = 0;
145     virtual
146     void FireBGCAllocWaitBegin(uint32_t reason) = 0;
147     virtual
148     void FireBGCAllocWaitEnd(uint32_t reason) = 0;
149     virtual
150     void FireGCFullNotify_V1(uint32_t genNumber, uint32_t isAlloc) = 0;
151     virtual
152     void FireSetGCHandle(void *handleID, void *objectID, uint32_t kind, uint32_t generation, uint64_t appDomainID) = 0;
153     virtual
154     void FirePrvSetGCHandle(void *handleID, void *objectID, uint32_t kind, uint32_t generation, uint64_t appDomainID) = 0;
155     virtual
156     void FireDestroyGCHandle(void *handleID) = 0;
157     virtual
158     void FirePrvDestroyGCHandle(void *handleID) = 0;
159 };
160
161 // This interface provides the interface that the GC will use to speak to the rest
162 // of the execution engine. Everything that the GC does that requires the EE
163 // to be informed or that requires EE action must go through this interface.
164 //
165 // When BUILD_AS_STANDALONE is defined, this class is named IGCToCLR and is
166 // an abstract class. The EE will provide a class that fulfills this interface,
167 // and the GC will dispatch virtually on it to call into the EE. When BUILD_AS_STANDALONE
168 // is not defined, this class is named GCToEEInterface and the GC will dispatch statically on it.
169 class IGCToCLR {
170 public:
171     // Suspends the EE for the given reason.
172     virtual
173     void SuspendEE(SUSPEND_REASON reason) = 0;
174
175     // Resumes all paused threads, with a boolean indicating
176     // if the EE is being restarted because a GC is complete.
177     virtual
178     void RestartEE(bool bFinishedGC) = 0;
179
180     // Performs a stack walk of all managed threads and invokes the given promote_func
181     // on all GC roots encountered on the stack. Depending on the condemned generation,
182     // this function may also enumerate all static GC refs if necessary.
183     virtual
184     void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) = 0;
185
186     // Callback from the GC informing the EE that it is preparing to start working.
187     virtual
188     void GcStartWork(int condemned, int max_gen) = 0;
189
190     // Callback from the GC informing the EE that it has completed the managed stack
191     // scan. User threads are still suspended at this point.
192     virtual
193     void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) = 0;
194
195     // Callback from the GC informing the EE that the background sweep phase of a BGC is
196     // about to begin.
197     virtual
198     void GcBeforeBGCSweepWork() = 0;
199
200     // Callback from the GC informing the EE that a GC has completed.
201     virtual
202     void GcDone(int condemned) = 0;
203
204     // Predicate for the GC to query whether or not a given refcounted handle should
205     // be promoted.
206     virtual
207     bool RefCountedHandleCallbacks(Object * pObject) = 0;
208
209     // Performs a weak pointer scan of the sync block cache.
210     virtual
211     void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2) = 0;
212
213     // Indicates to the EE that the GC intends to demote objects in the sync block cache.
214     virtual
215     void SyncBlockCacheDemote(int max_gen) = 0;
216
217     // Indicates to the EE that the GC has granted promotion to objects in the sync block cache.
218     virtual
219     void SyncBlockCachePromotionsGranted(int max_gen) = 0;
220
221     virtual
222     uint32_t GetActiveSyncBlockCount() = 0;
223
224     // Queries whether or not the current thread has preemptive GC disabled.
225     virtual
226     bool IsPreemptiveGCDisabled() = 0;
227
228     // Enables preemptive GC on the current thread. Returns true if the thread mode 
229     // was changed and false if the thread mode wasn't changed or the thread is not
230     // a managed thread. 
231     virtual
232     bool EnablePreemptiveGC() = 0;
233
234     // Disables preemptive GC on the current thread.
235     virtual
236     void DisablePreemptiveGC() = 0;
237
238     // Gets the Thread instance for the current thread, or null if no thread
239     // instance is associated with this thread.
240     //
241     // If the GC created the current thread, GetThread returns null for threads
242     // that were not created as suspendable (see `IGCHeap::CreateThread`).
243     virtual
244     Thread* GetThread() = 0;
245
246     // Retrieves the alloc context associated with the current thread.
247     virtual
248     gc_alloc_context * GetAllocContext() = 0;
249
250     // Calls the given enum_alloc_context_func with every active alloc context.
251     virtual
252     void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param) = 0;
253
254     // Creates and returns a new thread.
255     // Parameters:
256     //  threadStart - The function that will serve as the thread stub for the
257     //                new thread. It will be invoked immediately upon the
258     //                new thread upon creation.
259     //  arg - The argument that will be passed verbatim to threadStart.
260     //  is_suspendable - Whether or not the thread that is created should be suspendable
261     //                   from a runtime perspective. Threads that are suspendable have
262     //                   a VM Thread object associated with them that can be accessed
263     //                   using `IGCHeap::GetThread`.
264     //  name - The name of this thread, optionally used for diagnostic purposes.
265     // Returns:
266     //  true if the thread was started successfully, false if not.
267     virtual
268     bool CreateThread(void (*threadStart)(void*), void* arg, bool is_suspendable, const char* name) = 0;
269
270     // When a GC starts, gives the diagnostics code a chance to run.
271     virtual
272     void DiagGCStart(int gen, bool isInduced) = 0;
273
274     // When GC heap segments change, gives the diagnostics code a chance to run.
275     virtual
276     void DiagUpdateGenerationBounds() = 0;
277
278     // When a GC ends, gives the diagnostics code a chance to run.
279     virtual
280     void DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent) = 0;
281
282     // During a GC after we discover what objects' finalizers should run, gives the diagnostics code a chance to run.
283     virtual
284     void DiagWalkFReachableObjects(void* gcContext) = 0;
285
286     // During a GC after we discover the survivors and the relocation info, 
287     // gives the diagnostics code a chance to run. This includes LOH if we are 
288     // compacting LOH.
289     virtual
290     void DiagWalkSurvivors(void* gcContext) = 0;
291
292     // During a full GC after we discover what objects to survive on LOH,
293     // gives the diagnostics code a chance to run.
294     virtual
295     void DiagWalkLOHSurvivors(void* gcContext) = 0;
296
297     // At the end of a background GC, gives the diagnostics code a chance to run.
298     virtual
299     void DiagWalkBGCSurvivors(void* gcContext) = 0;
300
301     // Informs the EE of changes to the location of the card table, potentially updating the write
302     // barrier if it needs to be updated.
303     virtual
304     void StompWriteBarrier(WriteBarrierParameters* args) = 0;
305
306     // Signals to the finalizer thread that there are objects ready to
307     // be finalized.
308     virtual
309     void EnableFinalization(bool foundFinalizers) = 0;
310
311     // Signals to the EE that the GC encountered a fatal error and can't recover.
312     virtual
313     void HandleFatalError(unsigned int exitCode) = 0;
314
315     // Asks the EE if it wants a particular object to be finalized when unloading
316     // an app domain.
317     virtual
318     bool ShouldFinalizeObjectForUnload(AppDomain* pDomain, Object* obj) = 0;
319
320     // Offers the EE the option to finalize the given object eagerly, i.e.
321     // not on the finalizer thread but on the current thread. The
322     // EE returns true if it finalized the object eagerly and the GC does not
323     // need to do so, and false if it chose not to eagerly finalize the object
324     // and it's up to the GC to finalize it later.
325     virtual
326     bool EagerFinalized(Object* obj) = 0;
327
328     // Asks the EE if it wishes for the current GC to be a blocking GC. The GC will
329     // only invoke this callback when it intends to do a full GC, so at this point
330     // the EE can opt to elevate that collection to be a blocking GC and not a background one.
331     virtual
332     bool ForceFullGCToBeBlocking() = 0;
333
334     // Retrieves the method table for the free object, a special kind of object used by the GC
335     // to keep the heap traversable. Conceptually, the free object is similar to a managed array
336     // of bytes: it consists of an object header (like all objects) and a "numComponents" field,
337     // followed by some number of bytes of space that's free on the heap.
338     //
339     // The free object allows the GC to traverse the heap because it can inspect the numComponents
340     // field to see how many bytes to skip before the next object on a heap segment begins.
341     virtual
342     MethodTable* GetFreeObjectMethodTable() = 0;
343
344     // Asks the EE for the value of a given configuration key. If the EE does not know or does not
345     // have a value for the requeested config key, false is returned and the value of the passed-in
346     // pointer is undefined. Otherwise, true is returned and the config key's value is written to
347     // the passed-in pointer.
348     virtual
349     bool GetBooleanConfigValue(const char* key, bool* value) = 0;
350
351     virtual
352     bool GetIntConfigValue(const char* key, int64_t* value) = 0;
353
354     virtual
355     bool GetStringConfigValue(const char* key, const char** value) = 0;
356
357     virtual
358     void FreeStringConfigValue(const char* value) = 0;
359
360     // Returns true if this thread is a "GC thread", or a thread capable of
361     // doing GC work. Threads are either /always/ GC threads
362     // (if they were created for this purpose - background GC threads
363     // and server GC threads) or they became GC threads by suspending the EE
364     // and initiating a collection.
365     virtual
366     bool IsGCThread() = 0;
367
368     // Returns true if the current thread is either a background GC thread
369     // or a server GC thread.
370     virtual
371     bool WasCurrentThreadCreatedByGC() = 0;
372
373     // Given an object, if this object is an instance of `System.Threading.OverlappedData`,
374     // and the runtime treats instances of this class specially, traverses the objects that
375     // are directly or (once) indirectly pinned by this object and reports them to the GC for
376     // the purposes of relocation and promotion.
377     //
378     // Overlapped objects are very special and as such the objects they wrap can't be promoted in
379     // the same manner as normal objects. This callback gives the EE the opportunity to hide these
380     // details, if they are implemented at all.
381     //
382     // This function is a no-op if "object" is not an OverlappedData object.
383     virtual
384     void WalkAsyncPinnedForPromotion(Object* object, ScanContext* sc, promote_func* callback) = 0;
385
386     // Given an object, if this object is an instance of `System.Threading.OverlappedData` and the
387     // runtime treats instances of this class specially, traverses the objects that are directly
388     // or once indirectly pinned by this object and invokes the given callback on them. The callback
389     // is passed the following arguments:
390     //     Object* "from" - The object that "caused" the "to" object to be pinned. If a single object
391     //                      is pinned directly by this OverlappedData, this object will be the
392     //                      OverlappedData object itself. If an array is pinned by this OverlappedData,
393     //                      this object will be the pinned array.
394     //     Object* "to"   - The object that is pinned by the "from" object. If a single object is pinned
395     //                      by an OverlappedData, "to" will be that single object. If an array is pinned
396     //                      by an OverlappedData, the callback will be invoked on all elements of that
397     //                      array and each element will be a "to" object.
398     //     void* "context" - Passed verbatim from "WalkOverlappedObject" to the callback function.
399     // The "context" argument will be passed directly to the callback without modification or inspection.
400     //
401     // This function is a no-op if "object" is not an OverlappedData object.
402     virtual
403     void WalkAsyncPinned(Object* object, void* context, void(*callback)(Object*, Object*, void*)) = 0;
404
405     // Returns an IGCToCLREventSink instance that can be used to fire events.
406     virtual
407     IGCToCLREventSink* EventSink() = 0;
408 };
409
410 #endif // _GCINTERFACE_EE_H_