New test.
[mono.git] / samples / size / size.c
1 #include <glib.h>
2 #include <mono/jit/jit.h>
3 #include <mono/metadata/environment.h>
4 #include <mono/metadata/profiler.h>
5 #include <mono/metadata/tokentype.h>
6 #include <mono/metadata/debug-helpers.h>
7 #include <mono/metadata/assembly.h>
8 #include <string.h>
9
10 #define FIELD_ATTRIBUTE_STATIC 0x10
11
12 int
13 memory_usage (MonoObject *this, GHashTable *visited)
14 {
15         int total = 0;
16         MonoClass *class;
17         gpointer iter = (gpointer) 0;
18         MonoClassField *field;
19         
20         if (g_hash_table_lookup (visited, this))
21                 return total;
22
23         class = mono_object_get_class (this);
24         
25         g_hash_table_insert (visited, this, this);
26
27         while ((field = mono_class_get_fields (class, &iter)) != NULL){
28                 MonoType *ftype = mono_field_get_type (field);
29                 void *value;
30
31                 if ((ftype->attrs & FIELD_ATTRIBUTE_STATIC) != 0)
32                         continue;
33
34                 switch (ftype->type){
35                 case MONO_TYPE_CLASS: 
36                 case MONO_TYPE_OBJECT:
37                         mono_field_get_value (this, field, &value);
38
39                         if (value != NULL)
40                                 total += memory_usage ((MonoObject *) value, visited);
41                         break;
42
43                 case MONO_TYPE_SZARRAY:
44                         {
45                                 int len, i;
46                                 mono_field_get_value (this, field, &value);
47                                 len = mono_array_length ((MonoArray *)value);
48                                 for (i = 0; i < len; i++){
49                                         MonoObject *item = mono_array_get ((MonoArray *) value, gpointer, i);
50                                         if (item != NULL)
51                                                 total += memory_usage (item, visited);
52                                 }
53                         }
54                         break;
55                         
56                 case MONO_TYPE_I4:
57                 case MONO_TYPE_I1:
58                 case MONO_TYPE_I2:
59                 case MONO_TYPE_U4:
60                 case MONO_TYPE_U2:
61                 case MONO_TYPE_U1:
62                 case MONO_TYPE_VOID:
63                 case MONO_TYPE_BOOLEAN:
64                 case MONO_TYPE_CHAR:
65                         /* ignore */
66                         break;
67                 default:
68                         printf ("unhandled type: 0x%x\n", ftype->type);
69                 }
70         }
71         
72         total += mono_class_instance_size (class);
73
74         return total;
75 }
76
77 /*
78  * Only returns data for instances, not for static fields, those might
79  * be larger, or hold larger structures
80  */
81 static int
82 GetMemoryUsage (MonoObject *this)
83 {
84         GHashTable *visited = g_hash_table_new (NULL, NULL);
85         int n;
86         
87         n = memory_usage (this, visited);
88
89         g_hash_table_destroy (visited);
90         
91         return n;
92 }
93
94 static int installed = 0;
95
96 void install_icall (MonoProfiler *prof, MonoMethod *method, MonoJitInfo* jinfo, int result)
97 {
98         if (installed)
99                 return;
100
101         mono_add_internal_call ("Mono.ObjectServices.ObjectInspector::GetMemoryUsage", GetMemoryUsage);
102         installed = 1;
103 }
104
105 void
106 mono_profiler_startup (const char *desc)
107 {
108         mono_profiler_install_jit_end (install_icall);
109         mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
110 }