@@ -255,27 +255,106 @@ static int MonoImagesMemPoolNumChunks()
255
255
return count ;
256
256
}
257
257
258
+ static void AllocateMemoryForMemPool (MonoMemPool * pool , void * user_data )
259
+ {
260
+ mono_mempool_foreach_block (pool , AllocateMemoryForMemPoolChunk , user_data );
261
+ }
262
+
258
263
static void AllocateMemoryForImageMemPool (MonoAssembly * assembly , void * user_data )
259
264
{
260
265
MonoImage * image = assembly -> image ;
266
+ mono_image_lock (image );
267
+ AllocateMemoryForMemPool (image -> mempool , user_data );
268
+ mono_image_unlock (image );
269
+ }
270
+
271
+ static void CopyMemPool (MonoMemPool * pool , SectionIterationContext * context )
272
+ {
273
+ mono_mempool_foreach_block (pool , CopyMemPoolChunk , context );
274
+ }
275
+
276
+ static void CopyImageMemPool (MonoAssembly * assembly , SectionIterationContext * context )
277
+ {
278
+ MonoImage * image = assembly -> image ;
279
+
280
+ mono_image_lock (image );
281
+ CopyMemPool (image -> mempool , context );
282
+ mono_image_unlock (image );
283
+ }
284
+
285
+ static void MonoImagesCountCallback (MonoAssembly * assembly , void * user_data )
286
+ {
287
+ int * count = (int * )user_data ;
288
+ (* count )++ ;
289
+ }
290
+
291
+ static int MonoImagesCount ()
292
+ {
293
+ int count = 0 ;
294
+ mono_assembly_foreach ((GFunc )MonoImagesCountCallback , & count );
295
+ return count ;
296
+ }
297
+
298
+ static void AllocateMemoryForImageClassCache (MonoAssembly * assembly , void * user_data )
299
+ {
300
+ MonoImage * image = assembly -> image ;
301
+ mono_image_lock (image );
261
302
303
+ AllocateMemoryForSection (user_data , image -> class_cache .table , ((uint8_t * )image -> class_cache .table ) + image -> class_cache .size );
304
+ mono_image_unlock (image );
305
+ }
306
+
307
+ static void CopyImageClassCache (MonoAssembly * assembly , SectionIterationContext * context )
308
+ {
309
+ MonoImage * image = assembly -> image ;
262
310
mono_image_lock (image );
263
- mono_mempool_foreach_block (image -> mempool , AllocateMemoryForMemPoolChunk , user_data );
311
+
312
+ CopyHeapSection (context , image -> class_cache .table , ((uint8_t * )image -> class_cache .table ) + image -> class_cache .size );
313
+
264
314
mono_image_unlock (image );
265
315
}
266
316
317
+ static void IncrementCountForImageSetMemPoolNumChunks (MonoImageSet * imageSet , void * user_data )
318
+ {
319
+ int * count = (int * )user_data ;
320
+ (* count ) += MonoMemPoolNumChunks (imageSet -> mempool );
321
+ }
322
+
323
+ static int MonoImageSetsMemPoolNumChunks ()
324
+ {
325
+ int count = 0 ;
326
+ mono_metadata_image_set_foreach ((GFunc )IncrementCountForImageSetMemPoolNumChunks , & count );
327
+ return count ;
328
+ }
329
+
330
+ static void AllocateMemoryForImageSetMemPool (MonoImageSet * imageSet , void * user_data )
331
+ {
332
+ AllocateMemoryForMemPool (imageSet -> mempool , user_data );
333
+ }
334
+
335
+ static void CopyImageSetMemPool (MonoImageSet * imageSet , void * user_data )
336
+ {
337
+ CopyMemPool (imageSet -> mempool , user_data );
338
+ }
339
+
267
340
static void * CaptureHeapInfo (void * monoManagedHeap )
268
341
{
269
342
MonoManagedHeap * heap = (MonoManagedHeap * )monoManagedHeap ;
270
343
MonoDomain * domain = mono_domain_get ();
344
+ MonoDomain * rootDomain = mono_get_root_domain ();
271
345
SectionIterationContext iterationContext ;
272
346
273
347
// Increment count for each heap section
274
348
heap -> sectionCount = GC_get_heap_section_count ();
275
349
// Increment count for the domain mem pool chunk
350
+ heap -> sectionCount += MonoMemPoolNumChunks (rootDomain -> mp );
276
351
heap -> sectionCount += MonoMemPoolNumChunks (domain -> mp );
277
352
// Increment count for each image mem pool chunk
278
353
heap -> sectionCount += MonoImagesMemPoolNumChunks ();
354
+ // Increment count for each image->class_cache hash table.
355
+ heap -> sectionCount += MonoImagesCount ();
356
+ // Increment count for each image set mem pool chunk
357
+ heap -> sectionCount += MonoImageSetsMemPoolNumChunks ();
279
358
280
359
heap -> sections = g_new0 (MonoManagedMemorySection , heap -> sectionCount );
281
360
@@ -284,11 +363,18 @@ static void* CaptureHeapInfo(void* monoManagedHeap)
284
363
// Allocate memory for each heap section
285
364
GC_foreach_heap_section (& iterationContext , AllocateMemoryForSection );
286
365
// Allocate memory for the domain mem pool chunk
366
+ mono_domain_lock (rootDomain );
367
+ mono_mempool_foreach_block (rootDomain -> mp , AllocateMemoryForMemPoolChunk , & iterationContext );
368
+ mono_domain_unlock (rootDomain );
287
369
mono_domain_lock (domain );
288
370
mono_mempool_foreach_block (domain -> mp , AllocateMemoryForMemPoolChunk , & iterationContext );
289
371
mono_domain_unlock (domain );
290
372
// Allocate memory for each image mem pool chunk
291
373
mono_assembly_foreach ((GFunc )AllocateMemoryForImageMemPool , & iterationContext );
374
+ // Allocate memory for each image->class_cache hash table.
375
+ mono_assembly_foreach ((GFunc )AllocateMemoryForImageClassCache , & iterationContext );
376
+ // Allocate memory for each image->class_cache hash table.
377
+ mono_metadata_image_set_foreach ((GFunc )AllocateMemoryForImageSetMemPool , & iterationContext );
292
378
293
379
return NULL ;
294
380
}
@@ -324,13 +410,18 @@ static void VerifyHeapSectionIsStillValid(void* context, void* sectionStart, voi
324
410
325
411
static gboolean MonoManagedHeapStillValid (MonoManagedHeap * heap )
326
412
{
413
+ MonoDomain * rootDomain = mono_get_root_domain ();
327
414
MonoDomain * domain = mono_domain_get ();
415
+
328
416
VerifyHeapSectionStillValidIterationContext iterationContext ;
329
417
int currentSectionCount ;
330
418
331
419
currentSectionCount = GC_get_heap_section_count ();
420
+ currentSectionCount += MonoMemPoolNumChunks (rootDomain -> mp );
332
421
currentSectionCount += MonoMemPoolNumChunks (domain -> mp );
333
422
currentSectionCount += MonoImagesMemPoolNumChunks ();
423
+ currentSectionCount += MonoImagesCount (); // image->class_cache hash table.
424
+ currentSectionCount += MonoImageSetsMemPoolNumChunks ();
334
425
335
426
if (heap -> sectionCount != currentSectionCount )
336
427
return FALSE;
@@ -356,6 +447,7 @@ static gboolean MonoManagedHeapStillValid(MonoManagedHeap* heap)
356
447
357
448
static void CaptureManagedHeap (MonoManagedHeap * heap )
358
449
{
450
+ MonoDomain * rootDomain = mono_get_root_domain ();
359
451
MonoDomain * domain = mono_domain_get ();
360
452
SectionIterationContext iterationContext ;
361
453
@@ -373,9 +465,13 @@ static void CaptureManagedHeap(MonoManagedHeap* heap)
373
465
}
374
466
375
467
iterationContext .currentSection = heap -> sections ;
376
- GC_foreach_heap_section (& iterationContext , CopyHeapSection );
377
468
469
+ GC_foreach_heap_section (& iterationContext , CopyHeapSection );
470
+ mono_mempool_foreach_block (rootDomain -> mp , CopyMemPoolChunk , & iterationContext );
378
471
mono_mempool_foreach_block (domain -> mp , CopyMemPoolChunk , & iterationContext );
472
+ mono_assembly_foreach ((GFunc )CopyImageMemPool , & iterationContext );
473
+ mono_assembly_foreach ((GFunc )CopyImageClassCache , & iterationContext );
474
+ mono_metadata_image_set_foreach ((GFunc )CopyImageSetMemPool , & iterationContext );
379
475
380
476
GC_start_world_external ();
381
477
}
@@ -418,6 +514,45 @@ static void FillRuntimeInformation(MonoRuntimeInformation* runtimeInfo)
418
514
runtimeInfo -> allocationGranularity = (uint32_t )(2 * sizeof (void * ));
419
515
}
420
516
517
+ static gboolean ManagedHeapContainsAddress (MonoManagedHeap * heap , uint64_t address )
518
+ {
519
+ uint32_t i ;
520
+
521
+ for (i = 0 ; i < heap -> sectionCount ; ++ i )
522
+ {
523
+ MonoManagedMemorySection * section = & heap -> sections [i ];
524
+ uint64_t sectionBegin = section -> sectionStartAddress ;
525
+ uint64_t sectionEnd = sectionBegin + section -> sectionSize ;
526
+
527
+ if (address >= sectionBegin && address <= sectionEnd )
528
+ return TRUE;
529
+ }
530
+
531
+ return FALSE;
532
+ }
533
+
534
+ static void VerifySnapshot (MonoManagedMemorySnapshot * snapshot )
535
+ {
536
+ uint32_t i ;
537
+ FILE * file ;
538
+ MonoMetadataSnapshot * meta = & snapshot -> metadata ;
539
+
540
+ file = fopen ("MonoMemorySnapshotLog.txt" , "w" );
541
+
542
+ /* Verify that we have collected memory sections for all types */
543
+ for (i = 0 ; i < meta -> typeCount ; ++ i )
544
+ {
545
+ MonoMetadataType * type = & meta -> types [i ];
546
+
547
+ if (!ManagedHeapContainsAddress (& snapshot -> heap , type -> typeInfoAddress ))
548
+ {
549
+ fprintf (file , "The memory for type '%s' @ 0x%016X is not the part the snapshot.\n" , type -> name , type -> typeInfoAddress );
550
+ }
551
+ }
552
+
553
+ fclose (file );
554
+ }
555
+
421
556
MonoManagedMemorySnapshot * mono_unity_capture_memory_snapshot ()
422
557
{
423
558
MonoManagedMemorySnapshot * snapshot ;
@@ -428,6 +563,10 @@ MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot()
428
563
CaptureGCHandleTargets (& snapshot -> gcHandles );
429
564
FillRuntimeInformation (& snapshot -> runtimeInformation );
430
565
566
+ #if _DEBUG
567
+ VerifySnapshot (snapshot );
568
+ #endif
569
+
431
570
return snapshot ;
432
571
}
433
572
0 commit comments