2 * jit-icalls.c: internal calls used by the JIT
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2002 Ximian, Inc.
9 * Copyright 2003-2011 Novell Inc (http://www.novell.com)
10 * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
19 #include "jit-icalls.h"
20 #include <mono/utils/mono-error-internals.h>
22 mono_ldftn (MonoMethod *method)
26 addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
28 return mono_create_ftnptr (mono_domain_get (), addr);
32 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
38 mono_set_pending_exception (mono_get_exception_null_reference ());
42 res = mono_object_get_virtual_method (obj, method);
44 if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
45 MonoGenericContext context = { NULL, NULL };
47 if (res->klass->generic_class)
48 context.class_inst = res->klass->generic_class->context.class_inst;
49 else if (res->klass->generic_container)
50 context.class_inst = res->klass->generic_container->context.class_inst;
51 context.method_inst = mono_method_get_context (method)->method_inst;
53 res = mono_class_inflate_generic_method_checked (res, &context, &error);
54 if (!mono_error_ok (&error)) {
55 mono_error_set_pending_exception (&error);
60 /* An rgctx wrapper is added by the trampolines no need to do it here */
62 return mono_ldftn (res);
66 mono_ldvirtfn (MonoObject *obj, MonoMethod *method)
68 return ldvirtfn_internal (obj, method, FALSE);
72 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method)
74 return ldvirtfn_internal (obj, method, TRUE);
78 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
81 mono_set_pending_exception (mono_get_exception_null_reference ());
84 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class)) {
85 mono_set_pending_exception (mono_get_exception_array_type_mismatch ());
90 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
93 mono_llmult (gint64 a, gint64 b)
99 mono_llmult_ovf_un (guint64 a, guint64 b)
102 guint32 ah = a >> 32;
104 guint32 bh = b >> 32;
107 // fixme: this is incredible slow
110 goto raise_exception;
112 res = (guint64)al * (guint64)bl;
114 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
117 goto raise_exception;
119 res += ((guint64)t1) << 32;
124 mono_set_pending_exception (mono_get_exception_overflow ());
129 mono_llmult_ovf (gint64 a, gint64 b)
136 Use Karatsuba algorithm where:
137 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
138 where Ah is the "high half" (most significant 32 bits) of a and
139 where Al is the "low half" (least significant 32 bits) of a and
140 where Bh is the "high half" of b and Bl is the "low half" and
141 where R is the Radix or "size of the half" (in our case 32 bits)
143 Note, for the product of two 64 bit numbers to fit into a 64
144 result, ah and/or bh must be 0. This will save us from doing
145 the AhBh term at all.
147 Also note that we refactor so that we don't overflow 64 bits with
148 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
154 /* need to work with absoulte values, so find out what the
155 resulting sign will be and convert any negative numbers
156 from two's complement
160 if (((guint32)ah == 0x80000000) && (al == 0)) {
161 /* This has no two's complement */
167 goto raise_exception;
170 /* flip the bits and add 1 */
181 if (((guint32)bh == 0x80000000) && (bl == 0)) {
182 /* This has no two's complement */
188 goto raise_exception;
191 /* flip the bits and add 1 */
201 /* we overflow for sure if both upper halves are greater
202 than zero because we would need to shift their
203 product 64 bits to the left and that will not fit
204 in a 64 bit result */
206 goto raise_exception;
207 if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000)
208 goto raise_exception;
210 /* do the AlBl term first */
211 t1 = (gint64)al * (gint64)bl;
215 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
216 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
217 /* check for overflow */
219 if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
220 goto raise_exception;
225 goto raise_exception;
233 mono_set_pending_exception (mono_get_exception_overflow ());
238 mono_lldiv (gint64 a, gint64 b)
240 #ifdef MONO_ARCH_NEED_DIV_CHECK
242 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
245 else if (b == -1 && a == (-9223372036854775807LL - 1LL)) {
246 mono_set_pending_exception (mono_get_exception_arithmetic ());
254 mono_llrem (gint64 a, gint64 b)
256 #ifdef MONO_ARCH_NEED_DIV_CHECK
258 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
261 else if (b == -1 && a == (-9223372036854775807LL - 1LL)) {
262 mono_set_pending_exception (mono_get_exception_arithmetic ());
270 mono_lldiv_un (guint64 a, guint64 b)
272 #ifdef MONO_ARCH_NEED_DIV_CHECK
274 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
282 mono_llrem_un (guint64 a, guint64 b)
284 #ifdef MONO_ARCH_NEED_DIV_CHECK
286 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
295 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
298 mono_lshl (guint64 a, gint32 shamt)
302 res = a << (shamt & 0x7f);
304 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
310 mono_lshr_un (guint64 a, gint32 shamt)
314 res = a >> (shamt & 0x7f);
316 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
322 mono_lshr (gint64 a, gint32 shamt)
326 res = a >> (shamt & 0x7f);
328 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
335 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
338 mono_idiv (gint32 a, gint32 b)
340 #ifdef MONO_ARCH_NEED_DIV_CHECK
342 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
345 else if (b == -1 && a == (0x80000000)) {
346 mono_set_pending_exception (mono_get_exception_overflow ());
354 mono_idiv_un (guint32 a, guint32 b)
356 #ifdef MONO_ARCH_NEED_DIV_CHECK
358 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
366 mono_irem (gint32 a, gint32 b)
368 #ifdef MONO_ARCH_NEED_DIV_CHECK
370 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
373 else if (b == -1 && a == (0x80000000)) {
374 mono_set_pending_exception (mono_get_exception_overflow ());
382 mono_irem_un (guint32 a, guint32 b)
384 #ifdef MONO_ARCH_NEED_DIV_CHECK
386 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
395 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
398 mono_imul (gint32 a, gint32 b)
404 mono_imul_ovf (gint32 a, gint32 b)
408 res = (gint64)a * (gint64)b;
410 if ((res > 0x7fffffffL) || (res < -2147483648LL)) {
411 mono_set_pending_exception (mono_get_exception_overflow ());
419 mono_imul_ovf_un (guint32 a, guint32 b)
423 res = (guint64)a * (guint64)b;
426 mono_set_pending_exception (mono_get_exception_overflow ());
434 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
436 mono_fdiv (double a, double b)
442 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
445 mono_fsub (double a, double b)
451 mono_fadd (double a, double b)
457 mono_fmul (double a, double b)
469 mono_fconv_r4 (double a)
475 mono_conv_to_r8 (int a)
481 mono_conv_to_r4 (int a)
483 return (double)(float)a;
487 mono_fconv_i1 (double a)
493 mono_fconv_i2 (double a)
499 mono_fconv_i4 (double a)
505 mono_fconv_u1 (double a)
511 mono_fconv_u2 (double a)
517 mono_fcmp_eq (double a, double b)
523 mono_fcmp_ge (double a, double b)
529 mono_fcmp_gt (double a, double b)
535 mono_fcmp_le (double a, double b)
541 mono_fcmp_lt (double a, double b)
547 mono_fcmp_ne_un (double a, double b)
549 return isunordered (a, b) || a != b;
553 mono_fcmp_ge_un (double a, double b)
555 return isunordered (a, b) || a >= b;
559 mono_fcmp_gt_un (double a, double b)
561 return isunordered (a, b) || a > b;
565 mono_fcmp_le_un (double a, double b)
567 return isunordered (a, b) || a <= b;
571 mono_fcmp_lt_un (double a, double b)
573 return isunordered (a, b) || a < b;
577 mono_fceq (double a, double b)
583 mono_fcgt (double a, double b)
589 mono_fcgt_un (double a, double b)
591 return isunordered (a, b) || a > b;
595 mono_fclt (double a, double b)
601 mono_fclt_un (double a, double b)
603 return isunordered (a, b) || a < b;
607 mono_isfinite (double a)
612 g_assert_not_reached ();
618 mono_fload_r4 (float *ptr)
624 mono_fstore_r4 (double val, float *ptr)
629 /* returns the integer bitpattern that is passed in the regs or stack */
631 mono_fload_r4_arg (double val)
633 float v = (float)val;
634 return *(guint32*)&v;
640 mono_array_new_va (MonoMethod *cm, ...)
642 MonoDomain *domain = mono_domain_get ();
645 intptr_t *lower_bounds;
650 pcount = mono_method_signature (cm)->param_count;
651 rank = cm->klass->rank;
655 lengths = alloca (sizeof (uintptr_t) * pcount);
656 for (i = 0; i < pcount; ++i)
657 lengths [i] = d = va_arg(ap, int);
659 if (rank == pcount) {
660 /* Only lengths provided. */
661 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
662 lower_bounds = alloca (sizeof (intptr_t) * rank);
663 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
668 g_assert (pcount == (rank * 2));
669 /* lower bounds are first. */
670 lower_bounds = (intptr_t*)lengths;
675 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
678 /* Specialized version of mono_array_new_va () which avoids varargs */
680 mono_array_new_1 (MonoMethod *cm, guint32 length)
682 MonoDomain *domain = mono_domain_get ();
683 uintptr_t lengths [1];
684 intptr_t *lower_bounds;
688 pcount = mono_method_signature (cm)->param_count;
689 rank = cm->klass->rank;
691 lengths [0] = length;
693 g_assert (rank == pcount);
695 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
696 lower_bounds = alloca (sizeof (intptr_t) * rank);
697 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
702 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
706 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
708 MonoDomain *domain = mono_domain_get ();
709 uintptr_t lengths [2];
710 intptr_t *lower_bounds;
714 pcount = mono_method_signature (cm)->param_count;
715 rank = cm->klass->rank;
717 lengths [0] = length1;
718 lengths [1] = length2;
720 g_assert (rank == pcount);
722 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
723 lower_bounds = alloca (sizeof (intptr_t) * rank);
724 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
729 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
733 mono_array_new_3 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3)
735 MonoDomain *domain = mono_domain_get ();
736 uintptr_t lengths [3];
737 intptr_t *lower_bounds;
741 pcount = mono_method_signature (cm)->param_count;
742 rank = cm->klass->rank;
744 lengths [0] = length1;
745 lengths [1] = length2;
746 lengths [2] = length3;
748 g_assert (rank == pcount);
750 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
751 lower_bounds = alloca (sizeof (intptr_t) * rank);
752 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
757 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
761 mono_array_new_4 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3, guint32 length4)
763 MonoDomain *domain = mono_domain_get ();
764 uintptr_t lengths [4];
765 intptr_t *lower_bounds;
769 pcount = mono_method_signature (cm)->param_count;
770 rank = cm->klass->rank;
772 lengths [0] = length1;
773 lengths [1] = length2;
774 lengths [2] = length3;
775 lengths [3] = length4;
777 g_assert (rank == pcount);
779 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
780 lower_bounds = alloca (sizeof (intptr_t) * rank);
781 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
786 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
790 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
795 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
797 mono_class_init (field->parent);
799 vtable = mono_class_vtable_full (domain, field->parent, TRUE);
800 if (!vtable->initialized)
801 mono_runtime_class_init (vtable);
803 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
805 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
806 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
808 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
814 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
817 MonoClass *handle_class;
820 res = mono_ldtoken_checked (image, token, &handle_class, context, &error);
821 if (!mono_error_ok (&error)) {
822 mono_error_set_pending_exception (&error);
825 mono_class_init (handle_class);
831 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
833 MonoMethodSignature *sig = mono_method_signature (method);
834 MonoGenericContext *generic_context;
836 if (sig->is_inflated) {
837 generic_context = mono_method_get_context (method);
839 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
840 g_assert (generic_container);
841 generic_context = &generic_container->context;
844 return mono_ldtoken_wrapper (image, token, generic_context);
848 mono_fconv_u8 (double v)
854 mono_rconv_u8 (float v)
859 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
861 mono_fconv_i8 (double v)
868 mono_fconv_u4 (double v)
870 /* MS.NET behaves like this for some reason */
872 if (isinf (v) || isnan (v))
880 /* Solaris doesn't have trunc */
882 extern long double aintl (long double);
885 /* FIXME: This means we will never throw overflow exceptions */
888 #endif /* HAVE_TRUNC */
891 mono_fconv_ovf_i8 (double v)
897 if (isnan(v) || trunc (v) != res) {
898 mono_set_pending_exception (mono_get_exception_overflow ());
905 mono_fconv_ovf_u8 (double v)
910 * The soft-float implementation of some ARM devices have a buggy guin64 to double
911 * conversion that it looses precision even when the integer if fully representable
914 * This was found with 4294967295ull, converting to double and back looses one bit of precision.
916 * To work around this issue we test for value boundaries instead.
918 #if defined(__arm__) && defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
919 if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
920 mono_set_pending_exception (mono_get_exception_overflow ());
926 if (isnan(v) || trunc (v) != res) {
927 mono_set_pending_exception (mono_get_exception_overflow ());
934 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
936 mono_rconv_i8 (float v)
943 mono_rconv_ovf_i8 (float v)
949 if (isnan(v) || trunc (v) != res) {
950 mono_set_pending_exception (mono_get_exception_overflow ());
957 mono_rconv_ovf_u8 (float v)
962 if (isnan(v) || trunc (v) != res) {
963 mono_set_pending_exception (mono_get_exception_overflow ());
969 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
971 mono_lconv_to_r8 (gint64 a)
977 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
979 mono_lconv_to_r4 (gint64 a)
985 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
987 mono_conv_to_r8_un (guint32 a)
993 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
995 mono_lconv_to_r8_un (guint64 a)
1001 #if defined(__native_client_codegen__) || defined(__native_client__)
1002 /* When we cross-compile to Native Client we can't directly embed calls */
1003 /* to the math library on the host. This will use the fmod on the target*/
1005 mono_fmod(double a, double b)
1012 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
1014 MonoMethod *vmethod;
1016 MonoGenericContext *context = mono_method_get_context (method);
1018 mono_jit_stats.generic_virtual_invocations++;
1021 mono_set_pending_exception (mono_get_exception_null_reference ());
1024 vmethod = mono_object_get_virtual_method (obj, method);
1025 g_assert (!vmethod->klass->generic_container);
1026 g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
1027 g_assert (!context->method_inst || !context->method_inst->is_open);
1029 addr = mono_compile_method (vmethod);
1031 addr = mini_add_method_trampoline (vmethod, addr, mono_method_needs_static_rgctx_invoke (vmethod, FALSE), FALSE);
1033 /* Since this is a virtual call, have to unbox vtypes */
1034 if (obj->vtable->klass->valuetype)
1035 *this_arg = mono_object_unbox (obj);
1043 mono_helper_ldstr (MonoImage *image, guint32 idx)
1045 return mono_ldstr (mono_domain_get (), image, idx);
1049 mono_helper_ldstr_mscorlib (guint32 idx)
1051 return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
1055 mono_helper_newobj_mscorlib (guint32 idx)
1058 MonoClass *klass = mono_class_get_checked (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx, &error);
1060 if (!mono_error_ok (&error)) {
1061 mono_error_set_pending_exception (&error);
1065 return mono_object_new (mono_domain_get (), klass);
1069 * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
1070 * in generated code. So instead we emit a call to this function and place a gdb
1079 mono_create_corlib_exception_0 (guint32 token)
1081 return mono_exception_from_token (mono_defaults.corlib, token);
1085 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
1087 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
1091 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
1093 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
1097 mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
1099 MonoJitTlsData *jit_tls = NULL;
1102 if (mini_get_debug_options ()->better_cast_details) {
1103 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1104 jit_tls->class_cast_from = NULL;
1110 oklass = obj->vtable->klass;
1111 if ((klass->enumtype && oklass == klass->element_class) || (oklass->enumtype && klass == oklass->element_class))
1113 if (mono_object_isinst (obj, klass))
1116 if (mini_get_debug_options ()->better_cast_details) {
1117 jit_tls->class_cast_from = oklass;
1118 jit_tls->class_cast_to = klass;
1121 mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib,
1122 "System", "InvalidCastException"));
1128 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1130 MonoJitTlsData *jit_tls = NULL;
1131 gpointer cached_vtable, obj_vtable;
1133 if (mini_get_debug_options ()->better_cast_details) {
1134 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1135 jit_tls->class_cast_from = NULL;
1141 cached_vtable = *cache;
1142 obj_vtable = obj->vtable;
1144 if (cached_vtable == obj_vtable)
1147 if (mono_object_isinst (obj, klass)) {
1148 *cache = obj_vtable;
1152 if (mini_get_debug_options ()->better_cast_details) {
1153 jit_tls->class_cast_from = obj->vtable->klass;
1154 jit_tls->class_cast_to = klass;
1157 mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib,
1158 "System", "InvalidCastException"));
1164 mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1166 size_t cached_vtable, obj_vtable;
1171 cached_vtable = (size_t)*cache;
1172 obj_vtable = (size_t)obj->vtable;
1174 if ((cached_vtable & ~0x1) == obj_vtable) {
1175 return (cached_vtable & 0x1) ? NULL : obj;
1178 if (mono_object_isinst (obj, klass)) {
1179 *cache = (gpointer)obj_vtable;
1183 *cache = (gpointer)(obj_vtable | 0x1);
1189 mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpointer func)
1191 MonoMarshalSpec **mspecs;
1192 MonoMethodPInvoke piinfo;
1195 mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
1196 memset (&piinfo, 0, sizeof (piinfo));
1198 m = mono_marshal_get_native_func_wrapper (image, sig, &piinfo, mspecs, func);
1200 return mono_compile_method (m);
1204 constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg)
1209 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1210 mono_set_pending_exception (mono_get_exception_execution_engine ("Not yet supported."));
1214 if (mono_method_signature (cmethod)->pinvoke) {
1215 /* Object.GetType () */
1216 m = mono_marshal_get_native_wrapper (cmethod, TRUE, FALSE);
1218 /* Lookup the virtual method */
1219 mono_class_setup_vtable (klass);
1220 g_assert (klass->vtable);
1221 vt_slot = mono_method_get_vtable_slot (cmethod);
1222 if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1225 iface_offset = mono_class_interface_offset (klass, cmethod->klass);
1226 g_assert (iface_offset != -1);
1227 vt_slot += iface_offset;
1229 m = klass->vtable [vt_slot];
1230 if (cmethod->is_inflated)
1231 m = mono_class_inflate_generic_method (m, mono_method_get_context (cmethod));
1233 if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
1235 * Calling a non-vtype method with a vtype receiver, has to box.
1237 *this_arg = mono_value_box (mono_domain_get (), klass, mp);
1238 else if (klass->valuetype)
1240 * Calling a vtype method with a vtype receiver
1245 * Calling a non-vtype method
1247 *this_arg = *(gpointer*)mp;
1252 * mono_gsharedvt_constrained_call:
1254 * Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
1255 * the arguments to the method in the format used by mono_runtime_invoke ().
1258 mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
1262 gpointer new_args [16];
1264 m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
1267 if (args && deref_arg) {
1268 new_args [0] = *(gpointer*)args [0];
1271 if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
1272 /* Object.GetType () */
1274 args [0] = this_arg;
1277 return mono_runtime_invoke (m, this_arg, args, NULL);
1281 mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass)
1283 if (klass->valuetype)
1284 mono_value_copy (dest, src, klass);
1286 mono_gc_wbarrier_generic_store (dest, *(MonoObject**)src);
1290 mono_generic_class_init (MonoVTable *vtable)
1292 mono_runtime_class_init (vtable);
1296 mono_fill_class_rgctx (MonoVTable *vtable, int index)
1298 return mono_class_fill_runtime_generic_context (vtable, index);
1302 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index)
1304 return mono_method_fill_runtime_generic_context (mrgctx, index);