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