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