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
);
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
);
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
;
728 mono_array_new_n (MonoMethod
*cm
, int n
, uintptr_t lengths
[], intptr_t lower_bounds
[])
731 intptr_t *plower_bounds
= NULL
;
732 const int pcount
= mono_method_signature_internal (cm
)->param_count
;
733 const int rank
= m_class_get_rank (cm
->klass
);
735 g_assert (rank
== pcount
);
736 g_assert (rank
== n
);
738 if (m_class_get_byval_arg (cm
->klass
)->type
== MONO_TYPE_ARRAY
)
739 plower_bounds
= lower_bounds
;
741 MonoArray
*arr
= mono_array_new_full_checked (mono_domain_get (),
742 cm
->klass
, lengths
, plower_bounds
, error
);
744 return mono_error_set_pending_exception (error
) ? NULL
: arr
;
747 /* Specialized version of mono_array_new_va () which avoids varargs */
749 mono_array_new_1 (MonoMethod
*cm
, guint32 length
)
751 uintptr_t lengths
[ ] = {length
};
752 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
753 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
757 mono_array_new_2 (MonoMethod
*cm
, guint32 length1
, guint32 length2
)
759 uintptr_t lengths
[ ] = {length1
, length2
};
760 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
761 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
765 mono_array_new_3 (MonoMethod
*cm
, guint32 length1
, guint32 length2
, guint32 length3
)
767 uintptr_t lengths
[ ] = {length1
, length2
, length3
};
768 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
769 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
773 mono_array_new_4 (MonoMethod
*cm
, guint32 length1
, guint32 length2
, guint32 length3
, guint32 length4
)
775 uintptr_t lengths
[ ] = {length1
, length2
, length3
, length4
};
776 intptr_t lower_bounds
[G_N_ELEMENTS (lengths
)] = {0};
777 return mono_array_new_n (cm
, G_N_ELEMENTS (lengths
), lengths
, lower_bounds
);
781 mono_class_static_field_address (MonoDomain
*domain
, MonoClassField
*field
)
787 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
789 mono_class_init_internal (field
->parent
);
791 vtable
= mono_class_vtable_checked (domain
, field
->parent
, error
);
792 if (!is_ok (error
)) {
793 mono_error_set_pending_exception (error
);
796 if (!vtable
->initialized
) {
797 if (!mono_runtime_class_init_full (vtable
, error
)) {
798 mono_error_set_pending_exception (error
);
803 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
805 if (field
->offset
== -1) {
807 g_assert (domain
->special_static_fields
);
808 mono_domain_lock (domain
);
809 addr
= g_hash_table_lookup (domain
->special_static_fields
, field
);
810 mono_domain_unlock (domain
);
811 addr
= mono_get_special_static_data (GPOINTER_TO_UINT (addr
));
813 addr
= (char*)mono_vtable_get_static_field_data (vtable
) + field
->offset
;
819 mono_ldtoken_wrapper (MonoImage
*image
, int token
, MonoGenericContext
*context
)
822 MonoClass
*handle_class
;
825 res
= mono_ldtoken_checked (image
, token
, &handle_class
, context
, error
);
826 if (!is_ok (error
)) {
827 mono_error_set_pending_exception (error
);
830 mono_class_init_internal (handle_class
);
836 mono_ldtoken_wrapper_generic_shared (MonoImage
*image
, int token
, MonoMethod
*method
)
838 MonoMethodSignature
*sig
= mono_method_signature_internal (method
);
839 MonoGenericContext
*generic_context
;
841 if (sig
->is_inflated
) {
842 generic_context
= mono_method_get_context (method
);
844 MonoGenericContainer
*generic_container
= mono_method_get_generic_container (method
);
845 g_assert (generic_container
);
846 generic_context
= &generic_container
->context
;
849 return mono_ldtoken_wrapper (image
, token
, generic_context
);
853 mono_fconv_u8 (double v
)
855 #if defined(TARGET_X86) || defined(TARGET_AMD64)
856 const double two63
= 2147483648.0 * 4294967296.0;
860 return (gint64
)(v
- two63
) + ((guint64
)1 << 63);
863 if (mono_isinf (v
) || mono_isnan (v
))
869 #ifdef MONO_ARCH_EMULATE_FCONV_TO_U8
871 mono_fconv_u8_2 (double v
)
873 // Separate from mono_fconv_u8 to avoid duplicate JIT icall.
875 // When there are duplicates, there is single instancing
876 // against function address that breaks stuff. For example,
877 // wrappers are only produced for one of them, breaking FullAOT.
878 return mono_fconv_u8 (v
);
882 mono_rconv_u8 (float v
)
884 #if defined(TARGET_X86) || defined(TARGET_AMD64)
885 const float two63
= 2147483648.0 * 4294967296.0;
889 return (gint64
)(v
- two63
) + ((guint64
)1 << 63);
892 if (mono_isinf (v
) || mono_isnan (v
))
899 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
901 mono_fconv_i8 (double v
)
908 mono_fconv_u4 (double v
)
910 /* MS.NET behaves like this for some reason */
911 if (mono_isinf (v
) || mono_isnan (v
))
916 #ifdef MONO_ARCH_EMULATE_FCONV_TO_U4
918 mono_fconv_u4_2 (double v
)
920 // Separate from mono_fconv_u4 to avoid duplicate JIT icall.
922 // When there are duplicates, there is single instancing
923 // against function address that breaks stuff. For example,
924 // wrappers are only produced for one of them, breaking FullAOT.
925 return mono_fconv_u4 (v
);
929 mono_rconv_u4 (float v
)
931 if (mono_isinf (v
) || mono_isnan (v
))
938 mono_fconv_ovf_i8 (double v
)
940 const gint64 res
= (gint64
)v
;
942 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
944 mono_error_set_overflow (error
);
945 mono_error_set_pending_exception (error
);
952 mono_fconv_ovf_u8 (double v
)
957 * The soft-float implementation of some ARM devices have a buggy guin64 to double
958 * conversion that it looses precision even when the integer if fully representable
961 * This was found with 4294967295ull, converting to double and back looses one bit of precision.
963 * To work around this issue we test for value boundaries instead.
965 #if defined(__arm__) && defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
966 if (mono_isnan (v
) || !(v
>= -0.5 && v
<= ULLONG_MAX
+0.5)) {
968 mono_error_set_overflow (error
);
969 mono_error_set_pending_exception (error
);
975 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
977 mono_error_set_overflow (error
);
978 mono_error_set_pending_exception (error
);
986 mono_fconv_ovf_u8_un (double v
)
988 return mono_fconv_ovf_u8 (v
);
991 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
993 mono_rconv_i8 (float v
)
1000 mono_rconv_ovf_i8 (float v
)
1002 const gint64 res
= (gint64
)v
;
1004 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1006 mono_error_set_overflow (error
);
1007 mono_error_set_pending_exception (error
);
1014 mono_rconv_ovf_u8 (float v
)
1019 if (mono_isnan (v
) || mono_trunc (v
) != res
) {
1021 mono_error_set_overflow (error
);
1022 mono_error_set_pending_exception (error
);
1029 mono_rconv_ovf_u8_un (float v
)
1031 return mono_rconv_ovf_u8 (v
);
1034 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
1036 mono_lconv_to_r8 (gint64 a
)
1042 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
1044 mono_lconv_to_r4 (gint64 a
)
1050 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
1052 mono_conv_to_r8_un (guint32 a
)
1058 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
1060 mono_lconv_to_r8_un (guint64 a
)
1066 #ifdef MONO_ARCH_EMULATE_FREM
1067 // Wrapper to avoid taking address of overloaded function.
1069 mono_fmod (double a
, double b
)
1076 mono_helper_compile_generic_method (MonoObject
*obj
, MonoMethod
*method
, gpointer
*this_arg
)
1079 MonoMethod
*vmethod
;
1081 MonoGenericContext
*context
= mono_method_get_context (method
);
1083 UnlockedIncrement (&mono_jit_stats
.generic_virtual_invocations
);
1086 mono_error_set_null_reference (error
);
1087 mono_error_set_pending_exception (error
);
1090 vmethod
= mono_object_get_virtual_method_internal (obj
, method
);
1091 g_assert (!mono_class_is_gtd (vmethod
->klass
));
1092 g_assert (!mono_class_is_ginst (vmethod
->klass
) || !mono_class_get_generic_class (vmethod
->klass
)->context
.class_inst
->is_open
);
1093 g_assert (!context
->method_inst
|| !context
->method_inst
->is_open
);
1095 addr
= mono_compile_method_checked (vmethod
, error
);
1096 if (mono_error_set_pending_exception (error
))
1100 addr
= mini_add_method_trampoline (vmethod
, addr
, mono_method_needs_static_rgctx_invoke (vmethod
, FALSE
), FALSE
);
1102 /* Since this is a virtual call, have to unbox vtypes */
1103 if (m_class_is_valuetype (obj
->vtable
->klass
))
1104 *this_arg
= mono_object_unbox_internal (obj
);
1112 ves_icall_mono_ldstr (MonoDomain
*domain
, MonoImage
*image
, guint32 idx
)
1115 MonoString
*result
= mono_ldstr_checked (domain
, image
, idx
, error
);
1116 mono_error_set_pending_exception (error
);
1121 mono_helper_ldstr (MonoImage
*image
, guint32 idx
)
1124 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), image
, idx
, error
);
1125 mono_error_set_pending_exception (error
);
1130 mono_helper_ldstr_mscorlib (guint32 idx
)
1133 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), mono_defaults
.corlib
, idx
, error
);
1134 mono_error_set_pending_exception (error
);
1139 mono_helper_newobj_mscorlib (guint32 idx
)
1142 MonoClass
*klass
= mono_class_get_checked (mono_defaults
.corlib
, MONO_TOKEN_TYPE_DEF
| idx
, error
);
1144 if (!is_ok (error
)) {
1145 mono_error_set_pending_exception (error
);
1149 MonoObject
*obj
= mono_object_new_checked (mono_domain_get (), klass
, error
);
1151 mono_error_set_pending_exception (error
);
1156 * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
1157 * in generated code. So instead we emit a call to this function and place a gdb
1166 mono_create_corlib_exception_0 (guint32 token
)
1168 return mono_exception_from_token (mono_defaults
.corlib
, token
);
1172 mono_create_corlib_exception_1 (guint32 token
, MonoString
*arg_raw
)
1174 HANDLE_FUNCTION_ENTER ();
1176 MONO_HANDLE_DCL (MonoString
, arg
);
1177 MonoExceptionHandle ret
= mono_exception_from_token_two_strings_checked (
1178 mono_defaults
.corlib
, token
, arg
, NULL_HANDLE_STRING
, error
);
1179 mono_error_set_pending_exception (error
);
1180 HANDLE_FUNCTION_RETURN_OBJ (ret
);
1184 mono_create_corlib_exception_2 (guint32 token
, MonoString
*arg1_raw
, MonoString
*arg2_raw
)
1186 HANDLE_FUNCTION_ENTER ();
1188 MONO_HANDLE_DCL (MonoString
, arg1
);
1189 MONO_HANDLE_DCL (MonoString
, arg2
);
1190 MonoExceptionHandle ret
= mono_exception_from_token_two_strings_checked (
1191 mono_defaults
.corlib
, token
, arg1
, arg2
, error
);
1192 mono_error_set_pending_exception (error
);
1193 HANDLE_FUNCTION_RETURN_OBJ (ret
);
1197 mono_object_castclass_unbox (MonoObject
*obj
, MonoClass
*klass
)
1200 MonoJitTlsData
*jit_tls
= NULL
;
1203 if (mini_debug_options
.better_cast_details
) {
1204 jit_tls
= mono_tls_get_jit_tls ();
1205 jit_tls
->class_cast_from
= NULL
;
1211 oklass
= obj
->vtable
->klass
;
1212 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
)))
1214 if (mono_object_isinst_checked (obj
, klass
, error
))
1216 if (mono_error_set_pending_exception (error
))
1219 if (mini_debug_options
.better_cast_details
) {
1220 jit_tls
->class_cast_from
= oklass
;
1221 jit_tls
->class_cast_to
= klass
;
1224 mono_set_pending_exception (mono_exception_from_name (mono_defaults
.corlib
,
1225 "System", "InvalidCastException"));
1231 mono_object_castclass_with_cache (MonoObject
*obj
, MonoClass
*klass
, gpointer
*cache
)
1234 MonoJitTlsData
*jit_tls
= NULL
;
1235 gpointer cached_vtable
, obj_vtable
;
1237 if (mini_debug_options
.better_cast_details
) {
1238 jit_tls
= mono_tls_get_jit_tls ();
1239 jit_tls
->class_cast_from
= NULL
;
1245 cached_vtable
= *cache
;
1246 obj_vtable
= obj
->vtable
;
1248 if (cached_vtable
== obj_vtable
)
1251 if (mono_object_isinst_checked (obj
, klass
, error
)) {
1252 *cache
= obj_vtable
;
1255 if (mono_error_set_pending_exception (error
))
1258 if (mini_debug_options
.better_cast_details
) {
1259 jit_tls
->class_cast_from
= obj
->vtable
->klass
;
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_isinst_with_cache (MonoObject
*obj
, MonoClass
*klass
, gpointer
*cache
)
1273 size_t cached_vtable
, obj_vtable
;
1278 cached_vtable
= (size_t)*cache
;
1279 obj_vtable
= (size_t)obj
->vtable
;
1281 if ((cached_vtable
& ~0x1) == obj_vtable
) {
1282 return (cached_vtable
& 0x1) ? NULL
: obj
;
1285 if (mono_object_isinst_checked (obj
, klass
, error
)) {
1286 *cache
= (gpointer
)obj_vtable
;
1289 if (mono_error_set_pending_exception (error
))
1292 *cache
= (gpointer
)(obj_vtable
| 0x1);
1298 mono_get_native_calli_wrapper (MonoImage
*image
, MonoMethodSignature
*sig
, gpointer func
)
1301 MonoMarshalSpec
**mspecs
;
1302 MonoMethodPInvoke piinfo
;
1305 mspecs
= g_new0 (MonoMarshalSpec
*, sig
->param_count
+ 1);
1306 memset (&piinfo
, 0, sizeof (piinfo
));
1308 m
= mono_marshal_get_native_func_wrapper (image
, sig
, &piinfo
, mspecs
, func
);
1310 for (int i
= sig
->param_count
; i
>= 0; i
--)
1312 mono_metadata_free_marshal_spec (mspecs
[i
]);
1315 gpointer compiled_ptr
= mono_compile_method_checked (m
, error
);
1316 mono_error_set_pending_exception (error
);
1317 g_assert (compiled_ptr
);
1319 return compiled_ptr
;
1323 constrained_gsharedvt_call_setup (gpointer mp
, MonoMethod
*cmethod
, MonoClass
*klass
, gpointer
*this_arg
, MonoError
*error
)
1326 int vt_slot
, iface_offset
;
1327 gboolean is_iface
= FALSE
;
1331 if (mono_class_is_interface (klass
)) {
1332 MonoObject
*this_obj
;
1336 /* Have to use the receiver's type instead of klass, the receiver is a ref type */
1337 this_obj
= *(MonoObject
**)mp
;
1338 g_assert (this_obj
);
1340 klass
= this_obj
->vtable
->klass
;
1343 if (mono_method_signature_internal (cmethod
)->pinvoke
) {
1344 /* Object.GetType () */
1345 m
= mono_marshal_get_native_wrapper (cmethod
, TRUE
, FALSE
);
1347 /* Lookup the virtual method */
1348 mono_class_setup_vtable (klass
);
1349 g_assert (m_class_get_vtable (klass
));
1350 vt_slot
= mono_method_get_vtable_slot (cmethod
);
1351 if (mono_class_is_interface (cmethod
->klass
)) {
1352 iface_offset
= mono_class_interface_offset (klass
, cmethod
->klass
);
1353 g_assert (iface_offset
!= -1);
1354 vt_slot
+= iface_offset
;
1356 m
= m_class_get_vtable (klass
) [vt_slot
];
1357 if (cmethod
->is_inflated
) {
1358 m
= mono_class_inflate_generic_method_full_checked (m
, NULL
, mono_method_get_context (cmethod
), error
);
1359 return_val_if_nok (error
, NULL
);
1363 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
)) {
1365 * Calling a non-vtype method with a vtype receiver, has to box.
1367 *this_arg
= mono_value_box_checked (mono_domain_get (), klass
, mp
, error
);
1368 } else if (m_class_is_valuetype (klass
)) {
1371 * The original type is an interface, so the receiver is a ref,
1372 the called method is a vtype method, need to unbox.
1374 MonoObject
*this_obj
= *(MonoObject
**)mp
;
1376 *this_arg
= mono_object_unbox_internal (this_obj
);
1379 * Calling a vtype method with a vtype receiver
1385 * Calling a non-vtype method
1387 *this_arg
= *(gpointer
*)mp
;
1394 * mono_gsharedvt_constrained_call:
1396 * Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
1397 * the arguments to the method in the format used by mono_runtime_invoke_checked ().
1400 mono_gsharedvt_constrained_call (gpointer mp
, MonoMethod
*cmethod
, MonoClass
*klass
, gboolean deref_arg
, gpointer
*args
)
1406 gpointer new_args
[16];
1408 m
= constrained_gsharedvt_call_setup (mp
, cmethod
, klass
, &this_arg
, error
);
1409 if (!is_ok (error
)) {
1410 mono_error_set_pending_exception (error
);
1416 if (args
&& deref_arg
) {
1417 new_args
[0] = *(gpointer
*)args
[0];
1420 if (m
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
) {
1421 /* Object.GetType () */
1423 args
[0] = this_arg
;
1427 o
= mono_runtime_invoke_checked (m
, this_arg
, args
, error
);
1428 if (!is_ok (error
)) {
1429 mono_error_set_pending_exception (error
);
1437 mono_gsharedvt_value_copy (gpointer dest
, gpointer src
, MonoClass
*klass
)
1439 if (m_class_is_valuetype (klass
))
1440 mono_value_copy_internal (dest
, src
, klass
);
1442 mono_gc_wbarrier_generic_store_internal (dest
, *(MonoObject
**)src
);
1446 ves_icall_runtime_class_init (MonoVTable
*vtable
)
1448 MONO_REQ_GC_UNSAFE_MODE
;
1451 mono_runtime_class_init_full (vtable
, error
);
1452 mono_error_set_pending_exception (error
);
1457 mono_generic_class_init (MonoVTable
*vtable
)
1460 mono_runtime_class_init_full (vtable
, error
);
1461 mono_error_set_pending_exception (error
);
1465 ves_icall_mono_delegate_ctor (MonoObject
*this_obj_raw
, MonoObject
*target_raw
, gpointer addr
)
1467 HANDLE_FUNCTION_ENTER ();
1469 MONO_HANDLE_DCL (MonoObject
, this_obj
);
1470 MONO_HANDLE_DCL (MonoObject
, target
);
1473 mono_error_set_argument_null (error
, "method", "");
1474 mono_error_set_pending_exception (error
);
1477 mono_delegate_ctor (this_obj
, target
, addr
, error
);
1478 mono_error_set_pending_exception (error
);
1481 HANDLE_FUNCTION_RETURN ();
1485 ves_icall_mono_delegate_ctor_interp (MonoObject
*this_obj_raw
, MonoObject
*target_raw
, gpointer addr
)
1487 HANDLE_FUNCTION_ENTER ();
1489 MONO_HANDLE_DCL (MonoObject
, this_obj
);
1490 MONO_HANDLE_DCL (MonoObject
, target
);
1493 mono_error_set_argument_null (error
, "method", "");
1494 mono_error_set_pending_exception (error
);
1497 mini_get_interp_callbacks ()->delegate_ctor (this_obj
, target
, addr
, error
);
1498 mono_error_set_pending_exception (error
);
1501 HANDLE_FUNCTION_RETURN ();
1505 mono_fill_class_rgctx (MonoVTable
*vtable
, int index
)
1510 res
= mono_class_fill_runtime_generic_context (vtable
, index
, error
);
1511 if (!is_ok (error
)) {
1512 mono_error_set_pending_exception (error
);
1519 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext
*mrgctx
, int index
)
1524 res
= mono_method_fill_runtime_generic_context (mrgctx
, index
, error
);
1525 if (!is_ok (error
)) {
1526 mono_error_set_pending_exception (error
);
1533 mono_get_assembly_object (MonoImage
*image
)
1536 MonoObjectHandle result
= MONO_HANDLE_CAST (MonoObject
, mono_assembly_get_object_handle (mono_domain_get (), image
->assembly
, error
));
1537 ICALL_RETURN_OBJ (result
);
1541 mono_get_method_object (MonoMethod
*method
)
1544 MonoObject
* result
;
1545 result
= (MonoObject
*)mono_method_get_object_checked (mono_domain_get (), method
, method
->klass
, error
);
1546 mono_error_set_pending_exception (error
);
1551 mono_ckfinite (double d
)
1553 if (mono_isinf (d
) || mono_isnan (d
))
1554 mono_set_pending_exception (mono_get_exception_arithmetic ());
1559 mono_throw_method_access (MonoMethod
*caller
, MonoMethod
*callee
)
1561 char *caller_name
= mono_method_get_reflection_name (caller
);
1562 char *callee_name
= mono_method_get_reflection_name (callee
);
1565 mono_error_set_generic_error (error
, "System", "MethodAccessException", "Method `%s' is inaccessible from method `%s'", callee_name
, caller_name
);
1566 mono_error_set_pending_exception (error
);
1567 g_free (callee_name
);
1568 g_free (caller_name
);
1572 mono_throw_bad_image ()
1575 mono_error_set_generic_error (error
, "System", "BadImageFormatException", "Bad IL format.");
1576 mono_error_set_pending_exception (error
);
1580 mono_dummy_jit_icall (void)