2 * mono.c: Main driver for the Mono JIT engine
5 * Dietmar Maurer (dietmar@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc (http://www.ximian.com)
12 #include "mono/metadata/debug-helpers.h"
13 #include "mono/metadata/verify.h"
14 #include "mono/metadata/profiler.h"
15 #include "mono/metadata/threadpool.h"
16 #include "mono/metadata/mono-config.h"
17 #include <mono/metadata/profiler-private.h>
18 #include <mono/metadata/environment.h>
19 #include <mono/metadata/mono-debug.h>
20 #include <mono/metadata/mono-debug-debugger.h>
21 #include <mono/os/util.h>
25 find_class_in_assembly (MonoAssembly *assembly, const char *namespace, const char *name)
30 class = mono_class_from_name (assembly->image, namespace, name);
34 for (ptr = assembly->image->references; ptr && *ptr; ptr++) {
35 class = find_class_in_assembly (*ptr, namespace, name);
44 find_method_in_assembly (MonoAssembly *assembly, MonoMethodDesc *mdesc)
49 method = mono_method_desc_search_in_image (mdesc, assembly->image);
53 for (ptr = assembly->image->references; ptr && *ptr; ptr++) {
54 method = find_method_in_assembly (*ptr, mdesc);
63 * mono_jit_compile_class:
64 * @assembly: Lookup things in this assembly
65 * @compile_class: Name of the image/class/method to compile
66 * @compile_times: Compile it that many times
67 * @verbose: If true, print debugging information on stdout.
69 * JIT compilation of the image/class/method.
71 * @compile_class can be one of:
73 * - an image name (`@corlib')
74 * - a class name (`System.Int32')
75 * - a method name (`System.Int32:Parse')
78 mono_jit_compile_class (MonoAssembly *assembly, char *compile_class,
79 int compile_times, int verbose)
81 const char *cmethod = strrchr (compile_class, ':');
86 MonoDomain *domain = mono_domain_get ();
88 if (compile_class [0] == '@') {
89 MonoImage *image = mono_image_loaded (compile_class + 1);
91 g_error ("Cannot find image %s", compile_class + 1);
93 g_print ("Compiling image %s\n", image->name);
94 for (j = 0; j < compile_times; ++j)
95 mono_jit_compile_image (image, verbose);
97 MonoMethodDesc *mdesc;
99 mdesc = mono_method_desc_new (compile_class, FALSE);
101 g_error ("Invalid method name '%s'", compile_class);
102 m = find_method_in_assembly (assembly, mdesc);
104 g_error ("Cannot find method '%s'", compile_class);
105 for (j = 0; j < compile_times; ++j) {
106 code = mono_compile_method (m);
108 g_hash_table_remove (domain->jit_code_hash, m);
111 cname = strrchr (compile_class, '.');
115 cname = compile_class;
116 compile_class = (char *)"";
118 class = find_class_in_assembly (assembly, compile_class, cname);
120 g_error ("Cannot find class %s.%s", compile_class, cname);
121 mono_class_init (class);
122 for (j = 0; j < compile_times; ++j) {
123 for (i = 0; i < class->method.count; ++i) {
124 if (class->methods [i]->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)
126 if (class->methods [i]->flags & METHOD_ATTRIBUTE_ABSTRACT)
129 g_print ("Compiling: %s.%s:%s\n",
130 compile_class, cname, class->methods [i]->name);
131 code = mono_compile_method (class->methods [i]);
132 g_hash_table_remove (domain->jit_code_hash, class->methods [i]);
143 "mono %s, the Mono ECMA CLI JIT Compiler, (C) 2001, 2002 Ximian, Inc.\n\n"
144 "Usage is: %s [options] executable args...\n\n", VERSION, name);
146 "Runtime Debugging:\n"
147 " -d debug the jit, show disassembler output.\n"
148 " --dump-asm dumps the assembly code generated\n"
149 " --dump-forest dumps the reconstructed forest\n"
150 " --print-vtable print the VTable of all used classes\n"
151 " --stats print statistics about the jit operations\n"
152 " --trace printf function call trace\n"
153 " --compile NAME compile NAME, then exit.\n"
154 " NAME is in one of the following formats:\n"
155 " namespace.name compile the given class\n"
156 " namespace.name:method compile the given method\n"
157 " @imagename compile the given image\n"
158 " --ncompile NUM compile methods NUM times (default: 1000)\n"
159 " --noboundcheck Disables bound checks\n"
162 " --debug enable debugging support.\n"
163 " --profile record and dump profile info\n"
164 " --breakonex set a breakpoint for unhandled exception\n"
165 " --break NAME insert a breakpoint at the start of method NAME\n"
166 " (NAME is in `namespace.name:methodname' format\n"
167 " or `Main' to break on the application's main method)\n"
168 " --precompile name precompile NAME before executing the main application:\n"
169 " NAME is in one of the following formats:\n"
170 " namespace.name compile the given class\n"
171 " namespace.name:method compile the given method\n"
172 " @imagename compile the given image\n"
175 " --config filename Load specified config file instead of the default.\n"
176 " --fast-iconv Use fast floating point integer conversion\n"
177 " --noinline Disable code inliner\n"
178 " --nointrinsic Disable memcopy inliner\n"
179 " --nols disable linear scan register allocation\n"
180 " --share-code force jit to produce shared code\n"
181 " --workers n maximum number of worker threads\n"
191 gboolean enable_debugging;
194 GList *precompile_classes;
201 static void main_thread_handler (gpointer user_data)
203 MainThreadArgs *main_args=(MainThreadArgs *)user_data;
204 MonoAssembly *assembly;
206 if (main_args->enable_debugging)
207 mono_debug_init (MONO_DEBUG_FORMAT_MONO);
209 assembly = mono_domain_assembly_open (main_args->domain,
212 fprintf (stderr, "Can not open image %s\n", main_args->file);
216 if (main_args->enable_debugging)
217 mono_debug_init_2 (assembly);
219 if (main_args->testjit) {
220 mono_jit_compile_image (assembly->image, TRUE);
221 } else if (main_args->compile_class) {
222 mono_jit_compile_class (assembly, main_args->compile_class, main_args->compile_times, TRUE);
226 for (tmp = main_args->precompile_classes; tmp; tmp = tmp->next)
227 mono_jit_compile_class (assembly, tmp->data, 1,
230 if (main_args->break_on_main) {
231 MonoImage *image = assembly->image;
232 MonoMethodDesc *desc;
235 method = mono_get_method (image, mono_image_get_entry_point (image), NULL);
236 desc = mono_method_desc_from_method (method);
237 mono_debugger_insert_breakpoint_full (desc);
240 mono_jit_exec (main_args->domain, assembly, main_args->argc,
246 main (int argc, char *argv [])
250 int compile_times = 1000;
251 char *compile_class = NULL;
252 gboolean enable_debugging = FALSE;
253 char *file, *error, *config_file = NULL;
254 gboolean testjit = FALSE;
256 GList *precompile_classes = NULL;
257 int break_on_main = FALSE;
258 MainThreadArgs main_args;
260 setlocale(LC_ALL, "");
261 g_log_set_always_fatal (G_LOG_LEVEL_ERROR);
262 g_log_set_fatal_mask (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR);
267 for (i = 1; i < argc && argv [i][0] == '-'; i++){
268 if (strcmp (argv [i], "--help") == 0) {
270 } else if (strcmp (argv [i], "-d") == 0) {
272 mono_jit_dump_asm = TRUE;
273 mono_jit_dump_forest = TRUE;
274 } else if (strcmp (argv [i], "--dump-asm") == 0)
275 mono_jit_dump_asm = TRUE;
276 else if (strcmp (argv [i], "--dump-forest") == 0)
277 mono_jit_dump_forest = TRUE;
278 else if (strcmp (argv [i], "--trace") == 0)
279 mono_jit_trace_calls = TRUE;
280 else if (strcmp (argv [i], "--share-code") == 0)
281 mono_jit_share_code = TRUE;
282 else if (strcmp (argv [i], "--noinline") == 0)
283 mono_jit_inline_code = FALSE;
284 else if (strcmp (argv [i], "--nointrinsic") == 0)
285 mono_inline_memcpy = FALSE;
286 else if (strcmp (argv [i], "--noboundcheck") == 0)
287 mono_jit_boundcheck = FALSE;
288 else if (strcmp (argv [i], "--nols") == 0)
289 mono_use_linear_scan = FALSE;
290 else if (strcmp (argv [i], "--breakonex") == 0)
291 mono_break_on_exc = TRUE;
292 else if (strcmp (argv [i], "--print-vtable") == 0)
293 mono_print_vtable = TRUE;
294 else if (strcmp (argv [i], "--break") == 0) {
295 if (!strcmp (argv [i+1], "Main")) {
296 break_on_main = TRUE;
299 if (!mono_debugger_insert_breakpoint (argv [++i], FALSE))
300 g_error ("Invalid method name '%s'", argv [i]);
302 } else if (strcmp (argv [i], "--count") == 0) {
303 compile_times = atoi (argv [++i]);
304 } else if (strcmp (argv [i], "--config") == 0) {
305 config_file = argv [++i];
306 } else if (strcmp (argv [i], "--workers") == 0) {
307 mono_worker_threads = atoi (argv [++i]);
308 if (mono_worker_threads < 1)
309 mono_worker_threads = 1;
310 } else if (strcmp (argv [i], "--profile") == 0) {
311 mono_jit_profile = TRUE;
312 mono_profiler_install_simple ();
313 } else if (strcmp (argv [i], "--compile") == 0) {
314 compile_class = argv [++i];
315 } else if (strcmp (argv [i], "--ncompile") == 0) {
316 compile_times = atoi (argv [++i]);
317 } else if (strcmp (argv [i], "--stats") == 0) {
318 memset (&mono_jit_stats, 0, sizeof (MonoJitStats));
319 mono_jit_stats.enabled = TRUE;
320 } else if (strcmp (argv [i], "--debug") == 0) {
321 enable_debugging = TRUE;
322 } else if (strcmp (argv [i], "--precompile") == 0) {
323 precompile_classes = g_list_append (precompile_classes, argv [++i]);
324 } else if (strcmp (argv [i], "--verbose") == 0) {
326 } else if (strcmp (argv [i], "--fast-iconv") == 0) {
327 mono_use_fast_iconv = TRUE;
337 g_set_prgname (file);
338 mono_config_parse (config_file);
341 domain = mono_jit_init (file);
343 error = mono_verify_corlib ();
345 fprintf (stderr, "Corlib not in sync with this runtime: %s\n", error);
349 main_args.domain=domain;
351 main_args.testjit=testjit;
352 main_args.enable_debugging=enable_debugging;
353 main_args.compile_class=compile_class;
354 main_args.compile_times=compile_times;
355 main_args.precompile_classes=precompile_classes;
356 main_args.verbose=verbose;
357 main_args.break_on_main=break_on_main;
358 main_args.argc=argc-i;
359 main_args.argv=argv+i;
361 mono_runtime_exec_managed_code (domain, main_thread_handler,
364 mono_profiler_shutdown ();
365 mono_jit_cleanup (domain);
367 /* Look up return value from System.Environment.ExitCode */
368 retval=mono_environment_exitcode_get ();