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