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