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