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