Merge pull request #444 from knocte/xbuild_improvements
[mono-project.git] / mono / mini / jit-icalls.c
blob2f75e4301b5e28c9a6077afa56d9ee461dc135e3
1 /*
2 * jit-icalls.c: internal calls used by the JIT
4 * Author:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2002 Ximian, Inc.
9 * Copyright 2003-2011 Novell Inc (http://www.novell.com)
10 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
12 #include <config.h>
13 #include <math.h>
14 #include <limits.h>
15 #ifdef HAVE_ALLOCA_H
16 #include <alloca.h>
17 #endif
19 #include "jit-icalls.h"
21 void*
22 mono_ldftn (MonoMethod *method)
24 gpointer addr;
26 MONO_ARCH_SAVE_REGS;
28 addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
30 return mono_create_ftnptr (mono_domain_get (), addr);
33 static void*
34 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
36 MonoMethod *res;
38 MONO_ARCH_SAVE_REGS;
40 if (obj == NULL)
41 mono_raise_exception (mono_get_exception_null_reference ());
43 res = mono_object_get_virtual_method (obj, method);
45 if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
46 MonoGenericContext context = { NULL, NULL };
48 if (res->klass->generic_class)
49 context.class_inst = res->klass->generic_class->context.class_inst;
50 else if (res->klass->generic_container)
51 context.class_inst = res->klass->generic_container->context.class_inst;
52 context.method_inst = mono_method_get_context (method)->method_inst;
54 res = mono_class_inflate_generic_method (res, &context);
57 /* An rgctx wrapper is added by the trampolines no need to do it here */
59 return mono_ldftn (res);
62 void*
63 mono_ldvirtfn (MonoObject *obj, MonoMethod *method)
65 return ldvirtfn_internal (obj, method, FALSE);
68 void*
69 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method)
71 return ldvirtfn_internal (obj, method, TRUE);
74 void
75 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
77 MONO_ARCH_SAVE_REGS;
79 if (!array)
80 mono_raise_exception (mono_get_exception_null_reference ());
81 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
82 mono_raise_exception (mono_get_exception_array_type_mismatch ());
85 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
87 gint64
88 mono_llmult (gint64 a, gint64 b)
90 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
91 return a * b;
94 guint64
95 mono_llmult_ovf_un (guint64 a, guint64 b)
97 guint32 al = a;
98 guint32 ah = a >> 32;
99 guint32 bl = b;
100 guint32 bh = b >> 32;
101 guint64 res, t1;
103 MONO_ARCH_SAVE_REGS;
105 // fixme: this is incredible slow
107 if (ah && bh)
108 goto raise_exception;
110 res = (guint64)al * (guint64)bl;
112 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
114 if (t1 > 0xffffffff)
115 goto raise_exception;
117 res += ((guint64)t1) << 32;
119 return res;
121 raise_exception:
122 mono_raise_exception (mono_get_exception_overflow ());
123 return 0;
126 guint64
127 mono_llmult_ovf (gint64 a, gint64 b)
129 guint32 al = a;
130 gint32 ah = a >> 32;
131 guint32 bl = b;
132 gint32 bh = b >> 32;
134 Use Karatsuba algorithm where:
135 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
136 where Ah is the "high half" (most significant 32 bits) of a and
137 where Al is the "low half" (least significant 32 bits) of a and
138 where Bh is the "high half" of b and Bl is the "low half" and
139 where R is the Radix or "size of the half" (in our case 32 bits)
141 Note, for the product of two 64 bit numbers to fit into a 64
142 result, ah and/or bh must be 0. This will save us from doing
143 the AhBh term at all.
145 Also note that we refactor so that we don't overflow 64 bits with
146 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
149 gint64 res, t1;
150 gint32 sign;
152 MONO_ARCH_SAVE_REGS;
154 /* need to work with absoulte values, so find out what the
155 resulting sign will be and convert any negative numbers
156 from two's complement
158 sign = ah ^ bh;
159 if (ah < 0) {
160 if (((guint32)ah == 0x80000000) && (al == 0)) {
161 /* This has no two's complement */
162 if (b == 0)
163 return 0;
164 else if (b == 1)
165 return a;
166 else
167 goto raise_exception;
170 /* flip the bits and add 1 */
171 ah ^= ~0;
172 if (al == 0)
173 ah += 1;
174 else {
175 al ^= ~0;
176 al +=1;
180 if (bh < 0) {
181 if (((guint32)bh == 0x80000000) && (bl == 0)) {
182 /* This has no two's complement */
183 if (a == 0)
184 return 0;
185 else if (a == 1)
186 return b;
187 else
188 goto raise_exception;
191 /* flip the bits and add 1 */
192 bh ^= ~0;
193 if (bl == 0)
194 bh += 1;
195 else {
196 bl ^= ~0;
197 bl +=1;
201 /* we overflow for sure if both upper halves are greater
202 than zero because we would need to shift their
203 product 64 bits to the left and that will not fit
204 in a 64 bit result */
205 if (ah && bh)
206 goto raise_exception;
207 if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000)
208 goto raise_exception;
210 /* do the AlBl term first */
211 t1 = (gint64)al * (gint64)bl;
213 res = t1;
215 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
216 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
217 /* check for overflow */
218 t1 <<= 32;
219 if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
220 goto raise_exception;
222 res += t1;
224 if (res < 0)
225 goto raise_exception;
227 if (sign < 0)
228 return -res;
229 else
230 return res;
232 raise_exception:
233 mono_raise_exception (mono_get_exception_overflow ());
234 return 0;
237 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
239 gint32
240 mono_idiv (gint32 a, gint32 b)
242 MONO_ARCH_SAVE_REGS;
244 #ifdef MONO_ARCH_NEED_DIV_CHECK
245 if (!b)
246 mono_raise_exception (mono_get_exception_divide_by_zero ());
247 else if (b == -1 && a == (0x80000000))
248 mono_raise_exception (mono_get_exception_overflow ());
249 #endif
250 return a / b;
253 guint32
254 mono_idiv_un (guint32 a, guint32 b)
256 MONO_ARCH_SAVE_REGS;
258 #ifdef MONO_ARCH_NEED_DIV_CHECK
259 if (!b)
260 mono_raise_exception (mono_get_exception_divide_by_zero ());
261 #endif
262 return a / b;
265 gint32
266 mono_irem (gint32 a, gint32 b)
268 MONO_ARCH_SAVE_REGS;
270 #ifdef MONO_ARCH_NEED_DIV_CHECK
271 if (!b)
272 mono_raise_exception (mono_get_exception_divide_by_zero ());
273 else if (b == -1 && a == (0x80000000))
274 mono_raise_exception (mono_get_exception_overflow ());
275 #endif
277 return a % b;
280 guint32
281 mono_irem_un (guint32 a, guint32 b)
283 MONO_ARCH_SAVE_REGS;
285 #ifdef MONO_ARCH_NEED_DIV_CHECK
286 if (!b)
287 mono_raise_exception (mono_get_exception_divide_by_zero ());
288 #endif
289 return a % b;
292 #endif
294 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
296 gint32
297 mono_imul (gint32 a, gint32 b)
299 MONO_ARCH_SAVE_REGS;
301 return a * b;
304 gint32
305 mono_imul_ovf (gint32 a, gint32 b)
307 gint64 res;
309 MONO_ARCH_SAVE_REGS;
311 res = (gint64)a * (gint64)b;
313 if ((res > 0x7fffffffL) || (res < -2147483648LL))
314 mono_raise_exception (mono_get_exception_overflow ());
316 return res;
319 gint32
320 mono_imul_ovf_un (guint32 a, guint32 b)
322 guint64 res;
324 MONO_ARCH_SAVE_REGS;
326 res = (guint64)a * (guint64)b;
328 if ((res >> 32))
329 mono_raise_exception (mono_get_exception_overflow ());
331 return res;
333 #endif
335 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
336 double
337 mono_fdiv (double a, double b)
339 MONO_ARCH_SAVE_REGS;
341 return a / b;
343 #endif
345 gint64
346 mono_lldiv (gint64 a, gint64 b)
348 MONO_ARCH_SAVE_REGS;
350 #ifdef MONO_ARCH_NEED_DIV_CHECK
351 if (!b)
352 mono_raise_exception (mono_get_exception_divide_by_zero ());
353 else if (b == -1 && a == (-9223372036854775807LL - 1LL))
354 mono_raise_exception (mono_get_exception_arithmetic ());
355 #endif
356 return a / b;
359 gint64
360 mono_llrem (gint64 a, gint64 b)
362 MONO_ARCH_SAVE_REGS;
364 #ifdef MONO_ARCH_NEED_DIV_CHECK
365 if (!b)
366 mono_raise_exception (mono_get_exception_divide_by_zero ());
367 else if (b == -1 && a == (-9223372036854775807LL - 1LL))
368 mono_raise_exception (mono_get_exception_arithmetic ());
369 #endif
370 return a % b;
373 guint64
374 mono_lldiv_un (guint64 a, guint64 b)
376 MONO_ARCH_SAVE_REGS;
378 #ifdef MONO_ARCH_NEED_DIV_CHECK
379 if (!b)
380 mono_raise_exception (mono_get_exception_divide_by_zero ());
381 #endif
382 return a / b;
385 guint64
386 mono_llrem_un (guint64 a, guint64 b)
388 MONO_ARCH_SAVE_REGS;
390 #ifdef MONO_ARCH_NEED_DIV_CHECK
391 if (!b)
392 mono_raise_exception (mono_get_exception_divide_by_zero ());
393 #endif
394 return a % b;
397 #endif
399 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
401 guint64
402 mono_lshl (guint64 a, gint32 shamt)
404 guint64 res;
406 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
407 res = a << shamt;
409 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
411 return res;
414 guint64
415 mono_lshr_un (guint64 a, gint32 shamt)
417 guint64 res;
419 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
420 res = a >> shamt;
422 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
424 return res;
427 gint64
428 mono_lshr (gint64 a, gint32 shamt)
430 gint64 res;
432 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
433 res = a >> shamt;
435 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
437 return res;
440 #endif
442 #ifdef MONO_ARCH_SOFT_FLOAT
444 double
445 mono_fsub (double a, double b)
447 return a - b;
450 double
451 mono_fadd (double a, double b)
453 return a + b;
456 double
457 mono_fmul (double a, double b)
459 return a * b;
462 double
463 mono_fneg (double a)
465 return -a;
468 double
469 mono_fconv_r4 (double a)
471 return (float)a;
474 double
475 mono_conv_to_r8 (int a)
477 return (double)a;
480 double
481 mono_conv_to_r4 (int a)
483 return (double)(float)a;
486 gint8
487 mono_fconv_i1 (double a)
489 return (gint8)a;
492 gint16
493 mono_fconv_i2 (double a)
495 return (gint16)a;
498 gint32
499 mono_fconv_i4 (double a)
501 return (gint32)a;
504 guint8
505 mono_fconv_u1 (double a)
507 return (guint8)a;
510 guint16
511 mono_fconv_u2 (double a)
513 return (guint16)a;
516 gboolean
517 mono_fcmp_eq (double a, double b)
519 return a == b;
522 gboolean
523 mono_fcmp_ge (double a, double b)
525 return a >= b;
528 gboolean
529 mono_fcmp_gt (double a, double b)
531 return a > b;
534 gboolean
535 mono_fcmp_le (double a, double b)
537 return a <= b;
540 gboolean
541 mono_fcmp_lt (double a, double b)
543 return a < b;
546 gboolean
547 mono_fcmp_ne_un (double a, double b)
549 return isunordered (a, b) || a != b;
552 gboolean
553 mono_fcmp_ge_un (double a, double b)
555 return isunordered (a, b) || a >= b;
558 gboolean
559 mono_fcmp_gt_un (double a, double b)
561 return isunordered (a, b) || a > b;
564 gboolean
565 mono_fcmp_le_un (double a, double b)
567 return isunordered (a, b) || a <= b;
570 gboolean
571 mono_fcmp_lt_un (double a, double b)
573 return isunordered (a, b) || a < b;
576 gboolean
577 mono_fceq (double a, double b)
579 return a == b;
582 gboolean
583 mono_fcgt (double a, double b)
585 return a > b;
588 gboolean
589 mono_fcgt_un (double a, double b)
591 return isunordered (a, b) || a > b;
594 gboolean
595 mono_fclt (double a, double b)
597 return a < b;
600 gboolean
601 mono_fclt_un (double a, double b)
603 return isunordered (a, b) || a < b;
606 gboolean
607 mono_isfinite (double a)
609 #ifdef HAVE_ISFINITE
610 return isfinite (a);
611 #else
612 g_assert_not_reached ();
613 return TRUE;
614 #endif
617 double
618 mono_fload_r4 (float *ptr)
620 return *ptr;
623 void
624 mono_fstore_r4 (double val, float *ptr)
626 *ptr = (float)val;
629 /* returns the integer bitpattern that is passed in the regs or stack */
630 guint32
631 mono_fload_r4_arg (double val)
633 float v = (float)val;
634 return *(guint32*)&v;
637 #endif
639 MonoArray *
640 mono_array_new_va (MonoMethod *cm, ...)
642 MonoDomain *domain = mono_domain_get ();
643 va_list ap;
644 uintptr_t *lengths;
645 intptr_t *lower_bounds;
646 int pcount;
647 int rank;
648 int i, d;
650 MONO_ARCH_SAVE_REGS;
652 pcount = mono_method_signature (cm)->param_count;
653 rank = cm->klass->rank;
655 va_start (ap, cm);
657 lengths = alloca (sizeof (uintptr_t) * pcount);
658 for (i = 0; i < pcount; ++i)
659 lengths [i] = d = va_arg(ap, int);
661 if (rank == pcount) {
662 /* Only lengths provided. */
663 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
664 lower_bounds = alloca (sizeof (intptr_t) * rank);
665 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
666 } else {
667 lower_bounds = NULL;
669 } else {
670 g_assert (pcount == (rank * 2));
671 /* lower bounds are first. */
672 lower_bounds = (intptr_t*)lengths;
673 lengths += rank;
675 va_end(ap);
677 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
680 /* Specialized version of mono_array_new_va () which avoids varargs */
681 MonoArray *
682 mono_array_new_1 (MonoMethod *cm, guint32 length)
684 MonoDomain *domain = mono_domain_get ();
685 uintptr_t lengths [1];
686 intptr_t *lower_bounds;
687 int pcount;
688 int rank;
690 MONO_ARCH_SAVE_REGS;
692 pcount = mono_method_signature (cm)->param_count;
693 rank = cm->klass->rank;
695 lengths [0] = length;
697 g_assert (rank == pcount);
699 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
700 lower_bounds = alloca (sizeof (intptr_t) * rank);
701 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
702 } else {
703 lower_bounds = NULL;
706 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
709 MonoArray *
710 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
712 MonoDomain *domain = mono_domain_get ();
713 uintptr_t lengths [2];
714 intptr_t *lower_bounds;
715 int pcount;
716 int rank;
718 MONO_ARCH_SAVE_REGS;
720 pcount = mono_method_signature (cm)->param_count;
721 rank = cm->klass->rank;
723 lengths [0] = length1;
724 lengths [1] = length2;
726 g_assert (rank == pcount);
728 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
729 lower_bounds = alloca (sizeof (intptr_t) * rank);
730 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
731 } else {
732 lower_bounds = NULL;
735 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
738 MonoArray *
739 mono_array_new_3 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3)
741 MonoDomain *domain = mono_domain_get ();
742 uintptr_t lengths [3];
743 intptr_t *lower_bounds;
744 int pcount;
745 int rank;
747 MONO_ARCH_SAVE_REGS;
749 pcount = mono_method_signature (cm)->param_count;
750 rank = cm->klass->rank;
752 lengths [0] = length1;
753 lengths [1] = length2;
754 lengths [2] = length3;
756 g_assert (rank == pcount);
758 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
759 lower_bounds = alloca (sizeof (intptr_t) * rank);
760 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
761 } else {
762 lower_bounds = NULL;
765 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
768 gpointer
769 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
771 MonoVTable *vtable;
772 gpointer addr;
774 MONO_ARCH_SAVE_REGS;
776 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
778 mono_class_init (field->parent);
780 vtable = mono_class_vtable_full (domain, field->parent, TRUE);
781 if (!vtable->initialized)
782 mono_runtime_class_init (vtable);
784 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
786 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
787 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
788 else
789 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
791 return addr;
794 gpointer
795 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
797 MonoClass *handle_class;
798 gpointer res;
800 MONO_ARCH_SAVE_REGS;
801 res = mono_ldtoken (image, token, &handle_class, context);
802 mono_class_init (handle_class);
804 return res;
807 gpointer
808 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
810 MonoMethodSignature *sig = mono_method_signature (method);
811 MonoGenericContext *generic_context;
813 if (sig->is_inflated) {
814 generic_context = mono_method_get_context (method);
815 } else {
816 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
817 g_assert (generic_container);
818 generic_context = &generic_container->context;
821 return mono_ldtoken_wrapper (image, token, generic_context);
824 guint64
825 mono_fconv_u8 (double v)
827 return (guint64)v;
830 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
831 gint64
832 mono_fconv_i8 (double v)
834 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
835 return (gint64)v;
837 #endif
839 guint32
840 mono_fconv_u4 (double v)
842 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
843 return (guint32)v;
846 #ifndef HAVE_TRUNC
847 /* Solaris doesn't have trunc */
848 #ifdef HAVE_AINTL
849 extern long double aintl (long double);
850 #define trunc aintl
851 #else
852 /* FIXME: This means we will never throw overflow exceptions */
853 #define trunc(v) res
854 #endif
855 #endif /* HAVE_TRUNC */
857 gint64
858 mono_fconv_ovf_i8 (double v)
860 gint64 res;
862 MONO_ARCH_SAVE_REGS;
864 res = (gint64)v;
866 if (isnan(v) || trunc (v) != res) {
867 mono_raise_exception (mono_get_exception_overflow ());
869 return res;
872 guint64
873 mono_fconv_ovf_u8 (double v)
875 guint64 res;
877 MONO_ARCH_SAVE_REGS;
879 * The soft-float implementation of some ARM devices have a buggy guin64 to double
880 * conversion that it looses precision even when the integer if fully representable
881 * as a double.
883 * This was found with 4294967295ull, converting to double and back looses one bit of precision.
885 * To work around this issue we test for value boundaries instead.
887 #if defined(__arm__) && MONO_ARCH_SOFT_FLOAT
888 if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
889 mono_raise_exception (mono_get_exception_overflow ());
891 res = (guint64)v;
892 #else
893 res = (guint64)v;
894 if (isnan(v) || trunc (v) != res) {
895 mono_raise_exception (mono_get_exception_overflow ());
897 #endif
898 return res;
901 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
902 double
903 mono_lconv_to_r8 (gint64 a)
905 return (double)a;
907 #endif
909 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
910 float
911 mono_lconv_to_r4 (gint64 a)
913 return (float)a;
915 #endif
917 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
918 double
919 mono_conv_to_r8_un (guint32 a)
921 return (double)a;
923 #endif
925 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
926 double
927 mono_lconv_to_r8_un (guint64 a)
929 return (double)a;
931 #endif
933 #if defined(__native_client_codegen__) || defined(__native_client__)
934 /* When we cross-compile to Native Client we can't directly embed calls */
935 /* to the math library on the host. This will use the fmod on the target*/
936 double
937 mono_fmod(double a, double b)
939 return fmod(a, b);
941 #endif
943 gpointer
944 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
946 MonoMethod *vmethod;
947 gpointer addr;
948 MonoGenericContext *context = mono_method_get_context (method);
950 mono_jit_stats.generic_virtual_invocations++;
952 if (obj == NULL)
953 mono_raise_exception (mono_get_exception_null_reference ());
954 vmethod = mono_object_get_virtual_method (obj, method);
955 g_assert (!vmethod->klass->generic_container);
956 g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
957 g_assert (!context->method_inst || !context->method_inst->is_open);
959 addr = mono_compile_method (vmethod);
961 if (mono_method_needs_static_rgctx_invoke (vmethod, FALSE))
962 addr = mono_create_static_rgctx_trampoline (vmethod, addr);
964 /* Since this is a virtual call, have to unbox vtypes */
965 if (obj->vtable->klass->valuetype)
966 *this_arg = mono_object_unbox (obj);
967 else
968 *this_arg = obj;
970 return addr;
973 MonoString*
974 mono_helper_ldstr (MonoImage *image, guint32 idx)
976 return mono_ldstr (mono_domain_get (), image, idx);
979 MonoString*
980 mono_helper_ldstr_mscorlib (guint32 idx)
982 return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
985 MonoObject*
986 mono_helper_newobj_mscorlib (guint32 idx)
988 MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx);
990 g_assert (klass);
992 return mono_object_new (mono_domain_get (), klass);
996 * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
997 * in generated code. So instead we emit a call to this function and place a gdb
998 * breakpoint here.
1000 void
1001 mono_break (void)
1005 MonoException *
1006 mono_create_corlib_exception_0 (guint32 token)
1008 return mono_exception_from_token (mono_defaults.corlib, token);
1011 MonoException *
1012 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
1014 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
1017 MonoException *
1018 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
1020 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
1023 MonoObject*
1024 mono_object_castclass (MonoObject *obj, MonoClass *klass)
1026 MonoJitTlsData *jit_tls = NULL;
1028 if (mini_get_debug_options ()->better_cast_details) {
1029 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1030 jit_tls->class_cast_from = NULL;
1033 if (!obj)
1034 return NULL;
1036 if (mono_object_isinst (obj, klass))
1037 return obj;
1039 if (mini_get_debug_options ()->better_cast_details) {
1040 jit_tls->class_cast_from = obj->vtable->klass;
1041 jit_tls->class_cast_to = klass;
1044 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
1045 "System", "InvalidCastException"));
1047 return NULL;
1050 MonoObject*
1051 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1053 MonoJitTlsData *jit_tls = NULL;
1054 gpointer cached_vtable, obj_vtable;
1056 if (mini_get_debug_options ()->better_cast_details) {
1057 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1058 jit_tls->class_cast_from = NULL;
1061 if (!obj)
1062 return NULL;
1064 cached_vtable = *cache;
1065 obj_vtable = obj->vtable;
1067 if (cached_vtable == obj_vtable)
1068 return obj;
1070 if (mono_object_isinst (obj, klass)) {
1071 *cache = obj_vtable;
1072 return obj;
1075 if (mini_get_debug_options ()->better_cast_details) {
1076 jit_tls->class_cast_from = obj->vtable->klass;
1077 jit_tls->class_cast_to = klass;
1080 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
1081 "System", "InvalidCastException"));
1083 return NULL;
1086 MonoObject*
1087 mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1089 size_t cached_vtable, obj_vtable;
1091 if (!obj)
1092 return NULL;
1094 cached_vtable = (size_t)*cache;
1095 obj_vtable = (size_t)obj->vtable;
1097 if ((cached_vtable & ~0x1) == obj_vtable) {
1098 return (cached_vtable & 0x1) ? NULL : obj;
1101 if (mono_object_isinst (obj, klass)) {
1102 *cache = (gpointer)obj_vtable;
1103 return obj;
1104 } else {
1105 /*negative cache*/
1106 *cache = (gpointer)(obj_vtable | 0x1);
1107 return NULL;
1111 gpointer
1112 mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpointer func)
1114 MonoMarshalSpec **mspecs;
1115 MonoMethodPInvoke piinfo;
1116 MonoMethod *m;
1118 mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
1119 memset (&piinfo, 0, sizeof (piinfo));
1121 m = mono_marshal_get_native_func_wrapper (image, sig, &piinfo, mspecs, func);
1123 return mono_compile_method (m);