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