summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gc/gc.cpp45
-rw-r--r--src/gc/gc.h23
-rw-r--r--src/gc/gcee.cpp175
-rw-r--r--src/gc/gcevents.h18
-rw-r--r--src/gc/gcinterface.ee.h65
-rw-r--r--src/inc/eventtrace.h9
-rw-r--r--src/vm/eventtrace.cpp78
-rw-r--r--src/vm/gctoclreventsink.cpp183
-rw-r--r--src/vm/gctoclreventsink.h35
9 files changed, 393 insertions, 238 deletions
diff --git a/src/gc/gc.cpp b/src/gc/gc.cpp
index 2b31388d38..d6ab65a4f1 100644
--- a/src/gc/gc.cpp
+++ b/src/gc/gc.cpp
@@ -816,7 +816,7 @@ public:
inline void fire_event (int heap, join_time time, join_type type, int join_id)
{
- FireEtwGCJoin_V2(heap, time, type, GetClrInstanceId(), join_id);
+ FIRE_EVENT(GCJoin_V2, heap, time, type, join_id);
}
void join (gc_heap* gch, int join_id)
@@ -3028,13 +3028,12 @@ void gc_heap::fire_pevents()
settings.record (&gc_data_global);
gc_data_global.print();
- FireEtwGCGlobalHeapHistory_V2(gc_data_global.final_youngest_desired,
+ FIRE_EVENT(GCGlobalHeapHistory_V2, gc_data_global.final_youngest_desired,
gc_data_global.num_heaps,
gc_data_global.condemned_generation,
gc_data_global.gen0_reduction_count,
gc_data_global.reason,
gc_data_global.global_mechanims_p,
- GetClrInstanceId(),
gc_data_global.pause_mode,
gc_data_global.mem_pressure);
@@ -4677,10 +4676,9 @@ gc_heap::soh_get_segment_to_expand()
}
#endif //BACKGROUND_GC
- FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(result),
- (size_t)(heap_segment_reserved (result) - heap_segment_mem(result)),
- ETW::GCLog::ETW_GC_INFO::SMALL_OBJECT_HEAP,
- GetClrInstanceId());
+ FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(result),
+ (size_t)(heap_segment_reserved (result) - heap_segment_mem(result)),
+ gc_etw_segment_small_object_heap);
}
get_gc_data_per_heap()->set_mechanism (gc_heap_expand, (result ? expand_new_seg : expand_no_memory));
@@ -4846,7 +4844,7 @@ gc_heap::get_segment (size_t size, BOOL loh_p)
void release_segment (heap_segment* sg)
{
ptrdiff_t delta = 0;
- FireEtwGCFreeSegment_V1((size_t)heap_segment_mem(sg), GetClrInstanceId());
+ FIRE_EVENT(GCFreeSegment_V1, heap_segment_mem(sg));
virtual_free (sg, (uint8_t*)heap_segment_reserved (sg)-(uint8_t*)sg);
}
@@ -4867,7 +4865,7 @@ heap_segment* gc_heap::get_segment_for_loh (size_t size
#endif //MULTIPLE_HEAPS
res->flags |= heap_segment_flags_loh;
- FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(res), (size_t)(heap_segment_reserved (res) - heap_segment_mem(res)), ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP, GetClrInstanceId());
+ FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(res), (size_t)(heap_segment_reserved (res) - heap_segment_mem(res)), gc_etw_segment_large_object_heap);
GCToEEInterface::DiagUpdateGenerationBounds();
@@ -7837,7 +7835,7 @@ BOOL gc_heap::insert_ro_segment (heap_segment* seg)
set_ro_segment_in_range (seg);
}
- FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(seg), (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)), ETW::GCLog::ETW_GC_INFO::READ_ONLY_HEAP, GetClrInstanceId());
+ FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(seg), (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)), gc_etw_segment_read_only_heap);
leave_spin_lock (&gc_heap::gc_lock);
return TRUE;
@@ -10448,10 +10446,9 @@ gc_heap::init_gc_heap (int h_number)
if (!seg)
return 0;
- FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(seg),
- (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)),
- ETW::GCLog::ETW_GC_INFO::SMALL_OBJECT_HEAP,
- GetClrInstanceId());
+ FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(seg),
+ (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)),
+ gc_etw_segment_small_object_heap);
#ifdef SEG_MAPPING_TABLE
seg_mapping_table_add_segment (seg, __this);
@@ -10514,10 +10511,9 @@ gc_heap::init_gc_heap (int h_number)
return 0;
lseg->flags |= heap_segment_flags_loh;
- FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(lseg),
- (size_t)(heap_segment_reserved (lseg) - heap_segment_mem(lseg)),
- ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP,
- GetClrInstanceId());
+ FIRE_EVENT(GCCreateSegment_V1, heap_segment_mem(lseg),
+ (size_t)(heap_segment_reserved (lseg) - heap_segment_mem(lseg)),
+ gc_etw_segment_large_object_heap);
#ifdef SEG_MAPPING_TABLE
seg_mapping_table_add_segment (lseg, __this);
@@ -13229,9 +13225,8 @@ int gc_heap::try_allocate_more_space (alloc_context* acontext, size_t size,
if (etw_allocation_running_amount[etw_allocation_index] > etw_allocation_tick)
{
#ifdef FEATURE_REDHAWK
- FireEtwGCAllocationTick_V1((uint32_t)etw_allocation_running_amount[etw_allocation_index],
- ((gen_number == 0) ? ETW::GCLog::ETW_GC_INFO::AllocationSmall : ETW::GCLog::ETW_GC_INFO::AllocationLarge),
- GetClrInstanceId());
+ FIRE_EVENT(GCAllocationTick_V1, (uint32_t)etw_allocation_running_amount[etw_allocation_index],
+ (gen_number == 0) ? gc_etw_alloc_soh : gc_etw_alloc_loh);
#else
// Unfortunately some of the ETW macros do not check whether the ETW feature is enabled.
// The ones that do are much less efficient.
@@ -19163,7 +19158,7 @@ void gc_heap::get_memory_info (uint32_t* memory_load,
void fire_mark_event (int heap_num, int root_type, size_t bytes_marked)
{
dprintf (DT_LOG_0, ("-----------[%d]mark %d: %Id", heap_num, root_type, bytes_marked));
- FireEtwGCMarkWithType (heap_num, GetClrInstanceId(), root_type, bytes_marked);
+ FIRE_EVENT(GCMarkWithType, heap_num, root_type, bytes_marked);
}
//returns TRUE is an overflow happened.
@@ -26702,7 +26697,7 @@ BOOL gc_heap::prepare_bgc_thread(gc_heap* gh)
gh->bgc_threads_timeout_cs.Leave();
if(thread_created)
- FireEtwGCCreateConcurrentThread_V1(GetClrInstanceId());
+ FIRE_EVENT(GCCreateConcurrentThread_V1);
return success;
}
@@ -27044,7 +27039,7 @@ void gc_heap::bgc_thread_function()
//gc_heap::disable_preemptive (current_thread, TRUE);
}
- FireEtwGCTerminateConcurrentThread_V1(GetClrInstanceId());
+ FIRE_EVENT(GCTerminateConcurrentThread_V1);
dprintf (3, ("bgc_thread thread exiting"));
return;
@@ -35081,7 +35076,7 @@ GCHeap::GarbageCollectGeneration (unsigned int gen, gc_reason reason)
// We want to get a stack from the user thread that triggered the GC
// instead of on the GC thread which is the case for Server GC.
// But we are doing it for Workstation GC as well to be uniform.
- FireEtwGCTriggered((int) reason, GetClrInstanceId());
+ FIRE_EVENT(GCTriggered, static_cast<uint32_t>(reason));
#ifdef MULTIPLE_HEAPS
GcCondemnedGeneration = condemned_generation_number;
diff --git a/src/gc/gc.h b/src/gc/gc.h
index e16fccb91e..6641f0b097 100644
--- a/src/gc/gc.h
+++ b/src/gc/gc.h
@@ -70,6 +70,29 @@ enum gc_reason
reason_max
};
+// Types of GCs, emitted by the GCStart ETW event.
+enum gc_etw_type
+{
+ gc_etw_type_ngc = 0,
+ gc_etw_type_bgc = 1,
+ gc_etw_type_fgc = 2
+};
+
+// Types of segments, emitted by the GCCreateSegment ETW event.
+enum gc_etw_segment_type
+{
+ gc_etw_segment_small_object_heap = 0,
+ gc_etw_segment_large_object_heap = 1,
+ gc_etw_segment_read_only_heap = 2
+};
+
+// Types of allocations, emitted by the GCAllocationTick ETW event.
+enum gc_etw_alloc_kind
+{
+ gc_etw_alloc_soh = 0,
+ gc_etw_alloc_loh = 1
+};
+
/* forward declerations */
class CObjectHeader;
class Object;
diff --git a/src/gc/gcee.cpp b/src/gc/gcee.cpp
index c5cc88b373..358b40c403 100644
--- a/src/gc/gcee.cpp
+++ b/src/gc/gcee.cpp
@@ -77,7 +77,6 @@ void GCHeap::UpdatePreGCCounters()
#endif //ENABLE_PERF_COUNTERS
-#ifdef FEATURE_EVENT_TRACE
#ifdef MULTIPLE_HEAPS
//take the first heap....
gc_mechanisms *pSettings = &gc_heap::g_heaps[0]->settings;
@@ -85,27 +84,28 @@ void GCHeap::UpdatePreGCCounters()
gc_mechanisms *pSettings = &gc_heap::settings;
#endif //MULTIPLE_HEAPS
- ETW::GCLog::ETW_GC_INFO Info;
-
- Info.GCStart.Count = (uint32_t)pSettings->gc_index;
- Info.GCStart.Depth = (uint32_t)pSettings->condemned_generation;
- Info.GCStart.Reason = (ETW::GCLog::ETW_GC_INFO::GC_REASON)((int)(pSettings->reason));
-
- Info.GCStart.Type = ETW::GCLog::ETW_GC_INFO::GC_NGC;
+ uint32_t count = (uint32_t)pSettings->gc_index;
+ uint32_t depth = (uint32_t)pSettings->condemned_generation;
+ uint32_t reason = (uint32_t)pSettings->reason;
+ gc_etw_type type = gc_etw_type_ngc;
if (pSettings->concurrent)
{
- Info.GCStart.Type = ETW::GCLog::ETW_GC_INFO::GC_BGC;
+ type = gc_etw_type_bgc;
}
#ifdef BACKGROUND_GC
- else if (Info.GCStart.Depth < max_generation)
+ else if (depth < max_generation && pSettings->background_p)
{
- if (pSettings->background_p)
- Info.GCStart.Type = ETW::GCLog::ETW_GC_INFO::GC_FGC;
+ type = gc_etw_type_fgc;
}
-#endif //BACKGROUND_GC
+#endif // BACKGROUND_GC
- ETW::GCLog::FireGcStartAndGenerationRanges(&Info);
-#endif // FEATURE_EVENT_TRACE
+ FIRE_EVENT(GCStart_V2, count, depth, reason, static_cast<uint32_t>(type));
+ g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved)
+ {
+ uint64_t range = static_cast<uint64_t>(rangeEnd - rangeStart);
+ uint64_t rangeReserved = static_cast<uint64_t>(rangeEndReserved - rangeStart);
+ FIRE_EVENT(GCGenerationRange, generation, rangeStart, range, rangeReserved);
+ }, nullptr);
}
void GCHeap::UpdatePostGCCounters()
@@ -195,50 +195,34 @@ void GCHeap::UpdatePostGCCounters()
#endif //ENABLE_PERF_COUNTERS || FEATURE_EVENT_TRACE
#ifdef FEATURE_EVENT_TRACE
- ETW::GCLog::ETW_GC_INFO Info;
-
- Info.GCEnd.Depth = condemned_gen;
- Info.GCEnd.Count = (uint32_t)pSettings->gc_index;
- ETW::GCLog::FireGcEndAndGenerationRanges(Info.GCEnd.Count, Info.GCEnd.Depth);
-
- ETW::GCLog::ETW_GC_INFO HeapInfo;
- ZeroMemory(&HeapInfo, sizeof(HeapInfo));
-
- for (int gen_index = 0; gen_index <= (max_generation+1); gen_index++)
+ g_theGCHeap->DiagDescrGenerations([](void*, int generation, uint8_t* rangeStart, uint8_t* rangeEnd, uint8_t* rangeEndReserved)
{
- HeapInfo.HeapStats.GenInfo[gen_index].GenerationSize = g_GenerationSizes[gen_index];
- HeapInfo.HeapStats.GenInfo[gen_index].TotalPromotedSize = g_GenerationPromotedSizes[gen_index];
- }
+ uint64_t range = static_cast<uint64_t>(rangeEnd - rangeStart);
+ uint64_t rangeReserved = static_cast<uint64_t>(rangeEndReserved - rangeStart);
+ FIRE_EVENT(GCGenerationRange, generation, rangeStart, range, rangeReserved);
+ }, nullptr);
+
+ FIRE_EVENT(GCEnd_V1, static_cast<uint32_t>(pSettings->gc_index), condemned_gen);
#ifdef SIMPLE_DPRINTF
dprintf (2, ("GC#%d: 0: %Id(%Id); 1: %Id(%Id); 2: %Id(%Id); 3: %Id(%Id)",
- Info.GCEnd.Count,
- HeapInfo.HeapStats.GenInfo[0].GenerationSize,
- HeapInfo.HeapStats.GenInfo[0].TotalPromotedSize,
- HeapInfo.HeapStats.GenInfo[1].GenerationSize,
- HeapInfo.HeapStats.GenInfo[1].TotalPromotedSize,
- HeapInfo.HeapStats.GenInfo[2].GenerationSize,
- HeapInfo.HeapStats.GenInfo[2].TotalPromotedSize,
- HeapInfo.HeapStats.GenInfo[3].GenerationSize,
- HeapInfo.HeapStats.GenInfo[3].TotalPromotedSize));
+ pSettings->gc_index,
+ g_GenerationSizes[0], g_GenerationPromotedSizes[0],
+ g_GenerationSizes[1], g_GenerationPromotedSizes[1],
+ g_GenerationSizes[2], g_GenerationPromotedSizes[2],
+ g_GenerationSizes[3], g_GenerationPromotedSizes[3]));
#endif //SIMPLE_DPRINTF
- HeapInfo.HeapStats.FinalizationPromotedSize = promoted_finalization_mem;
- HeapInfo.HeapStats.FinalizationPromotedCount = GetFinalizablePromotedCount();
- HeapInfo.HeapStats.PinnedObjectCount = (uint32_t)total_num_pinned_objects;
- HeapInfo.HeapStats.SinkBlockCount = total_num_sync_blocks;
- HeapInfo.HeapStats.GCHandleCount = (uint32_t)total_num_gc_handles;
-
- FireEtwGCHeapStats_V1(HeapInfo.HeapStats.GenInfo[0].GenerationSize, HeapInfo.HeapStats.GenInfo[0].TotalPromotedSize,
- HeapInfo.HeapStats.GenInfo[1].GenerationSize, HeapInfo.HeapStats.GenInfo[1].TotalPromotedSize,
- HeapInfo.HeapStats.GenInfo[2].GenerationSize, HeapInfo.HeapStats.GenInfo[2].TotalPromotedSize,
- HeapInfo.HeapStats.GenInfo[3].GenerationSize, HeapInfo.HeapStats.GenInfo[3].TotalPromotedSize,
- HeapInfo.HeapStats.FinalizationPromotedSize,
- HeapInfo.HeapStats.FinalizationPromotedCount,
- HeapInfo.HeapStats.PinnedObjectCount,
- HeapInfo.HeapStats.SinkBlockCount,
- HeapInfo.HeapStats.GCHandleCount,
- GetClrInstanceId());
+ FIRE_EVENT(GCHeapStats_V1,
+ g_GenerationSizes[0], g_GenerationPromotedSizes[0],
+ g_GenerationSizes[1], g_GenerationPromotedSizes[1],
+ g_GenerationSizes[2], g_GenerationPromotedSizes[2],
+ g_GenerationSizes[3], g_GenerationPromotedSizes[3],
+ promoted_finalization_mem,
+ GetFinalizablePromotedCount(),
+ static_cast<uint32_t>(total_num_pinned_objects),
+ total_num_sync_blocks,
+ static_cast<uint32_t>(total_num_gc_handles));
#endif // FEATURE_EVENT_TRACE
#if defined(ENABLE_PERF_COUNTERS)
@@ -458,70 +442,13 @@ bool GCHeap::IsConcurrentGCInProgress()
#ifdef FEATURE_EVENT_TRACE
void gc_heap::fire_etw_allocation_event (size_t allocation_amount, int gen_number, uint8_t* object_address)
{
- void * typeId = nullptr;
- const WCHAR * name = nullptr;
-#ifdef FEATURE_REDHAWK
- typeId = RedhawkGCInterface::GetLastAllocEEType();
-#else
- InlineSString<MAX_CLASSNAME_LENGTH> strTypeName;
-
- EX_TRY
- {
- TypeHandle th = GCToEEInterface::GetThread()->GetTHAllocContextObj();
-
- if (th != 0)
- {
- th.GetName(strTypeName);
- name = strTypeName.GetUnicode();
- typeId = th.GetMethodTable();
- }
- }
- EX_CATCH {}
- EX_END_CATCH(SwallowAllExceptions)
-#endif
-
- if (typeId != nullptr)
- {
- FireEtwGCAllocationTick_V3((uint32_t)allocation_amount,
- ((gen_number == 0) ? ETW::GCLog::ETW_GC_INFO::AllocationSmall : ETW::GCLog::ETW_GC_INFO::AllocationLarge),
- GetClrInstanceId(),
- allocation_amount,
- typeId,
- name,
- heap_number,
- object_address
- );
- }
+ gc_etw_alloc_kind kind = gen_number == 0 ? gc_etw_alloc_soh : gc_etw_alloc_loh;
+ FIRE_EVENT(GCAllocationTick_V3, static_cast<uint64_t>(allocation_amount), kind, heap_number, object_address);
}
+
void gc_heap::fire_etw_pin_object_event (uint8_t* object, uint8_t** ppObject)
{
-#ifdef FEATURE_REDHAWK
- UNREFERENCED_PARAMETER(object);
- UNREFERENCED_PARAMETER(ppObject);
-#else
- Object* obj = (Object*)object;
-
- InlineSString<MAX_CLASSNAME_LENGTH> strTypeName;
-
- EX_TRY
- {
- FAULT_NOT_FATAL();
-
- TypeHandle th = obj->GetGCSafeTypeHandleIfPossible();
- if(th != NULL)
- {
- th.GetName(strTypeName);
- }
-
- FireEtwPinObjectAtGCTime(ppObject,
- object,
- obj->GetSize(),
- strTypeName.GetUnicode(),
- GetClrInstanceId());
- }
- EX_CATCH {}
- EX_END_CATCH(SwallowAllExceptions)
-#endif // FEATURE_REDHAWK
+ FIRE_EVENT(PinObjectAtGCTime, object, ppObject);
}
#endif // FEATURE_EVENT_TRACE
@@ -600,22 +527,18 @@ void GCHeap::DiagTraceGCSegments()
for (seg = generation_start_segment (h->generation_of (max_generation)); seg != 0; seg = heap_segment_next(seg))
{
- ETW::GCLog::ETW_GC_INFO Info;
- Info.GCCreateSegment.Address = (size_t)heap_segment_mem(seg);
- Info.GCCreateSegment.Size = (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg));
- Info.GCCreateSegment.Type = (heap_segment_read_only_p (seg) ?
- ETW::GCLog::ETW_GC_INFO::READ_ONLY_HEAP :
- ETW::GCLog::ETW_GC_INFO::SMALL_OBJECT_HEAP);
- FireEtwGCCreateSegment_V1(Info.GCCreateSegment.Address, Info.GCCreateSegment.Size, Info.GCCreateSegment.Type, GetClrInstanceId());
+ uint8_t* address = heap_segment_mem (seg);
+ size_t size = heap_segment_reserved (seg) - heap_segment_mem (seg);
+ gc_etw_segment_type type = heap_segment_read_only_p (seg) ? gc_etw_segment_read_only_heap : gc_etw_segment_small_object_heap;
+ FIRE_EVENT(GCCreateSegment_V1, address, size, static_cast<uint32_t>(type));
}
// large obj segments
for (seg = generation_start_segment (h->generation_of (max_generation+1)); seg != 0; seg = heap_segment_next(seg))
{
- FireEtwGCCreateSegment_V1((size_t)heap_segment_mem(seg),
- (size_t)(heap_segment_reserved (seg) - heap_segment_mem(seg)),
- ETW::GCLog::ETW_GC_INFO::LARGE_OBJECT_HEAP,
- GetClrInstanceId());
+ uint8_t* address = heap_segment_mem (seg);
+ size_t size = heap_segment_reserved (seg) - heap_segment_mem (seg);
+ FIRE_EVENT(GCCreateSegment_V1, address, size, static_cast<uint32_t>(gc_etw_segment_large_object_heap));
}
}
#endif // FEATURE_EVENT_TRACE
@@ -623,9 +546,7 @@ void GCHeap::DiagTraceGCSegments()
void GCHeap::DiagDescrGenerations (gen_walk_fn fn, void *context)
{
-#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
pGenGCHeap->descr_generations_to_profiler(fn, context);
-#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
}
segment_handle GCHeap::RegisterFrozenSegment(segment_info *pseginfo)
diff --git a/src/gc/gcevents.h b/src/gc/gcevents.h
index 974348a967..f0f6ff6f32 100644
--- a/src/gc/gcevents.h
+++ b/src/gc/gcevents.h
@@ -9,9 +9,25 @@
#define DYNAMIC_EVENT(name, level, keyword, ...)
#endif // DYNAMIC_EVENT
+KNOWN_EVENT(GCStart_V2, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCEnd_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCGenerationRange, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHeapSurvivalAndMovement)
+KNOWN_EVENT(GCHeapStats_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCCreateSegment_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCFreeSegment_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCCreateConcurrentThread_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCTerminateConcurrentThread_V1, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCTriggered, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCMarkWithType, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCJoin_V2, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC)
+KNOWN_EVENT(GCGlobalHeapHistory_V2, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+KNOWN_EVENT(GCAllocationTick_V1, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC)
+KNOWN_EVENT(GCAllocationTick_V3, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC)
+KNOWN_EVENT(PinObjectAtGCTime, GCEventProvider_Default, GCEventLevel_Verbose, GCEventKeyword_GC)
+KNOWN_EVENT(GCPerHeapHistory_V3, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GC)
+
KNOWN_EVENT(SetGCHandle, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHandle)
KNOWN_EVENT(DestroyGCHandle, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCHandle)
-KNOWN_EVENT(GCPerHeapHistory_V3, GCEventProvider_Default, GCEventLevel_Information, GCEventKeyword_GCPrivate)
KNOWN_EVENT(BGCBegin, GCEventProvider_Private, GCEventLevel_Information, GCEventKeyword_GCPrivate)
KNOWN_EVENT(BGC1stNonConEnd, GCEventProvider_Private, GCEventLevel_Information, GCEventKeyword_GCPrivate)
diff --git a/src/gc/gcinterface.ee.h b/src/gc/gcinterface.ee.h
index a153c1d0f1..a79043eea6 100644
--- a/src/gc/gcinterface.ee.h
+++ b/src/gc/gcinterface.ee.h
@@ -26,6 +26,71 @@ public:
void* payload,
uint32_t payloadSize) = 0;
virtual
+ void FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type) = 0;
+
+ virtual
+ void FireGCEnd_V1(uint32_t count, uint32_t depth) = 0;
+
+ virtual
+ void FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength) = 0;
+
+ virtual
+ void FireGCHeapStats_V1(
+ uint64_t generationSize0,
+ uint64_t totalPromotedSize0,
+ uint64_t generationSize1,
+ uint64_t totalPromotedSize1,
+ uint64_t generationSize2,
+ uint64_t totalPromotedSize2,
+ uint64_t generationSize3,
+ uint64_t totalPromotedSize3,
+ uint64_t finalizationPromotedSize,
+ uint64_t finalizationPromotedCount,
+ uint32_t pinnedObjectCount,
+ uint32_t sinkBlockCount,
+ uint32_t gcHandleCount) = 0;
+
+ virtual
+ void FireGCCreateSegment_V1(void* address, size_t size, uint32_t type) = 0;
+
+ virtual
+ void FireGCFreeSegment_V1(void* address) = 0;
+
+ virtual
+ void FireGCCreateConcurrentThread_V1() = 0;
+
+ virtual
+ void FireGCTerminateConcurrentThread_V1() = 0;
+
+ virtual
+ void FireGCTriggered(uint32_t reason) = 0;
+
+ virtual
+ void FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes) = 0;
+
+ virtual
+ void FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId) = 0;
+
+ virtual
+ void FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired,
+ int32_t numHeaps,
+ uint32_t condemnedGeneration,
+ uint32_t gen0reductionCount,
+ uint32_t reason,
+ uint32_t globalMechanisms,
+ uint32_t pauseMode,
+ uint32_t memoryPressure) = 0;
+
+ virtual
+ void FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind) = 0;
+
+ virtual
+ void FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress) = 0;
+
+ virtual
+ void FirePinObjectAtGCTime(void* object, uint8_t** ppObject) = 0;
+
+ virtual
void FireGCPerHeapHistory_V3(void *freeListAllocated,
void *freeListRejected,
void *endOfSegAllocated,
diff --git a/src/inc/eventtrace.h b/src/inc/eventtrace.h
index 765249e87f..1564c944b8 100644
--- a/src/inc/eventtrace.h
+++ b/src/inc/eventtrace.h
@@ -325,14 +325,7 @@ namespace ETW
static BOOL ShouldTrackMovementForEtw();
static HRESULT ForceGCForDiagnostics();
static VOID ForceGC(LONGLONG l64ClientSequenceNumber);
- static VOID FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo);
- static VOID FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth);
- static VOID FireSingleGenerationRangeEvent(
- void * /* context */,
- int generation,
- BYTE * rangeStart,
- BYTE * rangeEnd,
- BYTE * rangeEndReserved);
+ static VOID FireGcStart(ETW_GC_INFO * pGcInfo);
static VOID RootReference(
LPVOID pvHandle,
Object * pRootedNode,
diff --git a/src/vm/eventtrace.cpp b/src/vm/eventtrace.cpp
index 533a3bc7fa..5fb63c90fe 100644
--- a/src/vm/eventtrace.cpp
+++ b/src/vm/eventtrace.cpp
@@ -874,15 +874,14 @@ VOID ETW::GCLog::ForceGC(LONGLONG l64ClientSequenceNumber)
//---------------------------------------------------------------------------------------
//
// Helper to fire the GCStart event. Figures out which version of GCStart to fire, and
-// includes the client sequence number, if available. Also logs the generation range
-// events.
+// includes the client sequence number, if available.
//
// Arguments:
// pGcInfo - ETW_GC_INFO containing details from GC about this collection
//
// static
-VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo)
+VOID ETW::GCLog::FireGcStart(ETW_GC_INFO * pGcInfo)
{
LIMITED_METHOD_CONTRACT;
@@ -902,81 +901,8 @@ VOID ETW::GCLog::FireGcStartAndGenerationRanges(ETW_GC_INFO * pGcInfo)
}
FireEtwGCStart_V2(pGcInfo->GCStart.Count, pGcInfo->GCStart.Depth, pGcInfo->GCStart.Reason, pGcInfo->GCStart.Type, GetClrInstanceId(), l64ClientSequenceNumberToLog);
-
- // Fire an event per range per generation
- IGCHeap *hp = GCHeapUtilities::GetGCHeap();
- hp->DiagDescrGenerations(FireSingleGenerationRangeEvent, NULL /* context */);
- }
-}
-
-
-//---------------------------------------------------------------------------------------
-//
-// Helper to fire the GCEnd event and the generation range events.
-//
-// Arguments:
-// Count - (matching Count from corresponding GCStart event0
-// Depth - (matching Depth from corresponding GCStart event0
-//
-//
-
-// static
-VOID ETW::GCLog::FireGcEndAndGenerationRanges(ULONG Count, ULONG Depth)
-{
- LIMITED_METHOD_CONTRACT;
-
- if (ETW_TRACING_CATEGORY_ENABLED(
- MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context,
- TRACE_LEVEL_INFORMATION,
- CLR_GC_KEYWORD))
- {
- // Fire an event per range per generation
- IGCHeap *hp = GCHeapUtilities::GetGCHeap();
- hp->DiagDescrGenerations(FireSingleGenerationRangeEvent, NULL /* context */);
-
- // GCEnd
- FireEtwGCEnd_V1(Count, Depth, GetClrInstanceId());
}
}
-
-//---------------------------------------------------------------------------------------
-//
-// Callback made by GC when we call GCHeapUtilities::DiagDescrGenerations(). This is
-// called once per range per generation, and results in a single ETW event per range per
-// generation.
-//
-// Arguments:
-// context - unused
-// generation - Generation number
-// rangeStart - Where does this range start?
-// rangeEnd - How large is the used portion of this range?
-// rangeEndReserved - How large is the reserved portion of this range?
-//
-
-// static
-VOID ETW::GCLog::FireSingleGenerationRangeEvent(
- void * /* context */,
- int generation,
- BYTE * rangeStart,
- BYTE * rangeEnd,
- BYTE * rangeEndReserved)
-{
- CONTRACT_VOID
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY; // can be called even on GC threads
- PRECONDITION(0 <= generation && generation <= 3);
- PRECONDITION(CheckPointer(rangeStart));
- PRECONDITION(CheckPointer(rangeEnd));
- PRECONDITION(CheckPointer(rangeEndReserved));
- }
- CONTRACT_END;
-
- FireEtwGCGenerationRange((BYTE) generation, rangeStart, rangeEnd - rangeStart, rangeEndReserved - rangeStart, GetClrInstanceId());
-
- RETURN;
-}
//---------------------------------------------------------------------------------------
//
diff --git a/src/vm/gctoclreventsink.cpp b/src/vm/gctoclreventsink.cpp
index 3842babd90..50bd263eee 100644
--- a/src/vm/gctoclreventsink.cpp
+++ b/src/vm/gctoclreventsink.cpp
@@ -4,6 +4,7 @@
#include "common.h"
#include "gctoclreventsink.h"
+#include "eventtrace.h"
GCToCLREventSink g_gcToClrEventSink;
@@ -22,6 +23,188 @@ void GCToCLREventSink::FireDynamicEvent(const char* eventName, void* payload, ui
FireEtwGCDynamicEvent(wideEventName, payloadSize, (const BYTE*)payload, GetClrInstanceId());
}
+void GCToCLREventSink::FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ ETW::GCLog::ETW_GC_INFO gcStartInfo;
+ gcStartInfo.GCStart.Count = count;
+ gcStartInfo.GCStart.Depth = depth;
+ gcStartInfo.GCStart.Reason = static_cast<ETW::GCLog::ETW_GC_INFO::GC_REASON>(reason);
+ gcStartInfo.GCStart.Type = static_cast<ETW::GCLog::ETW_GC_INFO::GC_TYPE>(type);
+ ETW::GCLog::FireGcStart(&gcStartInfo);
+}
+
+void GCToCLREventSink::FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCGenerationRange(generation, rangeStart, rangeUsedLength, rangeReservedLength, GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCEnd_V1(uint32_t count, uint32_t depth)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCEnd_V1(count, depth, GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCHeapStats_V1(
+ uint64_t generationSize0,
+ uint64_t totalPromotedSize0,
+ uint64_t generationSize1,
+ uint64_t totalPromotedSize1,
+ uint64_t generationSize2,
+ uint64_t totalPromotedSize2,
+ uint64_t generationSize3,
+ uint64_t totalPromotedSize3,
+ uint64_t finalizationPromotedSize,
+ uint64_t finalizationPromotedCount,
+ uint32_t pinnedObjectCount,
+ uint32_t sinkBlockCount,
+ uint32_t gcHandleCount)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCHeapStats_V1(generationSize0, totalPromotedSize0, generationSize1, totalPromotedSize1,
+ generationSize2, totalPromotedSize2, generationSize3, totalPromotedSize3,
+ finalizationPromotedSize, finalizationPromotedCount, pinnedObjectCount,
+ sinkBlockCount, gcHandleCount, GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCCreateSegment_V1(void* address, size_t size, uint32_t type)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCCreateSegment_V1((uint64_t)address, static_cast<uint64_t>(size), type, GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCFreeSegment_V1(void* address)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCFreeSegment_V1((uint64_t)address, GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCCreateConcurrentThread_V1()
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCCreateConcurrentThread_V1(GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCTerminateConcurrentThread_V1()
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCTerminateConcurrentThread_V1(GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCTriggered(uint32_t reason)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCTriggered(reason, GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCMarkWithType(heapNum, GetClrInstanceId(), type, bytes);
+}
+
+void GCToCLREventSink::FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCJoin_V2(heap, joinTime, joinType, GetClrInstanceId(), joinId);
+}
+
+void GCToCLREventSink::FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired,
+ int32_t numHeaps,
+ uint32_t condemnedGeneration,
+ uint32_t gen0reductionCount,
+ uint32_t reason,
+ uint32_t globalMechanisms,
+ uint32_t pauseMode,
+ uint32_t memoryPressure)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCGlobalHeapHistory_V2(finalYoungestDesired, numHeaps, condemnedGeneration, gen0reductionCount, reason,
+ globalMechanisms, GetClrInstanceId(), pauseMode, memoryPressure);
+}
+
+void GCToCLREventSink::FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ FireEtwGCAllocationTick_V1(allocationAmount, allocationKind, GetClrInstanceId());
+}
+
+void GCToCLREventSink::FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ void * typeId = nullptr;
+ const WCHAR * name = nullptr;
+ InlineSString<MAX_CLASSNAME_LENGTH> strTypeName;
+ EX_TRY
+ {
+ TypeHandle th = GetThread()->GetTHAllocContextObj();
+
+ if (th != 0)
+ {
+ th.GetName(strTypeName);
+ name = strTypeName.GetUnicode();
+ typeId = th.GetMethodTable();
+ }
+ }
+ EX_CATCH {}
+ EX_END_CATCH(SwallowAllExceptions)
+
+ if (typeId != nullptr)
+ {
+ FireEtwGCAllocationTick_V3(static_cast<uint32_t>(allocationAmount),
+ allocationKind,
+ GetClrInstanceId(),
+ allocationAmount,
+ typeId,
+ name,
+ heapIndex,
+ objectAddress);
+ }
+}
+
+void GCToCLREventSink::FirePinObjectAtGCTime(void* object, uint8_t** ppObject)
+{
+ LIMITED_METHOD_CONTRACT;
+
+ Object* obj = (Object*)object;
+
+ InlineSString<MAX_CLASSNAME_LENGTH> strTypeName;
+
+ EX_TRY
+ {
+ FAULT_NOT_FATAL();
+
+ TypeHandle th = obj->GetGCSafeTypeHandleIfPossible();
+ if(th != NULL)
+ {
+ th.GetName(strTypeName);
+ }
+
+ FireEtwPinObjectAtGCTime(ppObject,
+ object,
+ obj->GetSize(),
+ strTypeName.GetUnicode(),
+ GetClrInstanceId());
+ }
+ EX_CATCH {}
+ EX_END_CATCH(SwallowAllExceptions)
+}
+
void GCToCLREventSink::FireGCPerHeapHistory_V3(void *freeListAllocated,
void *freeListRejected,
void *endOfSegAllocated,
diff --git a/src/vm/gctoclreventsink.h b/src/vm/gctoclreventsink.h
index ca3a219f30..e34cac4dea 100644
--- a/src/vm/gctoclreventsink.h
+++ b/src/vm/gctoclreventsink.h
@@ -11,7 +11,40 @@ class GCToCLREventSink : public IGCToCLREventSink
{
public:
void FireDynamicEvent(const char* eventName, void* payload, uint32_t payloadSize);
-
+ void FireGCStart_V2(uint32_t count, uint32_t depth, uint32_t reason, uint32_t type);
+ void FireGCEnd_V1(uint32_t count, uint32_t depth);
+ void FireGCGenerationRange(uint8_t generation, void* rangeStart, uint64_t rangeUsedLength, uint64_t rangeReservedLength);
+ void FireGCHeapStats_V1(uint64_t generationSize0,
+ uint64_t totalPromotedSize0,
+ uint64_t generationSize1,
+ uint64_t totalPromotedSize1,
+ uint64_t generationSize2,
+ uint64_t totalPromotedSize2,
+ uint64_t generationSize3,
+ uint64_t totalPromotedSize3,
+ uint64_t finalizationPromotedSize,
+ uint64_t finalizationPromotedCount,
+ uint32_t pinnedObjectCount,
+ uint32_t sinkBlockCount,
+ uint32_t gcHandleCount);
+ void FireGCCreateSegment_V1(void* address, size_t size, uint32_t type);
+ void FireGCFreeSegment_V1(void* address);
+ void FireGCCreateConcurrentThread_V1();
+ void FireGCTerminateConcurrentThread_V1();
+ void FireGCTriggered(uint32_t reason);
+ void FireGCMarkWithType(uint32_t heapNum, uint32_t type, uint64_t bytes);
+ void FireGCJoin_V2(uint32_t heap, uint32_t joinTime, uint32_t joinType, uint32_t joinId);
+ void FireGCGlobalHeapHistory_V2(uint64_t finalYoungestDesired,
+ int32_t numHeaps,
+ uint32_t condemnedGeneration,
+ uint32_t gen0reductionCount,
+ uint32_t reason,
+ uint32_t globalMechanisms,
+ uint32_t pauseMode,
+ uint32_t memoryPressure);
+ void FireGCAllocationTick_V1(uint32_t allocationAmount, uint32_t allocationKind);
+ void FireGCAllocationTick_V3(uint64_t allocationAmount, uint32_t allocationKind, uint32_t heapIndex, void* objectAddress);
+ void FirePinObjectAtGCTime(void* object, uint8_t** ppObject);
void FireGCPerHeapHistory_V3(void *freeListAllocated,
void *freeListRejected,
void *endOfSegAllocated,