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