2010-01-20 Zoltan Varga <vargaz@gmail.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
45         if (!mono_method_get_token (method) || mono_class_get_image (mono_method_get_class (method)) != udata->image)
46                 return;
47
48         fprintf (udata->outfile, "%d\n", mono_method_get_token (method));
49 }
50
51 static void
52 output_image (gpointer key, gpointer value, gpointer user_data)
53 {
54         MonoImage *image = (MonoImage*)key;
55         PerImageData *image_data = (PerImageData*)value;
56         MonoProfiler *prof = (MonoProfiler*)user_data;
57         char *tmp, *outfile_name;
58         FILE *outfile;
59         int i, err;
60         ForeachData data;
61
62         tmp = g_strdup_printf ("%s/.mono/aot-profile-data", g_get_home_dir ());
63
64         if (!g_file_test (tmp, G_FILE_TEST_IS_DIR)) {
65 #ifdef HOST_WIN32
66                 err = mkdir (tmp);
67 #else
68                 err = mkdir (tmp, 0777);
69 #endif
70                 if (err) {
71                         fprintf (stderr, "mono-profiler-aot: Unable to create output directory '%s': %s\n", tmp, g_strerror (errno));
72                         exit (1);
73                 }
74         }
75
76         i = 0;
77         while (TRUE) {
78                 outfile_name = g_strdup_printf ("%s/%s-%s-%d", tmp, mono_image_get_name (image), mono_image_get_guid (image), i);
79
80                 if (!g_file_test (outfile_name, G_FILE_TEST_IS_REGULAR))
81                         break;
82
83                 i ++;
84         }
85
86         printf ("Creating output file: %s\n", outfile_name);
87
88         outfile = fopen (outfile_name, "w+");
89         g_assert (outfile);
90
91         fprintf (outfile, "#VER:%d\n", 1);
92
93         data.prof = prof;
94         data.outfile = outfile;
95         data.image = image;
96
97         g_list_foreach (image_data->methods, foreach_method, &data);
98 }
99
100 /* called at the end of the program */
101 static void
102 prof_shutdown (MonoProfiler *prof)
103 {
104         g_hash_table_foreach (prof->images, output_image, prof);
105 }
106
107 static void
108 prof_jit_enter (MonoProfiler *prof, MonoMethod *method)
109 {
110 }
111
112 static void
113 prof_jit_leave (MonoProfiler *prof, MonoMethod *method, int result)
114 {
115         MonoImage *image = mono_class_get_image (mono_method_get_class (method));
116         PerImageData *data;
117
118         data = g_hash_table_lookup (prof->images, image);
119         if (!data) {
120                 data = g_new0 (PerImageData, 1);
121                 g_hash_table_insert (prof->images, image, data);
122         }
123
124         data->methods = g_list_append (data->methods, method);
125 }
126
127 void
128 mono_profiler_startup (const char *desc);
129
130 /* the entry point */
131 void
132 mono_profiler_startup (const char *desc)
133 {
134         MonoProfiler *prof;
135
136         prof = g_new0 (MonoProfiler, 1);
137         prof->images = g_hash_table_new (NULL, NULL);
138
139         mono_profiler_install (prof, prof_shutdown);
140         
141         mono_profiler_install_jit_compile (prof_jit_enter, prof_jit_leave);
142
143         mono_profiler_set_events (MONO_PROFILE_JIT_COMPILATION);
144 }
145
146