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"
22 mono_ldftn (MonoMethod *method)
28 addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
30 return mono_create_ftnptr (mono_domain_get (), addr);
34 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
41 mono_raise_exception (mono_get_exception_null_reference ());
43 res = mono_object_get_virtual_method (obj, method);
45 if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
46 MonoGenericContext context = { NULL, NULL };
48 if (res->klass->generic_class)
49 context.class_inst = res->klass->generic_class->context.class_inst;
50 else if (res->klass->generic_container)
51 context.class_inst = res->klass->generic_container->context.class_inst;
52 context.method_inst = mono_method_get_context (method)->method_inst;
54 res = mono_class_inflate_generic_method (res, &context);
57 /* An rgctx wrapper is added by the trampolines no need to do it here */
59 return mono_ldftn (res);
63 mono_ldvirtfn (MonoObject *obj, MonoMethod *method)
65 return ldvirtfn_internal (obj, method, FALSE);
69 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method)
71 return ldvirtfn_internal (obj, method, TRUE);
75 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
80 mono_raise_exception (mono_get_exception_null_reference ());
81 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
82 mono_raise_exception (mono_get_exception_array_type_mismatch ());
85 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
88 mono_llmult (gint64 a, gint64 b)
90 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
95 mono_llmult_ovf_un (guint64 a, guint64 b)
100 guint32 bh = b >> 32;
105 // fixme: this is incredible slow
108 goto raise_exception;
110 res = (guint64)al * (guint64)bl;
112 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
115 goto raise_exception;
117 res += ((guint64)t1) << 32;
122 mono_raise_exception (mono_get_exception_overflow ());
127 mono_llmult_ovf (gint64 a, gint64 b)
134 Use Karatsuba algorithm where:
135 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
136 where Ah is the "high half" (most significant 32 bits) of a and
137 where Al is the "low half" (least significant 32 bits) of a and
138 where Bh is the "high half" of b and Bl is the "low half" and
139 where R is the Radix or "size of the half" (in our case 32 bits)
141 Note, for the product of two 64 bit numbers to fit into a 64
142 result, ah and/or bh must be 0. This will save us from doing
143 the AhBh term at all.
145 Also note that we refactor so that we don't overflow 64 bits with
146 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
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_raise_exception (mono_get_exception_overflow ());
238 mono_lldiv (gint64 a, gint64 b)
242 #ifdef MONO_ARCH_NEED_DIV_CHECK
244 mono_raise_exception (mono_get_exception_divide_by_zero ());
245 else if (b == -1 && a == (-9223372036854775807LL - 1LL))
246 mono_raise_exception (mono_get_exception_arithmetic ());
252 mono_llrem (gint64 a, gint64 b)
256 #ifdef MONO_ARCH_NEED_DIV_CHECK
258 mono_raise_exception (mono_get_exception_divide_by_zero ());
259 else if (b == -1 && a == (-9223372036854775807LL - 1LL))
260 mono_raise_exception (mono_get_exception_arithmetic ());
266 mono_lldiv_un (guint64 a, guint64 b)
270 #ifdef MONO_ARCH_NEED_DIV_CHECK
272 mono_raise_exception (mono_get_exception_divide_by_zero ());
278 mono_llrem_un (guint64 a, guint64 b)
282 #ifdef MONO_ARCH_NEED_DIV_CHECK
284 mono_raise_exception (mono_get_exception_divide_by_zero ());
291 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
294 mono_lshl (guint64 a, gint32 shamt)
298 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
301 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
307 mono_lshr_un (guint64 a, gint32 shamt)
311 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
314 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
320 mono_lshr (gint64 a, gint32 shamt)
324 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
327 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
334 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
337 mono_idiv (gint32 a, gint32 b)
341 #ifdef MONO_ARCH_NEED_DIV_CHECK
343 mono_raise_exception (mono_get_exception_divide_by_zero ());
344 else if (b == -1 && a == (0x80000000))
345 mono_raise_exception (mono_get_exception_overflow ());
351 mono_idiv_un (guint32 a, guint32 b)
355 #ifdef MONO_ARCH_NEED_DIV_CHECK
357 mono_raise_exception (mono_get_exception_divide_by_zero ());
363 mono_irem (gint32 a, gint32 b)
367 #ifdef MONO_ARCH_NEED_DIV_CHECK
369 mono_raise_exception (mono_get_exception_divide_by_zero ());
370 else if (b == -1 && a == (0x80000000))
371 mono_raise_exception (mono_get_exception_overflow ());
378 mono_irem_un (guint32 a, guint32 b)
382 #ifdef MONO_ARCH_NEED_DIV_CHECK
384 mono_raise_exception (mono_get_exception_divide_by_zero ());
391 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
394 mono_imul (gint32 a, gint32 b)
402 mono_imul_ovf (gint32 a, gint32 b)
408 res = (gint64)a * (gint64)b;
410 if ((res > 0x7fffffffL) || (res < -2147483648LL))
411 mono_raise_exception (mono_get_exception_overflow ());
417 mono_imul_ovf_un (guint32 a, guint32 b)
423 res = (guint64)a * (guint64)b;
426 mono_raise_exception (mono_get_exception_overflow ());
432 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
434 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;
652 pcount = mono_method_signature (cm)->param_count;
653 rank = cm->klass->rank;
657 lengths = alloca (sizeof (uintptr_t) * pcount);
658 for (i = 0; i < pcount; ++i)
659 lengths [i] = d = va_arg(ap, int);
661 if (rank == pcount) {
662 /* Only lengths provided. */
663 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
664 lower_bounds = alloca (sizeof (intptr_t) * rank);
665 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
670 g_assert (pcount == (rank * 2));
671 /* lower bounds are first. */
672 lower_bounds = (intptr_t*)lengths;
677 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
680 /* Specialized version of mono_array_new_va () which avoids varargs */
682 mono_array_new_1 (MonoMethod *cm, guint32 length)
684 MonoDomain *domain = mono_domain_get ();
685 uintptr_t lengths [1];
686 intptr_t *lower_bounds;
692 pcount = mono_method_signature (cm)->param_count;
693 rank = cm->klass->rank;
695 lengths [0] = length;
697 g_assert (rank == pcount);
699 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
700 lower_bounds = alloca (sizeof (intptr_t) * rank);
701 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
706 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
710 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
712 MonoDomain *domain = mono_domain_get ();
713 uintptr_t lengths [2];
714 intptr_t *lower_bounds;
720 pcount = mono_method_signature (cm)->param_count;
721 rank = cm->klass->rank;
723 lengths [0] = length1;
724 lengths [1] = length2;
726 g_assert (rank == pcount);
728 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
729 lower_bounds = alloca (sizeof (intptr_t) * rank);
730 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
735 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
739 mono_array_new_3 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3)
741 MonoDomain *domain = mono_domain_get ();
742 uintptr_t lengths [3];
743 intptr_t *lower_bounds;
749 pcount = mono_method_signature (cm)->param_count;
750 rank = cm->klass->rank;
752 lengths [0] = length1;
753 lengths [1] = length2;
754 lengths [2] = length3;
756 g_assert (rank == pcount);
758 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
759 lower_bounds = alloca (sizeof (intptr_t) * rank);
760 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
765 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
769 mono_array_new_4 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3, guint32 length4)
771 MonoDomain *domain = mono_domain_get ();
772 uintptr_t lengths [4];
773 intptr_t *lower_bounds;
779 pcount = mono_method_signature (cm)->param_count;
780 rank = cm->klass->rank;
782 lengths [0] = length1;
783 lengths [1] = length2;
784 lengths [2] = length3;
785 lengths [3] = length4;
787 g_assert (rank == pcount);
789 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
790 lower_bounds = alloca (sizeof (intptr_t) * rank);
791 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
796 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
800 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
807 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
809 mono_class_init (field->parent);
811 vtable = mono_class_vtable_full (domain, field->parent, TRUE);
812 if (!vtable->initialized)
813 mono_runtime_class_init (vtable);
815 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
817 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
818 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
820 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
826 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
828 MonoClass *handle_class;
832 res = mono_ldtoken (image, token, &handle_class, context);
833 mono_class_init (handle_class);
839 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
841 MonoMethodSignature *sig = mono_method_signature (method);
842 MonoGenericContext *generic_context;
844 if (sig->is_inflated) {
845 generic_context = mono_method_get_context (method);
847 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
848 g_assert (generic_container);
849 generic_context = &generic_container->context;
852 return mono_ldtoken_wrapper (image, token, generic_context);
856 mono_fconv_u8 (double v)
861 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
863 mono_fconv_i8 (double v)
865 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
871 mono_fconv_u4 (double v)
873 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
875 /* MS.NET behaves like this for some reason */
877 if (isinf (v) || isnan (v))
885 /* Solaris doesn't have trunc */
887 extern long double aintl (long double);
890 /* FIXME: This means we will never throw overflow exceptions */
893 #endif /* HAVE_TRUNC */
896 mono_fconv_ovf_i8 (double v)
904 if (isnan(v) || trunc (v) != res) {
905 mono_raise_exception (mono_get_exception_overflow ());
911 mono_fconv_ovf_u8 (double v)
917 * The soft-float implementation of some ARM devices have a buggy guin64 to double
918 * conversion that it looses precision even when the integer if fully representable
921 * This was found with 4294967295ull, converting to double and back looses one bit of precision.
923 * To work around this issue we test for value boundaries instead.
925 #if defined(__arm__) && defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
926 if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
927 mono_raise_exception (mono_get_exception_overflow ());
932 if (isnan(v) || trunc (v) != res) {
933 mono_raise_exception (mono_get_exception_overflow ());
939 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
941 mono_lconv_to_r8 (gint64 a)
947 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
949 mono_lconv_to_r4 (gint64 a)
955 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
957 mono_conv_to_r8_un (guint32 a)
963 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
965 mono_lconv_to_r8_un (guint64 a)
971 #if defined(__native_client_codegen__) || defined(__native_client__)
972 /* When we cross-compile to Native Client we can't directly embed calls */
973 /* to the math library on the host. This will use the fmod on the target*/
975 mono_fmod(double a, double b)
982 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
986 MonoGenericContext *context = mono_method_get_context (method);
988 mono_jit_stats.generic_virtual_invocations++;
991 mono_raise_exception (mono_get_exception_null_reference ());
992 vmethod = mono_object_get_virtual_method (obj, method);
993 g_assert (!vmethod->klass->generic_container);
994 g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
995 g_assert (!context->method_inst || !context->method_inst->is_open);
997 addr = mono_compile_method (vmethod);
999 addr = mini_add_method_trampoline (NULL, vmethod, addr, mono_method_needs_static_rgctx_invoke (vmethod, FALSE), FALSE);
1001 /* Since this is a virtual call, have to unbox vtypes */
1002 if (obj->vtable->klass->valuetype)
1003 *this_arg = mono_object_unbox (obj);
1011 mono_helper_ldstr (MonoImage *image, guint32 idx)
1013 return mono_ldstr (mono_domain_get (), image, idx);
1017 mono_helper_ldstr_mscorlib (guint32 idx)
1019 return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
1023 mono_helper_newobj_mscorlib (guint32 idx)
1025 MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx);
1029 return mono_object_new (mono_domain_get (), klass);
1033 * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
1034 * in generated code. So instead we emit a call to this function and place a gdb
1043 mono_create_corlib_exception_0 (guint32 token)
1045 return mono_exception_from_token (mono_defaults.corlib, token);
1049 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
1051 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
1055 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
1057 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
1061 mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
1063 MonoJitTlsData *jit_tls = NULL;
1065 if (mini_get_debug_options ()->better_cast_details) {
1066 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1067 jit_tls->class_cast_from = NULL;
1073 if (klass->enumtype && obj->vtable->klass == klass->element_class)
1075 if (mono_object_isinst (obj, klass))
1078 if (mini_get_debug_options ()->better_cast_details) {
1079 jit_tls->class_cast_from = obj->vtable->klass;
1080 jit_tls->class_cast_to = klass;
1083 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
1084 "System", "InvalidCastException"));
1090 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1092 MonoJitTlsData *jit_tls = NULL;
1093 gpointer cached_vtable, obj_vtable;
1095 if (mini_get_debug_options ()->better_cast_details) {
1096 jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
1097 jit_tls->class_cast_from = NULL;
1103 cached_vtable = *cache;
1104 obj_vtable = obj->vtable;
1106 if (cached_vtable == obj_vtable)
1109 if (mono_object_isinst (obj, klass)) {
1110 *cache = obj_vtable;
1114 if (mini_get_debug_options ()->better_cast_details) {
1115 jit_tls->class_cast_from = obj->vtable->klass;
1116 jit_tls->class_cast_to = klass;
1119 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
1120 "System", "InvalidCastException"));
1126 mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1128 size_t cached_vtable, obj_vtable;
1133 cached_vtable = (size_t)*cache;
1134 obj_vtable = (size_t)obj->vtable;
1136 if ((cached_vtable & ~0x1) == obj_vtable) {
1137 return (cached_vtable & 0x1) ? NULL : obj;
1140 if (mono_object_isinst (obj, klass)) {
1141 *cache = (gpointer)obj_vtable;
1145 *cache = (gpointer)(obj_vtable | 0x1);
1151 mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpointer func)
1153 MonoMarshalSpec **mspecs;
1154 MonoMethodPInvoke piinfo;
1157 mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
1158 memset (&piinfo, 0, sizeof (piinfo));
1160 m = mono_marshal_get_native_func_wrapper (image, sig, &piinfo, mspecs, func);
1162 return mono_compile_method (m);
1166 constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg)
1171 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
1172 mono_raise_exception (mono_get_exception_execution_engine ("Not yet supported."));
1174 if (mono_method_signature (cmethod)->pinvoke) {
1175 /* Object.GetType () */
1176 m = mono_marshal_get_native_wrapper (cmethod, TRUE, FALSE);
1178 /* Lookup the virtual method */
1179 mono_class_setup_vtable (klass);
1180 g_assert (klass->vtable);
1181 vt_slot = mono_method_get_vtable_slot (cmethod);
1182 if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1185 iface_offset = mono_class_interface_offset (klass, cmethod->klass);
1186 g_assert (iface_offset != -1);
1187 vt_slot += iface_offset;
1189 m = klass->vtable [vt_slot];
1191 if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
1193 * Calling a non-vtype method with a vtype receiver, has to box.
1195 *this_arg = mono_value_box (mono_domain_get (), klass, mp);
1196 else if (klass->valuetype)
1198 * Calling a vtype method with a vtype receiver
1203 * Calling a non-vtype method
1205 *this_arg = *(gpointer*)mp;
1210 * mono_gsharedvt_constrained_call:
1212 * Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
1213 * the arguments to the method in the format used by mono_runtime_invoke ().
1216 mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
1220 gpointer new_args [16];
1222 m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
1223 if (args && deref_arg) {
1224 new_args [0] = *(gpointer*)args [0];
1227 if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
1228 /* Object.GetType () */
1230 args [0] = this_arg;
1233 return mono_runtime_invoke (m, this_arg, args, NULL);
1237 mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass)
1239 if (klass->valuetype)
1240 mono_value_copy (dest, src, klass);
1242 mono_gc_wbarrier_generic_store (dest, *(MonoObject**)src);