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