3 * internal calls used by the JIT
6 * Dietmar Maurer (dietmar@ximian.com)
7 * Paolo Molaro (lupus@ximian.com)
9 * (C) 2002 Ximian, Inc.
10 * Copyright 2003-2011 Novell Inc (http://www.novell.com)
11 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
12 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
21 #include "jit-icalls.h"
22 #include "aot-runtime.h"
23 #include "mini-runtime.h"
24 #include <mono/utils/mono-error-internals.h>
25 #include <mono/metadata/exception-internals.h>
26 #include <mono/metadata/threads-types.h>
27 #include <mono/metadata/reflection-internals.h>
28 #include <mono/utils/unlocked.h>
29 #include <mono/utils/mono-math.h>
30 #include "mono/utils/mono-tls-inline.h"
33 #include "mini-llvm-cpp.h"
37 mono_ldftn (MonoMethod
*method
)
43 // FIXME: No error handling
45 addr
= mono_compile_method_checked (method
, error
);
46 mono_error_assert_ok (error
);
49 if (mono_method_needs_static_rgctx_invoke (method
, FALSE
))
50 /* The caller doesn't pass it */
51 g_assert_not_reached ();
53 addr
= mini_add_method_trampoline (method
, addr
, mono_method_needs_static_rgctx_invoke (method
, FALSE
), FALSE
);
57 /* if we need the address of a native-to-managed wrapper, just compile it now, trampoline needs thread local
58 * variables that won't be there if we run on a thread that's not attached yet. */
59 if (method
->wrapper_type
== MONO_WRAPPER_NATIVE_TO_MANAGED
)
60 addr
= mono_compile_method_checked (method
, error
);
62 addr
= mono_create_jump_trampoline (mono_domain_get (), method
, FALSE
, error
);
64 mono_error_set_pending_exception (error
);
67 return mono_create_ftnptr (mono_domain_get (), addr
);
71 ldvirtfn_internal (MonoObject
*obj
, MonoMethod
*method
, gboolean gshared
)
78 mono_error_set_null_reference (error
);
79 mono_error_set_pending_exception (error
);
83 res
= mono_object_get_virtual_method_internal (obj
, method
);
85 if (gshared
&& method
->is_inflated
&& mono_method_get_context (method
)->method_inst
) {
86 MonoGenericContext context
= { NULL
, NULL
};
88 if (mono_class_is_ginst (res
->klass
))
89 context
.class_inst
= mono_class_get_generic_class (res
->klass
)->context
.class_inst
;
90 else if (mono_class_is_gtd (res
->klass
))
91 context
.class_inst
= mono_class_get_generic_container (res
->klass
)->context
.class_inst
;
92 context
.method_inst
= mono_method_get_context (method
)->method_inst
;
94 res
= mono_class_inflate_generic_method_checked (res
, &context
, error
);
96 mono_error_set_pending_exception (error
);
101 /* An rgctx wrapper is added by the trampolines no need to do it here */
102 gboolean need_unbox
= m_class_is_valuetype (res
->klass
) && !m_class_is_valuetype (method
->klass
);
105 * We can't return a jump trampoline here, because the trampoline code
106 * can't determine whenever to add an unbox trampoline (ldvirtftn) or
107 * not (ldftn). So compile the method here.
109 addr
= mono_compile_method_checked (res
, error
);
110 if (!is_ok (error
)) {
111 mono_error_set_pending_exception (error
);
115 if (mono_llvm_only
&& mono_method_needs_static_rgctx_invoke (res
, FALSE
))
117 g_assert_not_reached ();
119 addr
= mini_add_method_trampoline (res
, addr
, mono_method_needs_static_rgctx_invoke (res
, FALSE
), TRUE
);
121 addr
= mono_ldftn (res
);
127 mono_ldvirtfn (MonoObject
*obj
, MonoMethod
*method
)
129 return ldvirtfn_internal (obj
, method
, FALSE
);
133 mono_ldvirtfn_gshared (MonoObject
*obj
, MonoMethod
*method
)
135 return ldvirtfn_internal (obj
, method
, TRUE
);
139 mono_helper_stelem_ref_check (MonoArray
*array
, MonoObject
*val
)
143 mono_error_set_null_reference (error
);
144 mono_error_set_pending_exception (error
);
147 if (val
&& !mono_object_isinst_checked (val
, m_class_get_element_class (mono_object_class (array
)), error
)) {
148 if (mono_error_set_pending_exception (error
))
150 mono_set_pending_exception (mono_get_exception_array_type_mismatch ());
155 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
158 mono_llmult (gint64 a
, gint64 b
)
164 mono_llmult_ovf_un (guint64 a
, guint64 b
)
167 guint32 ah
= a
>> 32;
169 guint32 bh
= b
>> 32;
172 // fixme: this is incredible slow
175 goto raise_exception
;
177 res
= (guint64
)al
* (guint64
)bl
;
179 t1
= (guint64
)ah
* (guint64
)bl
+ (guint64
)al
* (guint64
)bh
;
182 goto raise_exception
;
184 res
+= ((guint64
)t1
) << 32;
191 mono_error_set_overflow (error
);
192 mono_error_set_pending_exception (error
);
198 mono_llmult_ovf (gint64 a
, gint64 b
)
205 Use Karatsuba algorithm where:
206 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
207 where Ah is the "high half" (most significant 32 bits) of a and
208 where Al is the "low half" (least significant 32 bits) of a and
209 where Bh is the "high half" of b and Bl is the "low half" and
210 where R is the Radix or "size of the half" (in our case 32 bits)
212 Note, for the product of two 64 bit numbers to fit into a 64
213 result, ah and/or bh must be 0. This will save us from doing
214 the AhBh term at all.
216 Also note that we refactor so that we don't overflow 64 bits with
217 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
223 /* need to work with absoulte values, so find out what the
224 resulting sign will be and convert any negative numbers
225 from two's complement
229 if (((guint32
)ah
== 0x80000000) && (al
== 0)) {
230 /* This has no two's complement */
236 goto raise_exception
;
239 /* flip the bits and add 1 */
250 if (((guint32
)bh
== 0x80000000) && (bl
== 0)) {
251 /* This has no two's complement */
257 goto raise_exception
;
260 /* flip the bits and add 1 */
270 /* we overflow for sure if both upper halves are greater
271 than zero because we would need to shift their
272 product 64 bits to the left and that will not fit
273 in a 64 bit result */
275 goto raise_exception
;
276 if ((gint64
)((gint64
)ah
* (gint64
)bl
) > (gint64
)0x80000000 || (gint64
)((gint64
)al
* (gint64
)bh
) > (gint64
)0x80000000)
277 goto raise_exception
;
279 /* do the AlBl term first */
280 t1
= (gint64
)al
* (gint64
)bl
;
284 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
285 t1
+= (gint64
)(ah
- al
) * (gint64
)(bl
- bh
);
286 /* check for overflow */
288 if (t1
> (0x7FFFFFFFFFFFFFFFLL
- res
))
289 goto raise_exception
;
294 goto raise_exception
;
304 mono_error_set_overflow (error
);
305 mono_error_set_pending_exception (error
);
311 mono_lldiv (gint64 a
, gint64 b
)
313 #ifdef MONO_ARCH_NEED_DIV_CHECK
316 mono_error_set_divide_by_zero (error
);
317 mono_error_set_pending_exception (error
);
320 else if (b
== -1 && a
== (-9223372036854775807LL - 1LL)) {
322 mono_error_set_overflow (error
);
323 mono_error_set_pending_exception (error
);
331 mono_llrem (gint64 a
, gint64 b
)
333 #ifdef MONO_ARCH_NEED_DIV_CHECK
336 mono_error_set_divide_by_zero (error
);
337 mono_error_set_pending_exception (error
);
340 else if (b
== -1 && a
== (-9223372036854775807LL - 1LL)) {
342 mono_error_set_overflow (error
);
343 mono_error_set_pending_exception (error
);
351 mono_lldiv_un (guint64 a
, guint64 b
)
353 #ifdef MONO_ARCH_NEED_DIV_CHECK
356 mono_error_set_divide_by_zero (error
);
357 mono_error_set_pending_exception (error
);
365 mono_llrem_un (guint64 a
, guint64 b
)
367 #ifdef MONO_ARCH_NEED_DIV_CHECK
370 mono_error_set_divide_by_zero (error
);
371 mono_error_set_pending_exception (error
);
380 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
383 mono_lshl (guint64 a
, gint32 shamt
)
385 const guint64 res
= a
<< (shamt
& 0x7f);
387 /*printf ("TESTL %" PRId64 " << %d = %" PRId64 "\n", a, shamt, (guint64)res);*/
393 mono_lshr_un (guint64 a
, gint32 shamt
)
395 const guint64 res
= a
>> (shamt
& 0x7f);
397 /*printf ("TESTR %" PRId64 " >> %d = %" PRId64 "\n", a, shamt, (guint64)res);*/
403 mono_lshr (gint64 a
, gint32 shamt
)
405 const gint64 res
= a
>> (shamt
& 0x7f);
407 /*printf ("TESTR %" PRId64 " >> %d = %" PRId64 "\n", a, shamt, (guint64)res);*/
414 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
417 mono_idiv (gint32 a
, gint32 b
)
419 #ifdef MONO_ARCH_NEED_DIV_CHECK
422 mono_error_set_divide_by_zero (error
);
423 mono_error_set_pending_exception (error
);
426 else if (b
== -1 && a
== (0x80000000)) {
428 mono_error_set_overflow (error
);
429 mono_error_set_pending_exception (error
);
437 mono_idiv_un (guint32 a
, guint32 b
)
439 #ifdef MONO_ARCH_NEED_DIV_CHECK
442 mono_error_set_divide_by_zero (error
);
443 mono_error_set_pending_exception (error
);
451 mono_irem (gint32 a
, gint32 b
)
453 #ifdef MONO_ARCH_NEED_DIV_CHECK
456 mono_error_set_divide_by_zero (error
);
457 mono_error_set_pending_exception (error
);
460 else if (b
== -1 && a
== (0x80000000)) {
462 mono_error_set_overflow (error
);
463 mono_error_set_pending_exception (error
);
471 mono_irem_un (guint32 a
, guint32 b
)
473 #ifdef MONO_ARCH_NEED_DIV_CHECK
476 mono_error_set_divide_by_zero (error
);
477 mono_error_set_pending_exception (error
);
486 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
489 mono_imul (gint32 a
, gint32 b
)
495 mono_imul_ovf (gint32 a
, gint32 b
)
497 const gint64 res
= (gint64
)a
* (gint64
)b
;
499 if ((res
> 0x7fffffffL
) || (res
< -2147483648LL)) {
501 mono_error_set_overflow (error
);
502 mono_error_set_pending_exception (error
);
510 mono_imul_ovf_un (guint32 a
, guint32 b
)
512 const guint64 res
= (guint64
)a
* (guint64
)b
;
516 mono_error_set_overflow (error
);
517 mono_error_set_pending_exception (error
);
525 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
527 mono_fdiv (double a
, double b
)
533 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
536 mono_fsub (double a
, double b
)
542 mono_fadd (double a
, double b
)
548 mono_fmul (double a
, double b
)
560 mono_fconv_r4 (double a
)
566 mono_conv_to_r8 (int a
)
572 mono_conv_to_r4 (int a
)
574 return (double)(float)a
;
578 mono_fconv_i1 (double a
)
584 mono_fconv_i2 (double a
)
590 mono_fconv_i4 (double a
)
596 mono_fconv_u1 (double a
)
602 mono_fconv_u2 (double a
)
608 mono_fcmp_eq (double a
, double b
)
614 mono_fcmp_ge (double a
, double b
)
620 mono_fcmp_gt (double a
, double b
)
626 mono_fcmp_le (double a
, double b
)
632 mono_fcmp_lt (double a
, double b
)
638 mono_fcmp_ne_un (double a
, double b
)
640 return isunordered (a
, b
) || a
!= b
;
644 mono_fcmp_ge_un (double a
, double b
)
646 return isunordered (a
, b
) || a
>= b
;
650 mono_fcmp_gt_un (double a
, double b
)
652 return isunordered (a
, b
) || a
> b
;
656 mono_fcmp_le_un (double a
, double b
)
658 return isunordered (a
, b
) || a
<= b
;
662 mono_fcmp_lt_un (double a
, double b
)
664 return isunordered (a
, b
) || a
< b
;
668 mono_fceq (double a
, double b
)
674 mono_fcgt (double a
, double b
)
680 mono_fcgt_un (double a
, double b
)
682 return isunordered (a
, b
) || a
> b
;
686 mono_fclt (double a
, double b
)
692 mono_fclt_un (double a
, double b
)
694 return isunordered (a
, b
) || a
< b
;
698 mono_fload_r4 (float *ptr
)
704 mono_fstore_r4 (double val
, float *ptr
)
709 /* returns the integer bitpattern that is passed in the regs or stack */
711 mono_fload_r4_arg (double val
)
713 float v
= (float)val
;
714 return *(guint32
*)&v
;
720 mono_array_new_n_icall (MonoMethod
*cm
, gint32 pcount
, intptr_t *params
)
726 intptr_t *lower_bounds
= NULL
;
728 const int pcount_sig
= mono_method_signature_internal (cm
)->param_count
;
729 const int rank
= m_class_get_rank (cm
->klass
);
730 g_assert (pcount
== pcount_sig
);
731 g_assert (rank
== pcount
|| rank
* 2 == pcount
);
733 uintptr_t *lengths
= (uintptr_t*)params
;
735 if (rank
== pcount
) {
736 /* Only lengths provided. */
737 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
) {
738 lower_bounds
= g_newa (intptr_t, rank
);
739 memset (lower_bounds
, 0, sizeof (intptr_t) * rank
);
742 g_assert (pcount
== (rank
* 2));
743 /* lower bounds are first. */
744 lower_bounds
= params
;
748 MonoArray
*arr
= mono_array_new_full_checked (mono_domain_get (),
749 cm
->klass
, lengths
, lower_bounds
, error
);
751 return mono_error_set_pending_exception (error
) ? NULL
: arr
;
755 mono_array_new_n (MonoMethod
*cm
, int n
, uintptr_t lengths
[], intptr_t lower_bounds
[])
758 intptr_t *plower_bounds
= NULL
;
759 const int pcount
= mono_method_signature_internal (cm
)->param_count
;
760 const int rank
= m_class_get_rank (cm
->klass
);
762 g_assert (rank
== pcount
);
763 g_assert (rank
== n
);
765 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
)
766 plower_bounds
= lower_bounds
;
768 MonoArray
*arr
= mono_array_new_full_checked (mono_domain_get (),
769 cm
->klass
, lengths
, plower_bounds
, error
);
771 return mono_error_set_pending_exception (error
) ? NULL
: arr
;
774 /* Specialized version of mono_array_new_va () which avoids varargs */
776 mono_array_new_1 (MonoMethod
*cm
, guint32 length
)
778 uintptr_t lengths
[ ] = {length
};
779 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
780 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
784 mono_array_new_2 (MonoMethod
*cm
, guint32 length1
, guint32 length2
)
786 uintptr_t lengths
[ ] = {length1
, length2
};
787 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
788 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
792 mono_array_new_3 (MonoMethod
*cm
, guint32 length1
, guint32 length2
, guint32 length3
)
794 uintptr_t lengths
[ ] = {length1
, length2
, length3
};
795 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
796 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
800 mono_array_new_4 (MonoMethod
*cm
, guint32 length1
, guint32 length2
, guint32 length3
, guint32 length4
)
802 uintptr_t lengths
[ ] = {length1
, length2
, length3
, length4
};
803 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
804 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
808 mono_class_static_field_address (MonoDomain
*domain
, MonoClassField
*field
)
814 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
816 mono_class_init_internal (field
->parent
);
818 vtable
= mono_class_vtable_checked (domain
, field
->parent
, error
);
819 if (!is_ok (error
)) {
820 mono_error_set_pending_exception (error
);
823 if (!vtable
->initialized
) {
824 if (!mono_runtime_class_init_full (vtable
, error
)) {
825 mono_error_set_pending_exception (error
);
830 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
832 if (field
->offset
== -1) {
834 g_assert (domain
->special_static_fields
);
835 mono_domain_lock (domain
);
836 addr
= g_hash_table_lookup (domain
->special_static_fields
, field
);
837 mono_domain_unlock (domain
);
838 addr
= mono_get_special_static_data (GPOINTER_TO_UINT (addr
));
840 addr
= (char*)mono_vtable_get_static_field_data (vtable
) + field
->offset
;
846 mono_ldtoken_wrapper (MonoImage
*image
, int token
, MonoGenericContext
*context
)
849 MonoClass
*handle_class
;
852 res
= mono_ldtoken_checked (image
, token
, &handle_class
, context
, error
);
853 if (!is_ok (error
)) {
854 mono_error_set_pending_exception (error
);
857 mono_class_init_internal (handle_class
);
863 mono_ldtoken_wrapper_generic_shared (MonoImage
*image
, int token
, MonoMethod
*method
)
865 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
866 MonoGenericContext
*generic_context
;
868 if (sig
->is_inflated
) {
869 generic_context
= mono_method_get_context (method
);
871 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
872 g_assert (generic_container
);
873 generic_context
= &generic_container
->context
;
876 return mono_ldtoken_wrapper (image
, token
, generic_context
);
880 mono_fconv_u8 (double v
)
882 #if defined(TARGET_X86) || defined(TARGET_AMD64)
883 const double two63
= 2147483648.0 * 4294967296.0;
887 return (gint64
)(v
- two63
) + ((guint64
)1 << 63);
890 if (mono_isinf (v
) || mono_isnan (v
))
896 #ifdef MONO_ARCH_EMULATE_FCONV_TO_U8
898 mono_fconv_u8_2 (double v
)
900 // Separate from mono_fconv_u8 to avoid duplicate JIT icall.
902 // When there are duplicates, there is single instancing
903 // against function address that breaks stuff. For example,
904 // wrappers are only produced for one of them, breaking FullAOT.
905 return mono_fconv_u8 (v
);
909 mono_rconv_u8 (float v
)
911 #if defined(TARGET_X86) || defined(TARGET_AMD64)
912 const float two63
= 2147483648.0 * 4294967296.0;
916 return (gint64
)(v
- two63
) + ((guint64
)1 << 63);
919 if (mono_isinf (v
) || mono_isnan (v
))
926 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
928 mono_fconv_i8 (double v
)
935 mono_fconv_u4 (double v
)
937 /* MS.NET behaves like this for some reason */
938 if (mono_isinf (v
) || mono_isnan (v
))
943 #ifdef MONO_ARCH_EMULATE_FCONV_TO_U4
945 mono_fconv_u4_2 (double v
)
947 // Separate from mono_fconv_u4 to avoid duplicate JIT icall.
949 // When there are duplicates, there is single instancing
950 // against function address that breaks stuff. For example,
951 // wrappers are only produced for one of them, breaking FullAOT.
952 return mono_fconv_u4 (v
);
956 mono_rconv_u4 (float v
)
958 if (mono_isinf (v
) || mono_isnan (v
))
965 mono_fconv_ovf_i8 (double v
)
967 const gint64 res
= (gint64
)v
;
969 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
971 mono_error_set_overflow (error
);
972 mono_error_set_pending_exception (error
);
979 mono_fconv_ovf_u8 (double v
)
984 * The soft-float implementation of some ARM devices have a buggy guin64 to double
985 * conversion that it looses precision even when the integer if fully representable
988 * This was found with 4294967295ull, converting to double and back looses one bit of precision.
990 * To work around this issue we test for value boundaries instead.
992 #if defined(__arm__) && defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
993 if (mono_isnan (v
) || !(v
>= -0.5 && v
<= ULLONG_MAX
+0.5)) {
995 mono_error_set_overflow (error
);
996 mono_error_set_pending_exception (error
);
1002 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1004 mono_error_set_overflow (error
);
1005 mono_error_set_pending_exception (error
);
1012 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
1014 mono_rconv_i8 (float v
)
1021 mono_rconv_ovf_i8 (float v
)
1023 const gint64 res
= (gint64
)v
;
1025 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1027 mono_error_set_overflow (error
);
1028 mono_error_set_pending_exception (error
);
1035 mono_rconv_ovf_u8 (float v
)
1040 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1042 mono_error_set_overflow (error
);
1043 mono_error_set_pending_exception (error
);
1049 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
1051 mono_lconv_to_r8 (gint64 a
)
1057 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
1059 mono_lconv_to_r4 (gint64 a
)
1065 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
1067 mono_conv_to_r8_un (guint32 a
)
1073 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
1075 mono_lconv_to_r8_un (guint64 a
)
1081 #ifdef MONO_ARCH_EMULATE_FREM
1082 // Wrapper to avoid taking address of overloaded function.
1084 mono_fmod (double a
, double b
)
1091 mono_helper_compile_generic_method (MonoObject
*obj
, MonoMethod
*method
, gpointer
*this_arg
)
1094 MonoMethod
*vmethod
;
1096 MonoGenericContext
*context
= mono_method_get_context (method
);
1098 UnlockedIncrement (&mono_jit_stats
.generic_virtual_invocations
);
1101 mono_error_set_null_reference (error
);
1102 mono_error_set_pending_exception (error
);
1105 vmethod
= mono_object_get_virtual_method_internal (obj
, method
);
1106 g_assert (!mono_class_is_gtd (vmethod
->klass
));
1107 g_assert (!mono_class_is_ginst (vmethod
->klass
) || !mono_class_get_generic_class (vmethod
->klass
)->context
.class_inst
->is_open
);
1108 g_assert (!context
->method_inst
|| !context
->method_inst
->is_open
);
1110 addr
= mono_compile_method_checked (vmethod
, error
);
1111 if (mono_error_set_pending_exception (error
))
1115 addr
= mini_add_method_trampoline (vmethod
, addr
, mono_method_needs_static_rgctx_invoke (vmethod
, FALSE
), FALSE
);
1117 /* Since this is a virtual call, have to unbox vtypes */
1118 if (m_class_is_valuetype (obj
->vtable
->klass
))
1119 *this_arg
= mono_object_unbox_internal (obj
);
1127 ves_icall_mono_ldstr (MonoDomain
*domain
, MonoImage
*image
, guint32 idx
)
1130 MonoString
*result
= mono_ldstr_checked (domain
, image
, idx
, error
);
1131 mono_error_set_pending_exception (error
);
1136 mono_helper_ldstr (MonoImage
*image
, guint32 idx
)
1139 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), image
, idx
, error
);
1140 mono_error_set_pending_exception (error
);
1145 mono_helper_ldstr_mscorlib (guint32 idx
)
1148 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), mono_defaults
.corlib
, idx
, error
);
1149 mono_error_set_pending_exception (error
);
1154 mono_helper_newobj_mscorlib (guint32 idx
)
1157 MonoClass
*klass
= mono_class_get_checked (mono_defaults
.corlib
, MONO_TOKEN_TYPE_DEF
| idx
, error
);
1159 if (!is_ok (error
)) {
1160 mono_error_set_pending_exception (error
);
1164 MonoObject
*obj
= mono_object_new_checked (mono_domain_get (), klass
, error
);
1166 mono_error_set_pending_exception (error
);
1171 * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
1172 * in generated code. So instead we emit a call to this function and place a gdb
1181 mono_create_corlib_exception_0 (guint32 token
)
1183 return mono_exception_from_token (mono_defaults
.corlib
, token
);
1187 mono_create_corlib_exception_1 (guint32 token
, MonoString
*arg_raw
)
1189 HANDLE_FUNCTION_ENTER ();
1191 MONO_HANDLE_DCL (MonoString
, arg
);
1192 MonoExceptionHandle ret
= mono_exception_from_token_two_strings_checked (
1193 mono_defaults
.corlib
, token
, arg
, NULL_HANDLE_STRING
, error
);
1194 mono_error_set_pending_exception (error
);
1195 HANDLE_FUNCTION_RETURN_OBJ (ret
);
1199 mono_create_corlib_exception_2 (guint32 token
, MonoString
*arg1_raw
, MonoString
*arg2_raw
)
1201 HANDLE_FUNCTION_ENTER ();
1203 MONO_HANDLE_DCL (MonoString
, arg1
);
1204 MONO_HANDLE_DCL (MonoString
, arg2
);
1205 MonoExceptionHandle ret
= mono_exception_from_token_two_strings_checked (
1206 mono_defaults
.corlib
, token
, arg1
, arg2
, error
);
1207 mono_error_set_pending_exception (error
);
1208 HANDLE_FUNCTION_RETURN_OBJ (ret
);
1212 mono_object_castclass_unbox (MonoObject
*obj
, MonoClass
*klass
)
1215 MonoJitTlsData
*jit_tls
= NULL
;
1218 if (mini_debug_options
.better_cast_details
) {
1219 jit_tls
= mono_tls_get_jit_tls ();
1220 jit_tls
->class_cast_from
= NULL
;
1226 oklass
= obj
->vtable
->klass
;
1227 if ((m_class_is_enumtype (klass
) && oklass
== m_class_get_element_class (klass
)) || (m_class_is_enumtype (oklass
) && klass
== m_class_get_element_class (oklass
)))
1229 if (mono_object_isinst_checked (obj
, klass
, error
))
1231 if (mono_error_set_pending_exception (error
))
1234 if (mini_debug_options
.better_cast_details
) {
1235 jit_tls
->class_cast_from
= oklass
;
1236 jit_tls
->class_cast_to
= klass
;
1239 mono_set_pending_exception (mono_exception_from_name (mono_defaults
.corlib
,
1240 "System", "InvalidCastException"));
1246 mono_object_castclass_with_cache (MonoObject
*obj
, MonoClass
*klass
, gpointer
*cache
)
1249 MonoJitTlsData
*jit_tls
= NULL
;
1250 gpointer cached_vtable
, obj_vtable
;
1252 if (mini_debug_options
.better_cast_details
) {
1253 jit_tls
= mono_tls_get_jit_tls ();
1254 jit_tls
->class_cast_from
= NULL
;
1260 cached_vtable
= *cache
;
1261 obj_vtable
= obj
->vtable
;
1263 if (cached_vtable
== obj_vtable
)
1266 if (mono_object_isinst_checked (obj
, klass
, error
)) {
1267 *cache
= obj_vtable
;
1270 if (mono_error_set_pending_exception (error
))
1273 if (mini_debug_options
.better_cast_details
) {
1274 jit_tls
->class_cast_from
= obj
->vtable
->klass
;
1275 jit_tls
->class_cast_to
= klass
;
1278 mono_set_pending_exception (mono_exception_from_name (mono_defaults
.corlib
,
1279 "System", "InvalidCastException"));
1285 mono_object_isinst_with_cache (MonoObject
*obj
, MonoClass
*klass
, gpointer
*cache
)
1288 size_t cached_vtable
, obj_vtable
;
1293 cached_vtable
= (size_t)*cache
;
1294 obj_vtable
= (size_t)obj
->vtable
;
1296 if ((cached_vtable
& ~0x1) == obj_vtable
) {
1297 return (cached_vtable
& 0x1) ? NULL
: obj
;
1300 if (mono_object_isinst_checked (obj
, klass
, error
)) {
1301 *cache
= (gpointer
)obj_vtable
;
1304 if (mono_error_set_pending_exception (error
))
1307 *cache
= (gpointer
)(obj_vtable
| 0x1);
1313 mono_get_native_calli_wrapper (MonoImage
*image
, MonoMethodSignature
*sig
, gpointer func
)
1316 MonoMarshalSpec
**mspecs
;
1317 MonoMethodPInvoke piinfo
;
1320 mspecs
= g_new0 (MonoMarshalSpec
*, sig
->param_count
+ 1);
1321 memset (&piinfo
, 0, sizeof (piinfo
));
1323 m
= mono_marshal_get_native_func_wrapper (image
, sig
, &piinfo
, mspecs
, func
);
1325 for (int i
= sig
->param_count
; i
>= 0; i
--)
1327 mono_metadata_free_marshal_spec (mspecs
[i
]);
1330 gpointer compiled_ptr
= mono_compile_method_checked (m
, error
);
1331 mono_error_set_pending_exception (error
);
1332 g_assert (compiled_ptr
);
1334 return compiled_ptr
;
1338 constrained_gsharedvt_call_setup (gpointer mp
, MonoMethod
*cmethod
, MonoClass
*klass
, gpointer
*this_arg
, MonoError
*error
)
1341 int vt_slot
, iface_offset
;
1342 gboolean is_iface
= FALSE
;
1346 if (mono_class_is_interface (klass
) || !m_class_is_valuetype (klass
)) {
1347 MonoObject
*this_obj
;
1349 is_iface
= mono_class_is_interface (klass
);
1351 /* Have to use the receiver's type instead of klass, the receiver is a ref type */
1352 this_obj
= *(MonoObject
**)mp
;
1353 g_assert (this_obj
);
1355 klass
= this_obj
->vtable
->klass
;
1358 if (mono_method_signature_internal (cmethod
)->pinvoke
) {
1359 /* Object.GetType () */
1360 m
= mono_marshal_get_native_wrapper (cmethod
, TRUE
, FALSE
);
1362 /* Lookup the virtual method */
1363 mono_class_setup_vtable (klass
);
1364 g_assert (m_class_get_vtable (klass
));
1365 vt_slot
= mono_method_get_vtable_slot (cmethod
);
1366 if (mono_class_is_interface (cmethod
->klass
)) {
1367 iface_offset
= mono_class_interface_offset (klass
, cmethod
->klass
);
1368 g_assert (iface_offset
!= -1);
1369 vt_slot
+= iface_offset
;
1371 m
= m_class_get_vtable (klass
) [vt_slot
];
1372 if (cmethod
->is_inflated
) {
1373 m
= mono_class_inflate_generic_method_full_checked (m
, NULL
, mono_method_get_context (cmethod
), error
);
1374 return_val_if_nok (error
, NULL
);
1378 if (m_class_is_valuetype (klass
) && (m
->klass
== mono_defaults
.object_class
|| m
->klass
== m_class_get_parent (mono_defaults
.enum_class
) || m
->klass
== mono_defaults
.enum_class
)) {
1380 * Calling a non-vtype method with a vtype receiver, has to box.
1382 *this_arg
= mono_value_box_checked (mono_domain_get (), klass
, mp
, error
);
1383 } else if (m_class_is_valuetype (klass
)) {
1386 * The original type is an interface, so the receiver is a ref,
1387 the called method is a vtype method, need to unbox.
1389 MonoObject
*this_obj
= *(MonoObject
**)mp
;
1391 *this_arg
= mono_object_unbox_internal (this_obj
);
1394 * Calling a vtype method with a vtype receiver
1400 * Calling a non-vtype method
1402 *this_arg
= *(gpointer
*)mp
;
1409 * mono_gsharedvt_constrained_call:
1411 * Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
1412 * the arguments to the method in the format used by mono_runtime_invoke_checked ().
1415 mono_gsharedvt_constrained_call (gpointer mp
, MonoMethod
*cmethod
, MonoClass
*klass
, gboolean deref_arg
, gpointer
*args
)
1421 gpointer new_args
[16];
1423 m
= constrained_gsharedvt_call_setup (mp
, cmethod
, klass
, &this_arg
, error
);
1424 if (!is_ok (error
)) {
1425 mono_error_set_pending_exception (error
);
1431 if (args
&& deref_arg
) {
1432 new_args
[0] = *(gpointer
*)args
[0];
1435 if (m
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
) {
1436 /* Object.GetType () */
1438 args
[0] = this_arg
;
1442 o
= mono_runtime_invoke_checked (m
, this_arg
, args
, error
);
1443 if (!is_ok (error
)) {
1444 mono_error_set_pending_exception (error
);
1452 mono_gsharedvt_value_copy (gpointer dest
, gpointer src
, MonoClass
*klass
)
1454 if (m_class_is_valuetype (klass
))
1455 mono_value_copy_internal (dest
, src
, klass
);
1457 mono_gc_wbarrier_generic_store_internal (dest
, *(MonoObject
**)src
);
1461 ves_icall_runtime_class_init (MonoVTable
*vtable
)
1463 MONO_REQ_GC_UNSAFE_MODE
;
1466 mono_runtime_class_init_full (vtable
, error
);
1467 mono_error_set_pending_exception (error
);
1472 mono_generic_class_init (MonoVTable
*vtable
)
1475 mono_runtime_class_init_full (vtable
, error
);
1476 mono_error_set_pending_exception (error
);
1480 ves_icall_mono_delegate_ctor (MonoObject
*this_obj_raw
, MonoObject
*target_raw
, gpointer addr
)
1482 HANDLE_FUNCTION_ENTER ();
1484 MONO_HANDLE_DCL (MonoObject
, this_obj
);
1485 MONO_HANDLE_DCL (MonoObject
, target
);
1488 mono_error_set_argument_null (error
, "method", "");
1489 mono_error_set_pending_exception (error
);
1492 mono_delegate_ctor (this_obj
, target
, addr
, NULL
, error
);
1493 mono_error_set_pending_exception (error
);
1496 HANDLE_FUNCTION_RETURN ();
1500 ves_icall_mono_delegate_ctor_interp (MonoObject
*this_obj_raw
, MonoObject
*target_raw
, gpointer addr
)
1502 HANDLE_FUNCTION_ENTER ();
1504 MONO_HANDLE_DCL (MonoObject
, this_obj
);
1505 MONO_HANDLE_DCL (MonoObject
, target
);
1508 mono_error_set_argument_null (error
, "method", "");
1509 mono_error_set_pending_exception (error
);
1512 mini_get_interp_callbacks ()->delegate_ctor (this_obj
, target
, addr
, error
);
1513 mono_error_set_pending_exception (error
);
1516 HANDLE_FUNCTION_RETURN ();
1520 mono_fill_class_rgctx (MonoVTable
*vtable
, int index
)
1526 * This is perf critical.
1527 * fill_runtime_generic_context () contains a fallpath.
1529 res
= mono_class_fill_runtime_generic_context (vtable
, index
, error
);
1530 if (!is_ok (error
)) {
1531 mono_error_set_pending_exception (error
);
1538 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext
*mrgctx
, int index
)
1543 res
= mono_method_fill_runtime_generic_context (mrgctx
, index
, error
);
1544 if (!is_ok (error
)) {
1545 mono_error_set_pending_exception (error
);
1552 mono_get_assembly_object (MonoImage
*image
)
1555 MonoObjectHandle result
= MONO_HANDLE_CAST (MonoObject
, mono_assembly_get_object_handle (mono_domain_get (), image
->assembly
, error
));
1556 ICALL_RETURN_OBJ (result
);
1560 mono_get_method_object (MonoMethod
*method
)
1563 MonoObject
* result
;
1564 result
= (MonoObject
*)mono_method_get_object_checked (mono_domain_get (), method
, method
->klass
, error
);
1565 mono_error_set_pending_exception (error
);
1570 mono_ckfinite (double d
)
1572 if (mono_isinf (d
) || mono_isnan (d
))
1573 mono_set_pending_exception (mono_get_exception_arithmetic ());
1578 mono_throw_method_access (MonoMethod
*caller
, MonoMethod
*callee
)
1580 char *caller_name
= mono_method_get_reflection_name (caller
);
1581 char *callee_name
= mono_method_get_reflection_name (callee
);
1584 mono_error_set_generic_error (error
, "System", "MethodAccessException", "Method `%s' is inaccessible from method `%s'", callee_name
, caller_name
);
1585 mono_error_set_pending_exception (error
);
1586 g_free (callee_name
);
1587 g_free (caller_name
);
1591 mono_throw_bad_image ()
1594 mono_error_set_generic_error (error
, "System", "BadImageFormatException", "Bad IL format.");
1595 mono_error_set_pending_exception (error
);
1599 mono_throw_not_supported ()
1602 mono_error_set_generic_error (error
, "System", "NotSupportedException", "");
1603 mono_error_set_pending_exception (error
);
1607 mono_throw_invalid_program (const char *msg
)
1610 mono_error_set_invalid_program (error
, "Invalid IL due to: %s", msg
);
1611 mono_error_set_pending_exception (error
);
1615 mono_dummy_jit_icall (void)