[runtime] Remove all NACL support. It was unmaintained for a long time. (#4955)
[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 #if ENABLE_JIT_MAP
1741 static FILE* perf_map_file;
1742
1743 void
1744 mono_enable_jit_map (void)
1745 {
1746         if (!perf_map_file) {
1747                 char name [64];
1748                 g_snprintf (name, sizeof (name), "/tmp/perf-%d.map", getpid ());
1749                 unlink (name);
1750                 perf_map_file = fopen (name, "w");
1751         }
1752 }
1753
1754 void
1755 mono_emit_jit_tramp (void *start, int size, const char *desc)
1756 {
1757         if (perf_map_file)
1758                 fprintf (perf_map_file, "%llx %x %s\n", (long long unsigned int)(gsize)start, size, desc);
1759 }
1760
1761 void
1762 mono_emit_jit_map (MonoJitInfo *jinfo)
1763 {
1764         if (perf_map_file) {
1765                 char *name = mono_method_full_name (jinfo_get_method (jinfo), TRUE);
1766                 mono_emit_jit_tramp (jinfo->code_start, jinfo->code_size, name);
1767                 g_free (name);
1768         }
1769 }
1770
1771 gboolean
1772 mono_jit_map_is_enabled (void)
1773 {
1774         return perf_map_file != NULL;
1775 }
1776
1777 #endif
1778
1779 static void
1780 no_gsharedvt_in_wrapper (void)
1781 {
1782         g_assert_not_reached ();
1783 }
1784
1785 /*
1786 Overall algorithm:
1787
1788 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.
1789         If the current thread is already JITing another method, don't wait as it might cause a deadlock.
1790         Dependency management in this case is too complex to justify implementing it.
1791
1792 If there are no outstanding requests, the current thread is doing nothing and there are already mono_cpu_count threads JITing, go to sleep.
1793
1794 TODO:
1795         Get rid of cctor invocations from within the JIT, it increases JIT duration and complicates things A LOT.
1796         Can we get rid of ref_count and use `done && threads_waiting == 0` as the equivalent of `ref_count == 0`?
1797         Reduce amount of dynamically allocated - possible once the JIT is no longer reentrant
1798         Maybe pool JitCompilationEntry, specially those with an inited cond var;
1799 */
1800 typedef struct {
1801         MonoMethod *method;
1802         MonoDomain *domain;
1803         int compilation_count; /* Number of threads compiling this method - This happens due to the JIT being reentrant */
1804         int ref_count; /* Number of threads using this JitCompilationEntry, roughtly 1 + threads_waiting */
1805         int threads_waiting; /* Number of threads waiting on this job */
1806         gboolean has_cond; /* True if @cond was initialized */
1807         gboolean done; /* True if the method finished JIT'ing */
1808         MonoCoopCond cond; /* Cond sleeping threads wait one */
1809 } JitCompilationEntry;
1810
1811 typedef struct {
1812         GPtrArray *in_flight_methods; //JitCompilationEntry*
1813         MonoCoopMutex lock;
1814 } JitCompilationData;
1815
1816 static JitCompilationData compilation_data;
1817 static int jit_methods_waited, jit_methods_multiple, jit_methods_overload, jit_spurious_wakeups;
1818
1819 static void
1820 mini_jit_init_job_control (void)
1821 {
1822         mono_coop_mutex_init (&compilation_data.lock);
1823         compilation_data.in_flight_methods = g_ptr_array_new ();
1824 }
1825
1826 static void
1827 lock_compilation_data (void)
1828 {
1829         mono_coop_mutex_lock (&compilation_data.lock);
1830 }
1831
1832 static void
1833 unlock_compilation_data (void)
1834 {
1835         mono_coop_mutex_unlock (&compilation_data.lock);
1836 }
1837
1838 static JitCompilationEntry*
1839 find_method (MonoMethod *method, MonoDomain *domain)
1840 {
1841         int i;
1842         for (i = 0; i < compilation_data.in_flight_methods->len; ++i){
1843                 JitCompilationEntry *e = compilation_data.in_flight_methods->pdata [i];
1844                 if (e->method == method && e->domain == domain)
1845                         return e;
1846         }
1847
1848         return NULL;
1849 }
1850
1851 static void
1852 add_current_thread (MonoJitTlsData *jit_tls)
1853 {
1854         ++jit_tls->active_jit_methods;
1855 }
1856
1857 static void
1858 unref_jit_entry (JitCompilationEntry *entry)
1859 {
1860         --entry->ref_count;
1861         if (entry->ref_count)
1862                 return;
1863         if (entry->has_cond)
1864                 mono_coop_cond_destroy (&entry->cond);
1865         g_free (entry);
1866 }
1867
1868 /*
1869  * Returns true if this method waited successfully for another thread to JIT it
1870  */
1871 static gboolean
1872 wait_or_register_method_to_compile (MonoMethod *method, MonoDomain *domain)
1873 {
1874         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1875         JitCompilationEntry *entry;
1876
1877         static gboolean inited;
1878         if (!inited) {
1879                 mono_counters_register ("JIT compile waited others", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_waited);
1880                 mono_counters_register ("JIT compile 1+ jobs", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_multiple);
1881                 mono_counters_register ("JIT compile overload wait", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_methods_overload);
1882                 mono_counters_register ("JIT compile spurious wakeups", MONO_COUNTER_INT|MONO_COUNTER_JIT, &jit_spurious_wakeups);
1883                 inited = TRUE;
1884         }
1885
1886         lock_compilation_data ();
1887
1888         if (!(entry = find_method (method, domain))) {
1889                 entry = g_new0 (JitCompilationEntry, 1);
1890                 entry->method = method;
1891                 entry->domain = domain;
1892                 entry->compilation_count = entry->ref_count = 1;
1893                 g_ptr_array_add (compilation_data.in_flight_methods, entry);
1894                 g_assert (find_method (method, domain) == entry);
1895                 add_current_thread (jit_tls);
1896
1897                 unlock_compilation_data ();
1898                 return FALSE;
1899         } else if (jit_tls->active_jit_methods > 0) {
1900                 //We can't suspend the current thread if it's already JITing a method.
1901                 //Dependency management is too compilated and we want to get rid of this anyways.
1902                 ++entry->compilation_count;
1903                 ++jit_methods_multiple;
1904                 ++jit_tls->active_jit_methods;
1905
1906                 unlock_compilation_data ();
1907                 return FALSE;
1908         } else {
1909                 ++jit_methods_waited;
1910                 ++entry->ref_count;
1911
1912                 if (!entry->has_cond) {
1913                         mono_coop_cond_init (&entry->cond);
1914                         entry->has_cond = TRUE;
1915                 }
1916
1917                 while (TRUE) {
1918                         ++entry->threads_waiting;
1919
1920                         g_assert (entry->has_cond);
1921                         mono_coop_cond_wait (&entry->cond, &compilation_data.lock);
1922                         --entry->threads_waiting;
1923
1924                         if (entry->done) {
1925                                 unref_jit_entry (entry);
1926                                 unlock_compilation_data ();
1927                                 return TRUE;
1928                         } else {
1929                                 ++jit_spurious_wakeups;
1930                         }
1931                 }
1932         }
1933 }
1934
1935 static void
1936 unregister_method_for_compile (MonoMethod *method, MonoDomain *target_domain)
1937 {
1938         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
1939
1940         lock_compilation_data ();
1941
1942         g_assert (jit_tls->active_jit_methods > 0);
1943         --jit_tls->active_jit_methods;
1944
1945         JitCompilationEntry *entry = find_method (method, target_domain);
1946         g_assert (entry); // It would be weird to fail
1947         entry->done = TRUE;
1948
1949         if (entry->threads_waiting) {
1950                 g_assert (entry->has_cond);
1951                 mono_coop_cond_broadcast (&entry->cond);
1952         }
1953
1954         if (--entry->compilation_count == 0) {
1955                 g_ptr_array_remove (compilation_data.in_flight_methods, entry);
1956                 unref_jit_entry (entry);
1957         }
1958
1959         unlock_compilation_data ();
1960 }
1961
1962
1963 static gpointer
1964 mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_only, MonoError *error)
1965 {
1966         MonoDomain *target_domain, *domain = mono_domain_get ();
1967         MonoJitInfo *info;
1968         gpointer code = NULL, p;
1969         MonoJitInfo *ji;
1970         MonoJitICallInfo *callinfo = NULL;
1971         WrapperInfo *winfo = NULL;
1972
1973         error_init (error);
1974
1975 #ifdef ENABLE_INTERPRETER
1976         if (mono_use_interpreter && !jit_only) {
1977                 code = mono_interp_create_method_pointer (method, error);
1978                 if (code)
1979                         return code;
1980         }
1981 #endif
1982
1983         if (mono_llvm_only)
1984                 /* Should be handled by the caller */
1985                 g_assert (!(method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED));
1986
1987         /*
1988          * ICALL wrappers are handled specially, since there is only one copy of them
1989          * shared by all appdomains.
1990          */
1991         if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
1992                 winfo = mono_marshal_get_wrapper_info (method);
1993         if (winfo && winfo->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER) {
1994                 callinfo = mono_find_jit_icall_by_addr (winfo->d.icall.func);
1995                 g_assert (callinfo);
1996
1997                 /* Must be domain neutral since there is only one copy */
1998                 opt |= MONO_OPT_SHARED;
1999         } else {
2000                 /* MONO_OPT_SHARED is no longer supported, we only use it for icall wrappers */
2001                 opt &= ~MONO_OPT_SHARED;
2002         }
2003
2004         if (opt & MONO_OPT_SHARED)
2005                 target_domain = mono_get_root_domain ();
2006         else
2007                 target_domain = domain;
2008
2009         if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2010                 WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2011
2012                 g_assert (info);
2013                 if (info->subtype == WRAPPER_SUBTYPE_SYNCHRONIZED_INNER) {
2014                         MonoGenericContext *ctx = NULL;
2015                         if (method->is_inflated)
2016                                 ctx = mono_method_get_context (method);
2017                         method = info->d.synchronized_inner.method;
2018                         if (ctx) {
2019                                 method = mono_class_inflate_generic_method_checked (method, ctx, error);
2020                                 g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */
2021                         }
2022                 }
2023         }
2024
2025 lookup_start:
2026         info = lookup_method (target_domain, method);
2027         if (info) {
2028                 /* We can't use a domain specific method in another domain */
2029                 if (! ((domain != target_domain) && !info->domain_neutral)) {
2030                         MonoVTable *vtable;
2031
2032                         mono_jit_stats.methods_lookups++;
2033                         vtable = mono_class_vtable_full (domain, method->klass, error);
2034                         if (!is_ok (error))
2035                                 return NULL;
2036                         g_assert (vtable);
2037                         if (!mono_runtime_class_init_full (vtable, error))
2038                                 return NULL;
2039                         return mono_create_ftnptr (target_domain, info->code_start);
2040                 }
2041         }
2042
2043 #ifdef MONO_USE_AOT_COMPILER
2044         if (opt & MONO_OPT_AOT) {
2045                 MonoDomain *domain = mono_domain_get ();
2046
2047                 mono_class_init (method->klass);
2048
2049                 if ((code = mono_aot_get_method_checked (domain, method, error))) {
2050                         MonoVTable *vtable;
2051
2052                         if (mono_runtime_is_critical_method (method) || mono_gc_is_critical_method (method)) {
2053                                 /*
2054                                  * The suspend code needs to be able to lookup these methods by ip in async context,
2055                                  * so preload their jit info.
2056                                  */
2057                                 MonoJitInfo *ji = mono_jit_info_table_find (domain, code);
2058                                 g_assert (ji);
2059                         }
2060
2061                         /*
2062                          * In llvm-only mode, method might be a shared method, so we can't initialize its class.
2063                          * This is not a problem, since it will be initialized when the method is first
2064                          * called by init_method ().
2065                          */
2066                         if (!mono_llvm_only) {
2067                                 vtable = mono_class_vtable (domain, method->klass);
2068                                 g_assert (vtable);
2069                                 if (!mono_runtime_class_init_full (vtable, error))
2070                                         return NULL;
2071                         }
2072                 }
2073                 if (!is_ok (error))
2074                         return NULL;
2075         }
2076 #endif
2077
2078         if (!code && mono_llvm_only) {
2079                 if (method->wrapper_type == MONO_WRAPPER_UNKNOWN) {
2080                         WrapperInfo *info = mono_marshal_get_wrapper_info (method);
2081
2082                         if (info->subtype == WRAPPER_SUBTYPE_GSHAREDVT_IN_SIG) {
2083                                 /*
2084                                  * These wrappers are only created for signatures which are in the program, but
2085                                  * sometimes we load methods too eagerly and have to create them even if they
2086                                  * will never be called.
2087                                  */
2088                                 return no_gsharedvt_in_wrapper;
2089                         }
2090                 }
2091         }
2092
2093         if (!code) {
2094                 if (wait_or_register_method_to_compile (method, target_domain))
2095                         goto lookup_start;
2096                 code = mono_jit_compile_method_inner (method, target_domain, opt, error);
2097                 unregister_method_for_compile (method, target_domain);
2098         }
2099         if (!mono_error_ok (error))
2100                 return NULL;
2101
2102         if (!code && mono_llvm_only) {
2103                 printf ("AOT method not found in llvmonly mode: %s\n", mono_method_full_name (method, 1));
2104                 g_assert_not_reached ();
2105         }
2106
2107         if (!code)
2108                 return NULL;
2109
2110         if (method->wrapper_type == MONO_WRAPPER_WRITE_BARRIER || method->wrapper_type == MONO_WRAPPER_ALLOC) {
2111                 MonoDomain *d;
2112
2113                 /*
2114                  * SGEN requires the JIT info for these methods to be registered, see is_ip_in_managed_allocator ().
2115                  */
2116                 ji = mini_jit_info_table_find (mono_domain_get (), (char *)code, &d);
2117                 g_assert (ji);
2118         }
2119
2120         p = mono_create_ftnptr (target_domain, code);
2121
2122         if (callinfo) {
2123                 /*mono_register_jit_icall_wrapper takes the loader lock, so we take it on the outside. */
2124                 mono_loader_lock ();
2125                 mono_jit_lock ();
2126                 if (!callinfo->wrapper) {
2127                         callinfo->wrapper = p;
2128                         mono_register_jit_icall_wrapper (callinfo, p);
2129                 }
2130                 mono_jit_unlock ();
2131                 mono_loader_unlock ();
2132         }
2133
2134         return p;
2135 }
2136
2137 gpointer
2138 mono_jit_compile_method (MonoMethod *method, MonoError *error)
2139 {
2140         gpointer code;
2141
2142         code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), FALSE, error);
2143         return code;
2144 }
2145
2146 /*
2147  * mono_jit_compile_method_jit_only:
2148  *
2149  *   Compile METHOD using the JIT/AOT, even in interpreted mode.
2150  */
2151 gpointer
2152 mono_jit_compile_method_jit_only (MonoMethod *method, MonoError *error)
2153 {
2154         gpointer code;
2155
2156         code = mono_jit_compile_method_with_opt (method, mono_get_optimizations_for_method (method, default_opt), TRUE, error);
2157         return code;
2158 }
2159
2160 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2161 static void
2162 invalidated_delegate_trampoline (char *desc)
2163 {
2164         g_error ("Unmanaged code called delegate of type %s which was already garbage collected.\n"
2165                  "See http://www.mono-project.com/Diagnostic:Delegate for an explanation and ways to fix this.",
2166                  desc);
2167 }
2168 #endif
2169
2170 /*
2171  * mono_jit_free_method:
2172  *
2173  *  Free all memory allocated by the JIT for METHOD.
2174  */
2175 static void
2176 mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
2177 {
2178         MonoJitDynamicMethodInfo *ji;
2179         gboolean destroy = TRUE;
2180         GHashTableIter iter;
2181         MonoJumpList *jlist;
2182
2183         g_assert (method->dynamic);
2184
2185         mono_domain_lock (domain);
2186         ji = mono_dynamic_code_hash_lookup (domain, method);
2187         mono_domain_unlock (domain);
2188
2189         if (!ji)
2190                 return;
2191
2192         mono_debug_remove_method (method, domain);
2193         mono_lldb_remove_method (domain, method, ji);
2194
2195         mono_domain_lock (domain);
2196         g_hash_table_remove (domain_jit_info (domain)->dynamic_code_hash, method);
2197         mono_domain_jit_code_hash_lock (domain);
2198         mono_internal_hash_table_remove (&domain->jit_code_hash, method);
2199         mono_domain_jit_code_hash_unlock (domain);
2200         g_hash_table_remove (domain_jit_info (domain)->jump_trampoline_hash, method);
2201
2202         /* requires the domain lock - took above */
2203         mono_conc_hashtable_remove (domain_jit_info (domain)->runtime_invoke_hash, method);
2204
2205         /* Remove jump targets in this method */
2206         g_hash_table_iter_init (&iter, domain_jit_info (domain)->jump_target_hash);
2207         while (g_hash_table_iter_next (&iter, NULL, (void**)&jlist)) {
2208                 GSList *tmp, *remove;
2209
2210                 remove = NULL;
2211                 for (tmp = jlist->list; tmp; tmp = tmp->next) {
2212                         guint8 *ip = (guint8 *)tmp->data;
2213
2214                         if (ip >= (guint8*)ji->ji->code_start && ip < (guint8*)ji->ji->code_start + ji->ji->code_size)
2215                                 remove = g_slist_prepend (remove, tmp);
2216                 }
2217                 for (tmp = remove; tmp; tmp = tmp->next) {
2218                         jlist->list = g_slist_delete_link ((GSList *)jlist->list, (GSList *)tmp->data);
2219                 }
2220                 g_slist_free (remove);
2221         }
2222         mono_domain_unlock (domain);
2223
2224 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
2225         if (debug_options.keep_delegates && method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) {
2226                 /*
2227                  * Instead of freeing the code, change it to call an error routine
2228                  * so people can fix their code.
2229                  */
2230                 char *type = mono_type_full_name (&method->klass->byval_arg);
2231                 char *type_and_method = g_strdup_printf ("%s.%s", type, method->name);
2232
2233                 g_free (type);
2234                 mono_arch_invalidate_method (ji->ji, invalidated_delegate_trampoline, type_and_method);
2235                 destroy = FALSE;
2236         }
2237 #endif
2238
2239         /*
2240          * This needs to be done before freeing code_mp, since the code address is the
2241          * key in the table, so if we free the code_mp first, another thread can grab the
2242          * same code address and replace our entry in the table.
2243          */
2244         mono_jit_info_table_remove (domain, ji->ji);
2245
2246         if (destroy)
2247                 mono_code_manager_destroy (ji->code_mp);
2248         g_free (ji);
2249 }
2250
2251 gpointer
2252 mono_jit_find_compiled_method_with_jit_info (MonoDomain *domain, MonoMethod *method, MonoJitInfo **ji)
2253 {
2254         MonoDomain *target_domain;
2255         MonoJitInfo *info;
2256
2257         if (default_opt & MONO_OPT_SHARED)
2258                 target_domain = mono_get_root_domain ();
2259         else
2260                 target_domain = domain;
2261
2262         info = lookup_method (target_domain, method);
2263         if (info) {
2264                 /* We can't use a domain specific method in another domain */
2265                 if (! ((domain != target_domain) && !info->domain_neutral)) {
2266                         mono_jit_stats.methods_lookups++;
2267                         if (ji)
2268                                 *ji = info;
2269                         return info->code_start;
2270                 }
2271         }
2272
2273         if (ji)
2274                 *ji = NULL;
2275         return NULL;
2276 }
2277
2278 static guint32 bisect_opt = 0;
2279 static GHashTable *bisect_methods_hash = NULL;
2280
2281 void
2282 mono_set_bisect_methods (guint32 opt, const char *method_list_filename)
2283 {
2284         FILE *file;
2285         char method_name [2048];
2286
2287         bisect_opt = opt;
2288         bisect_methods_hash = g_hash_table_new (g_str_hash, g_str_equal);
2289         g_assert (bisect_methods_hash);
2290
2291         file = fopen (method_list_filename, "r");
2292         g_assert (file);
2293
2294         while (fgets (method_name, sizeof (method_name), file)) {
2295                 size_t len = strlen (method_name);
2296                 g_assert (len > 0);
2297                 g_assert (method_name [len - 1] == '\n');
2298                 method_name [len - 1] = 0;
2299                 g_hash_table_insert (bisect_methods_hash, g_strdup (method_name), GINT_TO_POINTER (1));
2300         }
2301         g_assert (feof (file));
2302 }
2303
2304 gboolean mono_do_single_method_regression = FALSE;
2305 guint32 mono_single_method_regression_opt = 0;
2306 MonoMethod *mono_current_single_method;
2307 GSList *mono_single_method_list;
2308 GHashTable *mono_single_method_hash;
2309
2310 guint32
2311 mono_get_optimizations_for_method (MonoMethod *method, guint32 default_opt)
2312 {
2313         g_assert (method);
2314
2315         if (bisect_methods_hash) {
2316                 char *name = mono_method_full_name (method, TRUE);
2317                 void *res = g_hash_table_lookup (bisect_methods_hash, name);
2318                 g_free (name);
2319                 if (res)
2320                         return default_opt | bisect_opt;
2321         }
2322         if (!mono_do_single_method_regression)
2323                 return default_opt;
2324         if (!mono_current_single_method) {
2325                 if (!mono_single_method_hash)
2326                         mono_single_method_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
2327                 if (!g_hash_table_lookup (mono_single_method_hash, method)) {
2328                         g_hash_table_insert (mono_single_method_hash, method, method);
2329                         mono_single_method_list = g_slist_prepend (mono_single_method_list, method);
2330                 }
2331                 return default_opt;
2332         }
2333         if (method == mono_current_single_method)
2334                 return mono_single_method_regression_opt;
2335         return default_opt;
2336 }
2337
2338 gpointer
2339 mono_jit_find_compiled_method (MonoDomain *domain, MonoMethod *method)
2340 {
2341         return mono_jit_find_compiled_method_with_jit_info (domain, method, NULL);
2342 }
2343
2344 typedef struct {
2345         MonoMethod *method;
2346         gpointer compiled_method;
2347         gpointer runtime_invoke;
2348         MonoVTable *vtable;
2349         MonoDynCallInfo *dyn_call_info;
2350         MonoClass *ret_box_class;
2351         MonoMethodSignature *sig;
2352         gboolean gsharedvt_invoke;
2353         gpointer *wrapper_arg;
2354 } RuntimeInvokeInfo;
2355
2356 static RuntimeInvokeInfo*
2357 create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, MonoError *error)
2358 {
2359         MonoMethod *invoke;
2360         RuntimeInvokeInfo *info;
2361
2362         info = g_new0 (RuntimeInvokeInfo, 1);
2363         info->compiled_method = compiled_method;
2364         if (mono_llvm_only && method->string_ctor)
2365                 info->sig = mono_marshal_get_string_ctor_signature (method);
2366         else
2367                 info->sig = mono_method_signature (method);
2368
2369         invoke = mono_marshal_get_runtime_invoke (method, FALSE);
2370         info->vtable = mono_class_vtable_full (domain, method->klass, error);
2371         if (!mono_error_ok (error))
2372                 return NULL;
2373         g_assert (info->vtable);
2374
2375         MonoMethodSignature *sig = info->sig;
2376         MonoType *ret_type;
2377
2378         /*
2379          * We want to avoid AOTing 1000s of runtime-invoke wrappers when running
2380          * in full-aot mode, so we use a slower, but more generic wrapper if
2381          * possible, built on top of the OP_DYN_CALL opcode provided by the JIT.
2382          */
2383 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2384         if (!mono_llvm_only && (mono_aot_only || debug_options.dyn_runtime_invoke)) {
2385                 gboolean supported = TRUE;
2386                 int i;
2387
2388                 if (method->string_ctor)
2389                         sig = mono_marshal_get_string_ctor_signature (method);
2390
2391                 for (i = 0; i < sig->param_count; ++i) {
2392                         MonoType *t = sig->params [i];
2393
2394                         if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
2395                                 supported = FALSE;
2396                 }
2397
2398                 if (mono_class_is_contextbound (method->klass) || !info->compiled_method)
2399                         supported = FALSE;
2400
2401                 if (supported)
2402                         info->dyn_call_info = mono_arch_dyn_call_prepare (sig);
2403         }
2404 #endif
2405
2406         ret_type = sig->ret;
2407         switch (ret_type->type) {
2408         case MONO_TYPE_VOID:
2409                 break;
2410         case MONO_TYPE_I1:
2411         case MONO_TYPE_U1:
2412         case MONO_TYPE_I2:
2413         case MONO_TYPE_U2:
2414         case MONO_TYPE_I4:
2415         case MONO_TYPE_U4:
2416         case MONO_TYPE_I:
2417         case MONO_TYPE_U:
2418         case MONO_TYPE_I8:
2419         case MONO_TYPE_U8:
2420         case MONO_TYPE_BOOLEAN:
2421         case MONO_TYPE_CHAR:
2422         case MONO_TYPE_R4:
2423         case MONO_TYPE_R8:
2424                 info->ret_box_class = mono_class_from_mono_type (ret_type);
2425                 break;
2426         case MONO_TYPE_PTR:
2427                 info->ret_box_class = mono_defaults.int_class;
2428                 break;
2429         case MONO_TYPE_STRING:
2430         case MONO_TYPE_CLASS:
2431         case MONO_TYPE_ARRAY:
2432         case MONO_TYPE_SZARRAY:
2433         case MONO_TYPE_OBJECT:
2434                 break;
2435         case MONO_TYPE_GENERICINST:
2436                 if (!MONO_TYPE_IS_REFERENCE (ret_type))
2437                         info->ret_box_class = mono_class_from_mono_type (ret_type);
2438                 break;
2439         case MONO_TYPE_VALUETYPE:
2440                 info->ret_box_class = mono_class_from_mono_type (ret_type);
2441                 break;
2442         default:
2443                 g_assert_not_reached ();
2444                 break;
2445         }
2446
2447         if (!info->dyn_call_info) {
2448                 if (mono_llvm_only) {
2449 #ifndef MONO_ARCH_GSHAREDVT_SUPPORTED
2450                         g_assert_not_reached ();
2451 #endif
2452                         info->gsharedvt_invoke = TRUE;
2453                         if (!callee_gsharedvt) {
2454                                 /* Invoke a gsharedvt out wrapper instead */
2455                                 MonoMethod *wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
2456                                 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2457
2458                                 info->wrapper_arg = g_malloc0 (2 * sizeof (gpointer));
2459                                 info->wrapper_arg [0] = mini_add_method_wrappers_llvmonly (method, info->compiled_method, FALSE, FALSE, &(info->wrapper_arg [1]));
2460
2461                                 /* Pass has_rgctx == TRUE since the wrapper has an extra arg */
2462                                 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2463                                 g_free (wrapper_sig);
2464
2465                                 info->compiled_method = mono_jit_compile_method (wrapper, error);
2466                                 if (!mono_error_ok (error)) {
2467                                         g_free (info);
2468                                         return NULL;
2469                                 }
2470                         } else {
2471                                 /* Gsharedvt methods can be invoked the same way */
2472                                 /* The out wrapper has the same signature as the compiled gsharedvt method */
2473                                 MonoMethodSignature *wrapper_sig = mini_get_gsharedvt_out_sig_wrapper_signature (sig->hasthis, sig->ret->type != MONO_TYPE_VOID, sig->param_count);
2474
2475                                 info->wrapper_arg = mono_method_needs_static_rgctx_invoke (method, TRUE) ? mini_method_get_rgctx (method) : NULL;
2476
2477                                 invoke = mono_marshal_get_runtime_invoke_for_sig (wrapper_sig);
2478                                 g_free (wrapper_sig);
2479                         }
2480                 }
2481                 info->runtime_invoke = mono_jit_compile_method (invoke, error);
2482                 if (!mono_error_ok (error)) {
2483                         g_free (info);
2484                         return NULL;
2485                 }
2486         }
2487
2488         return info;
2489 }
2490
2491 static MonoObject*
2492 mono_llvmonly_runtime_invoke (MonoMethod *method, RuntimeInvokeInfo *info, void *obj, void **params, MonoObject **exc, MonoError *error)
2493 {
2494         MonoMethodSignature *sig = info->sig;
2495         MonoDomain *domain = mono_domain_get ();
2496         MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2497         gpointer *args;
2498         gpointer retval_ptr;
2499         guint8 retval [256];
2500         gpointer *param_refs;
2501         int i, pindex;
2502
2503         error_init (error);
2504
2505         g_assert (info->gsharedvt_invoke);
2506
2507         /*
2508          * Instead of invoking the method directly, we invoke a gsharedvt out wrapper.
2509          * The advantage of this is the gsharedvt out wrappers have a reduced set of
2510          * signatures, so we only have to generate runtime invoke wrappers for these
2511          * signatures.
2512          * This code also handles invocation of gsharedvt methods directly, no
2513          * out wrappers are used in that case.
2514          */
2515         args = (void **)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2516         param_refs = (gpointer*)g_alloca ((sig->param_count + sig->hasthis + 2) * sizeof (gpointer));
2517         pindex = 0;
2518         /*
2519          * The runtime invoke wrappers expects pointers to primitive types, so have to
2520          * use indirections.
2521          */
2522         if (sig->hasthis)
2523                 args [pindex ++] = &obj;
2524         if (sig->ret->type != MONO_TYPE_VOID) {
2525                 retval_ptr = (gpointer)&retval;
2526                 args [pindex ++] = &retval_ptr;
2527         }
2528         for (i = 0; i < sig->param_count; ++i) {
2529                 MonoType *t = sig->params [i];
2530
2531                 if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t))) {
2532                         MonoClass *klass = mono_class_from_mono_type (t);
2533                         guint8 *nullable_buf;
2534                         int size;
2535
2536                         size = mono_class_value_size (klass, NULL);
2537                         nullable_buf = g_alloca (size);
2538                         g_assert (nullable_buf);
2539
2540                         /* The argument pointed to by params [i] is either a boxed vtype or null */
2541                         mono_nullable_init (nullable_buf, (MonoObject*)params [i], klass);
2542                         params [i] = nullable_buf;
2543                 }
2544
2545                 if (!t->byref && (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR)) {
2546                         param_refs [i] = params [i];
2547                         params [i] = &(param_refs [i]);
2548                 }
2549                 args [pindex ++] = &params [i];
2550         }
2551         /* The gsharedvt out wrapper has an extra argument which contains the method to call */
2552         args [pindex ++] = &info->wrapper_arg;
2553
2554         runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2555
2556         runtime_invoke (NULL, args, exc, info->compiled_method);
2557         if (exc && *exc)
2558                 return NULL;
2559
2560         if (sig->ret->type != MONO_TYPE_VOID && info->ret_box_class)
2561                 return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2562         else
2563                 return *(MonoObject**)retval;
2564 }
2565
2566 /**
2567  * mono_jit_runtime_invoke:
2568  * \param method: the method to invoke
2569  * \param obj: this pointer
2570  * \param params: array of parameter values.
2571  * \param exc: Set to the exception raised in the managed method.
2572  * \param error: error or caught exception object
2573  * If \p exc is NULL, \p error is thrown instead.
2574  * If coop is enabled, \p exc argument is ignored -
2575  * all exceptions are caught and propagated through \p error
2576  */
2577 static MonoObject*
2578 mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error)
2579 {
2580         MonoMethod *invoke, *callee;
2581         MonoObject *(*runtime_invoke) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
2582         MonoDomain *domain = mono_domain_get ();
2583         MonoJitDomainInfo *domain_info;
2584         RuntimeInvokeInfo *info, *info2;
2585         MonoJitInfo *ji = NULL;
2586         gboolean callee_gsharedvt = FALSE;
2587
2588 #ifdef ENABLE_INTERPRETER
2589         if (mono_use_interpreter)
2590                 return mono_interp_runtime_invoke (method, obj, params, exc, error);
2591 #endif
2592
2593         error_init (error);
2594
2595         if (obj == NULL && !(method->flags & METHOD_ATTRIBUTE_STATIC) && !method->string_ctor && (method->wrapper_type == 0)) {
2596                 g_warning ("Ignoring invocation of an instance method on a NULL instance.\n");
2597                 return NULL;
2598         }
2599
2600         domain_info = domain_jit_info (domain);
2601
2602         info = (RuntimeInvokeInfo *)mono_conc_hashtable_lookup (domain_info->runtime_invoke_hash, method);
2603
2604         if (!info) {
2605                 if (mono_security_core_clr_enabled ()) {
2606                         /*
2607                          * This might be redundant since mono_class_vtable () already does this,
2608                          * but keep it just in case for moonlight.
2609                          */
2610                         mono_class_setup_vtable (method->klass);
2611                         if (mono_class_has_failure (method->klass)) {
2612                                 mono_error_set_for_class_failure (error, method->klass);
2613                                 if (exc)
2614                                         *exc = (MonoObject*)mono_class_get_exception_for_failure (method->klass);
2615                                 return NULL;
2616                         }
2617                 }
2618
2619                 gpointer compiled_method;
2620
2621                 callee = method;
2622                 if (method->klass->rank && (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) &&
2623                         (method->iflags & METHOD_IMPL_ATTRIBUTE_NATIVE)) {
2624                         /*
2625                          * Array Get/Set/Address methods. The JIT implements them using inline code
2626                          * inside the runtime invoke wrappers, so no need to compile them.
2627                          */
2628                         if (mono_aot_only) {
2629                                 /*
2630                                  * Call a wrapper, since the runtime invoke wrapper was not generated.
2631                                  */
2632                                 MonoMethod *wrapper;
2633
2634                                 wrapper = mono_marshal_get_array_accessor_wrapper (method);
2635                                 invoke = mono_marshal_get_runtime_invoke (wrapper, FALSE);
2636                                 callee = wrapper;
2637                         } else {
2638                                 callee = NULL;
2639                         }
2640                 }
2641
2642                 if (callee) {
2643                         compiled_method = mono_jit_compile_method (callee, error);
2644                         if (!compiled_method) {
2645                                 g_assert (!mono_error_ok (error));
2646                                 return NULL;
2647                         }
2648
2649                         if (mono_llvm_only) {
2650                                 ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
2651                                 callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
2652                                 if (callee_gsharedvt)
2653                                         callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
2654                         }
2655
2656                         if (!callee_gsharedvt)
2657                                 compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
2658                 } else {
2659                         compiled_method = NULL;
2660                 }
2661
2662                 info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error);
2663                 if (!mono_error_ok (error))
2664                         return NULL;
2665
2666                 mono_domain_lock (domain);
2667                 info2 = (RuntimeInvokeInfo *)mono_conc_hashtable_insert (domain_info->runtime_invoke_hash, method, info);
2668                 mono_domain_unlock (domain);
2669                 if (info2) {
2670                         g_free (info);
2671                         info = info2;
2672                 }
2673         }
2674
2675         /*
2676          * We need this here because mono_marshal_get_runtime_invoke can place
2677          * the helper method in System.Object and not the target class.
2678          */
2679         if (!mono_runtime_class_init_full (info->vtable, error)) {
2680                 if (exc)
2681                         *exc = (MonoObject*) mono_error_convert_to_exception (error);
2682                 return NULL;
2683         }
2684
2685         /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
2686            we always catch the exception and propagate it through the MonoError */
2687         gboolean catchExcInMonoError =
2688                 (exc == NULL) && mono_threads_is_coop_enabled ();
2689         MonoObject *invoke_exc = NULL;
2690         if (catchExcInMonoError)
2691                 exc = &invoke_exc;
2692
2693         /* The wrappers expect this to be initialized to NULL */
2694         if (exc)
2695                 *exc = NULL;
2696
2697 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
2698         if (info->dyn_call_info) {
2699                 MonoMethodSignature *sig = mono_method_signature (method);
2700                 gpointer *args;
2701                 static RuntimeInvokeDynamicFunction dyn_runtime_invoke;
2702                 int i, pindex;
2703                 guint8 buf [512];
2704                 guint8 retval [256];
2705
2706                 if (!dyn_runtime_invoke) {
2707                         invoke = mono_marshal_get_runtime_invoke_dynamic ();
2708                         dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error);
2709                         if (!mono_error_ok (error))
2710                                 return NULL;
2711                 }
2712
2713                 /* Convert the arguments to the format expected by start_dyn_call () */
2714                 args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));
2715                 pindex = 0;
2716                 if (sig->hasthis)
2717                         args [pindex ++] = &obj;
2718                 for (i = 0; i < sig->param_count; ++i) {
2719                         MonoType *t = sig->params [i];
2720
2721                         if (t->byref) {
2722                                 args [pindex ++] = &params [i];
2723                         } else if (MONO_TYPE_IS_REFERENCE (t) || t->type == MONO_TYPE_PTR) {
2724                                 args [pindex ++] = &params [i];
2725                         } else {
2726                                 args [pindex ++] = params [i];
2727                         }
2728                 }
2729
2730                 //printf ("M: %s\n", mono_method_full_name (method, TRUE));
2731
2732                 mono_arch_start_dyn_call (info->dyn_call_info, (gpointer**)args, retval, buf, sizeof (buf));
2733
2734                 dyn_runtime_invoke (buf, exc, info->compiled_method);
2735                 mono_arch_finish_dyn_call (info->dyn_call_info, buf);
2736
2737                 if (catchExcInMonoError && *exc != NULL) {
2738                         mono_error_set_exception_instance (error, (MonoException*) *exc);
2739                         return NULL;
2740                 }
2741
2742                 if (info->ret_box_class)
2743                         return mono_value_box_checked (domain, info->ret_box_class, retval, error);
2744                 else
2745                         return *(MonoObject**)retval;
2746         }
2747 #endif
2748
2749         MonoObject *result;
2750
2751         if (mono_llvm_only) {
2752                 result = mono_llvmonly_runtime_invoke (method, info, obj, params, exc, error);
2753                 if (!is_ok (error))
2754                         return NULL;
2755         } else {
2756                 runtime_invoke = (MonoObject *(*)(MonoObject *, void **, MonoObject **, void *))info->runtime_invoke;
2757
2758                 result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
2759         }
2760         if (catchExcInMonoError && *exc != NULL)
2761                 mono_error_set_exception_instance (error, (MonoException*) *exc);
2762         return result;
2763 }
2764
2765 typedef struct {
2766         MonoVTable *vtable;
2767         int slot;
2768 } IMTTrampInfo;
2769
2770 typedef gpointer (*IMTTrampFunc) (gpointer *arg, MonoMethod *imt_method);
2771
2772 /*
2773  * mini_llvmonly_initial_imt_tramp:
2774  *
2775  *  This function is called the first time a call is made through an IMT trampoline.
2776  * It should have the same signature as the mono_llvmonly_imt_tramp_... functions.
2777  */
2778 static gpointer
2779 mini_llvmonly_initial_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2780 {
2781         IMTTrampInfo *info = (IMTTrampInfo*)arg;
2782         gpointer *imt;
2783         gpointer *ftndesc;
2784         IMTTrampFunc func;
2785
2786         mono_vtable_build_imt_slot (info->vtable, info->slot);
2787
2788         imt = (gpointer*)info->vtable;
2789         imt -= MONO_IMT_SIZE;
2790
2791         /* Return what the real IMT trampoline returns */
2792         ftndesc = imt [info->slot];
2793         func = ftndesc [0];
2794
2795         if (func == (IMTTrampFunc)mini_llvmonly_initial_imt_tramp)
2796                 /* Happens when the imt slot contains only a generic virtual method */
2797                 return NULL;
2798         return func ((gpointer *)ftndesc [1], imt_method);
2799 }
2800
2801 /* This is called indirectly through an imt slot. */
2802 static gpointer
2803 mono_llvmonly_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2804 {
2805         int i = 0;
2806
2807         /* arg points to an array created in mono_llvmonly_get_imt_trampoline () */
2808         while (arg [i] && arg [i] != imt_method)
2809                 i += 2;
2810         g_assert (arg [i]);
2811
2812         return arg [i + 1];
2813 }
2814
2815 /* Optimized versions of mono_llvmonly_imt_trampoline () for different table sizes */
2816 static gpointer
2817 mono_llvmonly_imt_tramp_1 (gpointer *arg, MonoMethod *imt_method)
2818 {
2819         //g_assert (arg [0] == imt_method);
2820         return arg [1];
2821 }
2822
2823 static gpointer
2824 mono_llvmonly_imt_tramp_2 (gpointer *arg, MonoMethod *imt_method)
2825 {
2826         //g_assert (arg [0] == imt_method || arg [2] == imt_method);
2827         if (arg [0] == imt_method)
2828                 return arg [1];
2829         else
2830                 return arg [3];
2831 }
2832
2833 static gpointer
2834 mono_llvmonly_imt_tramp_3 (gpointer *arg, MonoMethod *imt_method)
2835 {
2836         //g_assert (arg [0] == imt_method || arg [2] == imt_method || arg [4] == imt_method);
2837         if (arg [0] == imt_method)
2838                 return arg [1];
2839         else if (arg [2] == imt_method)
2840                 return arg [3];
2841         else
2842                 return arg [5];
2843 }
2844
2845 /*
2846  * A version of the imt trampoline used for generic virtual/variant iface methods.
2847  * Unlikely a normal imt trampoline, its possible that IMT_METHOD is not found
2848  * in the search table. The original JIT code had a 'fallback' trampoline it could
2849  * call, but we can't do that, so we just return NULL, and the compiled code
2850  * will handle it.
2851  */
2852 static gpointer
2853 mono_llvmonly_fallback_imt_tramp (gpointer *arg, MonoMethod *imt_method)
2854 {
2855         int i = 0;
2856
2857         while (arg [i] && arg [i] != imt_method)
2858                 i += 2;
2859         if (!arg [i])
2860                 return NULL;
2861
2862         return arg [i + 1];
2863 }
2864
2865 static gpointer
2866 mono_llvmonly_get_imt_trampoline (MonoVTable *vtable, MonoDomain *domain, MonoIMTCheckItem **imt_entries, int count, gpointer fail_tramp)
2867 {
2868         gpointer *buf;
2869         gpointer *res;
2870         int i, index, real_count;
2871         gboolean virtual_generic = FALSE;
2872
2873         /*
2874          * Create an array which is passed to the imt trampoline functions.
2875          * The array contains MonoMethod-function descriptor pairs, terminated by a NULL entry.
2876          */
2877
2878         real_count = 0;
2879         for (i = 0; i < count; ++i) {
2880                 MonoIMTCheckItem *item = imt_entries [i];
2881
2882                 if (item->is_equals)
2883                         real_count ++;
2884                 if (item->has_target_code)
2885                         virtual_generic = TRUE;
2886         }
2887
2888         /*
2889          * Initialize all vtable entries reachable from this imt slot, so the compiled
2890          * code doesn't have to check it.
2891          */
2892         for (i = 0; i < count; ++i) {
2893                 MonoIMTCheckItem *item = imt_entries [i];
2894                 int vt_slot;
2895
2896                 if (!item->is_equals || item->has_target_code)
2897                         continue;
2898                 vt_slot = item->value.vtable_slot;
2899                 mono_init_vtable_slot (vtable, vt_slot);
2900         }
2901
2902         /* Save the entries into an array */
2903         buf = (void **)mono_domain_alloc (domain, (real_count + 1) * 2 * sizeof (gpointer));
2904         index = 0;
2905         for (i = 0; i < count; ++i) {
2906                 MonoIMTCheckItem *item = imt_entries [i];
2907
2908                 if (!item->is_equals)
2909                         continue;
2910
2911                 g_assert (item->key);
2912                 buf [(index * 2)] = item->key;
2913                 if (item->has_target_code)
2914                         buf [(index * 2) + 1] = item->value.target_code;
2915                 else
2916                         buf [(index * 2) + 1] = vtable->vtable [item->value.vtable_slot];
2917                 index ++;
2918         }
2919         buf [(index * 2)] = NULL;
2920         buf [(index * 2) + 1] = fail_tramp;
2921
2922         /*
2923          * Return a function descriptor for a C function with 'buf' as its argument.
2924          * It will by called by JITted code.
2925          */
2926         res = (void **)mono_domain_alloc (domain, 2 * sizeof (gpointer));
2927         switch (real_count) {
2928         case 1:
2929                 res [0] = mono_llvmonly_imt_tramp_1;
2930                 break;
2931         case 2:
2932                 res [0] = mono_llvmonly_imt_tramp_2;
2933                 break;
2934         case 3:
2935                 res [0] = mono_llvmonly_imt_tramp_3;
2936                 break;
2937         default:
2938                 res [0] = mono_llvmonly_imt_tramp;
2939                 break;
2940         }
2941         if (virtual_generic || fail_tramp)
2942                 res [0] = mono_llvmonly_fallback_imt_tramp;
2943         res [1] = buf;
2944
2945         return res;
2946 }
2947
2948 MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
2949 {
2950         MonoException *exc = NULL;
2951         MonoJitInfo *ji;
2952         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2953         MONO_SIG_HANDLER_GET_CONTEXT;
2954
2955         ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
2956
2957         MONO_ENTER_GC_UNSAFE_UNBALANCED;
2958
2959 #if defined(MONO_ARCH_HAVE_IS_INT_OVERFLOW)
2960         if (mono_arch_is_int_overflow (ctx, info))
2961                 /*
2962                  * The spec says this throws ArithmeticException, but MS throws the derived
2963                  * OverflowException.
2964                  */
2965                 exc = mono_get_exception_overflow ();
2966         else
2967                 exc = mono_get_exception_divide_by_zero ();
2968 #else
2969         exc = mono_get_exception_divide_by_zero ();
2970 #endif
2971
2972         if (!ji) {
2973                 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
2974                         goto exit;
2975
2976                 mono_handle_native_crash ("SIGFPE", ctx, info);
2977                 if (mono_do_crash_chaining) {
2978                         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
2979                         goto exit;
2980                 }
2981         }
2982
2983         mono_arch_handle_exception (ctx, exc);
2984
2985 exit:
2986         MONO_EXIT_GC_UNSAFE_UNBALANCED;
2987 }
2988
2989 MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
2990 {
2991         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
2992         MONO_SIG_HANDLER_GET_CONTEXT;
2993
2994         if (mono_runtime_get_no_exec ())
2995                 exit (1);
2996
2997
2998         mono_handle_native_crash ("SIGILL", ctx, info);
2999         if (mono_do_crash_chaining) {
3000                 mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3001                 return;
3002         }
3003
3004         g_assert_not_reached ();
3005 }
3006
3007 #if defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32)
3008 #define HAVE_SIG_INFO
3009 #endif
3010
3011 MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
3012 {
3013         MonoJitInfo *ji;
3014         MonoJitTlsData *jit_tls = (MonoJitTlsData *)mono_tls_get_jit_tls ();
3015         gpointer fault_addr = NULL;
3016 #ifdef HAVE_SIG_INFO
3017         MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
3018 #else
3019         void *info = NULL;
3020 #endif
3021         MONO_SIG_HANDLER_GET_CONTEXT;
3022
3023 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
3024         if (mono_arch_is_single_step_event (info, ctx)) {
3025                 mono_debugger_agent_single_step_event (ctx);
3026                 return;
3027         } else if (mono_arch_is_breakpoint_event (info, ctx)) {
3028                 mono_debugger_agent_breakpoint_hit (ctx);
3029                 return;
3030         }
3031 #endif
3032
3033 #if defined(HAVE_SIG_INFO)
3034 #if !defined(HOST_WIN32)
3035         fault_addr = info->si_addr;
3036         if (mono_aot_is_pagefault (info->si_addr)) {
3037                 mono_aot_handle_pagefault (info->si_addr);
3038                 return;
3039         }
3040 #endif
3041
3042         /* The thread might no be registered with the runtime */
3043         if (!mono_domain_get () || !jit_tls) {
3044                 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3045                         return;
3046                 mono_handle_native_crash ("SIGSEGV", ctx, info);
3047                 if (mono_do_crash_chaining) {
3048                         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3049                         return;
3050                 }
3051         }
3052 #endif
3053
3054         ji = mono_jit_info_table_find_internal (mono_domain_get (), (char *)mono_arch_ip_from_context (ctx), TRUE, TRUE);
3055
3056 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
3057         if (mono_handle_soft_stack_ovf (jit_tls, ji, ctx, info, (guint8*)info->si_addr))
3058                 return;
3059
3060 #ifdef MONO_ARCH_HAVE_SIGCTX_TO_MONOCTX
3061         /* info->si_addr seems to be NULL on some kernels when handling stack overflows */
3062         fault_addr = info->si_addr;
3063         if (fault_addr == NULL) {
3064                 MonoContext mctx;
3065
3066                 mono_sigctx_to_monoctx (ctx, &mctx);
3067
3068                 fault_addr = MONO_CONTEXT_GET_SP (&mctx);
3069         }
3070 #endif
3071
3072         if (jit_tls->stack_size &&
3073                 ABS ((guint8*)fault_addr - ((guint8*)jit_tls->end_of_stack - jit_tls->stack_size)) < 8192 * sizeof (gpointer)) {
3074                 /*
3075                  * The hard-guard page has been hit: there is not much we can do anymore
3076                  * Print a hopefully clear message and abort.
3077                  */
3078                 mono_handle_hard_stack_ovf (jit_tls, ji, ctx, (guint8*)info->si_addr);
3079                 g_assert_not_reached ();
3080         } else {
3081                 /* The original handler might not like that it is executed on an altstack... */
3082                 if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3083                         return;
3084
3085                 mono_arch_handle_altstack_exception (ctx, info, info->si_addr, FALSE);
3086         }
3087 #else
3088
3089         if (!ji) {
3090                 if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
3091                         return;
3092
3093                 mono_handle_native_crash ("SIGSEGV", ctx, info);
3094
3095                 if (mono_do_crash_chaining) {
3096                         mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
3097                         return;
3098                 }
3099         }
3100
3101         mono_arch_handle_exception (ctx, NULL);
3102 #endif
3103 }
3104
3105 MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
3106 {
3107         MonoException *exc;
3108         MONO_SIG_HANDLER_GET_CONTEXT;
3109
3110         MONO_ENTER_GC_UNSAFE_UNBALANCED;
3111
3112         exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
3113
3114         mono_arch_handle_exception (ctx, exc);
3115
3116         MONO_EXIT_GC_UNSAFE_UNBALANCED;
3117 }
3118
3119 #ifndef DISABLE_REMOTING
3120 /* mono_jit_create_remoting_trampoline:
3121  * @method: pointer to the method info
3122  *
3123  * Creates a trampoline which calls the remoting functions. This
3124  * is used in the vtable of transparent proxies.
3125  *
3126  * Returns: a pointer to the newly created code
3127  */
3128 static gpointer
3129 mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target, MonoError *error)
3130 {
3131         MonoMethod *nm;
3132         guint8 *addr = NULL;
3133
3134         error_init (error);
3135
3136         if ((method->flags & METHOD_ATTRIBUTE_VIRTUAL) && mono_method_signature (method)->generic_param_count) {
3137                 return mono_create_specific_trampoline (method, MONO_TRAMPOLINE_GENERIC_VIRTUAL_REMOTING,
3138                         domain, NULL);
3139         }
3140
3141         if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
3142             (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class)))
3143                 nm = mono_marshal_get_remoting_invoke_for_target (method, target);
3144         else
3145                 nm = method;
3146         addr = (guint8 *)mono_compile_method_checked (nm, error);
3147         return_val_if_nok (error, NULL);
3148         return mono_get_addr_from_ftnptr (addr);
3149 }
3150 #endif
3151
3152 static G_GNUC_UNUSED void
3153 no_imt_trampoline (void)
3154 {
3155         g_assert_not_reached ();
3156 }
3157
3158 static G_GNUC_UNUSED void
3159 no_vcall_trampoline (void)
3160 {
3161         g_assert_not_reached ();
3162 }
3163
3164 static gpointer *vtable_trampolines;
3165 static int vtable_trampolines_size;
3166
3167 gpointer
3168 mini_get_vtable_trampoline (MonoVTable *vt, int slot_index)
3169 {
3170         int index = slot_index + MONO_IMT_SIZE;
3171
3172         if (mono_llvm_only) {
3173                 if (slot_index < 0) {
3174                         /* Initialize the IMT trampoline to a 'trampoline' so the generated code doesn't have to initialize it */
3175                         // FIXME: Memory management
3176                         gpointer *ftndesc = g_malloc (2 * sizeof (gpointer));
3177                         IMTTrampInfo *info = g_new0 (IMTTrampInfo, 1);
3178                         info->vtable = vt;
3179                         info->slot = index;
3180                         ftndesc [0] = mini_llvmonly_initial_imt_tramp;
3181                         ftndesc [1] = info;
3182                         mono_memory_barrier ();
3183                         return ftndesc;
3184                 } else {
3185                         return NULL;
3186                 }
3187         }
3188
3189         g_assert (slot_index >= - MONO_IMT_SIZE);
3190         if (!vtable_trampolines || slot_index + MONO_IMT_SIZE >= vtable_trampolines_size) {
3191                 mono_jit_lock ();
3192                 if (!vtable_trampolines || index >= vtable_trampolines_size) {
3193                         int new_size;
3194                         gpointer new_table;
3195
3196                         new_size = vtable_trampolines_size ? vtable_trampolines_size * 2 : 128;
3197                         while (new_size <= index)
3198                                 new_size *= 2;
3199                         new_table = g_new0 (gpointer, new_size);
3200
3201                         if (vtable_trampolines)
3202                                 memcpy (new_table, vtable_trampolines, vtable_trampolines_size * sizeof (gpointer));
3203                         g_free (vtable_trampolines);
3204                         mono_memory_barrier ();
3205                         vtable_trampolines = (void **)new_table;
3206                         vtable_trampolines_size = new_size;
3207                 }
3208                 mono_jit_unlock ();
3209         }
3210
3211         if (!vtable_trampolines [index])
3212                 vtable_trampolines [index] = mono_create_specific_trampoline (GUINT_TO_POINTER (slot_index), MONO_TRAMPOLINE_VCALL, mono_get_root_domain (), NULL);
3213         return vtable_trampolines [index];
3214 }
3215
3216 static gpointer
3217 mini_get_imt_trampoline (MonoVTable *vt, int slot_index)
3218 {
3219         return mini_get_vtable_trampoline (vt, slot_index - MONO_IMT_SIZE);
3220 }
3221
3222 static gboolean
3223 mini_imt_entry_inited (MonoVTable *vt, int imt_slot_index)
3224 {
3225         if (mono_llvm_only)
3226                 return FALSE;
3227
3228         gpointer *imt = (gpointer*)vt;
3229         imt -= MONO_IMT_SIZE;
3230
3231         return (imt [imt_slot_index] != mini_get_imt_trampoline (vt, imt_slot_index));
3232 }
3233
3234 static gboolean
3235 is_callee_gsharedvt_variable (gpointer addr)
3236 {
3237         MonoJitInfo *ji;
3238         gboolean callee_gsharedvt;
3239
3240         ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (addr), NULL);
3241         g_assert (ji);
3242         callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
3243         if (callee_gsharedvt)
3244                 callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
3245         return callee_gsharedvt;
3246 }
3247
3248 gpointer
3249 mini_get_delegate_arg (MonoMethod *method, gpointer method_ptr)
3250 {
3251         gpointer arg = NULL;
3252
3253         if (mono_method_needs_static_rgctx_invoke (method, FALSE))
3254                 arg = mini_method_get_rgctx (method);
3255
3256         /*
3257          * Avoid adding gsharedvt in wrappers since they might not exist if
3258          * this delegate is called through a gsharedvt delegate invoke wrapper.
3259          * Instead, encode that the method is gsharedvt in del->extra_arg,
3260          * the CEE_MONO_CALLI_EXTRA_ARG implementation in the JIT depends on this.
3261          */
3262         if (method->is_inflated && is_callee_gsharedvt_variable (method_ptr)) {
3263                 g_assert ((((mgreg_t)arg) & 1) == 0);
3264                 arg = (gpointer)(((mgreg_t)arg) | 1);
3265         }
3266         return arg;
3267 }
3268
3269 void
3270 mini_init_delegate (MonoDelegate *del)
3271 {
3272         if (mono_llvm_only)
3273                 del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
3274 #ifdef ENABLE_INTERPRETER
3275         if (mono_use_interpreter)
3276                 mono_interp_init_delegate (del);
3277 #endif
3278 }
3279
3280 char*
3281 mono_get_delegate_virtual_invoke_impl_name (gboolean load_imt_reg, int offset)
3282 {
3283         int abs_offset;
3284
3285         abs_offset = offset;
3286         if (abs_offset < 0)
3287                 abs_offset = - abs_offset;
3288         return g_strdup_printf ("delegate_virtual_invoke%s_%s%d", load_imt_reg ? "_imt" : "", offset < 0 ? "m_" : "", abs_offset / SIZEOF_VOID_P);
3289 }
3290
3291 gpointer
3292 mono_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method)
3293 {
3294         gboolean is_virtual_generic, is_interface, load_imt_reg;
3295         int offset, idx;
3296
3297         static guint8 **cache = NULL;
3298         static int cache_size = 0;
3299
3300         if (!method)
3301                 return NULL;
3302
3303         if (MONO_TYPE_ISSTRUCT (sig->ret))
3304                 return NULL;
3305
3306         is_virtual_generic = method->is_inflated && mono_method_get_declaring_generic_method (method)->is_generic;
3307         is_interface = mono_class_is_interface (method->klass);
3308         load_imt_reg = is_virtual_generic || is_interface;
3309
3310         if (is_interface)
3311                 offset = ((gint32)mono_method_get_imt_slot (method) - MONO_IMT_SIZE) * SIZEOF_VOID_P;
3312         else
3313                 offset = G_STRUCT_OFFSET (MonoVTable, vtable) + ((mono_method_get_vtable_index (method)) * (SIZEOF_VOID_P));
3314
3315         idx = (offset / SIZEOF_VOID_P + MONO_IMT_SIZE) * 2 + (load_imt_reg ? 1 : 0);
3316         g_assert (idx >= 0);
3317
3318         /* Resize the cache to idx + 1 */
3319         if (cache_size < idx + 1) {
3320                 mono_jit_lock ();
3321                 if (cache_size < idx + 1) {
3322                         guint8 **new_cache;
3323                         int new_cache_size = idx + 1;
3324
3325                         new_cache = g_new0 (guint8*, new_cache_size);
3326                         if (cache)
3327                                 memcpy (new_cache, cache, cache_size * sizeof (guint8*));
3328                         g_free (cache);
3329
3330                         mono_memory_barrier ();
3331                         cache = new_cache;
3332                         cache_size = new_cache_size;
3333                 }
3334                 mono_jit_unlock ();
3335         }
3336
3337         if (cache [idx])
3338                 return cache [idx];
3339
3340         /* FIXME Support more cases */
3341         if (mono_aot_only) {
3342                 cache [idx] = (guint8 *)mono_aot_get_trampoline (mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset));
3343                 g_assert (cache [idx]);
3344         } else {
3345                 cache [idx] = (guint8 *)mono_arch_get_delegate_virtual_invoke_impl (sig, method, offset, load_imt_reg);
3346         }
3347         return cache [idx];
3348 }
3349
3350 /**
3351  * mini_parse_debug_option:
3352  * @option: The option to parse.
3353  *
3354  * Parses debug options for the mono runtime. The options are the same as for
3355  * the MONO_DEBUG environment variable.
3356  *
3357  */
3358 gboolean
3359 mini_parse_debug_option (const char *option)
3360 {
3361         if (!strcmp (option, "handle-sigint"))
3362                 debug_options.handle_sigint = TRUE;
3363         else if (!strcmp (option, "keep-delegates"))
3364                 debug_options.keep_delegates = TRUE;
3365         else if (!strcmp (option, "reverse-pinvoke-exceptions"))
3366                 debug_options.reverse_pinvoke_exceptions = TRUE;
3367         else if (!strcmp (option, "collect-pagefault-stats"))
3368                 debug_options.collect_pagefault_stats = TRUE;
3369         else if (!strcmp (option, "break-on-unverified"))
3370                 debug_options.break_on_unverified = TRUE;
3371         else if (!strcmp (option, "no-gdb-backtrace"))
3372                 debug_options.no_gdb_backtrace = TRUE;
3373         else if (!strcmp (option, "suspend-on-native-crash") || !strcmp (option, "suspend-on-sigsegv"))
3374                 debug_options.suspend_on_native_crash = TRUE;
3375         else if (!strcmp (option, "suspend-on-exception"))
3376                 debug_options.suspend_on_exception = TRUE;
3377         else if (!strcmp (option, "suspend-on-unhandled"))
3378                 debug_options.suspend_on_unhandled = TRUE;
3379         else if (!strcmp (option, "dont-free-domains"))
3380                 mono_dont_free_domains = TRUE;
3381         else if (!strcmp (option, "dyn-runtime-invoke"))
3382                 debug_options.dyn_runtime_invoke = TRUE;
3383         else if (!strcmp (option, "gdb"))
3384                 debug_options.gdb = TRUE;
3385         else if (!strcmp (option, "lldb"))
3386                 debug_options.lldb = TRUE;
3387         else if (!strcmp (option, "explicit-null-checks"))
3388                 debug_options.explicit_null_checks = TRUE;
3389         else if (!strcmp (option, "gen-seq-points"))
3390                 debug_options.gen_sdb_seq_points = TRUE;
3391         else if (!strcmp (option, "gen-compact-seq-points"))
3392                 fprintf (stderr, "Mono Warning: option gen-compact-seq-points is deprecated.\n");
3393         else if (!strcmp (option, "no-compact-seq-points"))
3394                 debug_options.no_seq_points_compact_data = TRUE;
3395         else if (!strcmp (option, "single-imm-size"))
3396                 debug_options.single_imm_size = TRUE;
3397         else if (!strcmp (option, "init-stacks"))
3398                 debug_options.init_stacks = TRUE;
3399         else if (!strcmp (option, "casts"))
3400                 debug_options.better_cast_details = TRUE;
3401         else if (!strcmp (option, "soft-breakpoints"))
3402                 debug_options.soft_breakpoints = TRUE;
3403         else if (!strcmp (option, "check-pinvoke-callconv"))
3404                 debug_options.check_pinvoke_callconv = TRUE;
3405         else if (!strcmp (option, "use-fallback-tls"))
3406                 debug_options.use_fallback_tls = TRUE;
3407         else if (!strcmp (option, "debug-domain-unload"))
3408                 mono_enable_debug_domain_unload (TRUE);
3409         else if (!strcmp (option, "partial-sharing"))
3410                 mono_set_partial_sharing_supported (TRUE);
3411         else if (!strcmp (option, "align-small-structs"))
3412                 mono_align_small_structs = TRUE;
3413         else if (!strcmp (option, "native-debugger-break"))
3414                 debug_options.native_debugger_break = TRUE;
3415         else if (!strcmp (option, "disable_omit_fp"))
3416                 debug_options.disable_omit_fp = TRUE;
3417         else
3418                 return FALSE;
3419
3420         return TRUE;
3421 }
3422
3423 static void
3424 mini_parse_debug_options (void)
3425 {
3426         char *options = g_getenv ("MONO_DEBUG");
3427         gchar **args, **ptr;
3428
3429         if (!options)
3430                 return;
3431
3432         args = g_strsplit (options, ",", -1);
3433         g_free (options);
3434
3435         for (ptr = args; ptr && *ptr; ptr++) {
3436                 const char *arg = *ptr;
3437
3438                 if (!mini_parse_debug_option (arg)) {
3439                         fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
3440                         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");
3441                         exit (1);
3442                 }
3443         }
3444
3445         g_strfreev (args);
3446 }
3447
3448 MonoDebugOptions *
3449 mini_get_debug_options (void)
3450 {
3451         return &debug_options;
3452 }
3453
3454 static gpointer
3455 mini_create_ftnptr (MonoDomain *domain, gpointer addr)
3456 {
3457 #if (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
3458         return addr;
3459 #else
3460         gpointer* desc = NULL;
3461
3462         if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
3463                 return desc;
3464 #       if defined(__ppc64__) || defined(__powerpc64__)
3465
3466         desc = mono_domain_alloc0 (domain, 3 * sizeof (gpointer));
3467
3468         desc [0] = addr;
3469         desc [1] = NULL;
3470         desc [2] = NULL;
3471 #       endif
3472         g_hash_table_insert (domain->ftnptrs_hash, addr, desc);
3473         return desc;
3474 #endif
3475 }
3476
3477 static gpointer
3478 mini_get_addr_from_ftnptr (gpointer descr)
3479 {
3480 #if ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
3481         return *(gpointer*)descr;
3482 #else
3483         return descr;
3484 #endif
3485 }
3486
3487 static void
3488 register_jit_stats (void)
3489 {
3490         mono_counters_register ("Compiled methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_compiled);
3491         mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot);
3492         mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
3493         mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);
3494         mono_counters_register ("JIT/method_to_ir (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
3495         mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses);
3496         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);
3497         mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts);
3498         mono_counters_register ("JIT/decompose_typechecks (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_typechecks);
3499         mono_counters_register ("JIT/local_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop);
3500         mono_counters_register ("JIT/local_emulate_ops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_emulate_ops);
3501         mono_counters_register ("JIT/optimize_branches (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches);
3502         mono_counters_register ("JIT/handle_global_vregs (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs);
3503         mono_counters_register ("JIT/local_deadce (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce);
3504         mono_counters_register ("JIT/local_alias_analysis (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_alias_analysis);
3505         mono_counters_register ("JIT/if_conversion (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_if_conversion);
3506         mono_counters_register ("JIT/bb_ordering (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_bb_ordering);
3507         mono_counters_register ("JIT/compile_dominator_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compile_dominator_info);
3508         mono_counters_register ("JIT/compute_natural_loops (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_compute_natural_loops);
3509         mono_counters_register ("JIT/insert_safepoints (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_insert_safepoints);
3510         mono_counters_register ("JIT/ssa_compute (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_compute);
3511         mono_counters_register ("JIT/ssa_cprop (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_cprop);
3512         mono_counters_register ("JIT/ssa_deadce(sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_deadce);
3513         mono_counters_register ("JIT/perform_abc_removal (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_perform_abc_removal);
3514         mono_counters_register ("JIT/ssa_remove (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_ssa_remove);
3515         mono_counters_register ("JIT/local_cprop2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop2);
3516         mono_counters_register ("JIT/handle_global_vregs2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_global_vregs2);
3517         mono_counters_register ("JIT/local_deadce2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce2);
3518         mono_counters_register ("JIT/optimize_branches2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_optimize_branches2);
3519         mono_counters_register ("JIT/decompose_vtype_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_vtype_opts);
3520         mono_counters_register ("JIT/decompose_array_access_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_array_access_opts);
3521         mono_counters_register ("JIT/liveness_handle_exception_clauses2 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses2);
3522         mono_counters_register ("JIT/analyze_liveness (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_analyze_liveness);
3523         mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
3524         mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
3525         mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
3526         mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
3527         mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
3528         mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
3529         mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
3530         mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
3531         mono_counters_register ("JIT/save_seq_point_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_save_seq_point_info);
3532         mono_counters_register ("Total time spent JITting (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_time);
3533         mono_counters_register ("Basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.basic_blocks);
3534         mono_counters_register ("Max basic blocks", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.max_basic_blocks);
3535         mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var);
3536         mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs);
3537         mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size);
3538         mono_counters_register ("Allocated seq points size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_seq_points_size);
3539         mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods);
3540         mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods);
3541         mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars);
3542         mono_counters_register ("Locals stack size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.locals_stack_size);
3543         mono_counters_register ("Method cache lookups", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_lookups);
3544         mono_counters_register ("Compiled CIL code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.cil_code_size);
3545         mono_counters_register ("Native code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.native_code_size);
3546         mono_counters_register ("Aliases found", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_found);
3547         mono_counters_register ("Aliases eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.alias_removed);
3548         mono_counters_register ("Aliased loads eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.loads_eliminated);
3549         mono_counters_register ("Aliased stores eliminated", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.stores_eliminated);
3550         mono_counters_register ("Optimized immediate divisions", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.optimized_divisions);
3551 }
3552
3553 static void runtime_invoke_info_free (gpointer value);
3554
3555 static gint
3556 class_method_pair_equal (gconstpointer ka, gconstpointer kb)
3557 {
3558         const MonoClassMethodPair *apair = (const MonoClassMethodPair *)ka;
3559         const MonoClassMethodPair *bpair = (const MonoClassMethodPair *)kb;
3560
3561         return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
3562 }
3563
3564 static guint
3565 class_method_pair_hash (gconstpointer data)
3566 {
3567         const MonoClassMethodPair *pair = (const MonoClassMethodPair *)data;
3568
3569         return (gsize)pair->klass ^ (gsize)pair->method;
3570 }
3571
3572 static void
3573 mini_create_jit_domain_info (MonoDomain *domain)
3574 {
3575         MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1);
3576
3577         info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3578         info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3579         info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
3580         info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
3581         info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
3582         info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
3583         info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
3584         info->jump_target_hash = g_hash_table_new (NULL, NULL);
3585         mono_jit_code_hash_init (&info->interp_code_hash);
3586
3587         domain->runtime_info = info;
3588 }
3589
3590 static void
3591 delete_jump_list (gpointer key, gpointer value, gpointer user_data)
3592 {
3593         MonoJumpList *jlist = (MonoJumpList *)value;
3594         g_slist_free (jlist->list);
3595 }
3596
3597 static void
3598 delete_got_slot_list (gpointer key, gpointer value, gpointer user_data)
3599 {
3600         GSList *list = (GSList *)value;
3601         g_slist_free (list);
3602 }
3603
3604 static void
3605 dynamic_method_info_free (gpointer key, gpointer value, gpointer user_data)
3606 {
3607         MonoJitDynamicMethodInfo *di = (MonoJitDynamicMethodInfo *)value;
3608         mono_code_manager_destroy (di->code_mp);
3609         g_free (di);
3610 }
3611
3612 static void
3613 runtime_invoke_info_free (gpointer value)
3614 {
3615         RuntimeInvokeInfo *info = (RuntimeInvokeInfo*)value;
3616
3617 #ifdef MONO_ARCH_DYN_CALL_SUPPORTED
3618         if (info->dyn_call_info)
3619                 mono_arch_dyn_call_free (info->dyn_call_info);
3620 #endif
3621         g_free (info);
3622 }
3623
3624 static void
3625 free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
3626 {
3627         g_slist_free (value);
3628 }
3629
3630 static void
3631 mini_free_jit_domain_info (MonoDomain *domain)
3632 {
3633         MonoJitDomainInfo *info = domain_jit_info (domain);
3634
3635         g_hash_table_foreach (info->jump_target_hash, delete_jump_list, NULL);
3636         g_hash_table_destroy (info->jump_target_hash);
3637         if (info->jump_target_got_slot_hash) {
3638                 g_hash_table_foreach (info->jump_target_got_slot_hash, delete_got_slot_list, NULL);
3639                 g_hash_table_destroy (info->jump_target_got_slot_hash);
3640         }
3641         if (info->dynamic_code_hash) {
3642                 g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
3643                 g_hash_table_destroy (info->dynamic_code_hash);
3644         }
3645         if (info->method_code_hash)
3646                 g_hash_table_destroy (info->method_code_hash);
3647         g_hash_table_destroy (info->jump_trampoline_hash);
3648         g_hash_table_destroy (info->jit_trampoline_hash);
3649         g_hash_table_destroy (info->delegate_trampoline_hash);
3650         if (info->static_rgctx_trampoline_hash)
3651                 g_hash_table_destroy (info->static_rgctx_trampoline_hash);
3652         g_hash_table_destroy (info->llvm_vcall_trampoline_hash);
3653         mono_conc_hashtable_destroy (info->runtime_invoke_hash);
3654         g_hash_table_destroy (info->seq_points);
3655         g_hash_table_destroy (info->arch_seq_points);
3656         if (info->agent_info)
3657                 mono_debugger_agent_free_domain_info (domain);
3658         if (info->gsharedvt_arg_tramp_hash)
3659                 g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
3660         if (info->llvm_jit_callees) {
3661                 g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
3662                 g_hash_table_destroy (info->llvm_jit_callees);
3663         }
3664         mono_internal_hash_table_destroy (&info->interp_code_hash);
3665 #ifdef ENABLE_LLVM
3666         mono_llvm_free_domain_info (domain);
3667 #endif
3668
3669         g_free (domain->runtime_info);
3670         domain->runtime_info = NULL;
3671 }
3672
3673 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3674
3675 static void
3676 code_manager_chunk_new (void *chunk, int size)
3677 {
3678         mono_arch_code_chunk_new (chunk, size);
3679 }
3680
3681 static void
3682 code_manager_chunk_destroy (void *chunk)
3683 {
3684         mono_arch_code_chunk_destroy (chunk);
3685 }
3686
3687 #endif
3688
3689 #ifdef ENABLE_LLVM
3690 static gboolean
3691 llvm_init_inner (void)
3692 {
3693         if (!mono_llvm_load (NULL))
3694                 return FALSE;
3695
3696         mono_llvm_init ();
3697         return TRUE;
3698 }
3699 #endif
3700
3701 /*
3702  * mini_llvm_init:
3703  *
3704  *   Load and initialize LLVM support.
3705  * Return TRUE on success.
3706  */
3707 gboolean
3708 mini_llvm_init (void)
3709 {
3710 #ifdef ENABLE_LLVM
3711         static gboolean llvm_inited;
3712         static gboolean init_result;
3713
3714         mono_loader_lock_if_inited ();
3715         if (!llvm_inited) {
3716                 init_result = llvm_init_inner ();
3717                 llvm_inited = TRUE;
3718         }
3719         mono_loader_unlock_if_inited ();
3720         return init_result;
3721 #else
3722         return FALSE;
3723 #endif
3724 }
3725
3726 void
3727 mini_profiler_enable_with_options (const char* profile_options)
3728 {
3729         mini_enable_profiler = TRUE;
3730         mini_profiler_options = g_strdup (profile_options);
3731 }
3732
3733 MonoDomain *
3734 mini_init (const char *filename, const char *runtime_version)
3735 {
3736         MonoError error;
3737         MonoDomain *domain;
3738         MonoRuntimeCallbacks callbacks;
3739         MonoThreadInfoRuntimeCallbacks ticallbacks;
3740         MonoCodeManagerCallbacks code_manager_callbacks;
3741
3742         MONO_VES_INIT_BEGIN ();
3743
3744         CHECKED_MONO_INIT ();
3745
3746 #if defined(__linux__)
3747         if (access ("/proc/self/maps", F_OK) != 0) {
3748                 g_print ("Mono requires /proc to be mounted.\n");
3749                 exit (1);
3750         }
3751 #endif
3752
3753 #ifdef ENABLE_INTERPRETER
3754         mono_interp_init ();
3755 #endif
3756
3757         mono_os_mutex_init_recursive (&jit_mutex);
3758
3759         mono_cross_helpers_run ();
3760
3761         mono_counters_init ();
3762
3763         mini_jit_init ();
3764
3765         mini_jit_init_job_control ();
3766
3767         /* Happens when using the embedding interface */
3768         if (!default_opt_set)
3769                 default_opt = mono_parse_default_optimizations (NULL);
3770
3771 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
3772         if (mono_aot_only)
3773                 mono_set_generic_sharing_vt_supported (TRUE);
3774 #else
3775         if (mono_llvm_only)
3776                 mono_set_generic_sharing_vt_supported (TRUE);
3777 #endif
3778
3779         mono_tls_init_runtime_keys ();
3780
3781         if (!global_codeman)
3782                 global_codeman = mono_code_manager_new ();
3783
3784         memset (&callbacks, 0, sizeof (callbacks));
3785         callbacks.create_ftnptr = mini_create_ftnptr;
3786         callbacks.get_addr_from_ftnptr = mini_get_addr_from_ftnptr;
3787         callbacks.get_runtime_build_info = mono_get_runtime_build_info;
3788         callbacks.set_cast_details = mono_set_cast_details;
3789         callbacks.debug_log = mono_debugger_agent_debug_log;
3790         callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
3791         callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
3792         callbacks.get_imt_trampoline = mini_get_imt_trampoline;
3793         callbacks.imt_entry_inited = mini_imt_entry_inited;
3794         callbacks.init_delegate = mini_init_delegate;
3795 #define JIT_INVOKE_WORKS
3796 #ifdef JIT_INVOKE_WORKS
3797         callbacks.runtime_invoke = mono_jit_runtime_invoke;
3798 #endif
3799 #define JIT_TRAMPOLINES_WORK
3800 #ifdef JIT_TRAMPOLINES_WORK
3801         callbacks.compile_method = mono_jit_compile_method;
3802         callbacks.create_jump_trampoline = mono_create_jump_trampoline;
3803         callbacks.create_jit_trampoline = mono_create_jit_trampoline;
3804         callbacks.create_delegate_trampoline = mono_create_delegate_trampoline;
3805         callbacks.free_method = mono_jit_free_method;
3806 #ifndef DISABLE_REMOTING
3807         callbacks.create_remoting_trampoline = mono_jit_create_remoting_trampoline;
3808 #endif
3809 #endif
3810
3811         mono_install_callbacks (&callbacks);
3812
3813         memset (&ticallbacks, 0, sizeof (ticallbacks));
3814         ticallbacks.setup_async_callback = mono_setup_async_callback;
3815         ticallbacks.thread_state_init_from_sigctx = mono_thread_state_init_from_sigctx;
3816         ticallbacks.thread_state_init_from_handle = mono_thread_state_init_from_handle;
3817         ticallbacks.thread_state_init = mono_thread_state_init;
3818
3819 #ifndef HOST_WIN32
3820         mono_w32handle_init ();
3821 #endif
3822
3823         mono_threads_runtime_init (&ticallbacks);
3824
3825         if (g_hasenv ("MONO_DEBUG")) {
3826                 mini_parse_debug_options ();
3827         }
3828
3829         mono_code_manager_init ();
3830
3831         memset (&code_manager_callbacks, 0, sizeof (code_manager_callbacks));
3832 #ifdef MONO_ARCH_HAVE_CODE_CHUNK_TRACKING
3833         code_manager_callbacks.chunk_new = code_manager_chunk_new;
3834         code_manager_callbacks.chunk_destroy = code_manager_chunk_destroy;
3835 #endif
3836         mono_code_manager_install_callbacks (&code_manager_callbacks);
3837
3838         mono_hwcap_init ();
3839
3840         mono_arch_cpu_init ();
3841
3842         mono_arch_init ();
3843
3844         mono_unwind_init ();
3845
3846         if (mini_get_debug_options ()->lldb || g_hasenv ("MONO_LLDB")) {
3847                 mono_lldb_init ("");
3848                 mono_dont_free_domains = TRUE;
3849         }
3850
3851 #ifdef XDEBUG_ENABLED
3852         char *mono_xdebug = g_getenv ("MONO_XDEBUG");
3853         if (mono_xdebug) {
3854                 mono_xdebug_init (mono_xdebug);
3855                 g_free (mono_xdebug);
3856                 /* So methods for multiple domains don't have the same address */
3857                 mono_dont_free_domains = TRUE;
3858                 mono_using_xdebug = TRUE;
3859         } else if (mini_get_debug_options ()->gdb) {
3860                 mono_xdebug_init ((char*)"gdb");
3861                 mono_dont_free_domains = TRUE;
3862                 mono_using_xdebug = TRUE;
3863         }
3864 #endif
3865
3866 #ifdef ENABLE_LLVM
3867         if (mono_use_llvm) {
3868                 if (!mono_llvm_load (NULL)) {
3869                         mono_use_llvm = FALSE;
3870                         fprintf (stderr, "Mono Warning: llvm support could not be loaded.\n");
3871                 }
3872         }
3873         if (mono_use_llvm)
3874                 mono_llvm_init ();
3875 #endif
3876
3877         mono_trampolines_init ();
3878
3879         if (default_opt & MONO_OPT_AOT)
3880                 mono_aot_init ();
3881
3882         mono_debugger_agent_init ();
3883
3884 #ifdef MONO_ARCH_GSHARED_SUPPORTED
3885         mono_set_generic_sharing_supported (TRUE);
3886 #endif
3887
3888         mono_threads_signals_init ();
3889
3890 #ifndef MONO_CROSS_COMPILE
3891         mono_runtime_install_handlers ();
3892 #endif
3893         mono_threads_install_cleanup (mini_thread_cleanup);
3894
3895 #ifdef JIT_TRAMPOLINES_WORK
3896         mono_install_create_domain_hook (mini_create_jit_domain_info);
3897         mono_install_free_domain_hook (mini_free_jit_domain_info);
3898 #endif
3899         mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
3900         mono_install_get_class_from_name (mono_aot_get_class_from_name);
3901         mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
3902
3903         if (mini_profiler_enabled ()) {
3904                 mono_profiler_load (mini_profiler_get_options ());
3905                 mono_profiler_thread_name (MONO_NATIVE_THREAD_ID_TO_UINT (mono_native_thread_id_get ()), "Main");
3906         }
3907
3908         if (debug_options.collect_pagefault_stats)
3909                 mono_aot_set_make_unreadable (TRUE);
3910
3911         if (runtime_version)
3912                 domain = mono_init_version (filename, runtime_version);
3913         else
3914                 domain = mono_init_from_assembly (filename, filename);
3915
3916         if (mono_aot_only) {
3917                 /* This helps catch code allocation requests */
3918                 mono_code_manager_set_read_only (domain->code_mp);
3919                 mono_marshal_use_aot_wrappers (TRUE);
3920         }
3921
3922         if (mono_llvm_only) {
3923                 mono_install_imt_trampoline_builder (mono_llvmonly_get_imt_trampoline);
3924                 mono_set_always_build_imt_trampolines (TRUE);
3925         } else if (mono_aot_only) {
3926                 mono_install_imt_trampoline_builder (mono_aot_get_imt_trampoline);
3927         } else {
3928                 mono_install_imt_trampoline_builder (mono_arch_build_imt_trampoline);
3929         }
3930
3931         /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
3932         mono_arch_finish_init ();
3933
3934         mono_icall_init ();
3935
3936         /* This must come after mono_init () in the aot-only case */
3937         mono_exceptions_init ();
3938
3939         /* This should come after mono_init () too */
3940         mini_gc_init ();
3941
3942 #ifndef DISABLE_JIT
3943         mono_create_helper_signatures ();
3944 #endif
3945
3946         register_jit_stats ();
3947
3948 #define JIT_CALLS_WORK
3949 #ifdef JIT_CALLS_WORK
3950         /* Needs to be called here since register_jit_icall depends on it */
3951         mono_marshal_init ();
3952
3953         mono_arch_register_lowlevel_calls ();
3954
3955         register_icalls ();
3956
3957         mono_generic_sharing_init ();
3958 #endif
3959
3960 #ifdef MONO_ARCH_SIMD_INTRINSICS
3961         mono_simd_intrinsics_init ();
3962 #endif
3963
3964         mono_tasklets_init ();
3965
3966         register_trampolines (domain);
3967
3968         if (mono_compile_aot)
3969                 /*
3970                  * Avoid running managed code when AOT compiling, since the platform
3971                  * might only support aot-only execution.
3972                  */
3973                 mono_runtime_set_no_exec (TRUE);
3974
3975         mono_mem_account_register_counters ();
3976
3977 #define JIT_RUNTIME_WORKS
3978 #ifdef JIT_RUNTIME_WORKS
3979         mono_install_runtime_cleanup ((MonoDomainFunc)mini_cleanup);
3980         mono_runtime_init_checked (domain, mono_thread_start_cb, mono_thread_attach_cb, &error);
3981         mono_error_assert_ok (&error);
3982         mono_thread_attach (domain);
3983 #endif
3984
3985         if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
3986                 mono_runtime_setup_stat_profiler ();
3987
3988         mono_profiler_runtime_initialized ();
3989
3990         MONO_VES_INIT_END ();
3991
3992         return domain;
3993 }
3994
3995 static void
3996 register_icalls (void)
3997 {
3998         mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
3999                                 ves_icall_get_frame_info);
4000         mono_add_internal_call ("System.Diagnostics.StackTrace::get_trace",
4001                                 ves_icall_get_trace);
4002         mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
4003                                 mono_runtime_install_handlers);
4004         mono_add_internal_call ("Mono.Runtime::mono_runtime_cleanup_handlers",
4005                                 mono_runtime_cleanup_handlers);
4006
4007 #if defined(PLATFORM_ANDROID) || defined(TARGET_ANDROID)
4008         mono_add_internal_call ("System.Diagnostics.Debugger::Mono_UnhandledException_internal",
4009                                 mono_debugger_agent_unhandled_exception);
4010 #endif
4011
4012         /*
4013          * It's important that we pass `TRUE` as the last argument here, as
4014          * it causes the JIT to omit a wrapper for these icalls. If the JIT
4015          * *did* emit a wrapper, we'd be looking at infinite recursion since
4016          * the wrapper would call the icall which would call the wrapper and
4017          * so on.
4018          */
4019         register_icall (mono_profiler_method_enter, "mono_profiler_method_enter", "void ptr", TRUE);
4020         register_icall (mono_profiler_method_leave, "mono_profiler_method_leave", "void ptr", TRUE);
4021
4022         register_icall (mono_trace_enter_method, "mono_trace_enter_method", NULL, TRUE);
4023         register_icall (mono_trace_leave_method, "mono_trace_leave_method", NULL, TRUE);
4024         register_icall (mono_get_lmf_addr, "mono_get_lmf_addr", "ptr", TRUE);
4025         register_icall (mono_jit_thread_attach, "mono_jit_thread_attach", "ptr ptr", TRUE);
4026         register_icall (mono_jit_set_domain, "mono_jit_set_domain", "void ptr", TRUE);
4027         register_icall (mono_domain_get, "mono_domain_get", "ptr", TRUE);
4028
4029         register_icall (mono_llvm_throw_exception, "mono_llvm_throw_exception", "void object", TRUE);
4030         register_icall (mono_llvm_rethrow_exception, "mono_llvm_rethrow_exception", "void object", TRUE);
4031         register_icall (mono_llvm_resume_exception, "mono_llvm_resume_exception", "void", TRUE);
4032         register_icall (mono_llvm_match_exception, "mono_llvm_match_exception", "int ptr int int", TRUE);
4033         register_icall (mono_llvm_clear_exception, "mono_llvm_clear_exception", NULL, TRUE);
4034         register_icall (mono_llvm_load_exception, "mono_llvm_load_exception", "object", TRUE);
4035         register_icall (mono_llvm_throw_corlib_exception, "mono_llvm_throw_corlib_exception", "void int", TRUE);
4036 #if defined(ENABLE_LLVM) && !defined(MONO_LLVM_LOADED)
4037         register_icall (mono_llvm_set_unhandled_exception_handler, "mono_llvm_set_unhandled_exception_handler", NULL, TRUE);
4038
4039         // FIXME: This is broken
4040         register_icall (mono_debug_personality, "mono_debug_personality", "int int int ptr ptr ptr", TRUE);
4041 #endif
4042
4043         register_dyn_icall (mono_get_throw_exception (), "mono_arch_throw_exception", "void object", TRUE);
4044         register_dyn_icall (mono_get_rethrow_exception (), "mono_arch_rethrow_exception", "void object", TRUE);
4045         register_dyn_icall (mono_get_throw_corlib_exception (), "mono_arch_throw_corlib_exception", "void ptr", TRUE);
4046         register_icall (mono_thread_get_undeniable_exception, "mono_thread_get_undeniable_exception", "object", FALSE);
4047         register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
4048         register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
4049
4050         if (mono_threads_is_coop_enabled ())
4051                 register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", FALSE);
4052
4053 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
4054         register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", FALSE);
4055         register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);
4056         register_opcode_emulation (OP_LDIV_UN, "__emul_ldiv_un", "long long long", mono_lldiv_un, "mono_lldiv_un", FALSE);
4057         register_opcode_emulation (OP_LREM, "__emul_lrem", "long long long", mono_llrem, "mono_llrem", FALSE);
4058         register_opcode_emulation (OP_LREM_UN, "__emul_lrem_un", "long long long", mono_llrem_un, "mono_llrem_un", FALSE);
4059 #endif
4060 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
4061         register_opcode_emulation (OP_LMUL_OVF_UN, "__emul_lmul_ovf_un", "long long long", mono_llmult_ovf_un, "mono_llmult_ovf_un", FALSE);
4062         register_opcode_emulation (OP_LMUL_OVF, "__emul_lmul_ovf", "long long long", mono_llmult_ovf, "mono_llmult_ovf", FALSE);
4063 #endif
4064
4065 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
4066         register_opcode_emulation (OP_LSHL, "__emul_lshl", "long long int32", mono_lshl, "mono_lshl", TRUE);
4067         register_opcode_emulation (OP_LSHR, "__emul_lshr", "long long int32", mono_lshr, "mono_lshr", TRUE);
4068         register_opcode_emulation (OP_LSHR_UN, "__emul_lshr_un", "long long int32", mono_lshr_un, "mono_lshr_un", TRUE);
4069 #endif
4070
4071 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
4072         register_opcode_emulation (OP_IDIV, "__emul_op_idiv", "int32 int32 int32", mono_idiv, "mono_idiv", FALSE);
4073         register_opcode_emulation (OP_IDIV_UN, "__emul_op_idiv_un", "int32 int32 int32", mono_idiv_un, "mono_idiv_un", FALSE);
4074         register_opcode_emulation (OP_IREM, "__emul_op_irem", "int32 int32 int32", mono_irem, "mono_irem", FALSE);
4075         register_opcode_emulation (OP_IREM_UN, "__emul_op_irem_un", "int32 int32 int32", mono_irem_un, "mono_irem_un", FALSE);
4076 #endif
4077
4078 #ifdef MONO_ARCH_EMULATE_MUL_DIV
4079         register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, "mono_imul", TRUE);
4080 #endif
4081
4082 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
4083         register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, "mono_imul_ovf", FALSE);
4084         register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, "mono_imul_ovf_un", FALSE);
4085 #endif
4086
4087 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
4088         register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, "mono_fdiv", FALSE);
4089 #endif
4090
4091         register_opcode_emulation (OP_FCONV_TO_U8, "__emul_fconv_to_u8", "ulong double", mono_fconv_u8, "mono_fconv_u8", FALSE);
4092         register_opcode_emulation (OP_RCONV_TO_U8, "__emul_rconv_to_u8", "ulong float", mono_rconv_u8, "mono_rconv_u8", FALSE);
4093         register_opcode_emulation (OP_FCONV_TO_U4, "__emul_fconv_to_u4", "uint32 double", mono_fconv_u4, "mono_fconv_u4", FALSE);
4094         register_opcode_emulation (OP_FCONV_TO_OVF_I8, "__emul_fconv_to_ovf_i8", "long double", mono_fconv_ovf_i8, "mono_fconv_ovf_i8", FALSE);
4095         register_opcode_emulation (OP_FCONV_TO_OVF_U8, "__emul_fconv_to_ovf_u8", "ulong double", mono_fconv_ovf_u8, "mono_fconv_ovf_u8", FALSE);
4096         register_opcode_emulation (OP_RCONV_TO_OVF_I8, "__emul_rconv_to_ovf_i8", "long float", mono_rconv_ovf_i8, "mono_rconv_ovf_i8", FALSE);
4097         register_opcode_emulation (OP_RCONV_TO_OVF_U8, "__emul_rconv_to_ovf_u8", "ulong float", mono_rconv_ovf_u8, "mono_rconv_ovf_u8", FALSE);
4098
4099
4100 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
4101         register_opcode_emulation (OP_FCONV_TO_I8, "__emul_fconv_to_i8", "long double", mono_fconv_i8, "mono_fconv_i8", FALSE);
4102         register_opcode_emulation (OP_RCONV_TO_I8, "__emul_rconv_to_i8", "long float", mono_rconv_i8, "mono_rconv_i8", FALSE);
4103 #endif
4104
4105 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
4106         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);
4107 #endif
4108 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
4109         register_opcode_emulation (OP_LCONV_TO_R8, "__emul_lconv_to_r8", "double long", mono_lconv_to_r8, "mono_lconv_to_r8", FALSE);
4110 #endif
4111 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
4112         register_opcode_emulation (OP_LCONV_TO_R4, "__emul_lconv_to_r4", "float long", mono_lconv_to_r4, "mono_lconv_to_r4", FALSE);
4113 #endif
4114 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
4115         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);
4116 #endif
4117 #ifdef MONO_ARCH_EMULATE_FREM
4118         register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
4119         register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
4120 #endif
4121
4122 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
4123         if (mono_arch_is_soft_float ()) {
4124                 register_opcode_emulation (OP_FSUB, "__emul_fsub", "double double double", mono_fsub, "mono_fsub", FALSE);
4125                 register_opcode_emulation (OP_FADD, "__emul_fadd", "double double double", mono_fadd, "mono_fadd", FALSE);
4126                 register_opcode_emulation (OP_FMUL, "__emul_fmul", "double double double", mono_fmul, "mono_fmul", FALSE);
4127                 register_opcode_emulation (OP_FNEG, "__emul_fneg", "double double", mono_fneg, "mono_fneg", FALSE);
4128                 register_opcode_emulation (OP_ICONV_TO_R8, "__emul_iconv_to_r8", "double int32", mono_conv_to_r8, "mono_conv_to_r8", FALSE);
4129                 register_opcode_emulation (OP_ICONV_TO_R4, "__emul_iconv_to_r4", "double int32", mono_conv_to_r4, "mono_conv_to_r4", FALSE);
4130                 register_opcode_emulation (OP_FCONV_TO_R4, "__emul_fconv_to_r4", "double double", mono_fconv_r4, "mono_fconv_r4", FALSE);
4131                 register_opcode_emulation (OP_FCONV_TO_I1, "__emul_fconv_to_i1", "int8 double", mono_fconv_i1, "mono_fconv_i1", FALSE);
4132                 register_opcode_emulation (OP_FCONV_TO_I2, "__emul_fconv_to_i2", "int16 double", mono_fconv_i2, "mono_fconv_i2", FALSE);
4133                 register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4134                 register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, "mono_fconv_u1", FALSE);
4135                 register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, "mono_fconv_u2", FALSE);
4136
4137 #if SIZEOF_VOID_P == 4
4138                 register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, "mono_fconv_i4", FALSE);
4139 #endif
4140
4141                 register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, "mono_fcmp_eq", FALSE);
4142                 register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, "mono_fcmp_lt", FALSE);
4143                 register_opcode_emulation (OP_FBGT, "__emul_fcmp_gt", "uint32 double double", mono_fcmp_gt, "mono_fcmp_gt", FALSE);
4144                 register_opcode_emulation (OP_FBLE, "__emul_fcmp_le", "uint32 double double", mono_fcmp_le, "mono_fcmp_le", FALSE);
4145                 register_opcode_emulation (OP_FBGE, "__emul_fcmp_ge", "uint32 double double", mono_fcmp_ge, "mono_fcmp_ge", FALSE);
4146                 register_opcode_emulation (OP_FBNE_UN, "__emul_fcmp_ne_un", "uint32 double double", mono_fcmp_ne_un, "mono_fcmp_ne_un", FALSE);
4147                 register_opcode_emulation (OP_FBLT_UN, "__emul_fcmp_lt_un", "uint32 double double", mono_fcmp_lt_un, "mono_fcmp_lt_un", FALSE);
4148                 register_opcode_emulation (OP_FBGT_UN, "__emul_fcmp_gt_un", "uint32 double double", mono_fcmp_gt_un, "mono_fcmp_gt_un", FALSE);
4149                 register_opcode_emulation (OP_FBLE_UN, "__emul_fcmp_le_un", "uint32 double double", mono_fcmp_le_un, "mono_fcmp_le_un", FALSE);
4150                 register_opcode_emulation (OP_FBGE_UN, "__emul_fcmp_ge_un", "uint32 double double", mono_fcmp_ge_un, "mono_fcmp_ge_un", FALSE);
4151
4152                 register_opcode_emulation (OP_FCEQ, "__emul_fcmp_ceq", "uint32 double double", mono_fceq, "mono_fceq", FALSE);
4153                 register_opcode_emulation (OP_FCGT, "__emul_fcmp_cgt", "uint32 double double", mono_fcgt, "mono_fcgt", FALSE);
4154                 register_opcode_emulation (OP_FCGT_UN, "__emul_fcmp_cgt_un", "uint32 double double", mono_fcgt_un, "mono_fcgt_un", FALSE);
4155                 register_opcode_emulation (OP_FCLT, "__emul_fcmp_clt", "uint32 double double", mono_fclt, "mono_fclt", FALSE);
4156                 register_opcode_emulation (OP_FCLT_UN, "__emul_fcmp_clt_un", "uint32 double double", mono_fclt_un, "mono_fclt_un", FALSE);
4157
4158                 register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
4159                 register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
4160                 register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
4161                 register_icall (mono_isfinite, "mono_isfinite", "uint32 double", FALSE);
4162         }
4163 #endif
4164         register_icall (mono_ckfinite, "mono_ckfinite", "double double", FALSE);
4165
4166 #ifdef COMPRESSED_INTERFACE_BITMAP
4167         register_icall (mono_class_interface_match, "mono_class_interface_match", "uint32 ptr int32", TRUE);
4168 #endif
4169
4170 #if SIZEOF_REGISTER == 4
4171         register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "uint32 double", mono_fconv_u4, "mono_fconv_u4", TRUE);
4172 #else
4173         register_opcode_emulation (OP_FCONV_TO_U, "__emul_fconv_to_u", "ulong double", mono_fconv_u8, "mono_fconv_u8", TRUE);
4174 #endif
4175
4176         /* other jit icalls */
4177         register_icall (ves_icall_mono_delegate_ctor, "ves_icall_mono_delegate_ctor", "void object object ptr", FALSE);
4178         register_icall (mono_class_static_field_address , "mono_class_static_field_address",
4179                                  "ptr ptr ptr", FALSE);
4180         register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
4181         register_icall (mono_ldtoken_wrapper_generic_shared, "mono_ldtoken_wrapper_generic_shared",
4182                 "ptr ptr ptr ptr", FALSE);
4183         register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
4184         register_icall (ves_icall_mono_ldstr, "ves_icall_mono_ldstr", "object ptr ptr int32", FALSE);
4185         register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
4186         register_icall (ves_icall_object_new, "ves_icall_object_new", "object ptr ptr", FALSE);
4187         register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
4188         register_icall (ves_icall_array_new, "ves_icall_array_new", "object ptr ptr int32", FALSE);
4189         register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE);
4190         register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
4191         register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
4192         register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
4193         register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);
4194         register_icall (mono_helper_compile_generic_method, "mono_helper_compile_generic_method", "ptr object ptr ptr", FALSE);
4195         register_icall (mono_helper_ldstr, "mono_helper_ldstr", "object ptr int", FALSE);
4196         register_icall (mono_helper_ldstr_mscorlib, "mono_helper_ldstr_mscorlib", "object int", FALSE);
4197         register_icall (mono_helper_newobj_mscorlib, "mono_helper_newobj_mscorlib", "object int", FALSE);
4198         register_icall (mono_value_copy, "mono_value_copy", "void ptr ptr ptr", FALSE);
4199         register_icall (mono_object_castclass_unbox, "mono_object_castclass_unbox", "object object ptr", FALSE);
4200         register_icall (mono_break, "mono_break", NULL, TRUE);
4201         register_icall (mono_create_corlib_exception_0, "mono_create_corlib_exception_0", "object int", TRUE);
4202         register_icall (mono_create_corlib_exception_1, "mono_create_corlib_exception_1", "object int object", TRUE);
4203         register_icall (mono_create_corlib_exception_2, "mono_create_corlib_exception_2", "object int object object", TRUE);
4204         register_icall (mono_array_new_1, "mono_array_new_1", "object ptr int", FALSE);
4205         register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE);
4206         register_icall (mono_array_new_3, "mono_array_new_3", "object ptr int int int", FALSE);
4207         register_icall (mono_array_new_4, "mono_array_new_4", "object ptr int int int int", FALSE);
4208         register_icall (mono_get_native_calli_wrapper, "mono_get_native_calli_wrapper", "ptr ptr ptr ptr", FALSE);
4209         register_icall (mono_resume_unwind, "mono_resume_unwind", "void", TRUE);
4210         register_icall (mono_gsharedvt_constrained_call, "mono_gsharedvt_constrained_call", "object ptr ptr ptr ptr ptr", FALSE);
4211         register_icall (mono_gsharedvt_value_copy, "mono_gsharedvt_value_copy", "void ptr ptr ptr", TRUE);
4212
4213         register_icall_no_wrapper (mono_gc_get_range_copy_func (), "mono_gc_range_copy", "void ptr ptr int");
4214
4215         register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
4216         register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
4217         register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE);
4218         register_icall (mono_fill_class_rgctx, "mono_fill_class_rgctx", "ptr ptr int", FALSE);
4219         register_icall (mono_fill_method_rgctx, "mono_fill_method_rgctx", "ptr ptr int", FALSE);
4220
4221         register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
4222
4223         register_icall (mono_aot_init_llvm_method, "mono_aot_init_llvm_method", "void ptr int", TRUE);
4224         register_icall (mono_aot_init_gshared_method_this, "mono_aot_init_gshared_method_this", "void ptr int object", TRUE);
4225         register_icall (mono_aot_init_gshared_method_mrgctx, "mono_aot_init_gshared_method_mrgctx", "void ptr int ptr", TRUE);
4226         register_icall (mono_aot_init_gshared_method_vtable, "mono_aot_init_gshared_method_vtable", "void ptr int ptr", TRUE);
4227
4228         register_icall_no_wrapper (mono_resolve_iface_call_gsharedvt, "mono_resolve_iface_call_gsharedvt", "ptr object int ptr ptr");
4229         register_icall_no_wrapper (mono_resolve_vcall_gsharedvt, "mono_resolve_vcall_gsharedvt", "ptr object int ptr ptr");
4230         register_icall_no_wrapper (mono_resolve_generic_virtual_call, "mono_resolve_generic_virtual_call", "ptr ptr int ptr");
4231         register_icall_no_wrapper (mono_resolve_generic_virtual_iface_call, "mono_resolve_generic_virtual_iface_call", "ptr ptr int ptr");
4232         /* This needs a wrapper so it can have a preserveall cconv */
4233         register_icall (mono_init_vtable_slot, "mono_init_vtable_slot", "ptr ptr int", FALSE);
4234         register_icall (mono_llvmonly_init_delegate, "mono_llvmonly_init_delegate", "void object", TRUE);
4235         register_icall (mono_llvmonly_init_delegate_virtual, "mono_llvmonly_init_delegate_virtual", "void object object ptr", TRUE);
4236         register_icall (mono_get_assembly_object, "mono_get_assembly_object", "object ptr", TRUE);
4237         register_icall (mono_get_method_object, "mono_get_method_object", "object ptr", TRUE);
4238         register_icall (mono_throw_method_access, "mono_throw_method_access", "void ptr ptr", FALSE);
4239         register_icall_no_wrapper (mono_dummy_jit_icall, "mono_dummy_jit_icall", "void");
4240
4241         register_icall_with_wrapper (mono_monitor_enter_internal, "mono_monitor_enter_internal", "void obj");
4242         register_icall_with_wrapper (mono_monitor_enter_v4_internal, "mono_monitor_enter_v4_internal", "void obj ptr");
4243         register_icall_no_wrapper (mono_monitor_enter_fast, "mono_monitor_enter_fast", "int obj");
4244         register_icall_no_wrapper (mono_monitor_enter_v4_fast, "mono_monitor_enter_v4_fast", "int obj ptr");
4245
4246 #ifdef TARGET_IOS
4247         register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
4248 #endif
4249         /* Register tls icalls */
4250         register_icall_no_wrapper (mono_tls_get_thread, "mono_tls_get_thread", "ptr");
4251         register_icall_no_wrapper (mono_tls_get_jit_tls, "mono_tls_get_jit_tls", "ptr");
4252         register_icall_no_wrapper (mono_tls_get_domain, "mono_tls_get_domain", "ptr");  
4253         register_icall_no_wrapper (mono_tls_get_sgen_thread_info, "mono_tls_get_sgen_thread_info", "ptr");
4254         register_icall_no_wrapper (mono_tls_get_lmf_addr, "mono_tls_get_lmf_addr", "ptr");
4255         register_icall_no_wrapper (mono_tls_set_thread, "mono_tls_set_thread", "void ptr");
4256         register_icall_no_wrapper (mono_tls_set_jit_tls, "mono_tls_set_jit_tls", "void ptr");
4257         register_icall_no_wrapper (mono_tls_set_domain, "mono_tls_set_domain", "void ptr");
4258         register_icall_no_wrapper (mono_tls_set_sgen_thread_info, "mono_tls_set_sgen_thread_info", "void ptr");
4259         register_icall_no_wrapper (mono_tls_set_lmf_addr, "mono_tls_set_lmf_addr", "void ptr");
4260 }
4261
4262 MonoJitStats mono_jit_stats = {0};
4263
4264 static void
4265 print_jit_stats (void)
4266 {
4267         if (mono_jit_stats.enabled) {
4268                 g_print ("Mono Jit statistics\n");
4269                 g_print ("Max code size ratio:    %.2f (%s)\n", mono_jit_stats.max_code_size_ratio/100.0,
4270                                  mono_jit_stats.max_ratio_method);
4271                 g_print ("Biggest method:         %ld (%s)\n", mono_jit_stats.biggest_method_size,
4272                                  mono_jit_stats.biggest_method);
4273
4274                 g_print ("Delegates created:      %ld\n", mono_stats.delegate_creations);
4275                 g_print ("Initialized classes:    %ld\n", mono_stats.initialized_class_count);
4276                 g_print ("Used classes:           %ld\n", mono_stats.used_class_count);
4277                 g_print ("Generic vtables:        %ld\n", mono_stats.generic_vtable_count);
4278                 g_print ("Methods:                %ld\n", mono_stats.method_count);
4279                 g_print ("Static data size:       %ld\n", mono_stats.class_static_data_size);
4280                 g_print ("VTable data size:       %ld\n", mono_stats.class_vtable_size);
4281                 g_print ("Mscorlib mempool size:  %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool));
4282
4283                 g_print ("\nInitialized classes:    %ld\n", mono_stats.generic_class_count);
4284                 g_print ("Inflated types:         %ld\n", mono_stats.inflated_type_count);
4285                 g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
4286
4287                 g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);
4288                 g_print ("Unsharable generic methods: %ld\n", mono_stats.generics_unsharable_methods);
4289                 g_print ("Shared generic methods: %ld\n", mono_stats.generics_shared_methods);
4290                 g_print ("Shared vtype generic methods: %ld\n", mono_stats.gsharedvt_methods);
4291
4292                 g_print ("IMT tables size:        %ld\n", mono_stats.imt_tables_size);
4293                 g_print ("IMT number of tables:   %ld\n", mono_stats.imt_number_of_tables);
4294                 g_print ("IMT number of methods:  %ld\n", mono_stats.imt_number_of_methods);
4295                 g_print ("IMT used slots:         %ld\n", mono_stats.imt_used_slots);
4296                 g_print ("IMT colliding slots:    %ld\n", mono_stats.imt_slots_with_collisions);
4297                 g_print ("IMT max collisions:     %ld\n", mono_stats.imt_max_collisions_in_slot);
4298                 g_print ("IMT methods at max col: %ld\n", mono_stats.imt_method_count_when_max_collisions);
4299                 g_print ("IMT trampolines size:   %ld\n", mono_stats.imt_trampolines_size);
4300
4301                 g_print ("JIT info table inserts: %ld\n", mono_stats.jit_info_table_insert_count);
4302                 g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
4303                 g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
4304
4305                 g_free (mono_jit_stats.max_ratio_method);
4306                 mono_jit_stats.max_ratio_method = NULL;
4307                 g_free (mono_jit_stats.biggest_method);
4308                 mono_jit_stats.biggest_method = NULL;
4309         }
4310 }
4311
4312 void
4313 mini_cleanup (MonoDomain *domain)
4314 {
4315         if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
4316                 mono_runtime_shutdown_stat_profiler ();
4317
4318 #ifndef DISABLE_COM
4319         cominterop_release_all_rcws ();
4320 #endif
4321
4322 #ifndef MONO_CROSS_COMPILE
4323         /*
4324          * mono_domain_finalize () needs to be called early since it needs the
4325          * execution engine still fully working (it may invoke managed finalizers).
4326          */
4327         mono_domain_finalize (domain, 2000);
4328 #endif
4329
4330         /* This accesses metadata so needs to be called before runtime shutdown */
4331         print_jit_stats ();
4332
4333 #ifndef MONO_CROSS_COMPILE
4334         mono_runtime_cleanup (domain);
4335 #endif
4336
4337         mono_threadpool_cleanup ();
4338
4339         mono_profiler_shutdown ();
4340
4341         free_jit_tls_data ((MonoJitTlsData *)mono_tls_get_jit_tls ());
4342
4343         mono_icall_cleanup ();
4344
4345         mono_runtime_cleanup_handlers ();
4346
4347 #ifndef MONO_CROSS_COMPILE
4348         mono_domain_free (domain, TRUE);
4349 #endif
4350
4351 #ifdef ENABLE_LLVM
4352         if (mono_use_llvm)
4353                 mono_llvm_cleanup ();
4354 #endif
4355
4356         mono_aot_cleanup ();
4357
4358         mono_trampolines_cleanup ();
4359
4360         mono_unwind_cleanup ();
4361
4362         mono_code_manager_destroy (global_codeman);
4363         g_free (vtable_trampolines);
4364
4365         mini_jit_cleanup ();
4366
4367         mono_tramp_info_cleanup ();
4368
4369         mono_arch_cleanup ();
4370
4371         mono_generic_sharing_cleanup ();
4372
4373         mono_cleanup ();
4374
4375         mono_trace_cleanup ();
4376
4377         mono_counters_dump (MONO_COUNTER_SECTION_MASK | MONO_COUNTER_MONOTONIC, stdout);
4378
4379         if (mono_inject_async_exc_method)
4380                 mono_method_desc_free (mono_inject_async_exc_method);
4381
4382         mono_tls_free_keys ();
4383
4384         mono_os_mutex_destroy (&jit_mutex);
4385
4386         mono_code_manager_cleanup ();
4387
4388 #ifndef HOST_WIN32
4389         mono_w32handle_cleanup ();
4390 #endif
4391 }
4392
4393 void
4394 mono_set_defaults (int verbose_level, guint32 opts)
4395 {
4396         mini_verbose = verbose_level;
4397         mono_set_optimizations (opts);
4398 }
4399
4400 void
4401 mono_disable_optimizations (guint32 opts)
4402 {
4403         default_opt &= ~opts;
4404 }
4405
4406 void
4407 mono_set_optimizations (guint32 opts)
4408 {
4409         default_opt = opts;
4410         default_opt_set = TRUE;
4411 #ifdef MONO_ARCH_GSHAREDVT_SUPPORTED
4412         mono_set_generic_sharing_vt_supported (mono_aot_only || ((default_opt & MONO_OPT_GSHAREDVT) != 0));
4413 #else
4414         if (mono_llvm_only)
4415                 mono_set_generic_sharing_vt_supported (TRUE);
4416 #endif
4417 }
4418
4419 void
4420 mono_set_verbose_level (guint32 level)
4421 {
4422         mini_verbose = level;
4423 }
4424
4425 /**
4426  * mono_get_runtime_build_info:
4427  * The returned string is owned by the caller. The returned string
4428  * format is <code>VERSION (FULL_VERSION BUILD_DATE)</code> and build date is optional.
4429  * \returns the runtime version + build date in string format.
4430  */
4431 char*
4432 mono_get_runtime_build_info (void)
4433 {
4434         if (mono_build_date)
4435                 return g_strdup_printf ("%s (%s %s)", VERSION, FULL_VERSION, mono_build_date);
4436         else
4437                 return g_strdup_printf ("%s (%s)", VERSION, FULL_VERSION);
4438 }
4439
4440 static void
4441 mono_precompile_assembly (MonoAssembly *ass, void *user_data)
4442 {
4443         GHashTable *assemblies = (GHashTable*)user_data;
4444         MonoImage *image = mono_assembly_get_image (ass);
4445         MonoMethod *method, *invoke;
4446         int i, count = 0;
4447
4448         if (g_hash_table_lookup (assemblies, ass))
4449                 return;
4450
4451         g_hash_table_insert (assemblies, ass, ass);
4452
4453         if (mini_verbose > 0)
4454                 printf ("PRECOMPILE: %s.\n", mono_image_get_filename (image));
4455
4456         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_METHOD); ++i) {
4457                 MonoError error;
4458
4459                 method = mono_get_method_checked (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL, NULL, &error);
4460                 if (!method) {
4461                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
4462                         continue;
4463                 }
4464                 if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
4465                         continue;
4466                 if (method->is_generic || mono_class_is_gtd (method->klass))
4467                         continue;
4468
4469                 count++;
4470                 if (mini_verbose > 1) {
4471                         char * desc = mono_method_full_name (method, TRUE);
4472                         g_print ("Compiling %d %s\n", count, desc);
4473                         g_free (desc);
4474                 }
4475                 mono_compile_method_checked (method, &error);
4476                 if (!is_ok (&error)) {
4477                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
4478                         continue;
4479                 }
4480                 if (strcmp (method->name, "Finalize") == 0) {
4481                         invoke = mono_marshal_get_runtime_invoke (method, FALSE);
4482                         mono_compile_method_checked (invoke, &error);
4483                         mono_error_assert_ok (&error);
4484                 }
4485 #ifndef DISABLE_REMOTING
4486                 if (mono_class_is_marshalbyref (method->klass) && mono_method_signature (method)->hasthis) {
4487                         invoke = mono_marshal_get_remoting_invoke_with_check (method);
4488                         mono_compile_method_checked (invoke, &error);
4489                         mono_error_assert_ok (&error);
4490                 }
4491 #endif
4492         }
4493
4494         /* Load and precompile referenced assemblies as well */
4495         for (i = 0; i < mono_image_get_table_rows (image, MONO_TABLE_ASSEMBLYREF); ++i) {
4496                 mono_assembly_load_reference (image, i);
4497                 if (image->references [i])
4498                         mono_precompile_assembly (image->references [i], assemblies);
4499         }
4500 }
4501
4502 void mono_precompile_assemblies ()
4503 {
4504         GHashTable *assemblies = g_hash_table_new (NULL, NULL);
4505
4506         mono_assembly_foreach ((GFunc)mono_precompile_assembly, assemblies);
4507
4508         g_hash_table_destroy (assemblies);
4509 }
4510
4511 /*
4512  * Used by LLVM.
4513  * Have to export this for AOT.
4514  */
4515 void
4516 mono_personality (void)
4517 {
4518         /* Not used */
4519         g_assert_not_reached ();
4520 }
4521
4522
4523 static MonoBreakPolicy
4524 always_insert_breakpoint (MonoMethod *method)
4525 {
4526         return MONO_BREAK_POLICY_ALWAYS;
4527 }
4528
4529 static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
4530
4531 /**
4532  * mono_set_break_policy:
4533  * \param policy_callback the new callback function
4534  *
4535  * Allow embedders to decide whether to actually obey breakpoint instructions
4536  * (both break IL instructions and \c Debugger.Break method calls), for example
4537  * to not allow an app to be aborted by a perfectly valid IL opcode when executing
4538  * untrusted or semi-trusted code.
4539  *
4540  * \p policy_callback will be called every time a break point instruction needs to
4541  * be inserted with the method argument being the method that calls \c Debugger.Break
4542  * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
4543  * if it wants the breakpoint to not be effective in the given method.
4544  * \c MONO_BREAK_POLICY_ALWAYS is the default.
4545  */
4546 void
4547 mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
4548 {
4549         if (policy_callback)
4550                 break_policy_func = policy_callback;
4551         else
4552                 break_policy_func = always_insert_breakpoint;
4553 }
4554
4555 gboolean
4556 mini_should_insert_breakpoint (MonoMethod *method)
4557 {
4558         switch (break_policy_func (method)) {
4559         case MONO_BREAK_POLICY_ALWAYS:
4560                 return TRUE;
4561         case MONO_BREAK_POLICY_NEVER:
4562                 return FALSE;
4563         case MONO_BREAK_POLICY_ON_DBG:
4564                 g_warning ("mdb no longer supported");
4565                 return FALSE;
4566         default:
4567                 g_warning ("Incorrect value returned from break policy callback");
4568                 return FALSE;
4569         }
4570 }
4571
4572 // Custom handlers currently only implemented by Windows.
4573 #ifndef HOST_WIN32
4574 gboolean
4575 mono_runtime_install_custom_handlers (const char *handlers)
4576 {
4577         return FALSE;
4578 }
4579
4580 void
4581 mono_runtime_install_custom_handlers_usage (void)
4582 {
4583         fprintf (stdout,
4584                  "Custom Handlers:\n"
4585                  "   --handlers=HANDLERS            Enable handler support, HANDLERS is a comma\n"
4586                  "                                  separated list of available handlers to install.\n"
4587                  "\n"
4588                  "No handlers supported on current platform.\n");
4589 }
4590 #endif /* HOST_WIN32 */