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