New test.
[mono.git] / mono / profiler / mono-profiler-aot.c
1 #include <mono/metadata/profiler.h>
2 #include <mono/metadata/tokentype.h>
3 #include <mono/metadata/tabledefs.h>
4 #include <mono/metadata/debug-helpers.h>
5 #include <mono/metadata/assembly.h>
6 #include <string.h>
7 #include <errno.h>
8 #include <stdlib.h>
9 #include <sys/stat.h>
10
11 /*
12  * This profiler collects profiling information usable by the Mono AOT compiler
13  * to generate better code. It saves the information into files under ~/.mono. 
14  * The AOT compiler can load these files during compilation.
15  * Currently, only the order in which methods were compiled is saved, 
16  * allowing more efficient function ordering in the AOT files.
17  */
18
19 struct _MonoProfiler {
20         GHashTable *images;
21 };
22
23 typedef struct {
24         GList *methods;
25 } PerImageData;
26
27 typedef struct ForeachData {
28         MonoProfiler *prof;
29         FILE *outfile;
30         MonoImage *image;
31         MonoMethod *method;
32 } ForeachData;
33
34 static void
35 foreach_method (gpointer data, gpointer user_data)
36 {
37         ForeachData *udata = (ForeachData*)user_data;
38         MonoMethod *method = (MonoMethod*)data;
39
40         if (!mono_method_get_token (method) || mono_class_get_image (mono_method_get_class (method)) != udata->image)
41                 return;
42
43         fprintf (udata->outfile, "%d\n", mono_method_get_token (method));
44 }
45
46 static void
47 output_image (gpointer key, gpointer value, gpointer user_data)
48 {
49         MonoImage *image = (MonoImage*)key;
50         PerImageData *image_data = (PerImageData*)value;
51         MonoProfiler *prof = (MonoProfiler*)user_data;
52         char *tmp, *outfile_name;
53         FILE *outfile;
54         int i, err;
55         ForeachData data;
56
57         tmp = g_strdup_printf ("%s/.mono/aot-profile-data", g_get_home_dir ());
58
59         if (!g_file_test (tmp, G_FILE_TEST_IS_DIR)) {
60 #ifdef PLATFORM_WIN32
61                 err = mkdir (tmp);
62 #else
63                 err = mkdir (tmp, 0777);
64 #endif
65                 if (err) {
66                         fprintf (stderr, "mono-profiler-aot: Unable to create output directory '%s': %s\n", tmp, g_strerror (errno));
67                         exit (1);
68                 }
69         }
70
71         i = 0;
72         while (TRUE) {
73                 outfile_name = g_strdup_printf ("%s/%s-%s-%d", tmp, mono_image_get_name (image), mono_image_get_guid (image), i);
74
75                 if (!g_file_test (outfile_name, G_FILE_TEST_IS_REGULAR))
76                         break;
77
78                 i ++;
79         }
80
81         printf ("Creating output file: %s\n", outfile_name);
82
83         outfile = fopen (outfile_name, "w+");
84         g_assert (outfile);
85
86         fprintf (outfile, "#VER:%d\n", 1);
87
88         data.prof = prof;
89         data.outfile = outfile;
90         data.image = image;
91
92         g_list_foreach (image_data->methods, foreach_method, &data);
93 }
94
95 /* called at the end of the program */
96 static void
97 prof_shutdown (MonoProfiler *prof)
98 {
99         g_hash_table_foreach (prof->images, output_image, prof);
100 }
101
102 static void
103 prof_jit_enter (MonoProfiler *prof, MonoMethod *method)
104 {
105 }
106
107 static void
108 prof_jit_leave (MonoProfiler *prof, MonoMethod *method, int result)
109 {
110         MonoImage *image = mono_class_get_image (mono_method_get_class (method));
111         PerImageData *data;
112
113         data = g_hash_table_lookup (prof->images, image);
114         if (!data) {
115                 data = g_new0 (PerImageData, 1);
116                 g_hash_table_insert (prof->images, image, data);
117         }
118
119         data->methods = g_list_append (data->methods, method);
120 }
121
122 /* the entry point */
123 void
124 mono_profiler_startup (const char *desc)
125 {
126         MonoProfiler *prof;
127
128         prof = g_new0 (MonoProfiler, 1);
129         prof->images = g_hash_table_new (NULL, NULL);
130
131         mono_profiler_install (prof, prof_shutdown);
132         
133         mono_profiler_install_jit_compile (prof_jit_enter, prof_jit_leave);
134
135         mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
136 }
137
138