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