[mini] Introduce job control to the JIT. Limits by active and duplicate jobs.
[mono.git] / mono / mini / mini-runtime.c
1 /**
2  * \file
3  * Runtime code for the JIT
4  *
5  * Authors:
6  *   Paolo Molaro (lupus@ximian.com)
7  *   Dietmar Maurer (dietmar@ximian.com)
8  *
9  * Copyright 2002-2003 Ximian, Inc.
10  * Copyright 2003-2010 Novell, Inc.
11  * Copyright 2011-2015 Xamarin, Inc (http://www.xamarin.com)
12  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
13  */
14
15 #include <config.h>
16 #ifdef HAVE_ALLOCA_H
17 #include <alloca.h>
18 #endif
19 #ifdef HAVE_UNISTD_H
20 #include <unistd.h>
21 #endif
22 #include <math.h>
23 #ifdef HAVE_SYS_TIME_H
24 #include <sys/time.h>
25 #endif
26 #ifdef HAVE_SIGNAL_H
27 #include <signal.h>
28 #endif
29
30 #include <mono/utils/memcheck.h>
31
32 #include <mono/metadata/assembly.h>
33 #include <mono/metadata/loader.h>
34 #include <mono/metadata/tabledefs.h>
35 #include <mono/metadata/class.h>
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/tokentype.h>
38 #include <mono/metadata/tabledefs.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/appdomain.h>
41 #include <mono/metadata/debug-helpers.h>
42 #include "mono/metadata/profiler.h"
43 #include <mono/metadata/profiler-private.h>
44 #include <mono/metadata/mono-config.h>
45 #include <mono/metadata/environment.h>
46 #include <mono/metadata/mono-debug.h>
47 #include <mono/metadata/gc-internals.h>
48 #include <mono/metadata/threads-types.h>
49 #include <mono/metadata/mempool-internals.h>
50 #include <mono/metadata/attach.h>
51 #include <mono/metadata/runtime.h>
52 #include <mono/metadata/reflection-internals.h>
53 #include <mono/metadata/monitor.h>
54 #include <mono/utils/mono-math.h>
55 #include <mono/utils/mono-compiler.h>
56 #include <mono/utils/mono-counters.h>
57 #include <mono/utils/mono-error-internals.h>
58 #include <mono/utils/mono-logger-internals.h>
59 #include <mono/utils/mono-mmap.h>
60 #include <mono/utils/mono-path.h>
61 #include <mono/utils/mono-tls.h>
62 #include <mono/utils/mono-hwcap.h>
63 #include <mono/utils/dtrace.h>
64 #include <mono/utils/mono-signal-handler.h>
65 #include <mono/utils/mono-threads.h>
66 #include <mono/utils/mono-threads-coop.h>
67 #include <mono/utils/checked-build.h>
68 #include <mono/utils/mono-proclib.h>
69 #include <mono/metadata/w32handle.h>
70 #include <mono/metadata/threadpool.h>
71
72 #include "mini.h"
73 #include "seq-points.h"
74 #include "tasklets.h"
75 #include <string.h>
76 #include <ctype.h>
77 #include "trace.h"
78 #include "version.h"
79
80 #include "jit-icalls.h"
81
82 #include "mini-gc.h"
83 #include "mini-llvm.h"
84 #include "debugger-agent.h"
85 #include "lldb.h"
86
87 #ifdef MONO_ARCH_LLVM_SUPPORTED
88 #ifdef ENABLE_LLVM
89 #include "mini-llvm-cpp.h"
90 #include "llvm-jit.h"
91 #endif
92 #endif
93
94 #ifdef ENABLE_INTERPRETER
95 #include "interp/interp.h"
96 #endif
97
98 static guint32 default_opt = 0;
99 static gboolean default_opt_set = FALSE;
100
101 gboolean mono_compile_aot = FALSE;
102 /* If this is set, no code is generated dynamically, everything is taken from AOT files */
103 gboolean mono_aot_only = FALSE;
104 /* Same as mono_aot_only, but only LLVM compiled code is used, no trampolines */
105 gboolean mono_llvm_only = FALSE;
106 MonoAotMode mono_aot_mode = MONO_AOT_MODE_NONE;
107
108 const char *mono_build_date;
109 gboolean mono_do_signal_chaining;
110 gboolean mono_do_crash_chaining;
111 int mini_verbose = 0;
112
113 /*
114  * This flag controls whenever the runtime uses LLVM for JIT compilation, and whenever
115  * it can load AOT code compiled by LLVM.
116  */
117 gboolean mono_use_llvm = FALSE;
118
119 gboolean mono_use_interpreter = FALSE;
120
121 #define mono_jit_lock() mono_os_mutex_lock (&jit_mutex)
122 #define mono_jit_unlock() mono_os_mutex_unlock (&jit_mutex)
123 static mono_mutex_t jit_mutex;
124
125 static MonoCodeManager *global_codeman;
126
127 MonoDebugOptions debug_options;
128
129 #ifdef VALGRIND_JIT_REGISTER_MAP
130 int valgrind_register;
131 #endif
132 GList* mono_aot_paths;
133
134 static gboolean mini_enable_profiler = FALSE;
135 static char* mini_profiler_options = NULL;
136
137 static GSList *tramp_infos;
138
139 static void register_icalls (void);
140
141 static gboolean mini_profiler_enabled (void) { return mini_enable_profiler; }
142 static const char* mini_profiler_get_options (void) {  return mini_profiler_options;  }
143
144 gboolean
145 mono_running_on_valgrind (void)
146 {
147 #ifndef HOST_WIN32
148         if (RUNNING_ON_VALGRIND){
149 #ifdef VALGRIND_JIT_REGISTER_MAP
150                 valgrind_register = TRUE;
151 #endif
152                 return TRUE;
153         } else
154 #endif
155                 return FALSE;
156 }
157
158 typedef struct {
159         void *ip;
160         MonoMethod *method;
161 } FindTrampUserData;
162
163 static void
164 find_tramp (gpointer key, gpointer value, gpointer user_data)
165 {
166         FindTrampUserData *ud = (FindTrampUserData*)user_data;
167
168         if (value == ud->ip)
169                 ud->method = (MonoMethod*)key;
170 }
171
172 /* debug function */
173 G_GNUC_UNUSED static char*
174 get_method_from_ip (void *ip)
175 {
176         MonoJitInfo *ji;
177         MonoMethod *method;
178         char *method_name;
179         char *res;
180         MonoDomain *domain = mono_domain_get ();
181         MonoDebugSourceLocation *location;
182         FindTrampUserData user_data;
183
184         if (!domain)
185                 domain = mono_get_root_domain ();
186
187         ji = mono_jit_info_table_find_internal (domain, (char *)ip, TRUE, TRUE);
188         if (!ji) {
189                 user_data.ip = ip;
190                 user_data.method = NULL;
191                 mono_domain_lock (domain);
192                 g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
193                 mono_domain_unlock (domain);
194                 if (user_data.method) {
195                         char *mname = mono_method_full_name (user_data.method, TRUE);
196                         res = g_strdup_printf ("<%p - JIT trampoline for %s>", ip, mname);
197                         g_free (mname);
198                         return res;
199                 }
200                 else
201                         return NULL;
202         } else if (ji->is_trampoline) {
203                 res = g_strdup_printf ("<%p - %s trampoline>", ip, ((MonoTrampInfo*)ji->d.tramp_info)->name);
204                 return res;
205         }
206
207         method = jinfo_get_method (ji);
208         method_name = mono_method_full_name (method, TRUE);
209         /* FIXME: unused ? */
210         location = mono_debug_lookup_source_location (method, (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
211
212         res = g_strdup_printf (" %s {%p} + 0x%x (%p %p) [%p - %s]", method_name, method, (int)((char*)ip - (char*)ji->code_start), ji->code_start, (char*)ji->code_start + ji->code_size, domain, domain->friendly_name);
213
214         mono_debug_free_source_location (location);
215         g_free (method_name);
216
217         return res;
218 }
219
220 /**
221  * mono_pmip:
222  * \param ip an instruction pointer address
223  *
224  * This method is used from a debugger to get the name of the
225  * method at address \p ip.   This routine is typically invoked from
226  * a debugger like this:
227  *
228  * (gdb) print mono_pmip ($pc)
229  *
230  * \returns the name of the method at address \p ip.
231  */
232 G_GNUC_UNUSED char *
233 mono_pmip (void *ip)
234 {
235         return get_method_from_ip (ip);
236 }
237
238 /**
239  * mono_print_method_from_ip:
240  * \param ip an instruction pointer address
241  *
242  * This method is used from a debugger to get the name of the
243  * method at address \p ip.
244  *
245  * This prints the name of the method at address \p ip in the standard
246  * output.  Unlike \c mono_pmip which returns a string, this routine
247  * prints the value on the standard output.
248  */
249 MONO_ATTR_USED void
250 mono_print_method_from_ip (void *ip)
251 {
252         MonoJitInfo *ji;
253         char *method;
254         MonoDebugSourceLocation *source;
255         MonoDomain *domain = mono_domain_get ();
256         MonoDomain *target_domain = mono_domain_get ();
257         FindTrampUserData user_data;
258         MonoGenericSharingContext*gsctx;
259         const char *shared_type;
260
261         if (!domain)
262                 domain = mono_get_root_domain ();
263         ji = mini_jit_info_table_find_ext (domain, (char *)ip, TRUE, &target_domain);
264         if (ji && ji->is_trampoline) {
265                 MonoTrampInfo *tinfo = (MonoTrampInfo *)ji->d.tramp_info;
266
267                 printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
268                 return;
269         }
270
271         if (!ji) {
272                 user_data.ip = ip;
273                 user_data.method = NULL;
274                 mono_domain_lock (domain);
275                 g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
276                 mono_domain_unlock (domain);
277
278                 if (user_data.method) {
279                         char *mname = mono_method_full_name (user_data.method, TRUE);
280                         printf ("IP %p is a JIT trampoline for %s\n", ip, mname);
281                         g_free (mname);
282                         return;
283                 }
284
285                 g_print ("No method at %p\n", ip);
286                 fflush (stdout);
287                 return;
288         }
289         method = mono_method_full_name (jinfo_get_method (ji), TRUE);
290         source = mono_debug_lookup_source_location (jinfo_get_method (ji), (guint32)((guint8*)ip - (guint8*)ji->code_start), target_domain);
291
292         gsctx = mono_jit_info_get_generic_sharing_context (ji);
293         shared_type = "";
294         if (gsctx) {
295                 if (gsctx->is_gsharedvt)
296                         shared_type = "gsharedvt ";
297                 else
298                         shared_type = "gshared ";
299         }
300
301         g_print ("IP %p at offset 0x%x of %smethod %s (%p %p)[domain %p - %s]\n", ip, (int)((char*)ip - (char*)ji->code_start), shared_type, method, ji->code_start, (char*)ji->code_start + ji->code_size, target_domain, target_domain->friendly_name);
302
303         if (source)
304                 g_print ("%s:%d\n", source->source_file, source->row);
305         fflush (stdout);
306
307         mono_debug_free_source_location (source);
308         g_free (method);
309 }
310
311 /*
312  * mono_method_same_domain:
313  *
314  * Determine whenever two compiled methods are in the same domain, thus
315  * the address of the callee can be embedded in the caller.
316  */
317 gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee)
318 {
319         MonoMethod *cmethod;
320
321         if (!caller || caller->is_trampoline || !callee || callee->is_trampoline)
322                 return FALSE;
323
324         /*
325          * If the call was made from domain-neutral to domain-specific
326          * code, we can't patch the call site.
327          */
328         if (caller->domain_neutral && !callee->domain_neutral)
329                 return FALSE;
330
331         cmethod = jinfo_get_method (caller);
332         if ((cmethod->klass == mono_defaults.appdomain_class) &&
333                 (strstr (cmethod->name, "InvokeInDomain"))) {
334                  /* The InvokeInDomain methods change the current appdomain */
335                 return FALSE;
336         }
337
338         return TRUE;
339 }
340
341 /*
342  * mono_global_codeman_reserve:
343  *
344  *  Allocate code memory from the global code manager.
345  */
346 void *mono_global_codeman_reserve (int size)
347 {
348         void *ptr;
349
350         if (mono_aot_only)
351                 g_error ("Attempting to allocate from the global code manager while running in aot-only mode.\n");
352
353         if (!global_codeman) {
354                 /* This can happen during startup */
355                 global_codeman = mono_code_manager_new ();
356                 return mono_code_manager_reserve (global_codeman, size);
357         }
358         else {
359                 mono_jit_lock ();
360                 ptr = mono_code_manager_reserve (global_codeman, size);
361                 mono_jit_unlock ();
362                 return ptr;
363         }
364 }
365
366 /* The callback shouldn't take any locks */
367 void
368 mono_global_codeman_foreach (MonoCodeManagerFunc func, void *user_data)
369 {
370         mono_jit_lock ();
371         mono_code_manager_foreach (global_codeman, func, user_data);
372         mono_jit_unlock ();
373 }
374
375 #if defined(__native_client_codegen__) && defined(__native_client__)
376 void
377 mono_nacl_gc()
378 {
379 #ifdef __native_client_gc__
380         __nacl_suspend_thread_if_needed();
381 #endif
382 }
383 #endif /* __native_client__ */
384
385 /**
386  * mono_create_unwind_op:
387  *
388  *   Create an unwind op with the given parameters.
389  */
390 MonoUnwindOp*
391 mono_create_unwind_op (int when, int tag, int reg, int val)
392 {
393         MonoUnwindOp *op = g_new0 (MonoUnwindOp, 1);
394
395         op->op = tag;
396         op->reg = reg;
397         op->val = val;
398         op->when = when;
399
400         return op;
401 }
402
403 MonoJumpInfoToken *
404 mono_jump_info_token_new2 (MonoMemPool *mp, MonoImage *image, guint32 token, MonoGenericContext *context)
405 {
406         MonoJumpInfoToken *res = (MonoJumpInfoToken *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoToken));
407         res->image = image;
408         res->token = token;
409         res->has_context = context != NULL;
410         if (context)
411                 memcpy (&res->context, context, sizeof (MonoGenericContext));
412
413         return res;
414 }
415
416 MonoJumpInfoToken *
417 mono_jump_info_token_new (MonoMemPool *mp, MonoImage *image, guint32 token)
418 {
419         return mono_jump_info_token_new2 (mp, image, token, NULL);
420 }
421
422 /*
423  * mono_tramp_info_create:
424  *
425  *   Create a MonoTrampInfo structure from the arguments. This function assumes ownership
426  * of JI, and UNWIND_OPS.
427  */
428 MonoTrampInfo*
429 mono_tramp_info_create (const char *name, guint8 *code, guint32 code_size, MonoJumpInfo *ji, GSList *unwind_ops)
430 {
431         MonoTrampInfo *info = g_new0 (MonoTrampInfo, 1);
432
433         info->name = g_strdup ((char*)name);
434         info->code = code;
435         info->code_size = code_size;
436         info->ji = ji;
437         info->unwind_ops = unwind_ops;
438
439         return info;
440 }
441
442 void
443 mono_tramp_info_free (MonoTrampInfo *info)
444 {
445         g_free (info->name);
446
447         // FIXME: ji
448         mono_free_unwind_info (info->unwind_ops);
449         if (info->owns_uw_info)
450                 g_free (info->uw_info);
451         g_free (info);
452 }
453
454 static void
455 register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
456 {
457         MonoJitInfo *ji;
458
459         ji = (MonoJitInfo *)mono_domain_alloc0 (domain, mono_jit_info_size ((MonoJitInfoFlags)0, 0, 0));
460         mono_jit_info_init (ji, NULL, info->code, info->code_size, (MonoJitInfoFlags)0, 0, 0);
461         ji->d.tramp_info = info;
462         ji->is_trampoline = TRUE;
463
464         ji->unwind_info = mono_cache_unwind_info (info->uw_info, info->uw_info_len);
465
466         mono_jit_info_table_add (domain, ji);
467 }
468
469 /*
470  * mono_tramp_info_register:
471  *
472  * Remember INFO for use by xdebug, mono_print_method_from_ip (), jit maps, etc.
473  * INFO can be NULL.
474  * Frees INFO.
475  */
476 static void
477 mono_tramp_info_register_internal (MonoTrampInfo *info, MonoDomain *domain, gboolean aot)
478 {
479         MonoTrampInfo *copy;
480
481         if (!info)
482                 return;
483
484         if (!domain)
485                 domain = mono_get_root_domain ();
486
487         copy = g_new0 (MonoTrampInfo, 1);
488         copy->code = info->code;
489         copy->code_size = info->code_size;
490         copy->name = g_strdup (info->name);
491
492         if (info->unwind_ops) {
493                 copy->uw_info = mono_unwind_ops_encode (info->unwind_ops, &copy->uw_info_len);
494                 copy->owns_uw_info = TRUE;
495         } else {
496                 /* Trampolines from aot have the unwind ops already encoded */
497                 copy->uw_info = info->uw_info;
498                 copy->uw_info_len = info->uw_info_len;
499         }
500
501         mono_jit_lock ();
502         tramp_infos = g_slist_prepend (tramp_infos, copy);
503         mono_jit_unlock ();
504
505         mono_save_trampoline_xdebug_info (info);
506         mono_lldb_save_trampoline_info (info);
507
508 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
509         if (!aot)
510                 mono_arch_unwindinfo_install_tramp_unwind_info (info->unwind_ops, info->code, info->code_size);
511 #endif
512
513         /* Only register trampolines that have unwind infos */
514         if (mono_get_root_domain () && copy->uw_info)
515                 register_trampoline_jit_info (domain, copy);
516
517         if (mono_jit_map_is_enabled ())
518                 mono_emit_jit_tramp (info->code, info->code_size, info->name);
519
520         mono_tramp_info_free (info);
521 }
522
523 void
524 mono_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
525 {
526         mono_tramp_info_register_internal (info, domain, FALSE);
527 }
528
529 void
530 mono_aot_tramp_info_register (MonoTrampInfo *info, MonoDomain *domain)
531 {
532         mono_tramp_info_register_internal (info, domain, TRUE);
533 }
534
535 static void
536 mono_tramp_info_cleanup (void)
537 {
538         GSList *l;
539
540         for (l = tramp_infos; l; l = l->next) {
541                 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
542
543                 mono_tramp_info_free (info);
544         }
545         g_slist_free (tramp_infos);
546 }
547
548 /* Register trampolines created before the root domain was created in the jit info tables */
549 static void
550 register_trampolines (MonoDomain *domain)
551 {
552         GSList *l;
553
554         for (l = tramp_infos; l; l = l->next) {
555                 MonoTrampInfo *info = (MonoTrampInfo *)l->data;
556
557                 register_trampoline_jit_info (domain, info);
558         }
559 }
560
561 G_GNUC_UNUSED static void
562 break_count (void)
563 {
564 }
565
566 /*
567  * Runtime debugging tool, use if (debug_count ()) <x> else <y> to do <x> the first COUNT times, then do <y> afterwards.
568  * Set a breakpoint in break_count () to break the last time <x> is done.
569  */
570 G_GNUC_UNUSED gboolean
571 mono_debug_count (void)
572 {
573         static int count = 0;
574         static gboolean inited;
575         static char *value;
576
577         count ++;
578
579         if (!inited) {
580                 value = g_getenv ("COUNT");
581                 inited = TRUE;
582         }
583
584         if (!value)
585                 return TRUE;
586
587         int int_val = atoi (value);
588         g_free (value);
589
590         if (count == int_val)
591                 break_count ();
592
593         if (count > int_val)
594                 return FALSE;
595
596         return TRUE;
597 }
598
599 gconstpointer
600 mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
601 {
602         MonoError error;
603         char *name;
604         MonoMethod *wrapper;
605         gconstpointer trampoline;
606         MonoDomain *domain = mono_get_root_domain ();
607         gboolean check_exc = TRUE;
608
609         if (callinfo->wrapper)
610                 return callinfo->wrapper;
611
612         if (callinfo->trampoline)
613                 return callinfo->trampoline;
614
615         if (!strcmp (callinfo->name, "mono_thread_interruption_checkpoint"))
616                 /* This icall is used to check for exceptions, so don't check in the wrapper */
617                 check_exc = FALSE;
618
619         name = g_strdup_printf ("__icall_wrapper_%s", callinfo->name);
620         wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc);
621         g_free (name);
622
623         if (do_compile) {
624                 trampoline = mono_compile_method_checked (wrapper, &error);
625                 mono_error_assert_ok (&error);
626         } else {
627
628                 trampoline = mono_create_jit_trampoline (domain, wrapper, &error);
629                 mono_error_assert_ok (&error);
630                 trampoline = mono_create_ftnptr (domain, (gpointer)trampoline);
631         }
632
633         mono_loader_lock ();
634         if (!callinfo->trampoline) {
635                 mono_register_jit_icall_wrapper (callinfo, trampoline);
636                 callinfo->trampoline = trampoline;
637         }
638         mono_loader_unlock ();
639
640         return callinfo->trampoline;
641 }
642
643 gconstpointer
644 mono_icall_get_wrapper (MonoJitICallInfo* callinfo)
645 {
646         return mono_icall_get_wrapper_full (callinfo, FALSE);
647 }
648
649 static MonoJitDynamicMethodInfo*
650 mono_dynamic_code_hash_lookup (MonoDomain *domain, MonoMethod *method)
651 {
652         MonoJitDynamicMethodInfo *res;
653
654         if (domain_jit_info (domain)->dynamic_code_hash)
655                 res = (MonoJitDynamicMethodInfo *)g_hash_table_lookup (domain_jit_info (domain)->dynamic_code_hash, method);
656         else
657                 res = NULL;
658         return res;
659 }
660
661 static void
662 register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, const char *symbol, gboolean no_throw)
663 {
664 #ifndef DISABLE_JIT
665         mini_register_opcode_emulation (opcode, name, sigstr, func, symbol, no_throw);
666 #else
667         MonoMethodSignature *sig = mono_create_icall_signature (sigstr);
668
669         g_assert (!sig->hasthis);
670         g_assert (sig->param_count < 3);
671
672         /* Opcode emulation functions are assumed to don't call mono_raise_exception () */
673         mono_register_jit_icall_full (func, name, sig, no_throw, TRUE, symbol);
674 #endif
675 }
676
677 /*
678  * For JIT icalls implemented in C.
679  * NAME should be the same as the name of the C function whose address is FUNC.
680  * If @avoid_wrapper is TRUE, no wrapper is generated. This is for perf critical icalls which
681  * can't throw exceptions.
682  */
683 static void
684 register_icall (gpointer func, const char *name, const char *sigstr, gboolean avoid_wrapper)
685 {
686         MonoMethodSignature *sig;
687
688         if (sigstr)
689                 sig = mono_create_icall_signature (sigstr);
690         else
691                 sig = NULL;
692
693         mono_register_jit_icall_full (func, name, sig, avoid_wrapper, FALSE, avoid_wrapper ? name : NULL);
694 }
695
696 static void
697 register_icall_no_wrapper (gpointer func, const char *name, const char *sigstr)
698 {
699         MonoMethodSignature *sig;
700
701         if (sigstr)
702                 sig = mono_create_icall_signature (sigstr);
703         else
704                 sig = NULL;
705
706         mono_register_jit_icall_full (func, name, sig, TRUE, FALSE, name);
707 }
708
709 static void
710 register_icall_with_wrapper (gpointer func, const char *name, const char *sigstr)
711 {
712         MonoMethodSignature *sig;
713
714         if (sigstr)
715                 sig = mono_create_icall_signature (sigstr);
716         else
717                 sig = NULL;
718
719         mono_register_jit_icall_full (func, name, sig, FALSE, FALSE, NULL);
720 }
721
722 static void
723 register_dyn_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
724 {
725         MonoMethodSignature *sig;
726
727         if (sigstr)
728                 sig = mono_create_icall_signature (sigstr);
729         else
730                 sig = NULL;
731
732         mono_register_jit_icall (func, name, sig, save);
733 }
734
735 MonoLMF *
736 mono_get_lmf (void)
737 {
738         MonoJitTlsData *jit_tls;
739
740         if ((jit_tls = mono_tls_get_jit_tls ()))
741                 return jit_tls->lmf;
742         /*
743          * We do not assert here because this function can be called from
744          * mini-gc.c on a thread that has not executed any managed code, yet
745          * (the thread object allocation can trigger a collection).
746          */
747         return NULL;
748 }
749
750 MonoLMF **
751 mono_get_lmf_addr (void)
752 {
753         return (MonoLMF **)mono_tls_get_lmf_addr ();
754 }
755
756 void
757 mono_set_lmf (MonoLMF *lmf)
758 {
759         (*mono_get_lmf_addr ()) = lmf;
760 }
761
762 MonoJitTlsData*
763 mono_get_jit_tls (void)
764 {
765         return (MonoJitTlsData *)mono_tls_get_jit_tls ();
766 }
767
768 static void
769 mono_set_jit_tls (MonoJitTlsData *jit_tls)
770 {
771         MonoThreadInfo *info;
772
773         mono_tls_set_jit_tls (jit_tls);
774
775         /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
776         info = mono_thread_info_current ();
777         if (info)
778                 mono_thread_info_tls_set (info, TLS_KEY_JIT_TLS, jit_tls);
779 }
780
781 static void
782 mono_set_lmf_addr (gpointer lmf_addr)
783 {
784         MonoThreadInfo *info;
785
786         mono_tls_set_lmf_addr (lmf_addr);
787
788         /* Save it into MonoThreadInfo so it can be accessed by mono_thread_state_init_from_handle () */
789         info = mono_thread_info_current ();
790         if (info)
791                 mono_thread_info_tls_set (info, TLS_KEY_LMF_ADDR, lmf_addr);
792 }
793
794 /*
795  * mono_jit_thread_attach:
796  *
797  * Called by Xamarin.Mac and other products. Attach thread to runtime if
798  * needed and switch to @domain.
799  *
800  * @return the original domain which needs to be restored, or NULL.
801  */
802 MonoDomain*
803 mono_jit_thread_attach (MonoDomain *domain)
804 {
805         MonoDomain *orig;
806         gboolean attached;
807
808         g_assert (!mono_threads_is_coop_enabled ());
809
810         if (!domain) {
811                 /* Happens when called from AOTed code which is only used in the root domain. */
812                 domain = mono_get_root_domain ();
813         }
814
815         g_assert (domain);
816
817         attached = mono_tls_get_jit_tls () != NULL;
818
819         if (!attached) {
820                 mono_thread_attach (domain);
821
822                 // #678164
823                 mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
824         }
825
826         orig = mono_domain_get ();
827         if (orig != domain)
828                 mono_domain_set (domain, TRUE);
829
830         return orig != domain ? orig : NULL;
831 }
832
833 /*
834  * mono_jit_set_domain:
835  *
836  * Set domain to @domain if @domain is not null
837  */
838 void
839 mono_jit_set_domain (MonoDomain *domain)
840 {
841         g_assert (!mono_threads_is_coop_enabled ());
842
843         if (domain)
844                 mono_domain_set (domain, TRUE);
845 }
846
847 /**
848  * mono_thread_abort:
849  * \param obj exception object
850  * Abort the thread, print exception information and stack trace
851  */
852 static void
853 mono_thread_abort (MonoObject *obj)
854 {
855         /* MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id); */
856
857         /* handle_remove should be eventually called for this thread, too
858         g_free (jit_tls);*/
859
860         if ((mono_runtime_unhandled_exception_policy_get () == MONO_UNHANDLED_POLICY_LEGACY) ||
861                         (obj->vtable->klass == mono_defaults.threadabortexception_class)) {
862                 mono_thread_exit ();
863         } else {
864                 mono_invoke_unhandled_exception_hook (obj);
865         }
866 }
867
868 static void*
869 setup_jit_tls_data (gpointer stack_start, gpointer abort_func)
870 {
871         MonoJitTlsData *jit_tls;
872         MonoLMF *lmf;
873
874         jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
875         if (jit_tls)
876                 return jit_tls;
877
878         jit_tls = g_new0 (MonoJitTlsData, 1);
879
880         jit_tls->abort_func = (void (*)(MonoObject *))abort_func;
881         jit_tls->end_of_stack = stack_start;
882
883         mono_set_jit_tls (jit_tls);
884
885         lmf = g_new0 (MonoLMF, 1);
886         MONO_ARCH_INIT_TOP_LMF_ENTRY (lmf);
887
888         jit_tls->first_lmf = lmf;
889
890         mono_set_lmf_addr (&jit_tls->lmf);
891
892         jit_tls->lmf = lmf;
893
894 #ifdef MONO_ARCH_HAVE_TLS_INIT
895         mono_arch_tls_init ();
896 #endif
897
898         mono_setup_altstack (jit_tls);
899
900         return jit_tls;
901 }
902
903 static void
904 free_jit_tls_data (MonoJitTlsData *jit_tls)
905 {
906         mono_arch_free_jit_tls_data (jit_tls);
907         mono_free_altstack (jit_tls);
908
909         g_free (jit_tls->first_lmf);
910         g_free (jit_tls);
911 }
912
913 static void
914 mono_thread_start_cb (intptr_t tid, gpointer stack_start, gpointer func)
915 {
916         MonoThreadInfo *thread;
917         void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort);
918         thread = mono_thread_info_current_unchecked ();
919         if (thread)
920                 thread->jit_data = jit_tls;
921
922         mono_arch_cpu_init ();
923 }
924
925 void (*mono_thread_attach_aborted_cb ) (MonoObject *obj) = NULL;
926
927 static void
928 mono_thread_abort_dummy (MonoObject *obj)
929 {
930   if (mono_thread_attach_aborted_cb)
931     mono_thread_attach_aborted_cb (obj);
932   else
933     mono_thread_abort (obj);
934 }
935
936 static void
937 mono_thread_attach_cb (intptr_t tid, gpointer stack_start)
938 {
939         MonoThreadInfo *thread;
940         void *jit_tls = setup_jit_tls_data (stack_start, mono_thread_abort_dummy);
941         thread = mono_thread_info_current_unchecked ();
942         if (thread)
943                 thread->jit_data = jit_tls;
944
945         mono_arch_cpu_init ();
946 }
947
948 static void
949 mini_thread_cleanup (MonoNativeThreadId tid)
950 {
951         MonoJitTlsData *jit_tls = NULL;
952         MonoThreadInfo *info;
953
954         info = mono_thread_info_current_unchecked ();
955
956         /* We can't clean up tls information if we are on another thread, it will clean up the wrong stuff
957          * It would be nice to issue a warning when this happens outside of the shutdown sequence. but it's
958          * not a trivial thing.
959          *
960          * The current offender is mono_thread_manage which cleanup threads from the outside.
961          */
962         if (info && mono_thread_info_get_tid (info) == tid) {
963                 jit_tls = (MonoJitTlsData *)info->jit_data;
964                 info->jit_data = NULL;
965
966                 mono_set_jit_tls (NULL);
967
968                 /* If we attach a thread but never call into managed land, we might never get an lmf.*/
969                 if (mono_get_lmf ()) {
970                         mono_set_lmf (NULL);
971                         mono_set_lmf_addr (NULL);
972                 }
973         } else {
974                 info = mono_thread_info_lookup (tid);
975                 if (info) {
976                         jit_tls = (MonoJitTlsData *)info->jit_data;
977                         info->jit_data = NULL;
978                 }
979                 mono_hazard_pointer_clear (mono_hazard_pointer_get (), 1);
980         }
981
982         if (jit_tls)
983                 free_jit_tls_data (jit_tls);
984 }
985
986 MonoJumpInfo *
987 mono_patch_info_list_prepend (MonoJumpInfo *list, int ip, MonoJumpInfoType type, gconstpointer target)
988 {
989         MonoJumpInfo *ji = g_new0 (MonoJumpInfo, 1);
990
991         ji->ip.i = ip;
992         ji->type = type;
993         ji->data.target = target;
994         ji->next = list;
995
996         return ji;
997 }
998
999 #if !defined(DISABLE_LOGGING) && !defined(DISABLE_JIT)
1000
1001 static const char* const patch_info_str[] = {
1002 #define PATCH_INFO(a,b) "" #a,
1003 #include "patch-info.h"
1004 #undef PATCH_INFO
1005 };
1006
1007 const char*
1008 mono_ji_type_to_string (MonoJumpInfoType type)
1009 {
1010         return patch_info_str [type];
1011 }
1012
1013 void
1014 mono_print_ji (const MonoJumpInfo *ji)
1015 {
1016         switch (ji->type) {
1017         case MONO_PATCH_INFO_RGCTX_FETCH: {
1018                 MonoJumpInfoRgctxEntry *entry = ji->data.rgctx_entry;
1019
1020                 printf ("[RGCTX_FETCH ");
1021                 mono_print_ji (entry->data);
1022                 printf (" - %s]", mono_rgctx_info_type_to_str (entry->info_type));
1023                 break;
1024         }
1025         case MONO_PATCH_INFO_METHODCONST: {
1026                 char *s = mono_method_full_name (ji->data.method, TRUE);
1027                 printf ("[METHODCONST - %s]", s);
1028                 g_free (s);
1029                 break;
1030         }
1031         case MONO_PATCH_INFO_INTERNAL_METHOD: {
1032                 printf ("[INTERNAL_METHOD - %s]", ji->data.name);
1033                 break;
1034         }
1035         default:
1036                 printf ("[%s]", patch_info_str [ji->type]);
1037                 break;
1038         }
1039 }
1040
1041 #else
1042
1043 const char*
1044 mono_ji_type_to_string (MonoJumpInfoType type)
1045 {
1046         return "";
1047 }
1048
1049 void
1050 mono_print_ji (const MonoJumpInfo *ji)
1051 {
1052 }
1053
1054 #endif
1055
1056 /**
1057  * mono_patch_info_dup_mp:
1058  *
1059  * Make a copy of PATCH_INFO, allocating memory from the mempool MP.
1060  */
1061 MonoJumpInfo*
1062 mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info)
1063 {
1064         MonoJumpInfo *res = (MonoJumpInfo *)mono_mempool_alloc (mp, sizeof (MonoJumpInfo));
1065         memcpy (res, patch_info, sizeof (MonoJumpInfo));
1066
1067         switch (patch_info->type) {
1068         case MONO_PATCH_INFO_RVA:
1069         case MONO_PATCH_INFO_LDSTR:
1070         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1071         case MONO_PATCH_INFO_LDTOKEN:
1072         case MONO_PATCH_INFO_DECLSEC:
1073                 res->data.token = (MonoJumpInfoToken *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoToken));
1074                 memcpy (res->data.token, patch_info->data.token, sizeof (MonoJumpInfoToken));
1075                 break;
1076         case MONO_PATCH_INFO_SWITCH:
1077                 res->data.table = (MonoJumpInfoBBTable *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoBBTable));
1078                 memcpy (res->data.table, patch_info->data.table, sizeof (MonoJumpInfoBBTable));
1079                 res->data.table->table = (MonoBasicBlock **)mono_mempool_alloc (mp, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1080                 memcpy (res->data.table->table, patch_info->data.table->table, sizeof (MonoBasicBlock*) * patch_info->data.table->table_size);
1081                 break;
1082         case MONO_PATCH_INFO_RGCTX_FETCH:
1083         case MONO_PATCH_INFO_RGCTX_SLOT_INDEX:
1084                 res->data.rgctx_entry = (MonoJumpInfoRgctxEntry *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoRgctxEntry));
1085                 memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
1086                 res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
1087                 break;
1088         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1089                 res->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
1090                 memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoDelegateClassMethodPair));
1091                 break;
1092         case MONO_PATCH_INFO_GSHAREDVT_CALL:
1093                 res->data.gsharedvt = (MonoJumpInfoGSharedVtCall *)mono_mempool_alloc (mp, sizeof (MonoJumpInfoGSharedVtCall));
1094                 memcpy (res->data.gsharedvt, patch_info->data.gsharedvt, sizeof (MonoJumpInfoGSharedVtCall));
1095                 break;
1096         case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
1097                 MonoGSharedVtMethodInfo *info;
1098                 MonoGSharedVtMethodInfo *oinfo;
1099                 int i;
1100
1101                 oinfo = patch_info->data.gsharedvt_method;
1102                 info = (MonoGSharedVtMethodInfo *)mono_mempool_alloc (mp, sizeof (MonoGSharedVtMethodInfo));
1103                 res->data.gsharedvt_method = info;
1104                 memcpy (info, oinfo, sizeof (MonoGSharedVtMethodInfo));
1105                 info->entries = (MonoRuntimeGenericContextInfoTemplate *)mono_mempool_alloc (mp, sizeof (MonoRuntimeGenericContextInfoTemplate) * info->count_entries);
1106                 for (i = 0; i < oinfo->num_entries; ++i) {
1107                         MonoRuntimeGenericContextInfoTemplate *otemplate = &oinfo->entries [i];
1108                         MonoRuntimeGenericContextInfoTemplate *template_ = &info->entries [i];
1109
1110                         memcpy (template_, otemplate, sizeof (MonoRuntimeGenericContextInfoTemplate));
1111                 }
1112                 //info->locals_types = mono_mempool_alloc0 (mp, info->nlocals * sizeof (MonoType*));
1113                 //memcpy (info->locals_types, oinfo->locals_types, info->nlocals * sizeof (MonoType*));
1114                 break;
1115         }
1116         case MONO_PATCH_INFO_VIRT_METHOD: {
1117                 MonoJumpInfoVirtMethod *info;
1118                 MonoJumpInfoVirtMethod *oinfo;
1119
1120                 oinfo = patch_info->data.virt_method;
1121                 info = (MonoJumpInfoVirtMethod *)mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoVirtMethod));
1122                 res->data.virt_method = info;
1123                 memcpy (info, oinfo, sizeof (MonoJumpInfoVirtMethod));
1124                 break;
1125         }
1126         default:
1127                 break;
1128         }
1129
1130         return res;
1131 }
1132
1133 guint
1134 mono_patch_info_hash (gconstpointer data)
1135 {
1136         const MonoJumpInfo *ji = (MonoJumpInfo*)data;
1137
1138         switch (ji->type) {
1139         case MONO_PATCH_INFO_RVA:
1140         case MONO_PATCH_INFO_LDSTR:
1141         case MONO_PATCH_INFO_LDTOKEN:
1142         case MONO_PATCH_INFO_DECLSEC:
1143                 return (ji->type << 8) | ji->data.token->token;
1144         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1145                 return (ji->type << 8) | ji->data.token->token | (ji->data.token->has_context ? (gsize)ji->data.token->context.class_inst : 0);
1146         case MONO_PATCH_INFO_INTERNAL_METHOD:
1147                 return (ji->type << 8) | g_str_hash (ji->data.name);
1148         case MONO_PATCH_INFO_VTABLE:
1149         case MONO_PATCH_INFO_CLASS:
1150         case MONO_PATCH_INFO_IID:
1151         case MONO_PATCH_INFO_ADJUSTED_IID:
1152         case MONO_PATCH_INFO_METHODCONST:
1153         case MONO_PATCH_INFO_METHOD:
1154         case MONO_PATCH_INFO_METHOD_JUMP:
1155         case MONO_PATCH_INFO_IMAGE:
1156         case MONO_PATCH_INFO_ICALL_ADDR:
1157         case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1158         case MONO_PATCH_INFO_FIELD:
1159         case MONO_PATCH_INFO_SFLDA:
1160         case MONO_PATCH_INFO_SEQ_POINT_INFO:
1161         case MONO_PATCH_INFO_METHOD_RGCTX:
1162         case MONO_PATCH_INFO_SIGNATURE:
1163         case MONO_PATCH_INFO_METHOD_CODE_SLOT:
1164         case MONO_PATCH_INFO_AOT_JIT_INFO:
1165         case MONO_PATCH_INFO_GET_TLS_TRAMP:
1166         case MONO_PATCH_INFO_SET_TLS_TRAMP:
1167                 return (ji->type << 8) | (gssize)ji->data.target;
1168         case MONO_PATCH_INFO_GSHAREDVT_CALL:
1169                 return (ji->type << 8) | (gssize)ji->data.gsharedvt->method;
1170         case MONO_PATCH_INFO_RGCTX_FETCH:
1171         case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1172                 MonoJumpInfoRgctxEntry *e = ji->data.rgctx_entry;
1173
1174                 return (ji->type << 8) | (gssize)e->method | (e->in_mrgctx) | e->info_type | mono_patch_info_hash (e->data);
1175         }
1176         case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1177         case MONO_PATCH_INFO_MSCORLIB_GOT_ADDR:
1178         case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR:
1179         case MONO_PATCH_INFO_GC_NURSERY_START:
1180         case MONO_PATCH_INFO_GC_NURSERY_BITS:
1181         case MONO_PATCH_INFO_GOT_OFFSET:
1182         case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1183         case MONO_PATCH_INFO_AOT_MODULE:
1184         case MONO_PATCH_INFO_JIT_THREAD_ATTACH:
1185                 return (ji->type << 8);
1186         case MONO_PATCH_INFO_CASTCLASS_CACHE:
1187                 return (ji->type << 8) | (ji->data.index);
1188         case MONO_PATCH_INFO_SWITCH:
1189                 return (ji->type << 8) | ji->data.table->table_size;
1190         case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1191                 return (ji->type << 8) | (gssize)ji->data.gsharedvt_method->method;
1192         case MONO_PATCH_INFO_OBJC_SELECTOR_REF:
1193                 /* Hash on the selector name */
1194                 return g_str_hash (ji->data.target);
1195         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1196                 return (ji->type << 8) | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->is_virtual;
1197         case MONO_PATCH_INFO_LDSTR_LIT:
1198                 return g_str_hash (ji->data.target);
1199         case MONO_PATCH_INFO_VIRT_METHOD: {
1200                 MonoJumpInfoVirtMethod *info = ji->data.virt_method;
1201
1202                 return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
1203         }
1204         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1205                 return (ji->type << 8) | g_str_hash (ji->data.target);
1206         case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1207                 return (ji->type << 8) | mono_signature_hash (ji->data.sig);
1208         default:
1209                 printf ("info type: %d\n", ji->type);
1210                 mono_print_ji (ji); printf ("\n");
1211                 g_assert_not_reached ();
1212                 return 0;
1213         }
1214 }
1215
1216 /*
1217  * mono_patch_info_equal:
1218  *
1219  * This might fail to recognize equivalent patches, i.e. floats, so its only
1220  * usable in those cases where this is not a problem, i.e. sharing GOT slots
1221  * in AOT.
1222  */
1223 gint
1224 mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
1225 {
1226         const MonoJumpInfo *ji1 = (MonoJumpInfo*)ka;
1227         const MonoJumpInfo *ji2 = (MonoJumpInfo*)kb;
1228
1229         if (ji1->type != ji2->type)
1230                 return 0;
1231
1232         switch (ji1->type) {
1233         case MONO_PATCH_INFO_RVA:
1234         case MONO_PATCH_INFO_LDSTR:
1235         case MONO_PATCH_INFO_TYPE_FROM_HANDLE:
1236         case MONO_PATCH_INFO_LDTOKEN:
1237         case MONO_PATCH_INFO_DECLSEC:
1238                 if ((ji1->data.token->image != ji2->data.token->image) ||
1239                         (ji1->data.token->token != ji2->data.token->token) ||
1240                         (ji1->data.token->has_context != ji2->data.token->has_context) ||
1241                         (ji1->data.token->context.class_inst != ji2->data.token->context.class_inst) ||
1242                         (ji1->data.token->context.method_inst != ji2->data.token->context.method_inst))
1243                         return 0;
1244                 break;
1245         case MONO_PATCH_INFO_INTERNAL_METHOD:
1246                 return g_str_equal (ji1->data.name, ji2->data.name);
1247         case MONO_PATCH_INFO_RGCTX_FETCH:
1248         case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1249                 MonoJumpInfoRgctxEntry *e1 = ji1->data.rgctx_entry;
1250                 MonoJumpInfoRgctxEntry *e2 = ji2->data.rgctx_entry;
1251
1252                 return e1->method == e2->method && e1->in_mrgctx == e2->in_mrgctx && e1->info_type == e2->info_type && mono_patch_info_equal (e1->data, e2->data);
1253         }
1254         case MONO_PATCH_INFO_GSHAREDVT_CALL: {
1255                 MonoJumpInfoGSharedVtCall *c1 = ji1->data.gsharedvt;
1256                 MonoJumpInfoGSharedVtCall *c2 = ji2->data.gsharedvt;
1257
1258                 return c1->sig == c2->sig && c1->method == c2->method;
1259         }
1260         case MONO_PATCH_INFO_GSHAREDVT_METHOD:
1261                 return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
1262         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
1263                 return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->is_virtual == ji2->data.del_tramp->is_virtual;
1264         case MONO_PATCH_INFO_CASTCLASS_CACHE:
1265                 return ji1->data.index == ji2->data.index;
1266         case MONO_PATCH_INFO_VIRT_METHOD:
1267                 return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
1268         case MONO_PATCH_INFO_JIT_ICALL_ADDR:
1269                 if (ji1->data.target == ji2->data.target)
1270                         return 1;
1271                 return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
1272         case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1273                 return mono_metadata_signature_equal (ji1->data.sig, ji2->data.sig) ? 1 : 0;
1274         default:
1275                 if (ji1->data.target != ji2->data.target)
1276                         return 0;
1277                 break;
1278         }
1279
1280         return 1;
1281 }
1282
1283 gpointer
1284 mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, MonoJumpInfo *patch_info, gboolean run_cctors, MonoError *error)
1285 {
1286         unsigned char *ip = patch_info->ip.i + code;
1287         gconstpointer target = NULL;
1288
1289         error_init (error);
1290
1291         switch (patch_info->type) {
1292         case MONO_PATCH_INFO_BB:
1293                 /*
1294                  * FIXME: This could be hit for methods without a prolog. Should use -1
1295                  * but too much code depends on a 0 initial value.
1296                  */
1297                 //g_assert (patch_info->data.bb->native_offset);
1298                 target = patch_info->data.bb->native_offset + code;
1299                 break;
1300         case MONO_PATCH_INFO_ABS:
1301                 target = patch_info->data.target;
1302                 break;
1303         case MONO_PATCH_INFO_LABEL:
1304                 target = patch_info->data.inst->inst_c0 + code;
1305                 break;
1306         case MONO_PATCH_INFO_IP:
1307                 target = ip;
1308                 break;
1309         case MONO_PATCH_INFO_METHOD_REL:
1310                 target = code + patch_info->data.offset;
1311                 break;
1312         case MONO_PATCH_INFO_INTERNAL_METHOD: {
1313                 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1314                 if (!mi) {
1315                         g_warning ("unknown MONO_PATCH_INFO_INTERNAL_METHOD %s", patch_info->data.name);
1316                         g_assert_not_reached ();
1317                 }
1318                 target = mono_icall_get_wrapper (mi);
1319                 break;
1320         }
1321         case MONO_PATCH_INFO_JIT_ICALL_ADDR: {
1322                 MonoJitICallInfo *mi = mono_find_jit_icall_by_name (patch_info->data.name);
1323                 if (!mi) {
1324                         g_warning ("unknown MONO_PATCH_INFO_JIT_ICALL_ADDR %s", patch_info->data.name);
1325                         g_assert_not_reached ();
1326                 }
1327                 target = mi->func;
1328                 break;
1329         }
1330         case MONO_PATCH_INFO_METHOD_JUMP:
1331                 target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE, error);
1332                 if (!mono_error_ok (error))
1333                         return NULL;
1334                 break;
1335         case MONO_PATCH_INFO_METHOD:
1336                 if (patch_info->data.method == method) {
1337                         target = code;
1338                 } else {
1339                         /* get the trampoline to the method from the domain */
1340                         target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
1341                         if (!mono_error_ok (error))
1342                                 return NULL;
1343                 }
1344                 break;
1345         case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
1346                 gpointer code_slot;
1347
1348                 mono_domain_lock (domain);
1349                 if (!domain_jit_info (domain)->method_code_hash)
1350                         domain_jit_info (domain)->method_code_hash = g_hash_table_new (NULL, NULL);
1351                 code_slot = g_hash_table_lookup (domain_jit_info (domain)->method_code_hash, patch_info->data.method);
1352                 if (!code_slot) {
1353                         code_slot = mono_domain_alloc0 (domain, sizeof (gpointer));
1354                         g_hash_table_insert (domain_jit_info (domain)->method_code_hash, patch_info->data.method, code_slot);
1355                 }
1356                 mono_domain_unlock (domain);
1357                 target = code_slot;
1358                 break;
1359         }
1360         case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
1361 #if defined(__native_client_codegen__)
1362                 target = (gpointer)&__nacl_thread_suspension_needed;
1363 #else
1364                 g_assert (mono_threads_is_coop_enabled ());
1365                 target = (gpointer)&mono_polling_required;
1366 #endif
1367                 break;
1368         case MONO_PATCH_INFO_SWITCH: {
1369                 gpointer *jump_table;
1370                 int i;
1371 #if defined(__native_client__) && defined(__native_client_codegen__)
1372                 /* This memory will leak, but we don't care if we're */
1373                 /* not deleting JIT'd methods anyway                 */
1374                 jump_table = g_malloc0 (sizeof(gpointer) * patch_info->data.table->table_size);
1375 #else
1376                 if (method && method->dynamic) {
1377                         jump_table = (void **)mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
1378                 } else {
1379                         if (mono_aot_only) {
1380                                 jump_table = (void **)mono_domain_alloc (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1381                         } else {
1382                                 jump_table = (void **)mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
1383                         }
1384                 }
1385 #endif
1386
1387                 for (i = 0; i < patch_info->data.table->table_size; i++) {
1388                         jump_table [i] = code + GPOINTER_TO_INT (patch_info->data.table->table [i]);
1389                 }
1390
1391                 target = jump_table;
1392                 break;
1393         }
1394         case MONO_PATCH_INFO_METHODCONST:
1395         case MONO_PATCH_INFO_CLASS:
1396         case MONO_PATCH_INFO_IMAGE:
1397         case MONO_PATCH_INFO_FIELD:
1398         case MONO_PATCH_INFO_SIGNATURE:
1399         case MONO_PATCH_INFO_AOT_MODULE:
1400                 target = patch_info->data.target;
1401                 break;
1402         case MONO_PATCH_INFO_IID:
1403                 mono_class_init (patch_info->data.klass);
1404                 target = GUINT_TO_POINTER (patch_info->data.klass->interface_id);
1405                 break;
1406         case MONO_PATCH_INFO_ADJUSTED_IID:
1407                 mono_class_init (patch_info->data.klass);
1408                 target = GUINT_TO_POINTER ((guint32)(-((patch_info->data.klass->interface_id + 1) * SIZEOF_VOID_P)));
1409                 break;
1410         case MONO_PATCH_INFO_VTABLE:
1411                 target = mono_class_vtable (domain, patch_info->data.klass);
1412                 g_assert (target);
1413                 break;
1414         case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
1415                 MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
1416
1417                 if (del_tramp->is_virtual)
1418                         target = mono_create_delegate_virtual_trampoline (domain, del_tramp->klass, del_tramp->method);
1419                 else
1420                         target = mono_create_delegate_trampoline_info (domain, del_tramp->klass, del_tramp->method);
1421                 break;
1422         }
1423         case MONO_PATCH_INFO_SFLDA: {
1424                 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
1425
1426                 if (mono_class_field_is_special_static (patch_info->data.field)) {
1427                         gpointer addr = NULL;
1428
1429                         mono_domain_lock (domain);
1430                         if (domain->special_static_fields)
1431                                 addr = g_hash_table_lookup (domain->special_static_fields, patch_info->data.field);
1432                         mono_domain_unlock (domain);
1433                         g_assert (addr);
1434                         return addr;
1435                 }
1436
1437                 g_assert (vtable);
1438                 if (!vtable->initialized && !mono_class_is_before_field_init (vtable->klass) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
1439                         /* Done by the generated code */
1440                         ;
1441                 else {
1442                         if (run_cctors) {
1443                                 if (!mono_runtime_class_init_full (vtable, error)) {
1444                                         return NULL;
1445                                 }
1446                         }
1447                 }
1448                 target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
1449                 break;
1450         }
1451         case MONO_PATCH_INFO_RVA: {
1452                 guint32 field_index = mono_metadata_token_index (patch_info->data.token->token);
1453                 guint32 rva;
1454
1455                 mono_metadata_field_info (patch_info->data.token->image, field_index - 1, NULL, &rva, NULL);
1456                 target = mono_image_rva_map (patch_info->data.token->image, rva);
1457                 break;
1458         }
1459         case MONO_PATCH_INFO_R4:
1460         case MONO_PATCH_INFO_R8:
1461                 target = patch_info->data.target;
1462                 break;
1463         case MONO_PATCH_INFO_EXC_NAME:
1464                 target = patch_info->data.name;
1465                 break;
1466         case MONO_PATCH_INFO_LDSTR:
1467                 target =
1468                         mono_ldstr_checked (domain, patch_info->data.token->image,
1469                                             mono_metadata_token_index (patch_info->data.token->token), error);
1470                 break;
1471         case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
1472                 gpointer handle;
1473                 MonoClass *handle_class;
1474
1475                 handle = mono_ldtoken_checked (patch_info->data.token->image,
1476                                                            patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1477                 if (!mono_error_ok (error))
1478                         return NULL;
1479                 mono_class_init (handle_class);
1480                 mono_class_init (mono_class_from_mono_type ((MonoType *)handle));
1481
1482                 target = mono_type_get_object_checked (domain, (MonoType *)handle, error);
1483                 if (!mono_error_ok (error))
1484                         return NULL;
1485                 break;
1486         }
1487         case MONO_PATCH_INFO_LDTOKEN: {
1488                 gpointer handle;
1489                 MonoClass *handle_class;
1490
1491                 handle = mono_ldtoken_checked (patch_info->data.token->image,
1492                                                            patch_info->data.token->token, &handle_class, patch_info->data.token->has_context ? &patch_info->data.token->context : NULL, error);
1493                 if (!mono_error_ok (error))
1494                         g_error ("Could not patch ldtoken due to %s", mono_error_get_message (error));
1495                 mono_class_init (handle_class);
1496
1497                 target = handle;
1498                 break;
1499         }
1500         case MONO_PATCH_INFO_DECLSEC:
1501                 target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2);
1502                 break;
1503         case MONO_PATCH_INFO_ICALL_ADDR:
1504         case MONO_PATCH_INFO_ICALL_ADDR_CALL:
1505                 /* run_cctors == 0 -> AOT */
1506                 if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
1507                         const char *exc_class;
1508                         const char *exc_arg;
1509
1510                         if (run_cctors) {
1511                                 target = mono_lookup_pinvoke_call (patch_info->data.method, &exc_class, &exc_arg);
1512                                 if (!target) {
1513                                         if (mono_aot_only) {
1514                                                 mono_error_set_exception_instance (error, mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
1515                                                 return NULL;
1516                                         }
1517                                         g_error ("Unable to resolve pinvoke method '%s' Re-run with MONO_LOG_LEVEL=debug for more information.\n", mono_method_full_name (patch_info->data.method, TRUE));
1518                                 }
1519                         } else {
1520                                 target = NULL;
1521                         }
1522                 } else {
1523                         target = mono_lookup_internal_call (patch_info->data.method);
1524
1525                         if (!target && run_cctors)
1526                                 g_error ("Unregistered icall '%s'\n", mono_method_full_name (patch_info->data.method, TRUE));
1527                 }
1528                 break;
1529         case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG:
1530                 target = mono_thread_interruption_request_flag ();
1531                 break;
1532         case MONO_PATCH_INFO_METHOD_RGCTX: {
1533                 MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.method->klass);
1534                 g_assert (vtable);
1535
1536                 target = mono_method_lookup_rgctx (vtable, mini_method_get_context (patch_info->data.method)->method_inst);
1537                 break;
1538         }
1539         case MONO_PATCH_INFO_RGCTX_SLOT_INDEX: {
1540                 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1541
1542                 target = GINT_TO_POINTER (MONO_RGCTX_SLOT_INDEX (slot));
1543                 break;
1544         }
1545         case MONO_PATCH_INFO_BB_OVF:
1546         case MONO_PATCH_INFO_EXC_OVF:
1547         case MONO_PATCH_INFO_GOT_OFFSET:
1548         case MONO_PATCH_INFO_NONE:
1549                 break;
1550         case MONO_PATCH_INFO_RGCTX_FETCH: {
1551                 int slot = mini_get_rgctx_entry_slot (patch_info->data.rgctx_entry);
1552
1553                 target = mono_create_rgctx_lazy_fetch_trampoline (slot);
1554                 break;
1555         }
1556 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
1557         case MONO_PATCH_INFO_SEQ_POINT_INFO:
1558                 if (!run_cctors)
1559                         /* AOT, not needed */
1560                         target = NULL;
1561                 else
1562                         target = mono_arch_get_seq_point_info (domain, code);
1563                 break;
1564 #endif
1565         case MONO_PATCH_INFO_GC_CARD_TABLE_ADDR: {
1566                 int card_table_shift_bits;
1567                 gpointer card_table_mask;
1568
1569                 target = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
1570                 break;
1571         }
1572         case MONO_PATCH_INFO_GC_NURSERY_START: {
1573                 int shift_bits;
1574                 size_t size;
1575
1576                 target = mono_gc_get_nursery (&shift_bits, &size);
1577                 break;
1578         }
1579         case MONO_PATCH_INFO_GC_NURSERY_BITS: {
1580                 int shift_bits;
1581                 size_t size;
1582
1583                 mono_gc_get_nursery (&shift_bits, &size);
1584
1585                 target = (gpointer)(mgreg_t)shift_bits;
1586                 break;
1587         }
1588         case MONO_PATCH_INFO_CASTCLASS_CACHE: {
1589                 target = mono_domain_alloc0 (domain, sizeof (gpointer));
1590                 break;
1591         }
1592         case MONO_PATCH_INFO_OBJC_SELECTOR_REF: {
1593                 target = NULL;
1594                 break;
1595         }
1596         case MONO_PATCH_INFO_LDSTR_LIT: {
1597                 int len;
1598                 char *s;
1599
1600                 len = strlen ((const char *)patch_info->data.target);
1601                 s = (char *)mono_domain_alloc0 (domain, len + 1);
1602                 memcpy (s, patch_info->data.target, len);
1603                 target = s;
1604
1605                 break;
1606         }
1607         case MONO_PATCH_INFO_GSHAREDVT_IN_WRAPPER:
1608                 target = mini_get_gsharedvt_wrapper (TRUE, NULL, patch_info->data.sig, NULL, -1, FALSE);
1609                 break;
1610         case MONO_PATCH_INFO_GET_TLS_TRAMP:
1611                 target = mono_tls_get_tls_getter (patch_info->data.index, FALSE);
1612                 break;
1613         case MONO_PATCH_INFO_SET_TLS_TRAMP:
1614                 target = mono_tls_get_tls_setter (patch_info->data.index, FALSE);
1615                 break;
1616         case MONO_PATCH_INFO_JIT_THREAD_ATTACH: {
1617                 MonoJitICallInfo *mi = mono_find_jit_icall_by_name ("mono_jit_thread_attach");
1618                 g_assert (mi);
1619                 target = mi->func;
1620                 break;
1621         }
1622         default:
1623                 g_assert_not_reached ();
1624         }
1625
1626         return (gpointer)target;
1627 }
1628
1629 void
1630 mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
1631 {
1632         MonoGenericInst *inst;
1633         int i;
1634
1635         memset (gsctx, 0, sizeof (MonoGenericSharingContext));
1636
1637         if (context && context->class_inst) {
1638                 inst = context->class_inst;
1639                 for (i = 0; i < inst->type_argc; ++i) {
1640                         MonoType *type = inst->type_argv [i];
1641
1642                         if (mini_is_gsharedvt_gparam (type))
1643                                 gsctx->is_gsharedvt = TRUE;
1644                 }
1645         }
1646         if (context && context->method_inst) {
1647                 inst = context->method_inst;
1648
1649                 for (i = 0; i < inst->type_argc; ++i) {
1650                         MonoType *type = inst->type_argv [i];
1651
1652                         if (mini_is_gsharedvt_gparam (type))
1653                                 gsctx->is_gsharedvt = TRUE;
1654                 }
1655         }
1656 }
1657
1658 /*
1659  * LOCKING: Acquires the jit code hash lock.
1660  */
1661 MonoJitInfo*
1662 mini_lookup_method (MonoDomain *domain, MonoMethod *method, MonoMethod *shared)
1663 {
1664         MonoJitInfo *ji;
1665         static gboolean inited = FALSE;
1666         static int lookups = 0;
1667         static int failed_lookups = 0;
1668
1669         mono_domain_jit_code_hash_lock (domain);
1670         ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, method);
1671         if (!ji && shared) {
1672                 /* Try generic sharing */
1673                 ji = (MonoJitInfo *)mono_internal_hash_table_lookup (&domain->jit_code_hash, shared);
1674                 if (ji && !ji->has_generic_jit_info)
1675                         ji = NULL;
1676                 if (!inited) {
1677                         mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
1678                         mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
1679                         inited = TRUE;
1680                 }
1681
1682                 ++lookups;
1683                 if (!ji)
1684                         ++failed_lookups;
1685         }
1686         mono_domain_jit_code_hash_unlock (domain);
1687
1688         return ji;
1689 }
1690
1691 static MonoJitInfo*
1692 lookup_method (MonoDomain *domain, MonoMethod *method)
1693 {
1694         MonoJitInfo *ji;
1695         MonoMethod *shared;
1696
1697         ji = mini_lookup_method (domain, method, NULL);
1698
1699         if (!ji) {
1700                 if (!mono_method_is_generic_sharable (method, FALSE))
1701                         return NULL;
1702                 shared = mini_get_shared_method (method);
1703                 ji = mini_lookup_method (domain, method, shared);
1704         }
1705
1706         return ji;
1707 }
1708
1709 MonoJitInfo *
1710 mono_get_jit_info_from_method (MonoDomain *domain, MonoMethod *method)
1711 {
1712         return lookup_method (domain, method);
1713 }
1714
1715 #if ENABLE_JIT_MAP
1716 static FILE* perf_map_file;
1717
1718 void
1719 mono_enable_jit_map (void)
1720 {
1721         if (!perf_map_file) {
1722                 char name [64];
1723                 g_snprintf (name, sizeof (name), "/tmp/perf-%d.map", getpid ());
1724                 unlink (name);
1725                 perf_map_file = fopen (name, "w");
1726         }
1727 }
1728
1729 void
1730 mono_emit_jit_tramp (void *start, int size, const char *desc)
1731 {
1732         if (perf_map_file)
1733                 fprintf (perf_map_file, "%llx %x %s\n", (long long unsigned int)(gsize)start, size, desc);
1734 }
1735
1736 void
1737 mono_emit_jit_map (MonoJitInfo *jinfo)
1738 {
1739         if (perf_map_file) {
1740                 char *name = mono_method_full_name (jinfo_get_method (jinfo), TRUE);
1741                 mono_emit_jit_tramp (jinfo->code_start, jinfo->code_size, name);
1742                 g_free (name);
1743         }
1744 }
1745
1746 gboolean
1747 mono_jit_map_is_enabled (void)
1748 {
1749         return perf_map_file != NULL;
1750 }
1751
1752 #endif
1753
1754 static void
1755 no_gsharedvt_in_wrapper (void)
1756 {
1757         g_assert_not_reached ();
1758 }
1759
1760 /*
1761 Overall algorithm:
1762
1763 Limit JITing to mono_cpu_count
1764         This ensures there's always room for application progress and not just JITing.
1765
1766 When a JIT request is made, we check if there's an outstanding one for that method and, if it exits, put the thread to sleep.
1767         If the current thread is already JITing another method, don't wait as it might cause a deadlock.
1768         Dependency management in this case is too complex to justify implementing it.
1769
1770 If there are no outstanding requests, the current thread is doing nothing and there are already mono_cpu_count threads JITing, go to sleep.
1771
1772 TODO:
1773         Get rid of cctor invocatio from within the JIT, it increases JIT duration and complicates things A LOT.
1774         Verify that we don't have too many spurious wakeups.
1775         Experiment with limiting to values around mono_cpu_count +/- 1 as this would enable progress during warmup.
1776 */
1777 typedef struct {
1778         MonoMethod *method;
1779         MonoDomain *domain;
1780         int count;
1781 } JitCompilationEntry;
1782
1783 typedef struct {
1784         GPtrArray *in_flight_methods; //JitCompilationEntry*
1785         int active_threads;
1786         int threads_waiting;
1787         MonoCoopMutex lock;
1788         MonoCoopCond cond;
1789 } JitCompilationData;
1790
1791 static JitCompilationData compilation_data;
1792 static int jit_methods_waited, jit_methods_multiple, jit_methods_overload, jit_spurious_wakeups;
1793
1794 static void
1795 mini_jit_init_job_control (void)
1796 {
1797         mono_coop_mutex_init (&compilation_data.lock);
1798         mono_coop_cond_init (&compilation_data.cond);
1799         compilation_data.in_flight_methods = g_ptr_array_new ();
1800 }
1801
1802 static void
1803 lock_compilation_data (void)
1804 {
1805         mono_coop_mutex_lock (&compilation_data.lock);
1806         fflush (stdout);
1807 }
1808
1809 static void
1810 unlock_compilation_data (void)
1811 {
1812         fflush (stdout);
1813         mono_coop_mutex_unlock (&compilation_data.lock);
1814 }
1815
1816 static JitCompilationEntry*
1817 find_method (MonoMethod *method, MonoDomain *domain)
1818 {
1819         int i;
1820         for (i = 0; i < compilation_data.in_flight_methods->len; ++i){
1821                 JitCompilationEntry *e = compilation_data.in_flight_methods->pdata [i];
1822                 if (e->method == method && e->domain == domain)
1823                         return e;
1824         }
1825
1826         return NULL;
1827 }
1828
1829 static void
1830 add_current_thread (MonoJitTlsData *jit_tls)
1831 {
1832         if (jit_tls->active_jit_methods == 0)
1833                 ++compilation_data.active_threads;
1834         ++jit_tls->active_jit_methods;
1835 }
1836
1837 //Returns true if this thread should wait
1838 static gboolean
1839 should_wait_for_available_cpu_capacity (void)
1840 {
1841         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1842
1843         //We can't suspend threads that are already JIT'ing something or we risk deadlocking
1844         if (jit_tls->active_jit_methods > 0)
1845                 return FALSE;
1846
1847         //If there are as many active threads as cores, JITing more will cause thrashing
1848         if (compilation_data.active_threads >= mono_cpu_count ()) {
1849                 ++jit_methods_overload;
1850                 return TRUE;
1851         }
1852         return FALSE;
1853 }
1854
1855 /*
1856  * Returns true if this method waited successfully for another thread to JIT it
1857  */
1858 static gboolean
1859 wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)
1860 {
1861         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1862         JitCompilationEntry *entry;
1863
1864
1865         static gboolean inited;
1866         if (!inited) {
1867                 mono_counters_register ("JIT compile waited others", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_waited);
1868                 mono_counters_register ("JIT compile 1+ jobs", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_multiple);
1869                 mono_counters_register ("JIT compile overload wait", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_overload);
1870                 mono_counters_register ("JIT compile spurious wakeups", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_spurious_wakeups);
1871                 inited = TRUE;
1872         }
1873
1874         lock_compilation_data ();
1875
1876         int waits = 0;
1877         while (should_wait_for_available_cpu_capacity ()) {
1878                 fflush (stdout);
1879                 ++compilation_data.threads_waiting;
1880                 mono_coop_cond_wait (&compilation_data.cond, &compilation_data.lock);
1881                 --compilation_data.threads_waiting;
1882                 if (waits)
1883                         ++jit_spurious_wakeups;
1884                 ++waits;
1885         }
1886
1887         if (!(entry = find_method (method, domain))) {
1888                 entry = g_new (JitCompilationEntry, 1);
1889                 entry->method = method;
1890                 entry->domain = domain;
1891                 entry->count = 1;
1892                 g_ptr_array_add (compilation_data.in_flight_methods, entry);
1893                 add_current_thread (jit_tls);
1894                 unlock_compilation_data ();
1895                 return FALSE;
1896         } else if (jit_tls->active_jit_methods > 0) {
1897                 //We can't suspend the current thread if it's already JITing a method.
1898                 //Dependency management is too compilated and we want to get rid of this anyways.
1899                 ++entry->count;
1900                 ++jit_methods_multiple;
1901                 unlock_compilation_data ();
1902                 return FALSE;
1903         } else {
1904                 ++jit_methods_waited;
1905                 while (TRUE) {
1906                         fflush (stdout);
1907                         ++compilation_data.threads_waiting;
1908                         mono_coop_cond_wait (&compilation_data.cond, &compilation_data.lock);
1909                         --compilation_data.threads_waiting;
1910
1911                         if (!find_method (method, domain)) {
1912                                 unlock_compilation_data ();
1913                                 return TRUE;
1914                         } else {
1915                                 ++jit_spurious_wakeups;
1916                         }
1917                 }
1918         }
1919 }
1920
1921 static void
1922 unregister_method_for_compile (MonoMethod *method, MonoDomain *target_domain)
1923 {
1924         MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1925
1926         lock_compilation_data ();
1927
1928         --jit_tls->active_jit_methods;
1929         if (jit_tls->active_jit_methods == 0)
1930                 --compilation_data.active_threads;
1931
1932         JitCompilationEntry *entry = find_method (method, target_domain);
1933         g_assert (entry); // It would be weird to fail
1934         if (--entry->count == 0) {
1935                 g_ptr_array_remove (compilation_data.in_flight_methods, entry);
1936                 g_free (entry);
1937         }
1938
1939         if (compilation_data.threads_waiting)
1940                 mono_coop_cond_broadcast (&compilation_data.cond);
1941         unlock_compilation_data ();
1942 }
1943
1944
1945 static gpointer
1946 mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_only, MonoError *error)
1947 {
1948         MonoDomain *target_domain, *domain = mono_domain_get ();
1949         MonoJitInfo *info;
1950         gpointer code = NULL, p;
1951         MonoJitInfo *ji;
1952         MonoJitICallInfo *callinfo = NULL;
1953         WrapperInfo *winfo = NULL;
1954
1955         error_init (error);
1956
1957 #ifdef ENABLE_INTERPRETER
1958         if (mono_use_interpreter && !jit_only) {
1959                 code = mono_interp_create_method_pointer (method, error);
1960                 if (code)
1961                         return code;
1962         }
1963 #endif
1964
1965         if (mono_llvm_only)
1966                 /* Should be handled by the caller */
1967                 g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED));
1968
1969         /*
1970          * ICALL wrappers are handled specially, since there is only one copy of them
1971          * shared by all appdomains.
1972          */
1973         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
1974                 winfo = mono_marshal_get_wrapper_info (method);
1975         if (winfo && winfo->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
1976                 callinfo = mono_find_jit_icall_by_addr (winfo->d.icall.func);
1977                 g_assert (callinfo);
1978
1979                 /* Must be domain neutral since there is only one copy */
1980                 opt |= MONO_OPT_SHARED;
1981         } else {
1982                 /* MONO_OPT_SHARED is no longer supported, we only use it for icall wrappers */
1983                 opt &= ~MONO_OPT_SHARED;
1984         }
1985
1986         if (opt & MONO_OPT_SHARED)
1987                 target_domain = mono_get_root_domain ();
1988         else
1989                 target_domain = domain;
1990
1991         if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
1992                 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
1993
1994                 g_assert (info);
1995                 if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
1996                         MonoGenericContext *ctx = NULL;
1997                         if (method->is_inflated)
1998                                 ctx = mono_method_get_context (method);
1999                         method = info->d.synchronized_inner.method;
2000                         if (ctx) {
2001                                 method = mono_class_inflate_generic_method_checked (method, ctx, error);
2002                                 g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */
2003                         }
2004                 }
2005         }
2006
2007 lookup_start:
2008         info = lookup_method (target_domain, method);
2009         if (info) {
2010                 /* We can't use a domain specific method in another domain */
2011                 if (! ((domain != target_domain) && !info->domain_neutral)) {
2012                         MonoVTable *vtable;
2013
2014                         mono_jit_stats.methods_lookups++;
2015                         vtable = mono_class_vtable_full (domain, method->klass, error);
2016                         if (!is_ok (error))
2017                                 return NULL;
2018                         g_assert (vtable);
2019                         if (!mono_runtime_class_init_full (vtable, error))
2020                                 return NULL;
2021                         return mono_create_ftnptr (target_domain, info->code_start);
2022                 }
2023         }
2024
2025 #ifdef MONO_USE_AOT_COMPILER
2026         if (opt & MONO_OPT_AOT) {
2027                 MonoDomain *domain = mono_domain_get ();
2028
2029                 mono_class_init (method->klass);
2030
2031                 if ((code = mono_aot_get_method_checked (domain, method, error))) {
2032                         MonoVTable *vtable;
2033
2034                         if (mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method)) {
2035                                 /*
2036                                  * The suspend code needs to be able to lookup these methods by ip in async context,
2037                                  * so preload their jit info.
2038                                  */
2039                                 MonoJitInfo *ji = mono_jit_info_table_find (domain, code);
2040                                 g_assert (ji);
2041                         }
2042
2043                         /*
2044                          * In llvm-only mode, method might be a shared method, so we can't initialize its class.
2045                          * This is not a problem, since it will be initialized when the method is first
2046                          * called by init_method ().
2047                          */
2048                         if (!mono_llvm_only) {
2049                                 vtable = mono_class_vtable (domain, method->klass);
2050                                 g_assert (vtable);
2051                                 if (!mono_runtime_class_init_full (vtable, error))
2052                                         return NULL;
2053                         }
2054                 }
2055                 if (!is_ok (error))
2056                         return NULL;
2057         }
2058 #endif
2059
2060         if (!code && mono_llvm_only) {
2061                 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2062                         WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2063
2064                         if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG) {
2065                                 /*
2066                                  * These wrappers are only created for signatures which are in the program, but
2067                                  * sometimes we load methods too eagerly and have to create them even if they
2068                                  * will never be called.
2069                                  */
2070                                 return no_gsharedvt_in_wrapper;
2071                         }
2072                 }
2073         }
2074
2075         if (!code) {
2076                 if (wait_or_register_method_to_compile (method, target_domain))
2077                         goto lookup_start;
2078                 code = mono_jit_compile_method_inner (method, target_domain, opt, error);
2079                 unregister_method_for_compile (method, target_domain);
2080         }
2081         if (!mono_error_ok (error))
2082                 return NULL;
2083
2084         if (!code && mono_llvm_only) {
2085                 printf ("AOT method not found in llvmonly mode: %s\n", mono_method_full_name (method, 1));
2086                 g_assert_not_reached ();
2087         }
2088
2089         if (!code)
2090                 return NULL;
2091
2092         if (method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER || method->wrapper_type == MONO_WRAPPER_ALLOC) {
2093                 MonoDomain *d;
2094
2095                 /*
2096                  * SGEN requires the JIT info for these methods to be registered, see is_ip_in_managed_allocator ().
2097                  */
2098                 ji = mini_jit_info_table_find (mono_domain_get (), (char *)code, &d);
2099                 g_assert (ji);
2100         }
2101
2102         p = mono_create_ftnptr (target_domain, code);
2103
2104         if (callinfo) {
2105                 /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */
2106                 mono_loader_lock ();
2107                 mono_jit_lock ();
2108                 if (!callinfo->wrapper) {
2109                         callinfo->wrapper = p;
2110                         mono_register_jit_icall_wrapper (callinfo, p);
2111                 }
2112                 mono_jit_unlock ();
2113                 mono_loader_unlock ();
2114         }
2115
2116         return p;
2117 }
2118
2119 gpointer
2120 mono_jit_compile_method (MonoMethod *method, MonoError *error)
2121 {
2122         gpointer code;
2123
2124         code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), FALSE, error);
2125         return code;
2126 }
2127
2128 /*
2129  * mono_jit_compile_method_jit_only:
2130  *
2131  *   Compile METHOD using the JIT/AOT, even in interpreted mode.
2132  */
2133 gpointer
2134 mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error)
2135 {
2136         gpointer code;
2137
2138         code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), TRUE, error);
2139         return code;
2140 }
2141
2142 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2143 static void
2144 invalidated_delegate_trampoline (char *desc)
2145 {
2146         g_error ("Unmanaged code called delegate of type %s which was already garbage collected.\n"
2147                  "See http://www.mono-project.com/Diagnostic:Delegate for an explanation and ways to fix this.",
2148                  desc);
2149 }
2150 #endif
2151
2152 /*
2153  * mono_jit_free_method:
2154  *
2155  *  Free all memory allocated by the JIT for METHOD.
2156  */
2157 static void
2158 mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
2159 {
2160         MonoJitDynamicMethodInfo *ji;
2161         gboolean destroy = TRUE;
2162         GHashTableIter iter;
2163         MonoJumpList *jlist;
2164
2165         g_assert (method->dynamic);
2166
2167         mono_domain_lock (domain);
2168         ji = mono_dynamic_code_hash_lookup (domain, method);
2169         mono_domain_unlock (domain);
2170
2171         if (!ji)
2172                 return;
2173
2174         mono_debug_remove_method (method, domain);
2175         mono_lldb_remove_method (domain, method, ji);
2176
2177         mono_domain_lock (domain);
2178         g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
2179         mono_domain_jit_code_hash_lock (domain);
2180         mono_internal_hash_table_remove (&domain->jit_code_hash, method);
2181         mono_domain_jit_code_hash_unlock (domain);
2182         g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
2183
2184         /* requires the domain lock - took above */
2185         mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
2186
2187         /* Remove jump targets in this method */
2188         g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
2189         while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) {
2190                 GSList *tmp, *remove;
2191
2192                 remove = NULL;
2193                 for (tmp = jlist->list; tmp; tmp = tmp->next) {
2194                         guint8 *ip = (guint8 *)tmp->data;
2195
2196                         if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size)
2197                                 remove = g_slist_prepend (remove, tmp);
2198                 }
2199                 for (tmp = remove; tmp; tmp = tmp->next) {
2200                         jlist->list = g_slist_delete_link ((GSList *)jlist->list, (GSList *)tmp->data);
2201                 }
2202                 g_slist_free (remove);
2203         }
2204         mono_domain_unlock (domain);
2205
2206 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2207         if (debug_options.keep_delegates && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
2208                 /*
2209                  * Instead of freeing the code, change it to call an error routine
2210                  * so people can fix their code.
2211                  */
2212                 char *type = mono_type_full_name (&method->klass->byval_arg);
2213                 char *type_and_method = g_strdup_printf ("%s.%s", type, method->name);
2214
2215                 g_free (type);
2216                 mono_arch_invalidate_method (ji->ji, invalidated_delegate_trampoline, type_and_method);
2217                 destroy = FALSE;
2218         }
2219 #endif
2220
2221         /*
2222          * This needs to be done before freeing code_mp, since the code address is the
2223          * key in the table, so if we free the code_mp first, another thread can grab the
2224          * same code address and replace our entry in the table.
2225          */
2226         mono_jit_info_table_remove (domain, ji->ji);
2227
2228         if (destroy)
2229                 mono_code_manager_destroy (ji->code_mp);
2230         g_free (ji);
2231 }
2232
2233 gpointer
2234 mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji)
2235 {
2236         MonoDomain *target_domain;
2237         MonoJitInfo *info;
2238
2239         if (default_opt & MONO_OPT_SHARED)
2240                 target_domain = mono_get_root_domain ();
2241         else
2242                 target_domain = domain;
2243
2244         info = lookup_method (target_domain, method);
2245         if (info) {
2246                 /* We can't use a domain specific method in another domain */
2247                 if (! ((domain != target_domain) && !info->domain_neutral)) {
2248                         mono_jit_stats.methods_lookups++;
2249                         if (ji)
2250                                 *ji = info;
2251                         return info->code_start;
2252                 }
2253         }
2254
2255         if (ji)
2256                 *ji = NULL;
2257         return NULL;
2258 }
2259
2260 static guint32 bisect_opt = 0;
2261 static GHashTable *bisect_methods_hash = NULL;
2262
2263 void
2264 mono_set_bisect_methods (guint32 opt, const char *method_list_filename)
2265 {
2266         FILE *file;
2267         char method_name [2048];
2268
2269         bisect_opt = opt;
2270         bisect_methods_hash = g_hash_table_new (g_str_hash, g_str_equal);
2271         g_assert (bisect_methods_hash);
2272
2273         file = fopen (method_list_filename, "r");
2274         g_assert (file);
2275
2276         while (fgets (method_name, sizeof (method_name), file)) {
2277                 size_t len = strlen (method_name);
2278                 g_assert (len > 0);
2279                 g_assert (method_name [len - 1] == '\n');
2280                 method_name [len - 1] = 0;
2281                 g_hash_table_insert (bisect_methods_hash, g_strdup (method_name), GINT_TO_POINTER (1));
2282         }
2283         g_assert (feof (file));
2284 }
2285
2286 gboolean mono_do_single_method_regression = FALSE;
2287 guint32 mono_single_method_regression_opt = 0;
2288 MonoMethod *mono_current_single_method;
2289 GSList *mono_single_method_list;
2290 GHashTable *mono_single_method_hash;
2291
2292 guint32
2293 mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
2294 {
2295         g_assert (method);
2296
2297         if (bisect_methods_hash) {
2298                 char *name = mono_method_full_name (method, TRUE);
2299                 void *res = g_hash_table_lookup (bisect_methods_hash, name);
2300                 g_free (name);
2301                 if (res)
2302                         return default_opt | bisect_opt;
2303         }
2304         if (!mono_do_single_method_regression)
2305                 return default_opt;
2306         if (!mono_current_single_method) {
2307                 if (!mono_single_method_hash)
2308                         mono_single_method_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
2309                 if (!g_hash_table_lookup (mono_single_method_hash, method)) {
2310                         g_hash_table_insert (mono_single_method_hash, method, method);
2311                         mono_single_method_list = g_slist_prepend (mono_single_method_list, method);
2312                 }
2313                 return default_opt;
2314         }
2315         if (method == mono_current_single_method)
2316                 return mono_single_method_regression_opt;
2317         return default_opt;
2318 }
2319
2320 gpointer
2321 mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
2322 {
2323         return mono_jit_find_compiled_method_with_jit_info (domain, method, NULL);
2324 }
2325
2326 typedef struct {
2327         MonoMethod *method;
2328         gpointer compiled_method;
2329         gpointer runtime_invoke;
2330         MonoVTable *vtable;
2331         MonoDynCallInfo *dyn_call_info;
2332         MonoClass *ret_box_class;
2333         MonoMethodSignature *sig;
2334         gboolean gsharedvt_invoke;
2335         gpointer *wrapper_arg;
2336 } RuntimeInvokeInfo;
2337
2338 static RuntimeInvokeInfo*
2339 create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, MonoError *error)
2340 {
2341         MonoMethod *invoke;
2342         RuntimeInvokeInfo *info;
2343
2344         info = g_new0 (RuntimeInvokeInfo, 1);
2345         info->compiled_method = compiled_method;
2346         if (mono_llvm_only && method->string_ctor)
2347                 info->sig = mono_marshal_get_string_ctor_signature (method);
2348         else
2349                 info->sig = mono_method_signature (method);
2350
2351         invoke = mono_marshal_get_runtime_invoke (method, FALSE);
2352         info->vtable = mono_class_vtable_full (domain, method->klass, error);
2353         if (!mono_error_ok (error))
2354                 return NULL;
2355         g_assert (info->vtable);
2356
2357         MonoMethodSignature *sig = info->sig;
2358         MonoType *ret_type;
2359
2360         /*
2361          * We want to avoid AOTing 1000s of runtime-invoke wrappers when running
2362          * in full-aot mode, so we use a slower, but more generic wrapper if
2363          * possible, built on top of the OP_DYN_CALL opcode provided by the JIT.
2364          */
2365 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2366         if (!mono_llvm_only && (mono_aot_only || debug_options.dyn_runtime_invoke)) {
2367                 gboolean supported = TRUE;
2368                 int i;
2369
2370                 if (method->string_ctor)
2371                         sig = mono_marshal_get_string_ctor_signature (method);
2372
2373                 for (i = 0; i < sig->param_count; ++i) {
2374                         MonoType *t = sig->params [i];
2375
2376                         if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
2377                                 supported = FALSE;
2378                 }
2379
2380                 if (mono_class_is_contextbound (method->klass) || !info->compiled_method)
2381                         supported = FALSE;
2382
2383                 if (supported)
2384                         info->dyn_call_info = mono_arch_dyn_call_prepare (sig);
2385         }
2386 #endif
2387
2388         ret_type = sig->ret;
2389         switch (ret_type->type) {
2390         case MONO_TYPE_VOID:
2391                 break;
2392         case MONO_TYPE_I1:
2393         case MONO_TYPE_U1:
2394         case MONO_TYPE_I2:
2395         case MONO_TYPE_U2:
2396         case MONO_TYPE_I4:
2397         case MONO_TYPE_U4:
2398         case MONO_TYPE_I:
2399         case MONO_TYPE_U:
2400         case MONO_TYPE_I8:
2401         case MONO_TYPE_U8:
2402         case MONO_TYPE_BOOLEAN:
2403         case MONO_TYPE_CHAR:
2404         case MONO_TYPE_R4:
2405         case MONO_TYPE_R8:
2406                 info->ret_box_class = mono_class_from_mono_type (ret_type);
2407                 break;
2408         case MONO_TYPE_PTR:
2409                 info->ret_box_class = mono_defaults.int_class;
2410                 break;
2411         case MONO_TYPE_STRING:
2412         case MONO_TYPE_CLASS:
2413         case MONO_TYPE_ARRAY:
2414         case MONO_TYPE_SZARRAY:
2415         case MONO_TYPE_OBJECT:
2416                 break;
2417         case MONO_TYPE_GENERICINST:
2418                 if (!MONO_TYPE_IS_REFERENCE (ret_type))
2419                         info->ret_box_class = mono_class_from_mono_type (ret_type);
2420                 break;
2421         case MONO_TYPE_VALUETYPE:
2422                 info->ret_box_class = mono_class_from_mono_type (ret_type);
2423                 break;
2424         default:
2425                 g_assert_not_reached ();
2426                 break;
2427         }
2428
2429         if (!info->dyn_call_info) {
2430                 if (mono_llvm_only) {
2431 #ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
2432                         g_assert_not_reached ();
2433 #endif
2434                         info->gsharedvt_invoke = TRUE;
2435                         if (!callee_gsharedvt) {
2436                                 /* Invoke a gsharedvt out wrapper instead */
2437                                 MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
2438                                 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2439
2440                                 info->wrapper_arg = g_malloc0 (2 * sizeof (gpointer));
2441                                 info->wrapper_arg [0] = mini_add_method_wrappers_llvmonly (method, info->compiled_method, FALSE, FALSE, &(info->wrapper_arg [1]));
2442
2443                                 /* Pass has_rgctx == TRUE since the wrapper has an extra arg */
2444                                 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2445                                 g_free (wrapper_sig);
2446
2447                                 info->compiled_method = mono_jit_compile_method (wrapper, error);
2448                                 if (!mono_error_ok (error)) {
2449                                         g_free (info);
2450                                         return NULL;
2451                                 }
2452                         } else {
2453                                 /* Gsharedvt methods can be invoked the same way */
2454                                 /* The out wrapper has the same signature as the compiled gsharedvt method */
2455                                 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2456
2457                                 info->wrapper_arg = mono_method_needs_static_rgctx_invoke (method, TRUE) ? mini_method_get_rgctx (method) : NULL;
2458
2459                                 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2460                                 g_free (wrapper_sig);
2461                         }
2462                 }
2463                 info->runtime_invoke = mono_jit_compile_method (invoke, error);
2464                 if (!mono_error_ok (error)) {
2465                         g_free (info);
2466                         return NULL;
2467                 }
2468         }
2469
2470         return info;
2471 }
2472
2473 static MonoObject*
2474 mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc, MonoError *error)
2475 {
2476         MonoMethodSignature *sig = info->sig;
2477         MonoDomain *domain = mono_domain_get ();
2478         MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2479         gpointer *args;
2480         gpointer retval_ptr;
2481         guint8 retval [256];
2482         gpointer *param_refs;
2483         int i, pindex;
2484
2485         error_init (error);
2486
2487         g_assert (info->gsharedvt_invoke);
2488
2489         /*
2490          * Instead of invoking the method directly, we invoke a gsharedvt out wrapper.
2491          * The advantage of this is the gsharedvt out wrappers have a reduced set of
2492          * signatures, so we only have to generate runtime invoke wrappers for these
2493          * signatures.
2494          * This code also handles invocation of gsharedvt methods directly, no
2495          * out wrappers are used in that case.
2496          */
2497         args = (void **)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2498         param_refs = (gpointer*)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2499         pindex = 0;
2500         /*
2501          * The runtime invoke wrappers expects pointers to primitive types, so have to
2502          * use indirections.
2503          */
2504         if (sig->hasthis)
2505                 args [pindex ++] = &obj;
2506         if (sig->ret->type != MONO_TYPE_VOID) {
2507                 retval_ptr = (gpointer)&retval;
2508                 args [pindex ++] = &retval_ptr;
2509         }
2510         for (i = 0; i < sig->param_count; ++i) {
2511                 MonoType *t = sig->params [i];
2512
2513                 if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
2514                         MonoClass *klass = mono_class_from_mono_type (t);
2515                         guint8 *nullable_buf;
2516                         int size;
2517
2518                         size = mono_class_value_size (klass, NULL);
2519                         nullable_buf = g_alloca (size);
2520                         g_assert (nullable_buf);
2521
2522                         /* The argument pointed to by params [i] is either a boxed vtype or null */
2523                         mono_nullable_init (nullable_buf, (MonoObject*)params [i], klass);
2524                         params [i] = nullable_buf;
2525                 }
2526
2527                 if (!t->byref && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) {
2528                         param_refs [i] = params [i];
2529                         params [i] = &(param_refs [i]);
2530                 }
2531                 args [pindex ++] = &params [i];
2532         }
2533         /* The gsharedvt out wrapper has an extra argument which contains the method to call */
2534         args [pindex ++] = &info->wrapper_arg;
2535
2536         runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2537
2538         runtime_invoke (NULL, args, exc, info->compiled_method);
2539         if (exc && *exc)
2540                 return NULL;
2541
2542         if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
2543                 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2544         else
2545                 return *(MonoObject**)retval;
2546 }
2547
2548 /**
2549  * mono_jit_runtime_invoke:
2550  * \param method: the method to invoke
2551  * \param obj: this pointer
2552  * \param params: array of parameter values.
2553  * \param exc: Set to the exception raised in the managed method.
2554  * \param error: error or caught exception object
2555  * If \p exc is NULL, \p error is thrown instead.
2556  * If coop is enabled, \p exc argument is ignored -
2557  * all exceptions are caught and propagated through \p error
2558  */
2559 static MonoObject*
2560 mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
2561 {
2562         MonoMethod *invoke, *callee;
2563         MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2564         MonoDomain *domain = mono_domain_get ();
2565         MonoJitDomainInfo *domain_info;
2566         RuntimeInvokeInfo *info, *info2;
2567         MonoJitInfo *ji = NULL;
2568         gboolean callee_gsharedvt = FALSE;
2569
2570 #ifdef ENABLE_INTERPRETER
2571         if (mono_use_interpreter)
2572                 return mono_interp_runtime_invoke (method, obj, params, exc, error);
2573 #endif
2574
2575         error_init (error);
2576
2577         if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
2578                 g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
2579                 return NULL;
2580         }
2581
2582         domain_info = domain_jit_info (domain);
2583
2584         info = (RuntimeInvokeInfo *)mono_conc_hashtable_lookup (domain_info->runtime_invoke_hash, method);
2585
2586         if (!info) {
2587                 if (mono_security_core_clr_enabled ()) {
2588                         /*
2589                          * This might be redundant since mono_class_vtable () already does this,
2590                          * but keep it just in case for moonlight.
2591                          */
2592                         mono_class_setup_vtable (method->klass);
2593                         if (mono_class_has_failure (method->klass)) {
2594                                 mono_error_set_for_class_failure (error, method->klass);
2595                                 if (exc)
2596                                         *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);
2597                                 return NULL;
2598                         }
2599                 }
2600
2601                 gpointer compiled_method;
2602
2603                 callee = method;
2604                 if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2605                         (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
2606                         /*
2607                          * Array Get/Set/Address methods. The JIT implements them using inline code
2608                          * inside the runtime invoke wrappers, so no need to compile them.
2609                          */
2610                         if (mono_aot_only) {
2611                                 /*
2612                                  * Call a wrapper, since the runtime invoke wrapper was not generated.
2613                                  */
2614                                 MonoMethod *wrapper;
2615
2616                                 wrapper = mono_marshal_get_array_accessor_wrapper (method);
2617                                 invoke = mono_marshal_get_runtime_invoke (wrapper, FALSE);
2618                                 callee = wrapper;
2619                         } else {
2620                                 callee = NULL;
2621                         }
2622                 }
2623
2624                 if (callee) {
2625                         compiled_method = mono_jit_compile_method (callee, error);
2626                         if (!compiled_method) {
2627                                 g_assert (!mono_error_ok (error));
2628                                 return NULL;
2629                         }
2630
2631                         if (mono_llvm_only) {
2632                                 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
2633                                 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
2634                                 if (callee_gsharedvt)
2635                                         callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
2636                         }
2637
2638                         if (!callee_gsharedvt)
2639                                 compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
2640                 } else {
2641                         compiled_method = NULL;
2642                 }
2643
2644                 info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error);
2645                 if (!mono_error_ok (error))
2646                         return NULL;
2647
2648                 mono_domain_lock (domain);
2649                 info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
2650                 mono_domain_unlock (domain);
2651                 if (info2) {
2652                         g_free (info);
2653                         info = info2;
2654                 }
2655         }
2656
2657         /*
2658          * We need this here because mono_marshal_get_runtime_invoke can place
2659          * the helper method in System.Object and not the target class.
2660          */
2661         if (!mono_runtime_class_init_full (info->vtable, error)) {
2662                 if (exc)
2663                         *exc = (MonoObject*) mono_error_convert_to_exception (error);
2664                 return NULL;
2665         }
2666
2667         /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
2668            we always catch the exception and propagate it through the MonoError */
2669         gboolean catchExcInMonoError =
2670                 (exc == NULL) && mono_threads_is_coop_enabled ();
2671         MonoObject *invoke_exc = NULL;
2672         if (catchExcInMonoError)
2673                 exc = &invoke_exc;
2674
2675         /* The wrappers expect this to be initialized to NULL */
2676         if (exc)
2677                 *exc = NULL;
2678
2679 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2680         if (info->dyn_call_info) {
2681                 MonoMethodSignature *sig = mono_method_signature (method);
2682                 gpointer *args;
2683                 static RuntimeInvokeDynamicFunction dyn_runtime_invoke;
2684                 int i, pindex;
2685                 guint8 buf [512];
2686                 guint8 retval [256];
2687
2688                 if (!dyn_runtime_invoke) {
2689                         invoke = mono_marshal_get_runtime_invoke_dynamic ();
2690                         dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error);
2691                         if (!mono_error_ok (error))
2692                                 return NULL;
2693                 }
2694
2695                 /* Convert the arguments to the format expected by start_dyn_call () */
2696                 args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));
2697                 pindex = 0;
2698                 if (sig->hasthis)
2699                         args [pindex ++] = &obj;
2700                 for (i = 0; i < sig->param_count; ++i) {
2701                         MonoType *t = sig->params [i];
2702
2703                         if (t->byref) {
2704                                 args [pindex ++] = &params [i];
2705                         } else if (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR) {
2706                                 args [pindex ++] = &params [i];
2707                         } else {
2708                                 args [pindex ++] = params [i];
2709                         }
2710                 }
2711
2712                 //printf ("M: %s\n", mono_method_full_name (method, TRUE));
2713
2714                 mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));
2715
2716                 dyn_runtime_invoke (buf, exc, info->compiled_method);
2717                 mono_arch_finish_dyn_call (info->dyn_call_info, buf);
2718
2719                 if (catchExcInMonoError && *exc != NULL) {
2720                         mono_error_set_exception_instance (error, (MonoException*) *exc);
2721                         return NULL;
2722                 }
2723
2724                 if (info->ret_box_class)
2725                         return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2726                 else
2727                         return *(MonoObject**)retval;
2728         }
2729 #endif
2730
2731         MonoObject *result;
2732
2733         if (mono_llvm_only) {
2734                 result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
2735                 if (!is_ok (error))
2736                         return NULL;
2737         } else {
2738                 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2739
2740                 result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
2741         }
2742         if (catchExcInMonoError && *exc != NULL)
2743                 mono_error_set_exception_instance (error, (MonoException*) *exc);
2744         return result;
2745 }
2746
2747 typedef struct {
2748         MonoVTable *vtable;
2749         int slot;
2750 } IMTTrampInfo;
2751
2752 typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method);
2753
2754 /*
2755  * mini_llvmonly_initial_imt_tramp:
2756  *
2757  *  This function is called the first time a call is made through an IMT trampoline.
2758  * It should have the same signature as the mono_llvmonly_imt_tramp_... functions.
2759  */
2760 static gpointer
2761 mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2762 {
2763         IMTTrampInfo *info = (IMTTrampInfo*)arg;
2764         gpointer *imt;
2765         gpointer *ftndesc;
2766         IMTTrampFunc func;
2767
2768         mono_vtable_build_imt_slot (info->vtable, info->slot);
2769
2770         imt = (gpointer*)info->vtable;
2771         imt -= MONO_IMT_SIZE;
2772
2773         /* Return what the real IMT trampoline returns */
2774         ftndesc = imt [info->slot];
2775         func = ftndesc [0];
2776
2777         if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp)
2778                 /* Happens when the imt slot contains only a generic virtual method */
2779                 return NULL;
2780         return func ((gpointer *)ftndesc [1], imt_method);
2781 }
2782
2783 /* This is called indirectly through an imt slot. */
2784 static gpointer
2785 mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2786 {
2787         int i = 0;
2788
2789         /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */
2790         while (arg [i] && arg [i] != imt_method)
2791                 i += 2;
2792         g_assert (arg [i]);
2793
2794         return arg [i + 1];
2795 }
2796
2797 /* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */
2798 static gpointer
2799 mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method)
2800 {
2801         //g_assert (arg [0] == imt_method);
2802         return arg [1];
2803 }
2804
2805 static gpointer
2806 mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method)
2807 {
2808         //g_assert (arg [0] == imt_method || arg [2] == imt_method);
2809         if (arg [0] == imt_method)
2810                 return arg [1];
2811         else
2812                 return arg [3];
2813 }
2814
2815 static gpointer
2816 mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method)
2817 {
2818         //g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method);
2819         if (arg [0] == imt_method)
2820                 return arg [1];
2821         else if (arg [2] == imt_method)
2822                 return arg [3];
2823         else
2824                 return arg [5];
2825 }
2826
2827 /*
2828  * A version of the imt trampoline used for generic virtual/variant iface methods.
2829  * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found
2830  * in the search table. The original JIT code had a 'fallback' trampoline it could
2831  * call, but we can't do that, so we just return NULL, and the compiled code
2832  * will handle it.
2833  */
2834 static gpointer
2835 mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2836 {
2837         int i = 0;
2838
2839         while (arg [i] && arg [i] != imt_method)
2840                 i += 2;
2841         if (!arg [i])
2842                 return NULL;
2843
2844         return arg [i + 1];
2845 }
2846
2847 static gpointer
2848 mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
2849 {
2850         gpointer *buf;
2851         gpointer *res;
2852         int i, index, real_count;
2853         gboolean virtual_generic = FALSE;
2854
2855         /*
2856          * Create an array which is passed to the imt trampoline functions.
2857          * The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry.
2858          */
2859
2860         real_count = 0;
2861         for (i = 0; i < count; ++i) {
2862                 MonoIMTCheckItem *item = imt_entries [i];
2863
2864                 if (item->is_equals)
2865                         real_count ++;
2866                 if (item->has_target_code)
2867                         virtual_generic = TRUE;
2868         }
2869
2870         /*
2871          * Initialize all vtable entries reachable from this imt slot, so the compiled
2872          * code doesn't have to check it.
2873          */
2874         for (i = 0; i < count; ++i) {
2875                 MonoIMTCheckItem *item = imt_entries [i];
2876                 int vt_slot;
2877
2878                 if (!item->is_equals || item->has_target_code)
2879                         continue;
2880                 vt_slot = item->value.vtable_slot;
2881                 mono_init_vtable_slot (vtable, vt_slot);
2882         }
2883
2884         /* Save the entries into an array */
2885         buf = (void **)mono_domain_alloc (domain, (real_count + 1) * 2 * sizeof (gpointer));
2886         index = 0;
2887         for (i = 0; i < count; ++i) {
2888                 MonoIMTCheckItem *item = imt_entries [i];
2889
2890                 if (!item->is_equals)
2891                         continue;
2892
2893                 g_assert (item->key);
2894                 buf [(index * 2)] = item->key;
2895                 if (item->has_target_code)
2896                         buf [(index * 2) + 1] = item->value.target_code;
2897                 else
2898                         buf [(index * 2) + 1] = vtable->vtable [item->value.vtable_slot];
2899                 index ++;
2900         }
2901         buf [(index * 2)] = NULL;
2902         buf [(index * 2) + 1] = fail_tramp;
2903
2904         /*
2905          * Return a function descriptor for a C function with 'buf' as its argument.
2906          * It will by called by JITted code.
2907          */
2908         res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer));
2909         switch (real_count) {
2910         case 1:
2911                 res [0] = mono_llvmonly_imt_tramp_1;
2912                 break;
2913         case 2:
2914                 res [0] = mono_llvmonly_imt_tramp_2;
2915                 break;
2916         case 3:
2917                 res [0] = mono_llvmonly_imt_tramp_3;
2918                 break;
2919         default:
2920                 res [0] = mono_llvmonly_imt_tramp;
2921                 break;
2922         }
2923         if (virtual_generic || fail_tramp)
2924                 res [0] = mono_llvmonly_fallback_imt_tramp;
2925         res [1] = buf;
2926
2927         return res;
2928 }
2929
2930 MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
2931 {
2932         MonoException *exc = NULL;
2933         MonoJitInfo *ji;
2934         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2935         MONO_SIG_HANDLER_GET_CONTEXT;
2936
2937         ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
2938
2939         MONO_ENTER_GC_UNSAFE_UNBALANCED;
2940
2941 #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
2942         if (mono_arch_is_int_overflow (ctx, info))
2943                 /*
2944                  * The spec says this throws ArithmeticException, but MS throws the derived
2945                  * OverflowException.
2946                  */
2947                 exc = mono_get_exception_overflow ();
2948         else
2949                 exc = mono_get_exception_divide_by_zero ();
2950 #else
2951         exc = mono_get_exception_divide_by_zero ();
2952 #endif
2953
2954         if (!ji) {
2955                 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
2956                         goto exit;
2957
2958                 mono_handle_native_crash ("SIGFPE", ctx, info);
2959                 if (mono_do_crash_chaining) {
2960                         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
2961                         goto exit;
2962                 }
2963         }
2964
2965         mono_arch_handle_exception (ctx, exc);
2966
2967 exit:
2968         MONO_EXIT_GC_UNSAFE_UNBALANCED;
2969 }
2970
2971 MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
2972 {
2973         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2974         MONO_SIG_HANDLER_GET_CONTEXT;
2975
2976         if (mono_runtime_get_no_exec ())
2977                 exit (1);
2978
2979
2980         mono_handle_native_crash ("SIGILL", ctx, info);
2981         if (mono_do_crash_chaining) {
2982                 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
2983                 return;
2984         }
2985
2986         g_assert_not_reached ();
2987 }
2988
2989 #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
2990 #define HAVE_SIG_INFO
2991 #endif
2992
2993 MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
2994 {
2995         MonoJitInfo *ji;
2996         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
2997         gpointer fault_addr = NULL;
2998 #ifdef HAVE_SIG_INFO
2999         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
3000 #else
3001         void *info = NULL;
3002 #endif
3003         MONO_SIG_HANDLER_GET_CONTEXT;
3004
3005 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
3006         if (mono_arch_is_single_step_event (info, ctx)) {
3007                 mono_debugger_agent_single_step_event (ctx);
3008                 return;
3009         } else if (mono_arch_is_breakpoint_event (info, ctx)) {
3010                 mono_debugger_agent_breakpoint_hit (ctx);
3011                 return;
3012         }
3013 #endif
3014
3015 #if defined(HAVE_SIG_INFO)
3016 #if !defined(HOST_WIN32)
3017         fault_addr = info->si_addr;
3018         if (mono_aot_is_pagefault (info->si_addr)) {
3019                 mono_aot_handle_pagefault (info->si_addr);
3020                 return;
3021         }
3022 #endif
3023
3024         /* The thread might no be registered with the runtime */
3025         if (!mono_domain_get () || !jit_tls) {
3026                 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3027                         return;
3028                 mono_handle_native_crash ("SIGSEGV", ctx, info);
3029                 if (mono_do_crash_chaining) {
3030                         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3031                         return;
3032                 }
3033         }
3034 #endif
3035
3036         ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
3037
3038 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
3039         if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
3040                 return;
3041
3042 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
3043         /* info->si_addr seems to be NULL on some kernels when handling stack overflows */
3044         fault_addr = info->si_addr;
3045         if (fault_addr == NULL) {
3046                 MonoContext mctx;
3047
3048                 mono_sigctx_to_monoctx (ctx, &mctx);
3049
3050                 fault_addr = MONO_CONTEXT_GET_SP (&mctx);
3051         }
3052 #endif
3053
3054         if (jit_tls->stack_size &&
3055                 ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
3056                 /*
3057                  * The hard-guard page has been hit: there is not much we can do anymore
3058                  * Print a hopefully clear message and abort.
3059                  */
3060                 mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
3061                 g_assert_not_reached ();
3062         } else {
3063                 /* The original handler might not like that it is executed on an altstack... */
3064                 if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3065                         return;
3066
3067                 mono_arch_handle_altstack_exception (ctx, info, info->si_addr, FALSE);
3068         }
3069 #else
3070
3071         if (!ji) {
3072                 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3073                         return;
3074
3075                 mono_handle_native_crash ("SIGSEGV", ctx, info);
3076
3077                 if (mono_do_crash_chaining) {
3078                         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3079                         return;
3080                 }
3081         }
3082
3083         mono_arch_handle_exception (ctx, NULL);
3084 #endif
3085 }
3086
3087 MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
3088 {
3089         MonoException *exc;
3090         MONO_SIG_HANDLER_GET_CONTEXT;
3091
3092         MONO_ENTER_GC_UNSAFE_UNBALANCED;
3093
3094         exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
3095
3096         mono_arch_handle_exception (ctx, exc);
3097
3098         MONO_EXIT_GC_UNSAFE_UNBALANCED;
3099 }
3100
3101 #ifndef DISABLE_REMOTING
3102 /* mono_jit_create_remoting_trampoline:
3103  * @method: pointer to the method info
3104  *
3105  * Creates a trampoline which calls the remoting functions. This
3106  * is used in the vtable of transparent proxies.
3107  *
3108  * Returns: a pointer to the newly created code
3109  */
3110 static gpointer
3111 mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
3112 {
3113         MonoMethod *nm;
3114         guint8 *addr = NULL;
3115
3116         error_init (error);
3117
3118         if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && mono_method_signature (method)->generic_param_count) {
3119                 return mono_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
3120                         domain, NULL);
3121         }
3122
3123         if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
3124             (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class)))
3125                 nm = mono_marshal_get_remoting_invoke_for_target (method, target);
3126         else
3127                 nm = method;
3128         addr = (guint8 *)mono_compile_method_checked (nm, error);
3129         return_val_if_nok (error, NULL);
3130         return mono_get_addr_from_ftnptr (addr);
3131 }
3132 #endif
3133
3134 static G_GNUC_UNUSED void
3135 no_imt_trampoline (void)
3136 {
3137         g_assert_not_reached ();
3138 }
3139
3140 static G_GNUC_UNUSED void
3141 no_vcall_trampoline (void)
3142 {
3143         g_assert_not_reached ();
3144 }
3145
3146 static gpointer *vtable_trampolines;
3147 static int vtable_trampolines_size;
3148
3149 gpointer
3150 mini_get_vtable_trampoline (MonoVTable *vt, int slot_index)
3151 {
3152         int index = slot_index + MONO_IMT_SIZE;
3153
3154         if (mono_llvm_only) {
3155                 if (slot_index < 0) {
3156                         /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
3157                         // FIXME: Memory management
3158                         gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
3159                         IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
3160                         info->vtable = vt;
3161                         info->slot = index;
3162                         ftndesc [0] = mini_llvmonly_initial_imt_tramp;
3163                         ftndesc [1] = info;
3164                         mono_memory_barrier ();
3165                         return ftndesc;
3166                 } else {
3167                         return NULL;
3168                 }
3169         }
3170
3171         g_assert (slot_index >= - MONO_IMT_SIZE);
3172         if (!vtable_trampolines || slot_index + MONO_IMT_SIZE >= vtable_trampolines_size) {
3173                 mono_jit_lock ();
3174                 if (!vtable_trampolines || index >= vtable_trampolines_size) {
3175                         int new_size;
3176                         gpointer new_table;
3177
3178                         new_size = vtable_trampolines_size ? vtable_trampolines_size * 2 : 128;
3179                         while (new_size <= index)
3180                                 new_size *= 2;
3181                         new_table = g_new0 (gpointer, new_size);
3182
3183                         if (vtable_trampolines)
3184                                 memcpy (new_table, vtable_trampolines, vtable_trampolines_size * sizeof (gpointer));
3185                         g_free (vtable_trampolines);
3186                         mono_memory_barrier ();
3187                         vtable_trampolines = (void **)new_table;
3188                         vtable_trampolines_size = new_size;
3189                 }
3190                 mono_jit_unlock ();
3191         }
3192
3193         if (!vtable_trampolines [index])
3194                 vtable_trampolines [index] = mono_create_specific_trampoline (GUINT_TO_POINTER (slot_index), MONO_TRAMPOLINE_VCALL, mono_get_root_domain (), NULL);
3195         return vtable_trampolines [index];
3196 }
3197
3198 static gpointer
3199 mini_get_imt_trampoline (MonoVTable *vt, int slot_index)
3200 {
3201         return mini_get_vtable_trampoline (vt, slot_index - MONO_IMT_SIZE);
3202 }
3203
3204 static gboolean
3205 mini_imt_entry_inited (MonoVTable *vt, int imt_slot_index)
3206 {
3207         if (mono_llvm_only)
3208                 return FALSE;
3209
3210         gpointer *imt = (gpointer*)vt;
3211         imt -= MONO_IMT_SIZE;
3212
3213         return (imt [imt_slot_index] != mini_get_imt_trampoline (vt, imt_slot_index));
3214 }
3215
3216 static gboolean
3217 is_callee_gsharedvt_variable (gpointer addr)
3218 {
3219         MonoJitInfo *ji;
3220         gboolean callee_gsharedvt;
3221
3222         ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
3223         g_assert (ji);
3224         callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
3225         if (callee_gsharedvt)
3226                 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
3227         return callee_gsharedvt;
3228 }
3229
3230 gpointer
3231 mini_get_delegate_arg (MonoMethod *method, gpointer method_ptr)
3232 {
3233         gpointer arg = NULL;
3234
3235         if (mono_method_needs_static_rgctx_invoke (method, FALSE))
3236                 arg = mini_method_get_rgctx (method);
3237
3238         /*
3239          * Avoid adding gsharedvt in wrappers since they might not exist if
3240          * this delegate is called through a gsharedvt delegate invoke wrapper.
3241          * Instead, encode that the method is gsharedvt in del->extra_arg,
3242          * the CEE_MONO_CALLI_EXTRA_ARG implementation in the JIT depends on this.
3243          */
3244         if (method->is_inflated && is_callee_gsharedvt_variable (method_ptr)) {
3245                 g_assert ((((mgreg_t)arg) & 1) == 0);
3246                 arg = (gpointer)(((mgreg_t)arg) | 1);
3247         }
3248         return arg;
3249 }
3250
3251 void
3252 mini_init_delegate (MonoDelegate *del)
3253 {
3254         if (mono_llvm_only)
3255                 del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
3256 #ifdef ENABLE_INTERPRETER
3257         if (mono_use_interpreter)
3258                 mono_interp_init_delegate (del);
3259 #endif
3260 }
3261
3262 char*
3263 mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset)
3264 {
3265         int abs_offset;
3266
3267         abs_offset = offset;
3268         if (abs_offset < 0)
3269                 abs_offset = - abs_offset;
3270         return g_strdup_printf ("delegate_virtual_invoke%s_%s%d", load_imt_reg ? "_imt" : "", offset < 0 ? "m_" : "", abs_offset / SIZEOF_VOID_P);
3271 }
3272
3273 gpointer
3274 mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
3275 {
3276         gboolean is_virtual_generic, is_interface, load_imt_reg;
3277         int offset, idx;
3278
3279         static guint8 **cache = NULL;
3280         static int cache_size = 0;
3281
3282         if (!method)
3283                 return NULL;
3284
3285         if (MONO_TYPE_ISSTRUCT (sig->ret))
3286                 return NULL;
3287
3288         is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
3289         is_interface = mono_class_is_interface (method->klass);
3290         load_imt_reg = is_virtual_generic || is_interface;
3291
3292         if (is_interface)
3293                 offset = ((gint32)mono_method_get_imt_slot (method) - MONO_IMT_SIZE) * SIZEOF_VOID_P;
3294         else
3295                 offset = G_STRUCT_OFFSET (MonoVTable, vtable) + ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));
3296
3297         idx = (offset / SIZEOF_VOID_P + MONO_IMT_SIZE) * 2 + (load_imt_reg ? 1 : 0);
3298         g_assert (idx >= 0);
3299
3300         /* Resize the cache to idx + 1 */
3301         if (cache_size < idx + 1) {
3302                 mono_jit_lock ();
3303                 if (cache_size < idx + 1) {
3304                         guint8 **new_cache;
3305                         int new_cache_size = idx + 1;
3306
3307                         new_cache = g_new0 (guint8*, new_cache_size);
3308                         if (cache)
3309                                 memcpy (new_cache, cache, cache_size * sizeof (guint8*));
3310                         g_free (cache);
3311
3312                         mono_memory_barrier ();
3313                         cache = new_cache;
3314                         cache_size = new_cache_size;
3315                 }
3316                 mono_jit_unlock ();
3317         }
3318
3319         if (cache [idx])
3320                 return cache [idx];
3321
3322         /* FIXME Support more cases */
3323         if (mono_aot_only) {
3324                 cache [idx] = (guint8 *)mono_aot_get_trampoline (mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset));
3325                 g_assert (cache [idx]);
3326         } else {
3327                 cache [idx] = (guint8 *)mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
3328         }
3329         return cache [idx];
3330 }
3331
3332 /**
3333  * mini_parse_debug_option:
3334  * @option: The option to parse.
3335  *
3336  * Parses debug options for the mono runtime. The options are the same as for
3337  * the MONO_DEBUG environment variable.
3338  *
3339  */
3340 gboolean
3341 mini_parse_debug_option (const char *option)
3342 {
3343         if (!strcmp (option, "handle-sigint"))
3344                 debug_options.handle_sigint = TRUE;
3345         else if (!strcmp (option, "keep-delegates"))
3346                 debug_options.keep_delegates = TRUE;
3347         else if (!strcmp (option, "reverse-pinvoke-exceptions"))
3348                 debug_options.reverse_pinvoke_exceptions = TRUE;
3349         else if (!strcmp (option, "collect-pagefault-stats"))
3350                 debug_options.collect_pagefault_stats = TRUE;
3351         else if (!strcmp (option, "break-on-unverified"))
3352                 debug_options.break_on_unverified = TRUE;
3353         else if (!strcmp (option, "no-gdb-backtrace"))
3354                 debug_options.no_gdb_backtrace = TRUE;
3355         else if (!strcmp (option, "suspend-on-native-crash") || !strcmp (option, "suspend-on-sigsegv"))
3356                 debug_options.suspend_on_native_crash = TRUE;
3357         else if (!strcmp (option, "suspend-on-exception"))
3358                 debug_options.suspend_on_exception = TRUE;
3359         else if (!strcmp (option, "suspend-on-unhandled"))
3360                 debug_options.suspend_on_unhandled = TRUE;
3361         else if (!strcmp (option, "dont-free-domains"))
3362                 mono_dont_free_domains = TRUE;
3363         else if (!strcmp (option, "dyn-runtime-invoke"))
3364                 debug_options.dyn_runtime_invoke = TRUE;
3365         else if (!strcmp (option, "gdb"))
3366                 debug_options.gdb = TRUE;
3367         else if (!strcmp (option, "lldb"))
3368                 debug_options.lldb = TRUE;
3369         else if (!strcmp (option, "explicit-null-checks"))
3370                 debug_options.explicit_null_checks = TRUE;
3371         else if (!strcmp (option, "gen-seq-points"))
3372                 debug_options.gen_sdb_seq_points = TRUE;
3373         else if (!strcmp (option, "gen-compact-seq-points"))
3374                 fprintf (stderr, "Mono Warning: option gen-compact-seq-points is deprecated.\n");
3375         else if (!strcmp (option, "no-compact-seq-points"))
3376                 debug_options.no_seq_points_compact_data = TRUE;
3377         else if (!strcmp (option, "single-imm-size"))
3378                 debug_options.single_imm_size = TRUE;
3379         else if (!strcmp (option, "init-stacks"))
3380                 debug_options.init_stacks = TRUE;
3381         else if (!strcmp (option, "casts"))
3382                 debug_options.better_cast_details = TRUE;
3383         else if (!strcmp (option, "soft-breakpoints"))
3384                 debug_options.soft_breakpoints = TRUE;
3385         else if (!strcmp (option, "check-pinvoke-callconv"))
3386                 debug_options.check_pinvoke_callconv = TRUE;
3387         else if (!strcmp (option, "use-fallback-tls"))
3388                 debug_options.use_fallback_tls = TRUE;
3389         else if (!strcmp (option, "debug-domain-unload"))
3390                 mono_enable_debug_domain_unload (TRUE);
3391         else if (!strcmp (option, "partial-sharing"))
3392                 mono_set_partial_sharing_supported (TRUE);
3393         else if (!strcmp (option, "align-small-structs"))
3394                 mono_align_small_structs = TRUE;
3395         else if (!strcmp (option, "native-debugger-break"))
3396                 debug_options.native_debugger_break = TRUE;
3397         else if (!strcmp (option, "disable_omit_fp"))
3398                 debug_options.disable_omit_fp = TRUE;
3399         else
3400                 return FALSE;
3401
3402         return TRUE;
3403 }
3404
3405 static void
3406 mini_parse_debug_options (void)
3407 {
3408         char *options = g_getenv ("MONO_DEBUG");
3409         gchar **args, **ptr;
3410
3411         if (!options)
3412                 return;
3413
3414         args = g_strsplit (options, ",", -1);
3415         g_free (options);
3416
3417         for (ptr = args; ptr && *ptr; ptr++) {
3418                 const char *arg = *ptr;
3419
3420                 if (!mini_parse_debug_option (arg)) {
3421                         fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
3422                         fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'suspend-on-native-crash', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dont-free-domains', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'gen-seq-points', 'no-compact-seq-points', 'single-imm-size', 'init-stacks', 'casts', 'soft-breakpoints', 'check-pinvoke-callconv', 'use-fallback-tls', 'debug-domain-unload', 'partial-sharing', 'align-small-structs', 'native-debugger-break'\n");
3423                         exit (1);
3424                 }
3425         }
3426
3427         g_strfreev (args);
3428 }
3429
3430 MonoDebugOptions *
3431 mini_get_debug_options (void)
3432 {
3433         return &debug_options;
3434 }
3435
3436 static gpointer
3437 mini_create_ftnptr (MonoDomain *domain, gpointer addr)
3438 {
3439 #if !defined(__ia64__) && (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
3440         return addr;
3441 #else
3442         gpointer* desc = NULL;
3443
3444         if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
3445                 return desc;
3446 #       ifdef __ia64__
3447         desc = mono_domain_code_reserve (domain, 2 * sizeof (gpointer));
3448
3449         desc [0] = addr;
3450         desc [1] = NULL;
3451 #       elif defined(__ppc64__) || defined(__powerpc64__)
3452
3453         desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
3454
3455         desc [0] = addr;
3456         desc [1] = NULL;
3457         desc [2] = NULL;
3458 #       endif
3459         g_hash_table_insert (domain->ftnptrs_hash, addr, desc);
3460         return desc;
3461 #endif
3462 }
3463
3464 static gpointer
3465 mini_get_addr_from_ftnptr (gpointer descr)
3466 {
3467 #if defined(__ia64__) || ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
3468         return *(gpointer*)descr;
3469 #else
3470         return descr;
3471 #endif
3472 }
3473
3474 static void
3475 register_jit_stats (void)
3476 {
3477         mono_counters_register ("Compiled methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_compiled);
3478         mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot);
3479         mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
3480         mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);
3481         mono_counters_register ("JIT/method_to_ir (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
3482         mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses);
3483         mono_counters_register ("JIT/handle_out_of_line_bblock (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_out_of_line_bblock);
3484         mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts);
3485         mono_counters_register ("JIT/decompose_typechecks (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_typechecks);
3486         mono_counters_register ("JIT/local_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop);
3487         mono_counters_register ("JIT/local_emulate_ops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_emulate_ops);
3488         mono_counters_register ("JIT/optimize_branches (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches);
3489         mono_counters_register ("JIT/handle_global_vregs (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs);
3490         mono_counters_register ("JIT/local_deadce (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce);
3491         mono_counters_register ("JIT/local_alias_analysis (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_alias_analysis);
3492         mono_counters_register ("JIT/if_conversion (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_if_conversion);
3493         mono_counters_register ("JIT/bb_ordering (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_bb_ordering);
3494         mono_counters_register ("JIT/compile_dominator_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compile_dominator_info);
3495         mono_counters_register ("JIT/compute_natural_loops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compute_natural_loops);
3496         mono_counters_register ("JIT/insert_safepoints (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_insert_safepoints);
3497         mono_counters_register ("JIT/ssa_compute (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_compute);
3498         mono_counters_register ("JIT/ssa_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_cprop);
3499         mono_counters_register ("JIT/ssa_deadce(sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_deadce);
3500         mono_counters_register ("JIT/perform_abc_removal (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_perform_abc_removal);
3501         mono_counters_register ("JIT/ssa_remove (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_remove);
3502         mono_counters_register ("JIT/local_cprop2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop2);
3503         mono_counters_register ("JIT/handle_global_vregs2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs2);
3504         mono_counters_register ("JIT/local_deadce2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce2);
3505         mono_counters_register ("JIT/optimize_branches2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches2);
3506         mono_counters_register ("JIT/decompose_vtype_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_vtype_opts);
3507         mono_counters_register ("JIT/decompose_array_access_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_array_access_opts);
3508         mono_counters_register ("JIT/liveness_handle_exception_clauses2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses2);
3509         mono_counters_register ("JIT/analyze_liveness (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_analyze_liveness);
3510         mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
3511         mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
3512         mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
3513         mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
3514         mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
3515         mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
3516         mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
3517         mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
3518         mono_counters_register ("JIT/save_seq_point_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_save_seq_point_info);
3519         mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time);
3520         mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks);
3521         mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks);
3522         mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var);
3523         mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs);
3524         mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size);
3525         mono_counters_register ("Allocated seq points size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_seq_points_size);
3526         mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods);
3527         mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods);
3528         mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars);
3529         mono_counters_register ("Locals stack size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.locals_stack_size);
3530         mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
3531         mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
3532         mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
3533         mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
3534         mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
3535         mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
3536         mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
3537         mono_counters_register ("Optimized immediate divisions", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.optimized_divisions);
3538 }
3539
3540 static void runtime_invoke_info_free (gpointer value);
3541
3542 static gint
3543 class_method_pair_equal (gconstpointer ka, gconstpointer kb)
3544 {
3545         const MonoClassMethodPair *apair = (const MonoClassMethodPair *)ka;
3546         const MonoClassMethodPair *bpair = (const MonoClassMethodPair *)kb;
3547
3548         return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
3549 }
3550
3551 static guint
3552 class_method_pair_hash (gconstpointer data)
3553 {
3554         const MonoClassMethodPair *pair = (const MonoClassMethodPair *)data;
3555
3556         return (gsize)pair->klass ^ (gsize)pair->method;
3557 }
3558
3559 static void
3560 mini_create_jit_domain_info (MonoDomain *domain)
3561 {
3562         MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
3563
3564         info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3565         info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3566         info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
3567         info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3568         info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
3569         info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
3570         info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
3571         info->jump_target_hash = g_hash_table_new (NULL, NULL);
3572         mono_jit_code_hash_init (&info->interp_code_hash);
3573
3574         domain->runtime_info = info;
3575 }
3576
3577 static void
3578 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
3579 {
3580         MonoJumpList *jlist = (MonoJumpList *)value;
3581         g_slist_free (jlist->list);
3582 }
3583
3584 static void
3585 delete_got_slot_list (gpointer key, gpointer value, gpointer user_data)
3586 {
3587         GSList *list = (GSList *)value;
3588         g_slist_free (list);
3589 }
3590
3591 static void
3592 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
3593 {
3594         MonoJitDynamicMethodInfo *di = (MonoJitDynamicMethodInfo *)value;
3595         mono_code_manager_destroy (di->code_mp);
3596         g_free (di);
3597 }
3598
3599 static void
3600 runtime_invoke_info_free (gpointer value)
3601 {
3602         RuntimeInvokeInfo *info = (RuntimeInvokeInfo*)value;
3603
3604 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
3605         if (info->dyn_call_info)
3606                 mono_arch_dyn_call_free (info->dyn_call_info);
3607 #endif
3608         g_free (info);
3609 }
3610
3611 static void
3612 free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
3613 {
3614         g_slist_free (value);
3615 }
3616
3617 static void
3618 mini_free_jit_domain_info (MonoDomain *domain)
3619 {
3620         MonoJitDomainInfo *info = domain_jit_info (domain);
3621
3622         g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
3623         g_hash_table_destroy (info->jump_target_hash);
3624         if (info->jump_target_got_slot_hash) {
3625                 g_hash_table_foreach (info->jump_target_got_slot_hash, delete_got_slot_list, NULL);
3626                 g_hash_table_destroy (info->jump_target_got_slot_hash);
3627         }
3628         if (info->dynamic_code_hash) {
3629                 g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
3630                 g_hash_table_destroy (info->dynamic_code_hash);
3631         }
3632         if (info->method_code_hash)
3633                 g_hash_table_destroy (info->method_code_hash);
3634         g_hash_table_destroy (info->jump_trampoline_hash);
3635         g_hash_table_destroy (info->jit_trampoline_hash);
3636         g_hash_table_destroy (info->delegate_trampoline_hash);
3637         if (info->static_rgctx_trampoline_hash)
3638                 g_hash_table_destroy (info->static_rgctx_trampoline_hash);
3639         g_hash_table_destroy (info->llvm_vcall_trampoline_hash);
3640         mono_conc_hashtable_destroy (info->runtime_invoke_hash);
3641         g_hash_table_destroy (info->seq_points);
3642         g_hash_table_destroy (info->arch_seq_points);
3643         if (info->agent_info)
3644                 mono_debugger_agent_free_domain_info (domain);
3645         if (info->gsharedvt_arg_tramp_hash)
3646                 g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
3647         if (info->llvm_jit_callees) {
3648                 g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
3649                 g_hash_table_destroy (info->llvm_jit_callees);
3650         }
3651 #ifdef ENABLE_LLVM
3652         mono_llvm_free_domain_info (domain);
3653 #endif
3654
3655         g_free (domain->runtime_info);
3656         domain->runtime_info = NULL;
3657 }
3658
3659 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3660
3661 static void
3662 code_manager_chunk_new (void *chunk, int size)
3663 {
3664         mono_arch_code_chunk_new (chunk, size);
3665 }
3666
3667 static void
3668 code_manager_chunk_destroy (void *chunk)
3669 {
3670         mono_arch_code_chunk_destroy (chunk);
3671 }
3672
3673 #endif
3674
3675 #ifdef ENABLE_LLVM
3676 static gboolean
3677 llvm_init_inner (void)
3678 {
3679         if (!mono_llvm_load (NULL))
3680                 return FALSE;
3681
3682         mono_llvm_init ();
3683         return TRUE;
3684 }
3685 #endif
3686
3687 /*
3688  * mini_llvm_init:
3689  *
3690  *   Load and initialize LLVM support.
3691  * Return TRUE on success.
3692  */
3693 gboolean
3694 mini_llvm_init (void)
3695 {
3696 #ifdef ENABLE_LLVM
3697         static gboolean llvm_inited;
3698         static gboolean init_result;
3699
3700         mono_loader_lock_if_inited ();
3701         if (!llvm_inited) {
3702                 init_result = llvm_init_inner ();
3703                 llvm_inited = TRUE;
3704         }
3705         mono_loader_unlock_if_inited ();
3706         return init_result;
3707 #else
3708         return FALSE;
3709 #endif
3710 }
3711
3712 void
3713 mini_profiler_enable_with_options (const char* profile_options)
3714 {
3715         mini_enable_profiler = TRUE;
3716         mini_profiler_options = g_strdup (profile_options);
3717 }
3718
3719 MonoDomain *
3720 mini_init (const char *filename, const char *runtime_version)
3721 {
3722         MonoError error;
3723         MonoDomain *domain;
3724         MonoRuntimeCallbacks callbacks;
3725         MonoThreadInfoRuntimeCallbacks ticallbacks;
3726         MonoCodeManagerCallbacks code_manager_callbacks;
3727
3728         MONO_VES_INIT_BEGIN ();
3729
3730         CHECKED_MONO_INIT ();
3731
3732 #if defined(__linux__) && !defined(__native_client__)
3733         if (access ("/proc/self/maps", F_OK) != 0) {
3734                 g_print ("Mono requires /proc to be mounted.\n");
3735                 exit (1);
3736         }
3737 #endif
3738
3739         mono_os_mutex_init_recursive (&jit_mutex);
3740
3741         mono_cross_helpers_run ();
3742
3743         mono_counters_init ();
3744
3745         mini_jit_init ();
3746
3747         mini_jit_init_job_control ();
3748
3749         /* Happens when using the embedding interface */
3750         if (!default_opt_set)
3751                 default_opt = mono_parse_default_optimizations (NULL);
3752
3753 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
3754         if (mono_aot_only)
3755                 mono_set_generic_sharing_vt_supported (TRUE);
3756 #else
3757         if (mono_llvm_only)
3758                 mono_set_generic_sharing_vt_supported (TRUE);
3759 #endif
3760
3761         mono_tls_init_runtime_keys ();
3762
3763         if (!global_codeman)
3764                 global_codeman = mono_code_manager_new ();
3765
3766         memset (&callbacks, 0, sizeof (callbacks));
3767         callbacks.create_ftnptr = mini_create_ftnptr;
3768         callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
3769         callbacks.get_runtime_build_info = mono_get_runtime_build_info;
3770         callbacks.set_cast_details = mono_set_cast_details;
3771         callbacks.debug_log = mono_debugger_agent_debug_log;
3772         callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
3773         callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
3774         callbacks.get_imt_trampoline = mini_get_imt_trampoline;
3775         callbacks.imt_entry_inited = mini_imt_entry_inited;
3776         callbacks.init_delegate = mini_init_delegate;
3777 #define JIT_INVOKE_WORKS
3778 #ifdef JIT_INVOKE_WORKS
3779         callbacks.runtime_invoke = mono_jit_runtime_invoke;
3780 #endif
3781 #define JIT_TRAMPOLINES_WORK
3782 #ifdef JIT_TRAMPOLINES_WORK
3783         callbacks.compile_method = mono_jit_compile_method;
3784         callbacks.create_jump_trampoline = mono_create_jump_trampoline;
3785         callbacks.create_jit_trampoline = mono_create_jit_trampoline;
3786         callbacks.create_delegate_trampoline = mono_create_delegate_trampoline;
3787         callbacks.free_method = mono_jit_free_method;
3788 #ifndef DISABLE_REMOTING
3789         callbacks.create_remoting_trampoline = mono_jit_create_remoting_trampoline;
3790 #endif
3791 #endif
3792
3793         mono_install_callbacks (&callbacks);
3794
3795         memset (&ticallbacks, 0, sizeof (ticallbacks));
3796         ticallbacks.setup_async_callback = mono_setup_async_callback;
3797         ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
3798         ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
3799         ticallbacks.thread_state_init = mono_thread_state_init;
3800
3801 #ifndef HOST_WIN32
3802         mono_w32handle_init ();
3803 #endif
3804
3805         mono_threads_runtime_init (&ticallbacks);
3806
3807         if (g_hasenv ("MONO_DEBUG")) {
3808                 mini_parse_debug_options ();
3809         }
3810
3811         mono_code_manager_init ();
3812
3813         memset (&code_manager_callbacks, 0, sizeof (code_manager_callbacks));
3814 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3815         code_manager_callbacks.chunk_new = code_manager_chunk_new;
3816         code_manager_callbacks.chunk_destroy = code_manager_chunk_destroy;
3817 #endif
3818         mono_code_manager_install_callbacks (&code_manager_callbacks);
3819
3820         mono_hwcap_init ();
3821
3822         mono_arch_cpu_init ();
3823
3824         mono_arch_init ();
3825
3826         mono_unwind_init ();
3827
3828         if (mini_get_debug_options ()->lldb || g_hasenv ("MONO_LLDB")) {
3829                 mono_lldb_init ("");
3830                 mono_dont_free_domains = TRUE;
3831         }
3832
3833 #ifdef XDEBUG_ENABLED
3834         char *mono_xdebug = g_getenv ("MONO_XDEBUG");
3835         if (mono_xdebug) {
3836                 mono_xdebug_init (mono_xdebug);
3837                 g_free (mono_xdebug);
3838                 /* So methods for multiple domains don't have the same address */
3839                 mono_dont_free_domains = TRUE;
3840                 mono_using_xdebug = TRUE;
3841         } else if (mini_get_debug_options ()->gdb) {
3842                 mono_xdebug_init ((char*)"gdb");
3843                 mono_dont_free_domains = TRUE;
3844                 mono_using_xdebug = TRUE;
3845         }
3846 #endif
3847
3848 #ifdef ENABLE_LLVM
3849         if (mono_use_llvm) {
3850                 if (!mono_llvm_load (NULL)) {
3851                         mono_use_llvm = FALSE;
3852                         fprintf (stderr, "Mono Warning: llvm support could not be loaded.\n");
3853                 }
3854         }
3855         if (mono_use_llvm)
3856                 mono_llvm_init ();
3857 #endif
3858
3859         mono_trampolines_init ();
3860
3861         if (default_opt & MONO_OPT_AOT)
3862                 mono_aot_init ();
3863
3864         mono_debugger_agent_init ();
3865
3866 #ifdef MONO_ARCH_GSHARED_SUPPORTED
3867         mono_set_generic_sharing_supported (TRUE);
3868 #endif
3869
3870         mono_threads_signals_init ();
3871
3872 #ifndef MONO_CROSS_COMPILE
3873         mono_runtime_install_handlers ();
3874 #endif
3875         mono_threads_install_cleanup (mini_thread_cleanup);
3876
3877 #ifdef JIT_TRAMPOLINES_WORK
3878         mono_install_create_domain_hook (mini_create_jit_domain_info);
3879         mono_install_free_domain_hook (mini_free_jit_domain_info);
3880 #endif
3881         mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
3882         mono_install_get_class_from_name (mono_aot_get_class_from_name);
3883         mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
3884
3885         if (mini_profiler_enabled ()) {
3886                 mono_profiler_load (mini_profiler_get_options ());
3887                 mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main");
3888         }
3889
3890         if (debug_options.collect_pagefault_stats)
3891                 mono_aot_set_make_unreadable (TRUE);
3892
3893         if (runtime_version)
3894                 domain = mono_init_version (filename, runtime_version);
3895         else
3896                 domain = mono_init_from_assembly (filename, filename);
3897
3898         if (mono_aot_only) {
3899                 /* This helps catch code allocation requests */
3900                 mono_code_manager_set_read_only (domain->code_mp);
3901                 mono_marshal_use_aot_wrappers (TRUE);
3902         }
3903
3904         if (mono_llvm_only) {
3905                 mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline);
3906                 mono_set_always_build_imt_trampolines (TRUE);
3907         } else if (mono_aot_only) {
3908                 mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline);
3909         } else {
3910                 mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline);
3911         }
3912
3913         /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
3914         mono_arch_finish_init ();
3915
3916         mono_icall_init ();
3917
3918         /* This must come after mono_init () in the aot-only case */
3919         mono_exceptions_init ();
3920
3921         /* This should come after mono_init () too */
3922         mini_gc_init ();
3923
3924 #ifndef DISABLE_JIT
3925         mono_create_helper_signatures ();
3926 #endif
3927
3928         register_jit_stats ();
3929
3930 #define JIT_CALLS_WORK
3931 #ifdef JIT_CALLS_WORK
3932         /* Needs to be called here since register_jit_icall depends on it */
3933         mono_marshal_init ();
3934
3935         mono_arch_register_lowlevel_calls ();
3936
3937         register_icalls ();
3938
3939         mono_generic_sharing_init ();
3940 #endif
3941
3942 #ifdef MONO_ARCH_SIMD_INTRINSICS
3943         mono_simd_intrinsics_init ();
3944 #endif
3945
3946         mono_tasklets_init ();
3947
3948         register_trampolines (domain);
3949
3950         if (mono_compile_aot)
3951                 /*
3952                  * Avoid running managed code when AOT compiling, since the platform
3953                  * might only support aot-only execution.
3954                  */
3955                 mono_runtime_set_no_exec (TRUE);
3956
3957         mono_mem_account_register_counters ();
3958
3959 #define JIT_RUNTIME_WORKS
3960 #ifdef JIT_RUNTIME_WORKS
3961         mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
3962         mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
3963         mono_error_assert_ok (&error);
3964         mono_thread_attach (domain);
3965 #endif
3966
3967         if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
3968                 mono_runtime_setup_stat_profiler ();
3969
3970         mono_profiler_runtime_initialized ();
3971
3972         MONO_VES_INIT_END ();
3973
3974         return domain;
3975 }
3976
3977 static void
3978 register_icalls (void)
3979 {
3980         mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
3981                                 ves_icall_get_frame_info);
3982         mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",
3983                                 ves_icall_get_trace);
3984         mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
3985                                 mono_runtime_install_handlers);
3986         mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers",
3987                                 mono_runtime_cleanup_handlers);
3988
3989 #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID)
3990         mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
3991                                 mono_debugger_agent_unhandled_exception);
3992 #endif
3993
3994         /*
3995          * It's important that we pass `TRUE` as the last argument here, as
3996          * it causes the JIT to omit a wrapper for these icalls. If the JIT
3997          * *did* emit a wrapper, we'd be looking at infinite recursion since
3998          * the wrapper would call the icall which would call the wrapper and
3999          * so on.
4000          */
4001         register_icall (mono_profiler_method_enter, "mono_profiler_method_enter", "void ptr", TRUE);
4002         register_icall (mono_profiler_method_leave, "mono_profiler_method_leave", "void ptr", TRUE);
4003
4004         register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
4005         register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
4006         register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
4007         register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
4008         register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
4009         register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
4010
4011         register_icall (mono_llvm_throw_exception, "mono_llvm_throw_exception", "void object", TRUE);
4012         register_icall (mono_llvm_rethrow_exception, "mono_llvm_rethrow_exception", "void object", TRUE);
4013         register_icall (mono_llvm_resume_exception, "mono_llvm_resume_exception", "void", TRUE);
4014         register_icall (mono_llvm_match_exception, "mono_llvm_match_exception", "int ptr int int", TRUE);
4015         register_icall (mono_llvm_clear_exception, "mono_llvm_clear_exception", NULL, TRUE);
4016         register_icall (mono_llvm_load_exception, "mono_llvm_load_exception", "object", TRUE);
4017         register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", TRUE);
4018 #if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED)
4019         register_icall (mono_llvm_set_unhandled_exception_handler, "mono_llvm_set_unhandled_exception_handler", NULL, TRUE);
4020
4021         // FIXME: This is broken
4022         register_icall (mono_debug_personality, "mono_debug_personality", "int int int ptr ptr ptr", TRUE);
4023 #endif
4024
4025         register_dyn_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
4026         register_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
4027         register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
4028         register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
4029         register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
4030         register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
4031
4032 #if defined(__native_client__) || defined(__native_client_codegen__)
4033         register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE);
4034 #endif
4035
4036         if (mono_threads_is_coop_enabled ())
4037                 register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", FALSE);
4038
4039 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
4040         register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", FALSE);
4041         register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);
4042         register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, "mono_lldiv_un", FALSE);
4043         register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, "mono_llrem", FALSE);
4044         register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, "mono_llrem_un", FALSE);
4045 #endif
4046 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
4047         register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, "mono_llmult_ovf_un", FALSE);
4048         register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, "mono_llmult_ovf", FALSE);
4049 #endif
4050
4051 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
4052         register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, "mono_lshl", TRUE);
4053         register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, "mono_lshr", TRUE);
4054         register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, "mono_lshr_un", TRUE);
4055 #endif
4056
4057 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
4058         register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, "mono_idiv", FALSE);
4059         register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, "mono_idiv_un", FALSE);
4060         register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, "mono_irem", FALSE);
4061         register_opcode_emulation (OP_IREM_UN, "__emul_op_irem_un", "int32 int32 int32", mono_irem_un, "mono_irem_un", FALSE);
4062 #endif
4063
4064 #ifdef MONO_ARCH_EMULATE_MUL_DIV
4065         register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, "mono_imul", TRUE);
4066 #endif
4067
4068 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
4069         register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, "mono_imul_ovf", FALSE);
4070         register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, "mono_imul_ovf_un", FALSE);
4071 #endif
4072
4073 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
4074         register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
4075 #endif
4076
4077         register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
4078         register_opcode_emulation (OP_RCONV_TO_U8, "__emul_rconv_to_u8", "ulong float", mono_rconv_u8, "mono_rconv_u8", FALSE);
4079         register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
4080         register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
4081         register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
4082         register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
4083         register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
4084
4085
4086 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
4087         register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
4088         register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
4089 #endif
4090
4091 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
4092         register_opcode_emulation (OP_ICONV_TO_R_UN, "__emul_iconv_to_r_un", "double int32", mono_conv_to_r8_un, "mono_conv_to_r8_un", FALSE);
4093 #endif
4094 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
4095         register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, "mono_lconv_to_r8", FALSE);
4096 #endif
4097 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
4098         register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, "mono_lconv_to_r4", FALSE);
4099 #endif
4100 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
4101         register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, "mono_lconv_to_r8_un", FALSE);
4102 #endif
4103 #ifdef MONO_ARCH_EMULATE_FREM
4104 #if !defined(__native_client__)
4105         register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
4106         register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
4107 #else
4108         register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
4109 #endif
4110 #endif
4111
4112 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
4113         if (mono_arch_is_soft_float ()) {
4114                 register_opcode_emulation (OP_FSUB, "__emul_fsub", "double double double", mono_fsub, "mono_fsub", FALSE);
4115                 register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, "mono_fadd", FALSE);
4116                 register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, "mono_fmul", FALSE);
4117                 register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, "mono_fneg", FALSE);
4118                 register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, "mono_conv_to_r8", FALSE);
4119                 register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, "mono_conv_to_r4", FALSE);
4120                 register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, "mono_fconv_r4", FALSE);
4121                 register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, "mono_fconv_i1", FALSE);
4122                 register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, "mono_fconv_i2", FALSE);
4123                 register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4124                 register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, "mono_fconv_u1", FALSE);
4125                 register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, "mono_fconv_u2", FALSE);
4126
4127 #if SIZEOF_VOID_P == 4
4128                 register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4129 #endif
4130
4131                 register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, "mono_fcmp_eq", FALSE);
4132                 register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, "mono_fcmp_lt", FALSE);
4133                 register_opcode_emulation (OP_FBGT, "__emul_fcmp_gt", "uint32 double double", mono_fcmp_gt, "mono_fcmp_gt", FALSE);
4134                 register_opcode_emulation (OP_FBLE, "__emul_fcmp_le", "uint32 double double", mono_fcmp_le, "mono_fcmp_le", FALSE);
4135                 register_opcode_emulation (OP_FBGE, "__emul_fcmp_ge", "uint32 double double", mono_fcmp_ge, "mono_fcmp_ge", FALSE);
4136                 register_opcode_emulation (OP_FBNE_UN, "__emul_fcmp_ne_un", "uint32 double double", mono_fcmp_ne_un, "mono_fcmp_ne_un", FALSE);
4137                 register_opcode_emulation (OP_FBLT_UN, "__emul_fcmp_lt_un", "uint32 double double", mono_fcmp_lt_un, "mono_fcmp_lt_un", FALSE);
4138                 register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, "mono_fcmp_gt_un", FALSE);
4139                 register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, "mono_fcmp_le_un", FALSE);
4140                 register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, "mono_fcmp_ge_un", FALSE);
4141
4142                 register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, "mono_fceq", FALSE);
4143                 register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, "mono_fcgt", FALSE);
4144                 register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, "mono_fcgt_un", FALSE);
4145                 register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, "mono_fclt", FALSE);
4146                 register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, "mono_fclt_un", FALSE);
4147
4148                 register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
4149                 register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
4150                 register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
4151                 register_icall (mono_isfinite, "mono_isfinite", "uint32 double", FALSE);
4152         }
4153 #endif
4154         register_icall (mono_ckfinite, "mono_ckfinite", "double double", FALSE);
4155
4156 #ifdef COMPRESSED_INTERFACE_BITMAP
4157         register_icall (mono_class_interface_match, "mono_class_interface_match", "uint32 ptr int32", TRUE);
4158 #endif
4159
4160 #if SIZEOF_REGISTER == 4
4161         register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
4162 #else
4163         register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
4164 #endif
4165
4166         /* other jit icalls */
4167         register_icall (ves_icall_mono_delegate_ctor, "ves_icall_mono_delegate_ctor", "void object object ptr", FALSE);
4168         register_icall (mono_class_static_field_address , "mono_class_static_field_address",
4169                                  "ptr ptr ptr", FALSE);
4170         register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
4171         register_icall (mono_ldtoken_wrapper_generic_shared, "mono_ldtoken_wrapper_generic_shared",
4172                 "ptr ptr ptr ptr", FALSE);
4173         register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
4174         register_icall (ves_icall_mono_ldstr, "ves_icall_mono_ldstr", "object ptr ptr int32", FALSE);
4175         register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
4176         register_icall (ves_icall_object_new, "ves_icall_object_new", "object ptr ptr", FALSE);
4177         register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
4178         register_icall (ves_icall_array_new, "ves_icall_array_new", "object ptr ptr int32", FALSE);
4179         register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE);
4180         register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
4181         register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
4182         register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
4183         register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);
4184         register_icall (mono_helper_compile_generic_method, "mono_helper_compile_generic_method", "ptr object ptr ptr", FALSE);
4185         register_icall (mono_helper_ldstr, "mono_helper_ldstr", "object ptr int", FALSE);
4186         register_icall (mono_helper_ldstr_mscorlib, "mono_helper_ldstr_mscorlib", "object int", FALSE);
4187         register_icall (mono_helper_newobj_mscorlib, "mono_helper_newobj_mscorlib", "object int", FALSE);
4188         register_icall (mono_value_copy, "mono_value_copy", "void ptr ptr ptr", FALSE);
4189         register_icall (mono_object_castclass_unbox, "mono_object_castclass_unbox", "object object ptr", FALSE);
4190         register_icall (mono_break, "mono_break", NULL, TRUE);
4191         register_icall (mono_create_corlib_exception_0, "mono_create_corlib_exception_0", "object int", TRUE);
4192         register_icall (mono_create_corlib_exception_1, "mono_create_corlib_exception_1", "object int object", TRUE);
4193         register_icall (mono_create_corlib_exception_2, "mono_create_corlib_exception_2", "object int object object", TRUE);
4194         register_icall (mono_array_new_1, "mono_array_new_1", "object ptr int", FALSE);
4195         register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE);
4196         register_icall (mono_array_new_3, "mono_array_new_3", "object ptr int int int", FALSE);
4197         register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
4198         register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
4199         register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
4200         register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
4201         register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
4202
4203         register_icall (mono_gc_wbarrier_value_copy_bitmap, "mono_gc_wbarrier_value_copy_bitmap", "void ptr ptr int int", FALSE);
4204
4205         register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
4206         register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
4207         register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE);
4208         register_icall (mono_fill_class_rgctx, "mono_fill_class_rgctx", "ptr ptr int", FALSE);
4209         register_icall (mono_fill_method_rgctx, "mono_fill_method_rgctx", "ptr ptr int", FALSE);
4210
4211         register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
4212
4213         register_icall (mono_aot_init_llvm_method, "mono_aot_init_llvm_method", "void ptr int", TRUE);
4214         register_icall (mono_aot_init_gshared_method_this, "mono_aot_init_gshared_method_this", "void ptr int object", TRUE);
4215         register_icall (mono_aot_init_gshared_method_mrgctx, "mono_aot_init_gshared_method_mrgctx", "void ptr int ptr", TRUE);
4216         register_icall (mono_aot_init_gshared_method_vtable, "mono_aot_init_gshared_method_vtable", "void ptr int ptr", TRUE);
4217
4218         register_icall_no_wrapper (mono_resolve_iface_call_gsharedvt, "mono_resolve_iface_call_gsharedvt", "ptr object int ptr ptr");
4219         register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
4220         register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
4221         register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
4222         /* This needs a wrapper so it can have a preserveall cconv */
4223         register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
4224         register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object", TRUE);
4225         register_icall (mono_llvmonly_init_delegate_virtual, "mono_llvmonly_init_delegate_virtual", "void object object ptr", TRUE);
4226         register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
4227         register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
4228         register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE);
4229         register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void");
4230
4231         register_icall_with_wrapper (mono_monitor_enter_internal, "mono_monitor_enter_internal", "void obj");
4232         register_icall_with_wrapper (mono_monitor_enter_v4_internal, "mono_monitor_enter_v4_internal", "void obj ptr");
4233         register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj");
4234         register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr");
4235
4236 #ifdef TARGET_IOS
4237         register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
4238 #endif
4239         /* Register tls icalls */
4240         register_icall_no_wrapper (mono_tls_get_thread, "mono_tls_get_thread", "ptr");
4241         register_icall_no_wrapper (mono_tls_get_jit_tls, "mono_tls_get_jit_tls", "ptr");
4242         register_icall_no_wrapper (mono_tls_get_domain, "mono_tls_get_domain", "ptr");  
4243         register_icall_no_wrapper (mono_tls_get_sgen_thread_info, "mono_tls_get_sgen_thread_info", "ptr");
4244         register_icall_no_wrapper (mono_tls_get_lmf_addr, "mono_tls_get_lmf_addr", "ptr");
4245         register_icall_no_wrapper (mono_tls_set_thread, "mono_tls_set_thread", "void ptr");
4246         register_icall_no_wrapper (mono_tls_set_jit_tls, "mono_tls_set_jit_tls", "void ptr");
4247         register_icall_no_wrapper (mono_tls_set_domain, "mono_tls_set_domain", "void ptr");
4248         register_icall_no_wrapper (mono_tls_set_sgen_thread_info, "mono_tls_set_sgen_thread_info", "void ptr");
4249         register_icall_no_wrapper (mono_tls_set_lmf_addr, "mono_tls_set_lmf_addr", "void ptr");
4250 }
4251
4252 MonoJitStats mono_jit_stats = {0};
4253
4254 static void
4255 print_jit_stats (void)
4256 {
4257         if (mono_jit_stats.enabled) {
4258                 g_print ("Mono Jit statistics\n");
4259                 g_print ("Max code size ratio:    %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
4260                                  mono_jit_stats.max_ratio_method);
4261                 g_print ("Biggest method:         %ld (%s)\n", mono_jit_stats.biggest_method_size,
4262                                  mono_jit_stats.biggest_method);
4263
4264                 g_print ("Delegates created:      %ld\n", mono_stats.delegate_creations);
4265                 g_print ("Initialized classes:    %ld\n", mono_stats.initialized_class_count);
4266                 g_print ("Used classes:           %ld\n", mono_stats.used_class_count);
4267                 g_print ("Generic vtables:        %ld\n", mono_stats.generic_vtable_count);
4268                 g_print ("Methods:                %ld\n", mono_stats.method_count);
4269                 g_print ("Static data size:       %ld\n", mono_stats.class_static_data_size);
4270                 g_print ("VTable data size:       %ld\n", mono_stats.class_vtable_size);
4271                 g_print ("Mscorlib mempool size:  %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool));
4272
4273                 g_print ("\nInitialized classes:    %ld\n", mono_stats.generic_class_count);
4274                 g_print ("Inflated types:         %ld\n", mono_stats.inflated_type_count);
4275                 g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
4276
4277                 g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
4278                 g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods);
4279                 g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
4280                 g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods);
4281
4282                 g_print ("IMT tables size:        %ld\n", mono_stats.imt_tables_size);
4283                 g_print ("IMT number of tables:   %ld\n", mono_stats.imt_number_of_tables);
4284                 g_print ("IMT number of methods:  %ld\n", mono_stats.imt_number_of_methods);
4285                 g_print ("IMT used slots:         %ld\n", mono_stats.imt_used_slots);
4286                 g_print ("IMT colliding slots:    %ld\n", mono_stats.imt_slots_with_collisions);
4287                 g_print ("IMT max collisions:     %ld\n", mono_stats.imt_max_collisions_in_slot);
4288                 g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
4289                 g_print ("IMT trampolines size:   %ld\n", mono_stats.imt_trampolines_size);
4290
4291                 g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
4292                 g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
4293                 g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
4294
4295                 g_free (mono_jit_stats.max_ratio_method);
4296                 mono_jit_stats.max_ratio_method = NULL;
4297                 g_free (mono_jit_stats.biggest_method);
4298                 mono_jit_stats.biggest_method = NULL;
4299         }
4300 }
4301
4302 void
4303 mini_cleanup (MonoDomain *domain)
4304 {
4305         if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
4306                 mono_runtime_shutdown_stat_profiler ();
4307
4308 #ifndef DISABLE_COM
4309         cominterop_release_all_rcws ();
4310 #endif
4311
4312 #ifndef MONO_CROSS_COMPILE
4313         /*
4314          * mono_domain_finalize () needs to be called early since it needs the
4315          * execution engine still fully working (it may invoke managed finalizers).
4316          */
4317         mono_domain_finalize (domain, 2000);
4318 #endif
4319
4320         /* This accesses metadata so needs to be called before runtime shutdown */
4321         print_jit_stats ();
4322
4323 #ifndef MONO_CROSS_COMPILE
4324         mono_runtime_cleanup (domain);
4325 #endif
4326
4327         mono_threadpool_cleanup ();
4328
4329         mono_profiler_shutdown ();
4330
4331         free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
4332
4333         mono_icall_cleanup ();
4334
4335         mono_runtime_cleanup_handlers ();
4336
4337 #ifndef MONO_CROSS_COMPILE
4338         mono_domain_free (domain, TRUE);
4339 #endif
4340
4341 #ifdef ENABLE_LLVM
4342         if (mono_use_llvm)
4343                 mono_llvm_cleanup ();
4344 #endif
4345
4346         mono_aot_cleanup ();
4347
4348         mono_trampolines_cleanup ();
4349
4350         mono_unwind_cleanup ();
4351
4352         mono_code_manager_destroy (global_codeman);
4353         g_free (vtable_trampolines);
4354
4355         mini_jit_cleanup ();
4356
4357         mono_tramp_info_cleanup ();
4358
4359         mono_arch_cleanup ();
4360
4361         mono_generic_sharing_cleanup ();
4362
4363         mono_cleanup ();
4364
4365         mono_trace_cleanup ();
4366
4367         mono_counters_dump (MONO_COUNTER_SECTION_MASK | MONO_COUNTER_MONOTONIC, stdout);
4368
4369         if (mono_inject_async_exc_method)
4370                 mono_method_desc_free (mono_inject_async_exc_method);
4371
4372         mono_tls_free_keys ();
4373
4374         mono_os_mutex_destroy (&jit_mutex);
4375
4376         mono_code_manager_cleanup ();
4377
4378 #ifndef HOST_WIN32
4379         mono_w32handle_cleanup ();
4380 #endif
4381 }
4382
4383 void
4384 mono_set_defaults (int verbose_level, guint32 opts)
4385 {
4386         mini_verbose = verbose_level;
4387         mono_set_optimizations (opts);
4388 }
4389
4390 void
4391 mono_disable_optimizations (guint32 opts)
4392 {
4393         default_opt &= ~opts;
4394 }
4395
4396 void
4397 mono_set_optimizations (guint32 opts)
4398 {
4399         default_opt = opts;
4400         default_opt_set = TRUE;
4401 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
4402         mono_set_generic_sharing_vt_supported (mono_aot_only || ((default_opt & MONO_OPT_GSHAREDVT) != 0));
4403 #else
4404         if (mono_llvm_only)
4405                 mono_set_generic_sharing_vt_supported (TRUE);
4406 #endif
4407 }
4408
4409 void
4410 mono_set_verbose_level (guint32 level)
4411 {
4412         mini_verbose = level;
4413 }
4414
4415 /**
4416  * mono_get_runtime_build_info:
4417  * The returned string is owned by the caller. The returned string
4418  * format is <code>VERSION (FULL_VERSION BUILD_DATE)</code> and build date is optional.
4419  * \returns the runtime version + build date in string format.
4420  */
4421 char*
4422 mono_get_runtime_build_info (void)
4423 {
4424         if (mono_build_date)
4425                 return g_strdup_printf ("%s (%s %s)", VERSION, FULL_VERSION, mono_build_date);
4426         else
4427                 return g_strdup_printf ("%s (%s)", VERSION, FULL_VERSION);
4428 }
4429
4430 static void
4431 mono_precompile_assembly (MonoAssembly *ass, void *user_data)
4432 {
4433         GHashTable *assemblies = (GHashTable*)user_data;
4434         MonoImage *image = mono_assembly_get_image (ass);
4435         MonoMethod *method, *invoke;
4436         int i, count = 0;
4437
4438         if (g_hash_table_lookup (assemblies, ass))
4439                 return;
4440
4441         g_hash_table_insert (assemblies, ass, ass);
4442
4443         if (mini_verbose > 0)
4444                 printf ("PRECOMPILE: %s.\n", mono_image_get_filename (image));
4445
4446         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
4447                 MonoError error;
4448
4449                 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
4450                 if (!method) {
4451                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
4452                         continue;
4453                 }
4454                 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
4455                         continue;
4456                 if (method->is_generic || mono_class_is_gtd (method->klass))
4457                         continue;
4458
4459                 count++;
4460                 if (mini_verbose > 1) {
4461                         char * desc = mono_method_full_name (method, TRUE);
4462                         g_print ("Compiling %d %s\n", count, desc);
4463                         g_free (desc);
4464                 }
4465                 mono_compile_method_checked (method, &error);
4466                 if (!is_ok (&error)) {
4467                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
4468                         continue;
4469                 }
4470                 if (strcmp (method->name, "Finalize") == 0) {
4471                         invoke = mono_marshal_get_runtime_invoke (method, FALSE);
4472                         mono_compile_method_checked (invoke, &error);
4473                         mono_error_assert_ok (&error);
4474                 }
4475 #ifndef DISABLE_REMOTING
4476                 if (mono_class_is_marshalbyref (method->klass) && mono_method_signature (method)->hasthis) {
4477                         invoke = mono_marshal_get_remoting_invoke_with_check (method);
4478                         mono_compile_method_checked (invoke, &error);
4479                         mono_error_assert_ok (&error);
4480                 }
4481 #endif
4482         }
4483
4484         /* Load and precompile referenced assemblies as well */
4485         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_ASSEMBLYREF); ++i) {
4486                 mono_assembly_load_reference (image, i);
4487                 if (image->references [i])
4488                         mono_precompile_assembly (image->references [i], assemblies);
4489         }
4490 }
4491
4492 void mono_precompile_assemblies ()
4493 {
4494         GHashTable *assemblies = g_hash_table_new (NULL, NULL);
4495
4496         mono_assembly_foreach ((GFunc)mono_precompile_assembly, assemblies);
4497
4498         g_hash_table_destroy (assemblies);
4499 }
4500
4501 /*
4502  * Used by LLVM.
4503  * Have to export this for AOT.
4504  */
4505 void
4506 mono_personality (void)
4507 {
4508         /* Not used */
4509         g_assert_not_reached ();
4510 }
4511
4512 // Custom handlers currently only implemented by Windows.
4513 #ifndef HOST_WIN32
4514 gboolean
4515 mono_runtime_install_custom_handlers (const char *handlers)
4516 {
4517         return FALSE;
4518 }
4519
4520 void
4521 mono_runtime_install_custom_handlers_usage (void)
4522 {
4523         fprintf (stdout,
4524                  "Custom Handlers:\n"
4525                  "   --handlers=HANDLERS            Enable handler support, HANDLERS is a comma\n"
4526                  "                                  separated list of available handlers to install.\n"
4527                  "\n"
4528                  "No handlers supported on current platform.\n");
4529 }
4530 #endif /* HOST_WIN32 */