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