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>
32 #include "mini-llvm-cpp.h"
36 mono_ldftn (MonoMethod
*method
)
42 // FIXME: No error handling
44 addr
= mono_compile_method_checked (method
, error
);
45 mono_error_assert_ok (error
);
48 if (mono_method_needs_static_rgctx_invoke (method
, FALSE
))
49 /* The caller doesn't pass it */
50 g_assert_not_reached ();
52 addr
= mini_add_method_trampoline (method
, addr
, mono_method_needs_static_rgctx_invoke (method
, FALSE
), FALSE
);
56 addr
= mono_create_jump_trampoline (mono_domain_get (), method
, FALSE
, error
);
57 if (!mono_error_ok (error
)) {
58 mono_error_set_pending_exception (error
);
61 return mono_create_ftnptr (mono_domain_get (), addr
);
65 ldvirtfn_internal (MonoObject
*obj
, MonoMethod
*method
, gboolean gshared
)
71 mono_error_set_null_reference (error
);
72 mono_error_set_pending_exception (error
);
76 res
= mono_object_get_virtual_method_internal (obj
, method
);
78 if (gshared
&& method
->is_inflated
&& mono_method_get_context (method
)->method_inst
) {
79 MonoGenericContext context
= { NULL
, NULL
};
81 if (mono_class_is_ginst (res
->klass
))
82 context
.class_inst
= mono_class_get_generic_class (res
->klass
)->context
.class_inst
;
83 else if (mono_class_is_gtd (res
->klass
))
84 context
.class_inst
= mono_class_get_generic_container (res
->klass
)->context
.class_inst
;
85 context
.method_inst
= mono_method_get_context (method
)->method_inst
;
87 res
= mono_class_inflate_generic_method_checked (res
, &context
, error
);
88 if (!mono_error_ok (error
)) {
89 mono_error_set_pending_exception (error
);
94 /* An rgctx wrapper is added by the trampolines no need to do it here */
96 return mono_ldftn (res
);
100 mono_ldvirtfn (MonoObject
*obj
, MonoMethod
*method
)
102 return ldvirtfn_internal (obj
, method
, FALSE
);
106 mono_ldvirtfn_gshared (MonoObject
*obj
, MonoMethod
*method
)
108 return ldvirtfn_internal (obj
, method
, TRUE
);
112 mono_helper_stelem_ref_check (MonoArray
*array
, MonoObject
*val
)
116 mono_error_set_null_reference (error
);
117 mono_error_set_pending_exception (error
);
120 if (val
&& !mono_object_isinst_checked (val
, m_class_get_element_class (mono_object_class (array
)), error
)) {
121 if (mono_error_set_pending_exception (error
))
123 mono_set_pending_exception (mono_get_exception_array_type_mismatch ());
128 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
131 mono_llmult (gint64 a
, gint64 b
)
137 mono_llmult_ovf_un (guint64 a
, guint64 b
)
140 guint32 ah
= a
>> 32;
142 guint32 bh
= b
>> 32;
145 // fixme: this is incredible slow
148 goto raise_exception
;
150 res
= (guint64
)al
* (guint64
)bl
;
152 t1
= (guint64
)ah
* (guint64
)bl
+ (guint64
)al
* (guint64
)bh
;
155 goto raise_exception
;
157 res
+= ((guint64
)t1
) << 32;
164 mono_error_set_overflow (error
);
165 mono_error_set_pending_exception (error
);
171 mono_llmult_ovf (gint64 a
, gint64 b
)
178 Use Karatsuba algorithm where:
179 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
180 where Ah is the "high half" (most significant 32 bits) of a and
181 where Al is the "low half" (least significant 32 bits) of a and
182 where Bh is the "high half" of b and Bl is the "low half" and
183 where R is the Radix or "size of the half" (in our case 32 bits)
185 Note, for the product of two 64 bit numbers to fit into a 64
186 result, ah and/or bh must be 0. This will save us from doing
187 the AhBh term at all.
189 Also note that we refactor so that we don't overflow 64 bits with
190 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
196 /* need to work with absoulte values, so find out what the
197 resulting sign will be and convert any negative numbers
198 from two's complement
202 if (((guint32
)ah
== 0x80000000) && (al
== 0)) {
203 /* This has no two's complement */
209 goto raise_exception
;
212 /* flip the bits and add 1 */
223 if (((guint32
)bh
== 0x80000000) && (bl
== 0)) {
224 /* This has no two's complement */
230 goto raise_exception
;
233 /* flip the bits and add 1 */
243 /* we overflow for sure if both upper halves are greater
244 than zero because we would need to shift their
245 product 64 bits to the left and that will not fit
246 in a 64 bit result */
248 goto raise_exception
;
249 if ((gint64
)((gint64
)ah
* (gint64
)bl
) > (gint64
)0x80000000 || (gint64
)((gint64
)al
* (gint64
)bh
) > (gint64
)0x80000000)
250 goto raise_exception
;
252 /* do the AlBl term first */
253 t1
= (gint64
)al
* (gint64
)bl
;
257 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
258 t1
+= (gint64
)(ah
- al
) * (gint64
)(bl
- bh
);
259 /* check for overflow */
261 if (t1
> (0x7FFFFFFFFFFFFFFFLL
- res
))
262 goto raise_exception
;
267 goto raise_exception
;
277 mono_error_set_overflow (error
);
278 mono_error_set_pending_exception (error
);
284 mono_lldiv (gint64 a
, gint64 b
)
286 #ifdef MONO_ARCH_NEED_DIV_CHECK
289 mono_error_set_divide_by_zero (error
);
290 mono_error_set_pending_exception (error
);
293 else if (b
== -1 && a
== (-9223372036854775807LL - 1LL)) {
295 mono_error_set_overflow (error
);
296 mono_error_set_pending_exception (error
);
304 mono_llrem (gint64 a
, gint64 b
)
306 #ifdef MONO_ARCH_NEED_DIV_CHECK
309 mono_error_set_divide_by_zero (error
);
310 mono_error_set_pending_exception (error
);
313 else if (b
== -1 && a
== (-9223372036854775807LL - 1LL)) {
315 mono_error_set_overflow (error
);
316 mono_error_set_pending_exception (error
);
324 mono_lldiv_un (guint64 a
, guint64 b
)
326 #ifdef MONO_ARCH_NEED_DIV_CHECK
329 mono_error_set_divide_by_zero (error
);
330 mono_error_set_pending_exception (error
);
338 mono_llrem_un (guint64 a
, guint64 b
)
340 #ifdef MONO_ARCH_NEED_DIV_CHECK
343 mono_error_set_divide_by_zero (error
);
344 mono_error_set_pending_exception (error
);
353 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
356 mono_lshl (guint64 a
, gint32 shamt
)
358 const guint64 res
= a
<< (shamt
& 0x7f);
360 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
366 mono_lshr_un (guint64 a
, gint32 shamt
)
368 const guint64 res
= a
>> (shamt
& 0x7f);
370 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
376 mono_lshr (gint64 a
, gint32 shamt
)
378 const gint64 res
= a
>> (shamt
& 0x7f);
380 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
387 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
390 mono_idiv (gint32 a
, gint32 b
)
392 #ifdef MONO_ARCH_NEED_DIV_CHECK
395 mono_error_set_divide_by_zero (error
);
396 mono_error_set_pending_exception (error
);
399 else if (b
== -1 && a
== (0x80000000)) {
401 mono_error_set_overflow (error
);
402 mono_error_set_pending_exception (error
);
410 mono_idiv_un (guint32 a
, guint32 b
)
412 #ifdef MONO_ARCH_NEED_DIV_CHECK
415 mono_error_set_divide_by_zero (error
);
416 mono_error_set_pending_exception (error
);
424 mono_irem (gint32 a
, gint32 b
)
426 #ifdef MONO_ARCH_NEED_DIV_CHECK
429 mono_error_set_divide_by_zero (error
);
430 mono_error_set_pending_exception (error
);
433 else if (b
== -1 && a
== (0x80000000)) {
435 mono_error_set_overflow (error
);
436 mono_error_set_pending_exception (error
);
444 mono_irem_un (guint32 a
, guint32 b
)
446 #ifdef MONO_ARCH_NEED_DIV_CHECK
449 mono_error_set_divide_by_zero (error
);
450 mono_error_set_pending_exception (error
);
459 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
462 mono_imul (gint32 a
, gint32 b
)
468 mono_imul_ovf (gint32 a
, gint32 b
)
470 const gint64 res
= (gint64
)a
* (gint64
)b
;
472 if ((res
> 0x7fffffffL
) || (res
< -2147483648LL)) {
474 mono_error_set_overflow (error
);
475 mono_error_set_pending_exception (error
);
483 mono_imul_ovf_un (guint32 a
, guint32 b
)
485 const guint64 res
= (guint64
)a
* (guint64
)b
;
489 mono_error_set_overflow (error
);
490 mono_error_set_pending_exception (error
);
498 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
500 mono_fdiv (double a
, double b
)
506 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
509 mono_fsub (double a
, double b
)
515 mono_fadd (double a
, double b
)
521 mono_fmul (double a
, double b
)
533 mono_fconv_r4 (double a
)
539 mono_conv_to_r8 (int a
)
545 mono_conv_to_r4 (int a
)
547 return (double)(float)a
;
551 mono_fconv_i1 (double a
)
557 mono_fconv_i2 (double a
)
563 mono_fconv_i4 (double a
)
569 mono_fconv_u1 (double a
)
575 mono_fconv_u2 (double a
)
581 mono_fcmp_eq (double a
, double b
)
587 mono_fcmp_ge (double a
, double b
)
593 mono_fcmp_gt (double a
, double b
)
599 mono_fcmp_le (double a
, double b
)
605 mono_fcmp_lt (double a
, double b
)
611 mono_fcmp_ne_un (double a
, double b
)
613 return isunordered (a
, b
) || a
!= b
;
617 mono_fcmp_ge_un (double a
, double b
)
619 return isunordered (a
, b
) || a
>= b
;
623 mono_fcmp_gt_un (double a
, double b
)
625 return isunordered (a
, b
) || a
> b
;
629 mono_fcmp_le_un (double a
, double b
)
631 return isunordered (a
, b
) || a
<= b
;
635 mono_fcmp_lt_un (double a
, double b
)
637 return isunordered (a
, b
) || a
< b
;
641 mono_fceq (double a
, double b
)
647 mono_fcgt (double a
, double b
)
653 mono_fcgt_un (double a
, double b
)
655 return isunordered (a
, b
) || a
> b
;
659 mono_fclt (double a
, double b
)
665 mono_fclt_un (double a
, double b
)
667 return isunordered (a
, b
) || a
< b
;
671 mono_fload_r4 (float *ptr
)
677 mono_fstore_r4 (double val
, float *ptr
)
682 /* returns the integer bitpattern that is passed in the regs or stack */
684 mono_fload_r4_arg (double val
)
686 float v
= (float)val
;
687 return *(guint32
*)&v
;
693 mono_array_new_n_icall (MonoMethod
*cm
, gint32 pcount
, intptr_t *params
)
699 intptr_t *lower_bounds
= NULL
;
701 const int pcount_sig
= mono_method_signature_internal (cm
)->param_count
;
702 const int rank
= m_class_get_rank (cm
->klass
);
703 g_assert (pcount
== pcount_sig
);
704 g_assert (rank
== pcount
|| rank
* 2 == pcount
);
706 uintptr_t *lengths
= (uintptr_t*)params
;
708 if (rank
== pcount
) {
709 /* Only lengths provided. */
710 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
) {
711 lower_bounds
= g_newa (intptr_t, rank
);
712 memset (lower_bounds
, 0, sizeof (intptr_t) * rank
);
715 g_assert (pcount
== (rank
* 2));
716 /* lower bounds are first. */
717 lower_bounds
= params
;
721 MonoArray
*arr
= mono_array_new_full_checked (mono_domain_get (),
722 cm
->klass
, lengths
, lower_bounds
, error
);
724 return mono_error_set_pending_exception (error
) ? NULL
: arr
;
727 /* Specialized version of mono_array_new_va () which avoids varargs */
729 mono_array_new_1 (MonoMethod
*cm
, guint32 length
)
733 MonoDomain
*domain
= mono_domain_get ();
734 uintptr_t lengths
[1];
735 intptr_t *lower_bounds
;
739 pcount
= mono_method_signature_internal (cm
)->param_count
;
740 rank
= m_class_get_rank (cm
->klass
);
742 lengths
[0] = length
;
744 g_assert (rank
== pcount
);
746 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
) {
747 lower_bounds
= g_newa (intptr_t, rank
);
748 memset (lower_bounds
, 0, sizeof (intptr_t) * rank
);
753 arr
= mono_array_new_full_checked (domain
, cm
->klass
, lengths
, lower_bounds
, error
);
755 if (!mono_error_ok (error
)) {
756 mono_error_set_pending_exception (error
);
764 mono_array_new_2 (MonoMethod
*cm
, guint32 length1
, guint32 length2
)
768 MonoDomain
*domain
= mono_domain_get ();
769 uintptr_t lengths
[2];
770 intptr_t *lower_bounds
;
774 pcount
= mono_method_signature_internal (cm
)->param_count
;
775 rank
= m_class_get_rank (cm
->klass
);
777 lengths
[0] = length1
;
778 lengths
[1] = length2
;
780 g_assert (rank
== pcount
);
782 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
) {
783 lower_bounds
= g_newa (intptr_t, rank
);
784 memset (lower_bounds
, 0, sizeof (intptr_t) * rank
);
789 arr
= mono_array_new_full_checked (domain
, cm
->klass
, lengths
, lower_bounds
, error
);
791 if (!mono_error_ok (error
)) {
792 mono_error_set_pending_exception (error
);
800 mono_array_new_3 (MonoMethod
*cm
, guint32 length1
, guint32 length2
, guint32 length3
)
804 MonoDomain
*domain
= mono_domain_get ();
805 uintptr_t lengths
[3];
806 intptr_t *lower_bounds
;
810 pcount
= mono_method_signature_internal (cm
)->param_count
;
811 rank
= m_class_get_rank (cm
->klass
);
813 lengths
[0] = length1
;
814 lengths
[1] = length2
;
815 lengths
[2] = length3
;
817 g_assert (rank
== pcount
);
819 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
) {
820 lower_bounds
= g_newa (intptr_t, rank
);
821 memset (lower_bounds
, 0, sizeof (intptr_t) * rank
);
826 arr
= mono_array_new_full_checked (domain
, cm
->klass
, lengths
, lower_bounds
, error
);
828 if (!mono_error_ok (error
)) {
829 mono_error_set_pending_exception (error
);
837 mono_array_new_4 (MonoMethod
*cm
, guint32 length1
, guint32 length2
, guint32 length3
, guint32 length4
)
841 MonoDomain
*domain
= mono_domain_get ();
842 uintptr_t lengths
[4];
843 intptr_t *lower_bounds
;
847 pcount
= mono_method_signature_internal (cm
)->param_count
;
848 rank
= m_class_get_rank (cm
->klass
);
850 lengths
[0] = length1
;
851 lengths
[1] = length2
;
852 lengths
[2] = length3
;
853 lengths
[3] = length4
;
855 g_assert (rank
== pcount
);
857 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
) {
858 lower_bounds
= g_newa (intptr_t, rank
);
859 memset (lower_bounds
, 0, sizeof (intptr_t) * rank
);
864 arr
= mono_array_new_full_checked (domain
, cm
->klass
, lengths
, lower_bounds
, error
);
866 if (!mono_error_ok (error
)) {
867 mono_error_set_pending_exception (error
);
875 mono_class_static_field_address (MonoDomain
*domain
, MonoClassField
*field
)
881 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
883 mono_class_init_internal (field
->parent
);
885 vtable
= mono_class_vtable_checked (domain
, field
->parent
, error
);
886 if (!is_ok (error
)) {
887 mono_error_set_pending_exception (error
);
890 if (!vtable
->initialized
) {
891 if (!mono_runtime_class_init_full (vtable
, error
)) {
892 mono_error_set_pending_exception (error
);
897 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
899 if (field
->offset
== -1) {
901 g_assert (domain
->special_static_fields
);
902 mono_domain_lock (domain
);
903 addr
= g_hash_table_lookup (domain
->special_static_fields
, field
);
904 mono_domain_unlock (domain
);
905 addr
= mono_get_special_static_data (GPOINTER_TO_UINT (addr
));
907 addr
= (char*)mono_vtable_get_static_field_data (vtable
) + field
->offset
;
913 mono_ldtoken_wrapper (MonoImage
*image
, int token
, MonoGenericContext
*context
)
916 MonoClass
*handle_class
;
919 res
= mono_ldtoken_checked (image
, token
, &handle_class
, context
, error
);
920 if (!mono_error_ok (error
)) {
921 mono_error_set_pending_exception (error
);
924 mono_class_init_internal (handle_class
);
930 mono_ldtoken_wrapper_generic_shared (MonoImage
*image
, int token
, MonoMethod
*method
)
932 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
933 MonoGenericContext
*generic_context
;
935 if (sig
->is_inflated
) {
936 generic_context
= mono_method_get_context (method
);
938 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
939 g_assert (generic_container
);
940 generic_context
= &generic_container
->context
;
943 return mono_ldtoken_wrapper (image
, token
, generic_context
);
947 mono_fconv_u8 (double v
)
953 mono_fconv_u8_2 (double v
)
955 // Separate from mono_fconv_u8 to avoid duplicate JIT icall.
957 // When there are duplicates, there is single instancing
958 // against function address that breaks stuff. For example,
959 // wrappers are only produced for one of them, breaking FullAOT.
960 return mono_fconv_u8 (v
);
964 mono_rconv_u8 (float v
)
969 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
971 mono_fconv_i8 (double v
)
978 mono_fconv_u4 (double v
)
980 /* MS.NET behaves like this for some reason */
981 if (mono_isinf (v
) || mono_isnan (v
))
987 mono_fconv_u4_2 (double v
)
989 // Separate from mono_fconv_u4 to avoid duplicate JIT icall.
991 // When there are duplicates, there is single instancing
992 // against function address that breaks stuff. For example,
993 // wrappers are only produced for one of them, breaking FullAOT.
994 return mono_fconv_u4 (v
);
998 mono_fconv_ovf_i8 (double v
)
1000 const gint64 res
= (gint64
)v
;
1002 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1004 mono_error_set_overflow (error
);
1005 mono_error_set_pending_exception (error
);
1012 mono_fconv_ovf_u8 (double v
)
1017 * The soft-float implementation of some ARM devices have a buggy guin64 to double
1018 * conversion that it looses precision even when the integer if fully representable
1021 * This was found with 4294967295ull, converting to double and back looses one bit of precision.
1023 * To work around this issue we test for value boundaries instead.
1025 #if defined(__arm__) && defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
1026 if (mono_isnan (v
) || !(v
>= -0.5 && v
<= ULLONG_MAX
+0.5)) {
1028 mono_error_set_overflow (error
);
1029 mono_error_set_pending_exception (error
);
1035 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1037 mono_error_set_overflow (error
);
1038 mono_error_set_pending_exception (error
);
1045 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
1047 mono_rconv_i8 (float v
)
1054 mono_rconv_ovf_i8 (float v
)
1056 const gint64 res
= (gint64
)v
;
1058 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1060 mono_error_set_overflow (error
);
1061 mono_error_set_pending_exception (error
);
1068 mono_rconv_ovf_u8 (float v
)
1073 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1075 mono_error_set_overflow (error
);
1076 mono_error_set_pending_exception (error
);
1082 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
1084 mono_lconv_to_r8 (gint64 a
)
1090 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
1092 mono_lconv_to_r4 (gint64 a
)
1098 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
1100 mono_conv_to_r8_un (guint32 a
)
1106 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
1108 mono_lconv_to_r8_un (guint64 a
)
1115 mono_helper_compile_generic_method (MonoObject
*obj
, MonoMethod
*method
, gpointer
*this_arg
)
1118 MonoMethod
*vmethod
;
1120 MonoGenericContext
*context
= mono_method_get_context (method
);
1122 UnlockedIncrement (&mono_jit_stats
.generic_virtual_invocations
);
1125 mono_error_set_null_reference (error
);
1126 mono_error_set_pending_exception (error
);
1129 vmethod
= mono_object_get_virtual_method_internal (obj
, method
);
1130 g_assert (!mono_class_is_gtd (vmethod
->klass
));
1131 g_assert (!mono_class_is_ginst (vmethod
->klass
) || !mono_class_get_generic_class (vmethod
->klass
)->context
.class_inst
->is_open
);
1132 g_assert (!context
->method_inst
|| !context
->method_inst
->is_open
);
1134 addr
= mono_compile_method_checked (vmethod
, error
);
1135 if (mono_error_set_pending_exception (error
))
1139 addr
= mini_add_method_trampoline (vmethod
, addr
, mono_method_needs_static_rgctx_invoke (vmethod
, FALSE
), FALSE
);
1141 /* Since this is a virtual call, have to unbox vtypes */
1142 if (m_class_is_valuetype (obj
->vtable
->klass
))
1143 *this_arg
= mono_object_unbox_internal (obj
);
1151 ves_icall_mono_ldstr (MonoDomain
*domain
, MonoImage
*image
, guint32 idx
)
1154 MonoString
*result
= mono_ldstr_checked (domain
, image
, idx
, error
);
1155 mono_error_set_pending_exception (error
);
1160 mono_helper_ldstr (MonoImage
*image
, guint32 idx
)
1163 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), image
, idx
, error
);
1164 mono_error_set_pending_exception (error
);
1169 mono_helper_ldstr_mscorlib (guint32 idx
)
1172 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), mono_defaults
.corlib
, idx
, error
);
1173 mono_error_set_pending_exception (error
);
1178 mono_helper_newobj_mscorlib (guint32 idx
)
1181 MonoClass
*klass
= mono_class_get_checked (mono_defaults
.corlib
, MONO_TOKEN_TYPE_DEF
| idx
, error
);
1183 if (!mono_error_ok (error
)) {
1184 mono_error_set_pending_exception (error
);
1188 MonoObject
*obj
= mono_object_new_checked (mono_domain_get (), klass
, error
);
1189 if (!mono_error_ok (error
))
1190 mono_error_set_pending_exception (error
);
1195 * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
1196 * in generated code. So instead we emit a call to this function and place a gdb
1205 mono_create_corlib_exception_0 (guint32 token
)
1207 return mono_exception_from_token (mono_defaults
.corlib
, token
);
1211 mono_create_corlib_exception_1 (guint32 token
, MonoString
*arg_raw
)
1213 HANDLE_FUNCTION_ENTER ();
1215 MONO_HANDLE_DCL (MonoString
, arg
);
1216 MonoExceptionHandle ret
= mono_exception_from_token_two_strings_checked (
1217 mono_defaults
.corlib
, token
, arg
, NULL_HANDLE_STRING
, error
);
1218 mono_error_set_pending_exception (error
);
1219 HANDLE_FUNCTION_RETURN_OBJ (ret
);
1223 mono_create_corlib_exception_2 (guint32 token
, MonoString
*arg1_raw
, MonoString
*arg2_raw
)
1225 HANDLE_FUNCTION_ENTER ();
1227 MONO_HANDLE_DCL (MonoString
, arg1
);
1228 MONO_HANDLE_DCL (MonoString
, arg2
);
1229 MonoExceptionHandle ret
= mono_exception_from_token_two_strings_checked (
1230 mono_defaults
.corlib
, token
, arg1
, arg2
, error
);
1231 mono_error_set_pending_exception (error
);
1232 HANDLE_FUNCTION_RETURN_OBJ (ret
);
1236 mono_object_castclass_unbox (MonoObject
*obj
, MonoClass
*klass
)
1239 MonoJitTlsData
*jit_tls
= NULL
;
1242 if (mini_get_debug_options ()->better_cast_details
) {
1243 jit_tls
= mono_tls_get_jit_tls ();
1244 jit_tls
->class_cast_from
= NULL
;
1250 oklass
= obj
->vtable
->klass
;
1251 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
)))
1253 if (mono_object_isinst_checked (obj
, klass
, error
))
1255 if (mono_error_set_pending_exception (error
))
1258 if (mini_get_debug_options ()->better_cast_details
) {
1259 jit_tls
->class_cast_from
= oklass
;
1260 jit_tls
->class_cast_to
= klass
;
1263 mono_set_pending_exception (mono_exception_from_name (mono_defaults
.corlib
,
1264 "System", "InvalidCastException"));
1270 mono_object_castclass_with_cache (MonoObject
*obj
, MonoClass
*klass
, gpointer
*cache
)
1273 MonoJitTlsData
*jit_tls
= NULL
;
1274 gpointer cached_vtable
, obj_vtable
;
1276 if (mini_get_debug_options ()->better_cast_details
) {
1277 jit_tls
= mono_tls_get_jit_tls ();
1278 jit_tls
->class_cast_from
= NULL
;
1284 cached_vtable
= *cache
;
1285 obj_vtable
= obj
->vtable
;
1287 if (cached_vtable
== obj_vtable
)
1290 if (mono_object_isinst_checked (obj
, klass
, error
)) {
1291 *cache
= obj_vtable
;
1294 if (mono_error_set_pending_exception (error
))
1297 if (mini_get_debug_options ()->better_cast_details
) {
1298 jit_tls
->class_cast_from
= obj
->vtable
->klass
;
1299 jit_tls
->class_cast_to
= klass
;
1302 mono_set_pending_exception (mono_exception_from_name (mono_defaults
.corlib
,
1303 "System", "InvalidCastException"));
1309 mono_object_isinst_with_cache (MonoObject
*obj
, MonoClass
*klass
, gpointer
*cache
)
1312 size_t cached_vtable
, obj_vtable
;
1317 cached_vtable
= (size_t)*cache
;
1318 obj_vtable
= (size_t)obj
->vtable
;
1320 if ((cached_vtable
& ~0x1) == obj_vtable
) {
1321 return (cached_vtable
& 0x1) ? NULL
: obj
;
1324 if (mono_object_isinst_checked (obj
, klass
, error
)) {
1325 *cache
= (gpointer
)obj_vtable
;
1328 if (mono_error_set_pending_exception (error
))
1331 *cache
= (gpointer
)(obj_vtable
| 0x1);
1337 mono_get_native_calli_wrapper (MonoImage
*image
, MonoMethodSignature
*sig
, gpointer func
)
1340 MonoMarshalSpec
**mspecs
;
1341 MonoMethodPInvoke piinfo
;
1344 mspecs
= g_new0 (MonoMarshalSpec
*, sig
->param_count
+ 1);
1345 memset (&piinfo
, 0, sizeof (piinfo
));
1347 m
= mono_marshal_get_native_func_wrapper (image
, sig
, &piinfo
, mspecs
, func
);
1349 for (int i
= sig
->param_count
; i
>= 0; i
--)
1351 mono_metadata_free_marshal_spec (mspecs
[i
]);
1354 gpointer compiled_ptr
= mono_compile_method_checked (m
, error
);
1355 mono_error_set_pending_exception (error
);
1356 g_assert (compiled_ptr
);
1358 return compiled_ptr
;
1362 constrained_gsharedvt_call_setup (gpointer mp
, MonoMethod
*cmethod
, MonoClass
*klass
, gpointer
*this_arg
, MonoError
*error
)
1365 int vt_slot
, iface_offset
;
1366 gboolean is_iface
= FALSE
;
1370 if (mono_class_is_interface (klass
)) {
1371 MonoObject
*this_obj
;
1375 /* Have to use the receiver's type instead of klass, the receiver is a ref type */
1376 this_obj
= *(MonoObject
**)mp
;
1377 g_assert (this_obj
);
1379 klass
= this_obj
->vtable
->klass
;
1382 if (mono_method_signature_internal (cmethod
)->pinvoke
) {
1383 /* Object.GetType () */
1384 m
= mono_marshal_get_native_wrapper (cmethod
, TRUE
, FALSE
);
1386 /* Lookup the virtual method */
1387 mono_class_setup_vtable (klass
);
1388 g_assert (m_class_get_vtable (klass
));
1389 vt_slot
= mono_method_get_vtable_slot (cmethod
);
1390 if (mono_class_is_interface (cmethod
->klass
)) {
1391 iface_offset
= mono_class_interface_offset (klass
, cmethod
->klass
);
1392 g_assert (iface_offset
!= -1);
1393 vt_slot
+= iface_offset
;
1395 m
= m_class_get_vtable (klass
) [vt_slot
];
1396 if (cmethod
->is_inflated
) {
1397 m
= mono_class_inflate_generic_method_full_checked (m
, NULL
, mono_method_get_context (cmethod
), error
);
1398 return_val_if_nok (error
, NULL
);
1402 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
)) {
1404 * Calling a non-vtype method with a vtype receiver, has to box.
1406 *this_arg
= mono_value_box_checked (mono_domain_get (), klass
, mp
, error
);
1407 } else if (m_class_is_valuetype (klass
)) {
1410 * The original type is an interface, so the receiver is a ref,
1411 the called method is a vtype method, need to unbox.
1413 MonoObject
*this_obj
= *(MonoObject
**)mp
;
1415 *this_arg
= mono_object_unbox_internal (this_obj
);
1418 * Calling a vtype method with a vtype receiver
1424 * Calling a non-vtype method
1426 *this_arg
= *(gpointer
*)mp
;
1433 * mono_gsharedvt_constrained_call:
1435 * Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
1436 * the arguments to the method in the format used by mono_runtime_invoke_checked ().
1439 mono_gsharedvt_constrained_call (gpointer mp
, MonoMethod
*cmethod
, MonoClass
*klass
, gboolean deref_arg
, gpointer
*args
)
1445 gpointer new_args
[16];
1447 m
= constrained_gsharedvt_call_setup (mp
, cmethod
, klass
, &this_arg
, error
);
1448 if (!mono_error_ok (error
)) {
1449 mono_error_set_pending_exception (error
);
1455 if (args
&& deref_arg
) {
1456 new_args
[0] = *(gpointer
*)args
[0];
1459 if (m
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
) {
1460 /* Object.GetType () */
1462 args
[0] = this_arg
;
1466 o
= mono_runtime_invoke_checked (m
, this_arg
, args
, error
);
1467 if (!mono_error_ok (error
)) {
1468 mono_error_set_pending_exception (error
);
1476 mono_gsharedvt_value_copy (gpointer dest
, gpointer src
, MonoClass
*klass
)
1478 if (m_class_is_valuetype (klass
))
1479 mono_value_copy_internal (dest
, src
, klass
);
1481 mono_gc_wbarrier_generic_store_internal (dest
, *(MonoObject
**)src
);
1485 ves_icall_runtime_class_init (MonoVTable
*vtable
)
1487 MONO_REQ_GC_UNSAFE_MODE
;
1490 mono_runtime_class_init_full (vtable
, error
);
1491 mono_error_set_pending_exception (error
);
1496 mono_generic_class_init (MonoVTable
*vtable
)
1499 mono_runtime_class_init_full (vtable
, error
);
1500 mono_error_set_pending_exception (error
);
1504 ves_icall_mono_delegate_ctor (MonoObject
*this_obj_raw
, MonoObject
*target_raw
, gpointer addr
)
1506 HANDLE_FUNCTION_ENTER ();
1508 MONO_HANDLE_DCL (MonoObject
, this_obj
);
1509 MONO_HANDLE_DCL (MonoObject
, target
);
1510 mono_delegate_ctor (this_obj
, target
, addr
, error
);
1511 mono_error_set_pending_exception (error
);
1512 HANDLE_FUNCTION_RETURN ();
1516 ves_icall_mono_delegate_ctor_interp (MonoObject
*this_obj_raw
, MonoObject
*target_raw
, gpointer addr
)
1518 HANDLE_FUNCTION_ENTER ();
1520 MONO_HANDLE_DCL (MonoObject
, this_obj
);
1521 MONO_HANDLE_DCL (MonoObject
, target
);
1523 mini_get_interp_callbacks ()->delegate_ctor (this_obj
, target
, addr
, error
);
1524 mono_error_set_pending_exception (error
);
1525 HANDLE_FUNCTION_RETURN ();
1529 mono_fill_class_rgctx (MonoVTable
*vtable
, int index
)
1534 res
= mono_class_fill_runtime_generic_context (vtable
, index
, error
);
1535 if (!mono_error_ok (error
)) {
1536 mono_error_set_pending_exception (error
);
1543 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext
*mrgctx
, int index
)
1548 res
= mono_method_fill_runtime_generic_context (mrgctx
, index
, error
);
1549 if (!mono_error_ok (error
)) {
1550 mono_error_set_pending_exception (error
);
1557 mono_get_assembly_object (MonoImage
*image
)
1560 MonoObjectHandle result
= MONO_HANDLE_CAST (MonoObject
, mono_assembly_get_object_handle (mono_domain_get (), image
->assembly
, error
));
1561 ICALL_RETURN_OBJ (result
);
1565 mono_get_method_object (MonoMethod
*method
)
1568 MonoObject
* result
;
1569 result
= (MonoObject
*)mono_method_get_object_checked (mono_domain_get (), method
, method
->klass
, error
);
1570 mono_error_set_pending_exception (error
);
1575 mono_ckfinite (double d
)
1577 if (mono_isinf (d
) || mono_isnan (d
))
1578 mono_set_pending_exception (mono_get_exception_arithmetic ());
1583 mono_throw_method_access (MonoMethod
*caller
, MonoMethod
*callee
)
1585 char *caller_name
= mono_method_get_reflection_name (caller
);
1586 char *callee_name
= mono_method_get_reflection_name (callee
);
1589 mono_error_set_generic_error (error
, "System", "MethodAccessException", "Method `%s' is inaccessible from method `%s'", callee_name
, caller_name
);
1590 mono_error_set_pending_exception (error
);
1591 g_free (callee_name
);
1592 g_free (caller_name
);
1596 mono_dummy_jit_icall (void)