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