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