Skip to content

Commit

Permalink
[Memoryprofiler] Exposing required mono API for backend migration (#1206
Browse files Browse the repository at this point in the history
)

* improve mempool chunk reporting in order to get exact range for each chunk

* added mono_unity_class_for_each in order to allow for simple iteration logic over all initialized classes in the VM

* added mono_type_get_name_chunked in order to report type names in null terminated chunks.
A good example for this can be using a preallocated instance of core::string as user_data for the callback which will then append onto the preallocated string

* added mono_unity_image_set_mempool_chunk_foreach in order to report memory blocks from the VM heap
added mono_unity_domain_mempool_chunk_foreach in order to report memory blocks inside the current domain's memory pool
added mono_unity_root_domain_mempool_chunk_foreach in order to report memory blocks inside the root domain's memory pool
added mono_unity_assembly_mempool_chunk_foreach in order to report memory blocks inside an assembly's image's memory pool
added mono_unity_class_get_data_size in order to return static field data size for a MonoClass
added mono_unity_class_get_static_field_data in order to access static fields memory for a given MonoClass
added mono_unity_class_field_is_literal in order to find out if the attributes
added mono_unity_start/stop_gc_world() in order to control the GC world state
added mono_unity_gc_heap_foreach in order to report each allocated GC heap section
added mono_unity_gchandles_foreach_get_target in order to report all gc handle targets tracked by the garbage collector
added mono_unity_object_header_size in order to report mono object header size
added mono_unity_array_object_header_size in order to report mono array object header size
added mono_unity_offset_of_array_length/bounds_in_array_object_header in order to report the offset of the length/bounds of the array within the header
added mono_unity_allocation_granularity in order to report the minimum allocation granulariy inside the vm
added mono_unity_get_name_full_chunked in order to extract a types name in chunks
added mono_unity_type_is_static in order to report if the given type is static
added mono_unity_type_is_pointer_type in order to report if the given type is a pointer type

* added missing include

* fixed up missing user_data assignment during context initialization for mono_unity_class_for_each

* move type name streaming utility out of class.h/.c
  • Loading branch information
realek committed Jul 29, 2019
1 parent 7a3ac72 commit 610a9ac
Show file tree
Hide file tree
Showing 4 changed files with 634 additions and 3 deletions.
4 changes: 1 addition & 3 deletions mono/metadata/mempool.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,8 @@ mono_mempool_foreach_block(MonoMemPool* pool, mono_mempool_block_proc callback,

while (current)
{
gpointer start = (guint8*)current + SIZEOF_MEM_POOL;
gpointer end = (guint8*)current + current->size;

callback(start, end, user_data);
callback(current, end, user_data);
current = current->next;
}
}
Expand Down
111 changes: 111 additions & 0 deletions mono/metadata/unity-memory-info.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,117 @@ static void CollectMonoImageFromAssembly(MonoAssembly *assembly, void *user_data
CollectMonoImage(assembly->image, monoImages);
}



typedef struct ClassReportContext {
ClassReportFunc callback;
void *user_data;
} ClassReportContext;

static void
ReportHashMapClasses(gpointer key, gpointer value, gpointer user_data)
{
ClassReportContext *context = (ClassReportContext *)user_data;
MonoClass *klass = (MonoClass *)value;
if (klass->inited)
context->callback(klass, context->user_data);
}

static void
ReportHashMapListClasses(gpointer key, gpointer value, gpointer user_data)
{
ClassReportContext *context = (ClassReportContext *)user_data;
GSList *list = (GSList *)value;

while (list != NULL) {
MonoClass *klass = (MonoClass *)list->data;

if (klass->inited)
context->callback(klass, context->user_data);

list = g_slist_next(list);
}
}

static void
ReportClassesFromAssembly(MonoAssembly *assembly, void *user_data)
{
MonoImage *image = mono_assembly_get_image(assembly);
int i;
MonoTableInfo *tdef = &image->tables[MONO_TABLE_TYPEDEF];
GSList *list;
ClassReportContext *context = (ClassReportContext*)user_data;

if (image->dynamic) {
GHashTableIter iter;
gpointer key;
MonoDynamicImage *dynamicImage = (MonoDynamicImage *)image;
g_hash_table_iter_init(&iter, dynamicImage->typeref);

while (g_hash_table_iter_next(&iter, &key, NULL)) {
MonoType *monoType = (MonoType *)key;
MonoClass *klass = mono_class_from_mono_type(monoType);

if (klass && klass->inited)
context->callback(klass, context->user_data);
}
}

/* Some classes are only in this list.
They are added in reflection_setup_internal_class_internal.
*/
list = image->reflection_info_unregister_classes;

while (list) {
MonoClass *klass = (MonoClass *)list->data;

if (klass && klass->inited)
context->callback(klass, context->user_data);

list = list->next;
}

for (i = 1; i < tdef->rows; ++i) {
MonoClass *klass;
MonoError error;

guint32 token = (i + 1) | MONO_TOKEN_TYPE_DEF;

klass = mono_class_get_checked(image, token, &error);

if (klass && klass->inited)
context->callback(klass, context->user_data);
}

if (image->array_cache)
g_hash_table_foreach(image->array_cache, ReportHashMapListClasses, user_data);

if (image->szarray_cache)
g_hash_table_foreach(image->szarray_cache, ReportHashMapClasses, user_data);

if (image->ptr_cache)
g_hash_table_foreach(image->ptr_cache, ReportHashMapClasses, user_data);
}

static void
ReportGenericClasses(MonoGenericClass *genericClass, gpointer user_data)
{
ClassReportContext *context = (ClassReportContext *)user_data;

if (genericClass->cached_class != NULL)
context->callback(genericClass->cached_class, context->user_data);
}

void
mono_unity_class_for_each(ClassReportFunc callback, void *user_data)
{
ClassReportContext reportContext;
reportContext.callback = callback;
reportContext.user_data = user_data;
mono_domain_assembly_foreach(mono_domain_get(), ReportClassesFromAssembly, &reportContext);
mono_metadata_generic_class_foreach(ReportGenericClasses, &reportContext);
}

MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot()
{
GC_disable();
Expand Down
7 changes: 7 additions & 0 deletions mono/metadata/unity-memory-info.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,13 @@ typedef struct MonoManagedMemorySnapshot
void* additionalUserInformation;
} MonoManagedMemorySnapshot;

typedef struct _MonoClass MonoClass;

typedef void(*ClassReportFunc) (MonoClass* klass, void *user_data);

MONO_API void
mono_unity_class_for_each(ClassReportFunc callback, void* user_data);

MONO_API MonoManagedMemorySnapshot* mono_unity_capture_memory_snapshot();
MONO_API void mono_unity_free_captured_memory_snapshot(MonoManagedMemorySnapshot* snapshot);

Expand Down
Loading

0 comments on commit 610a9ac

Please sign in to comment.