Skip to content

Commit 043dafa

Browse files
committed
Fix bug where image mem pool would not be copied. Copy image class cache hash table and root domain mem pool.
Add code in debug builds to verify that all collected classes are in the collect memory sections.
1 parent c41badc commit 043dafa

File tree

3 files changed

+164
-3
lines changed

3 files changed

+164
-3
lines changed

mono/metadata/metadata.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5118,6 +5118,28 @@ mono_metadata_generic_class_foreach(GFunc func, gpointer user_data)
51185118
}
51195119
}
51205120

5121+
void
5122+
mono_metadata_image_set_foreach(GFunc func, gpointer user_data)
5123+
{
5124+
GenericClassForeachData data;
5125+
guint i;
5126+
5127+
data.func = func;
5128+
data.user_data = user_data;
5129+
5130+
for (i = 0; i < HASH_TABLE_SIZE; ++i)
5131+
{
5132+
MonoImageSet* imageSet = img_set_cache[i];
5133+
5134+
if (imageSet == NULL)
5135+
continue;
5136+
5137+
mono_image_set_lock(imageSet);
5138+
func(imageSet, user_data);
5139+
mono_image_set_unlock(imageSet);
5140+
}
5141+
}
5142+
51215143
static gboolean
51225144
_mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
51235145
{

mono/metadata/metadata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,9 +424,9 @@ MONO_API int mono_type_stack_size (MonoType *type,
424424

425425
MONO_API mono_bool mono_type_generic_inst_is_valuetype (MonoType *type);
426426
MONO_API mono_bool mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass);
427+
MONO_API void mono_metadata_image_set_foreach(GFunc func, gpointer user_data);
427428
MONO_API void mono_metadata_generic_class_foreach(GFunc func, gpointer user_data);
428429

429-
430430
MONO_API unsigned int mono_metadata_type_hash (MonoType *t1);
431431
MONO_API mono_bool mono_metadata_type_equal (MonoType *t1, MonoType *t2);
432432

mono/metadata/unity-memory-info.c

Lines changed: 141 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,27 +255,106 @@ static int MonoImagesMemPoolNumChunks()
255255
return count;
256256
}
257257

258+
static void AllocateMemoryForMemPool(MonoMemPool* pool, void *user_data)
259+
{
260+
mono_mempool_foreach_block(pool, AllocateMemoryForMemPoolChunk, user_data);
261+
}
262+
258263
static void AllocateMemoryForImageMemPool(MonoAssembly *assembly, void *user_data)
259264
{
260265
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);
261302

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;
262310
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+
264314
mono_image_unlock(image);
265315
}
266316

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+
267340
static void* CaptureHeapInfo(void* monoManagedHeap)
268341
{
269342
MonoManagedHeap* heap = (MonoManagedHeap*)monoManagedHeap;
270343
MonoDomain* domain = mono_domain_get();
344+
MonoDomain* rootDomain = mono_get_root_domain();
271345
SectionIterationContext iterationContext;
272346

273347
// Increment count for each heap section
274348
heap->sectionCount = GC_get_heap_section_count();
275349
// Increment count for the domain mem pool chunk
350+
heap->sectionCount += MonoMemPoolNumChunks(rootDomain->mp);
276351
heap->sectionCount += MonoMemPoolNumChunks(domain->mp);
277352
// Increment count for each image mem pool chunk
278353
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();
279358

280359
heap->sections = g_new0(MonoManagedMemorySection, heap->sectionCount);
281360

@@ -284,11 +363,18 @@ static void* CaptureHeapInfo(void* monoManagedHeap)
284363
// Allocate memory for each heap section
285364
GC_foreach_heap_section(&iterationContext, AllocateMemoryForSection);
286365
// 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);
287369
mono_domain_lock(domain);
288370
mono_mempool_foreach_block(domain->mp, AllocateMemoryForMemPoolChunk, &iterationContext);
289371
mono_domain_unlock(domain);
290372
// Allocate memory for each image mem pool chunk
291373
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);
292378

293379
return NULL;
294380
}
@@ -324,13 +410,18 @@ static void VerifyHeapSectionIsStillValid(void* context, void* sectionStart, voi
324410

325411
static gboolean MonoManagedHeapStillValid(MonoManagedHeap* heap)
326412
{
413+
MonoDomain* rootDomain = mono_get_root_domain();
327414
MonoDomain* domain = mono_domain_get();
415+
328416
VerifyHeapSectionStillValidIterationContext iterationContext;
329417
int currentSectionCount;
330418

331419
currentSectionCount = GC_get_heap_section_count();
420+
currentSectionCount += MonoMemPoolNumChunks(rootDomain->mp);
332421
currentSectionCount += MonoMemPoolNumChunks(domain->mp);
333422
currentSectionCount += MonoImagesMemPoolNumChunks();
423+
currentSectionCount += MonoImagesCount(); // image->class_cache hash table.
424+
currentSectionCount += MonoImageSetsMemPoolNumChunks();
334425

335426
if (heap->sectionCount != currentSectionCount)
336427
return FALSE;
@@ -356,6 +447,7 @@ static gboolean MonoManagedHeapStillValid(MonoManagedHeap* heap)
356447

357448
static void CaptureManagedHeap(MonoManagedHeap* heap)
358449
{
450+
MonoDomain* rootDomain = mono_get_root_domain();
359451
MonoDomain* domain = mono_domain_get();
360452
SectionIterationContext iterationContext;
361453

@@ -373,9 +465,13 @@ static void CaptureManagedHeap(MonoManagedHeap* heap)
373465
}
374466

375467
iterationContext.currentSection = heap->sections;
376-
GC_foreach_heap_section(&iterationContext, CopyHeapSection);
377468

469+
GC_foreach_heap_section(&iterationContext, CopyHeapSection);
470+
mono_mempool_foreach_block(rootDomain->mp, CopyMemPoolChunk, &iterationContext);
378471
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);
379475

380476
GC_start_world_external();
381477
}
@@ -418,6 +514,45 @@ static void FillRuntimeInformation(MonoRuntimeInformation* runtimeInfo)
418514
runtimeInfo->allocationGranularity = (uint32_t)(2 * sizeof(void*));
419515
}
420516

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+
421556
MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot()
422557
{
423558
MonoManagedMemorySnapshot* snapshot;
@@ -428,6 +563,10 @@ MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot()
428563
CaptureGCHandleTargets(&snapshot->gcHandles);
429564
FillRuntimeInformation(&snapshot->runtimeInformation);
430565

566+
#if _DEBUG
567+
VerifySnapshot(snapshot);
568+
#endif
569+
431570
return snapshot;
432571
}
433572

0 commit comments

Comments
 (0)