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