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