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