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