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