2222
2323BulkTypeValue::BulkTypeValue ()
2424 : cTypeParameters(0 )
25- , rgTypeParameters()
2625 , ullSingleTypeParameter(0 )
2726{
2827 LIMITED_METHOD_CONTRACT;
@@ -47,7 +46,6 @@ void BulkTypeValue::Clear()
4746 ZeroMemory (&fixedSizedData, sizeof (fixedSizedData));
4847 cTypeParameters = 0 ;
4948 ullSingleTypeParameter = 0 ;
50- rgTypeParameters.Release ();
5149}
5250
5351// ---------------------------------------------------------------------------------------
@@ -59,7 +57,6 @@ void BulkTypeValue::Clear()
5957// Fire an ETW event for all the types we batched so far, and then reset our state
6058// so we can start batching new types at the beginning of the array.
6159//
62-
6360void BulkTypeEventLogger::FireBulkTypeEvent ()
6461{
6562 LIMITED_METHOD_CONTRACT;
@@ -69,64 +66,51 @@ void BulkTypeEventLogger::FireBulkTypeEvent()
6966 // No types were batched up, so nothing to send
7067 return ;
7168 }
72-
73- // Normally, we'd use the MC-generated FireEtwBulkType for all this gunk, but
74- // it's insufficient as the bulk type event is too complex (arrays of structs of
75- // varying size). So we directly log the event via EventDataDescCreate and
76- // EventWrite
77-
78- // We use one descriptor for the count + one for the ClrInstanceID + 4
79- // per batched type (to include fixed-size data + name + param count + param
80- // array). But the system limit of 128 descriptors per event kicks in way
81- // before the 64K event size limit, and we already limit our batch size
82- // (m_nBulkTypeValueCount) to stay within the 128 descriptor limit.
83- EVENT_DATA_DESCRIPTOR EventData[128 ];
8469 UINT16 nClrInstanceID = GetClrInstanceId ();
8570
86- UINT iDesc = 0 ;
87-
88- _ASSERTE (iDesc < _countof (EventData));
89- EventDataDescCreate (&EventData[iDesc++], &m_nBulkTypeValueCount, sizeof (m_nBulkTypeValueCount));
71+ if (m_pBulkTypeEventBuffer == NULL )
72+ {
73+ // The buffer could not be allocated when this object was created, so bail.
74+ return ;
75+ }
9076
91- _ASSERTE (iDesc < _countof (EventData));
92- EventDataDescCreate (&EventData[iDesc++], &nClrInstanceID, sizeof (nClrInstanceID));
77+ UINT iSize = 0 ;
9378
9479 for (int iTypeData = 0 ; iTypeData < m_nBulkTypeValueCount; iTypeData++)
9580 {
81+ BulkTypeValue& target = m_rgBulkTypeValues[iTypeData];
82+
9683 // Do fixed-size data as one bulk copy
97- _ASSERTE (iDesc < _countof (EventData));
98- EventDataDescCreate (
99- &EventData[iDesc++] ,
100- &(m_rgBulkTypeValues[iTypeData] .fixedSizedData ),
101- sizeof (m_rgBulkTypeValues[iTypeData] .fixedSizedData ) );
84+ memcpy (
85+ m_pBulkTypeEventBuffer + iSize,
86+ &(target. fixedSizedData ) ,
87+ sizeof (target .fixedSizedData ));
88+ iSize += sizeof (target .fixedSizedData );
10289
10390 // Do var-sized data individually per field
104-
105- // Type name (nonexistent and thus empty on nativeaot)
106- _ASSERTE (iDesc < _countof (EventData));
107- EventDataDescCreate (&EventData[iDesc++], L" " , sizeof (WCHAR));
91+ // No name in event, so just the null terminator
92+ m_pBulkTypeEventBuffer[iSize++] = 0 ;
93+ m_pBulkTypeEventBuffer[iSize++] = 0 ;
10894
10995 // Type parameter count
110- _ASSERTE (iDesc < _countof (EventData));
111- EventDataDescCreate (
112- &EventData[iDesc++],
113- &(m_rgBulkTypeValues[iTypeData].cTypeParameters ),
114- sizeof (m_rgBulkTypeValues[iTypeData].cTypeParameters ));
96+ ULONG cTypeParams = target.cTypeParameters ;
97+ ULONG *ptrInt = (ULONG*)(m_pBulkTypeEventBuffer + iSize);
98+ *ptrInt = cTypeParams;
99+ iSize += sizeof (ULONG);
115100
116101 // Type parameter array
117- if (m_rgBulkTypeValues[iTypeData].cTypeParameters > 0 )
102+ if (cTypeParams == 1 )
103+ {
104+ memcpy (m_pBulkTypeEventBuffer + iSize, &target.ullSingleTypeParameter , sizeof (ULONGLONG) * cTypeParams);
105+ iSize += sizeof (ULONGLONG) * cTypeParams;
106+ }
107+ else if (cTypeParams > 1 )
118108 {
119- _ASSERTE (iDesc < _countof (EventData));
120- EventDataDescCreate (
121- &EventData[iDesc++],
122- ((m_rgBulkTypeValues[iTypeData].cTypeParameters == 1 ) ?
123- &(m_rgBulkTypeValues[iTypeData].ullSingleTypeParameter ) :
124- (ULONGLONG*)(m_rgBulkTypeValues[iTypeData].rgTypeParameters )),
125- sizeof (ULONGLONG) * m_rgBulkTypeValues[iTypeData].cTypeParameters );
109+ ASSERT_UNCONDITIONALLY (" unexpected value of cTypeParams greater than 1" );
126110 }
127111 }
128112
129- EventWrite (Microsoft_Windows_DotNETRuntimeHandle, &BulkType, iDesc, EventData );
113+ FireEtwBulkType (m_nBulkTypeValueCount, GetClrInstanceId (), iSize, m_pBulkTypeEventBuffer );
130114
131115 // Reset state
132116 m_nBulkTypeValueCount = 0 ;
@@ -251,7 +235,6 @@ SHash<LoggedTypesTraits>* s_loggedTypesHash = NULL;
251235// Index into internal array where the info got batched. Or -1 if there was a
252236// failure.
253237//
254-
255238int BulkTypeEventLogger::LogSingleType (MethodTable * pEEType)
256239{
257240#ifdef MULTIPLE_HEAPS
@@ -295,8 +278,13 @@ int BulkTypeEventLogger::LogSingleType(MethodTable * pEEType)
295278 // Determine this MethodTable's module.
296279 RuntimeInstance * pRuntimeInstance = GetRuntimeInstance ();
297280
298- ULONGLONG osModuleHandle = (ULONGLONG) pEEType->GetTypeManagerPtr ()->AsTypeManager ()->GetOsModuleHandle ();
299-
281+ // EEType for GC statics are not fully populated and they do not have a valid TypeManager. We will identify them by checking for `ElementType_Unknown`.
282+ // We will not be able to get the osModuleHandle for these
283+ ULONGLONG osModuleHandle = 0 ;
284+ if (pEEType->GetElementType () != ElementType_Unknown)
285+ {
286+ osModuleHandle = (ULONGLONG) pEEType->GetTypeManagerPtr ()->AsTypeManager ()->GetOsModuleHandle ();
287+ }
300288 pVal->fixedSizedData .ModuleID = osModuleHandle;
301289
302290 if (pEEType->IsParameterizedType ())
@@ -371,15 +359,6 @@ int BulkTypeEventLogger::LogSingleType(MethodTable * pEEType)
371359
372360void BulkTypeEventLogger::LogTypeAndParameters (uint64_t thAsAddr)
373361{
374- // BulkTypeEventLogger currently fires ETW events only
375- if (!ETW_TRACING_CATEGORY_ENABLED (
376- MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context,
377- TRACE_LEVEL_INFORMATION,
378- CLR_TYPE_KEYWORD))
379- {
380- return ;
381- }
382-
383362 MethodTable * pEEType = (MethodTable *) thAsAddr;
384363
385364 // Batch up this type. This grabs useful info about the type, including any
@@ -398,25 +377,15 @@ void BulkTypeEventLogger::LogTypeAndParameters(uint64_t thAsAddr)
398377 // We're about to recursively call ourselves for the type parameters, so make a
399378 // local copy of their type handles first (else, as we log them we could flush
400379 // and clear out m_rgBulkTypeValues, thus trashing pVal)
401- NewArrayHolder<ULONGLONG> rgTypeParameters;
402380 DWORD cTypeParams = pVal->cTypeParameters ;
403381 if (cTypeParams == 1 )
404382 {
405383 LogTypeAndParameters (pVal->ullSingleTypeParameter );
406384 }
407385 else if (cTypeParams > 1 )
408386 {
409- rgTypeParameters = new (nothrow) ULONGLONG[cTypeParams];
410- for (DWORD i=0 ; i < cTypeParams; i++)
411- {
412- rgTypeParameters[i] = pVal->rgTypeParameters [i];
413- }
414-
415- // Recursively log any referenced parameter types
416- for (DWORD i=0 ; i < cTypeParams; i++)
417- {
418- LogTypeAndParameters (rgTypeParameters[i]);
419- }
387+
388+ ASSERT_UNCONDITIONALLY (" unexpected value of cTypeParams greater than 1" );
420389 }
421390}
422391
0 commit comments