X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fjit-icalls.c;h=d1bb391250e2d5c21d81af283d126b55bd8e0ab3;hb=a8d9ca9c379b2d87b8d39c573bedc328d3af2fc0;hp=865fe9227679770b662188f05adc36ac5def8382;hpb=ee4ccb6971f7a639440bfdfe784f3f64486c8e33;p=mono.git diff --git a/mono/mini/jit-icalls.c b/mono/mini/jit-icalls.c index 865fe922767..d1bb391250e 100644 --- a/mono/mini/jit-icalls.c +++ b/mono/mini/jit-icalls.c @@ -17,45 +17,38 @@ mono_ldftn (MonoMethod *method) MONO_ARCH_SAVE_REGS; - addr = mono_compile_method (method); + addr = mono_create_jump_trampoline (mono_domain_get (), method, TRUE); return addr; } +/* + * Same as mono_ldftn, but do not add a synchronized wrapper. Used in the + * synchronized wrappers to avoid infinite recursion. + */ static void* -mono_ldvirtfn (MonoObject *obj, MonoMethod *method) +mono_ldftn_nosync (MonoMethod *method) { - MONO_ARCH_SAVE_REGS; - - method = mono_object_get_virtual_method (obj, method); - if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED) - method = mono_marshal_get_synchronized_wrapper (method); - - return mono_ldftn (method); -} + gpointer addr; -static void -helper_initobj (void *addr, int size) -{ MONO_ARCH_SAVE_REGS; - memset (addr, 0, size); + addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE); + + return addr; } -static void -helper_memcpy (void *addr, void *src, int size) +static void* +mono_ldvirtfn (MonoObject *obj, MonoMethod *method) { MONO_ARCH_SAVE_REGS; - memcpy (addr, src, size); -} + if (obj == NULL) + mono_raise_exception (mono_get_exception_null_reference ()); -static void -helper_memset (void *addr, int val, int size) -{ - MONO_ARCH_SAVE_REGS; + method = mono_object_get_virtual_method (obj, method); - memset (addr, val, size); + return mono_ldftn (method); } static void @@ -72,6 +65,17 @@ helper_stelem_ref (MonoArray *array, int index, MonoObject *val) mono_array_set (array, gpointer, index, val); } +static void +helper_stelem_ref_check (MonoArray *array, MonoObject *val) +{ + MONO_ARCH_SAVE_REGS; + + if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class)) + mono_raise_exception (mono_get_exception_array_type_mismatch ()); +} + +#ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS + static gint64 mono_llmult (gint64 a, gint64 b) { @@ -111,7 +115,6 @@ mono_llmult_ovf_un (guint64 a, guint64 b) return 0; } - static guint64 mono_llmult_ovf (gint64 a, gint64 b) { @@ -146,6 +149,16 @@ mono_llmult_ovf (gint64 a, gint64 b) */ sign = ah ^ bh; if (ah < 0) { + if (((guint32)ah == 0x80000000) && (al == 0)) { + /* This has no two's complement */ + if (b == 0) + return 0; + else if (b == 1) + return a; + else + goto raise_exception; + } + /* flip the bits and add 1 */ ah ^= ~0; if (al == 0) @@ -157,6 +170,16 @@ mono_llmult_ovf (gint64 a, gint64 b) } if (bh < 0) { + if (((guint32)bh == 0x80000000) && (bl == 0)) { + /* This has no two's complement */ + if (a == 0) + return 0; + else if (a == 1) + return b; + else + goto raise_exception; + } + /* flip the bits and add 1 */ bh ^= ~0; if (bl == 0) @@ -173,6 +196,8 @@ mono_llmult_ovf (gint64 a, gint64 b) in a 64 bit result */ if (ah && bh) goto raise_exception; + if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000) + goto raise_exception; /* do the AlBl term first */ t1 = (gint64)al * (gint64)bl; @@ -181,8 +206,8 @@ mono_llmult_ovf (gint64 a, gint64 b) /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */ t1 += (gint64)(ah - al) * (gint64)(bl - bh); - t1 <<= 32; /* check for overflow */ + t1 <<= 32; if (t1 > (0x7FFFFFFFFFFFFFFFLL - res)) goto raise_exception; @@ -206,6 +231,12 @@ mono_lldiv (gint64 a, gint64 b) { MONO_ARCH_SAVE_REGS; +#ifdef MONO_ARCH_NEED_DIV_CHECK + if (!b) + mono_raise_exception (mono_get_exception_divide_by_zero ()); + else if (b == -1 && a == (-9223372036854775807LL - 1LL)) + mono_raise_exception (mono_get_exception_arithmetic ()); +#endif return a / b; } @@ -214,6 +245,12 @@ mono_llrem (gint64 a, gint64 b) { MONO_ARCH_SAVE_REGS; +#ifdef MONO_ARCH_NEED_DIV_CHECK + if (!b) + mono_raise_exception (mono_get_exception_divide_by_zero ()); + else if (b == -1 && a == (-9223372036854775807LL - 1LL)) + mono_raise_exception (mono_get_exception_arithmetic ()); +#endif return a % b; } @@ -222,6 +259,10 @@ mono_lldiv_un (guint64 a, guint64 b) { MONO_ARCH_SAVE_REGS; +#ifdef MONO_ARCH_NEED_DIV_CHECK + if (!b) + mono_raise_exception (mono_get_exception_divide_by_zero ()); +#endif return a / b; } @@ -230,9 +271,17 @@ mono_llrem_un (guint64 a, guint64 b) { MONO_ARCH_SAVE_REGS; +#ifdef MONO_ARCH_NEED_DIV_CHECK + if (!b) + mono_raise_exception (mono_get_exception_divide_by_zero ()); +#endif return a % b; } +#endif + +#ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS + static guint64 mono_lshl (guint64 a, gint32 shamt) { @@ -272,6 +321,8 @@ mono_lshr (gint64 a, gint32 shamt) return res; } +#endif + /** * ves_array_element_address: * @this: a pointer to the array object @@ -330,7 +381,7 @@ mono_array_new_va (MonoMethod *cm, ...) MONO_ARCH_SAVE_REGS; - pcount = cm->signature->param_count; + pcount = mono_method_signature (cm)->param_count; rank = cm->klass->rank; va_start (ap, cm); @@ -380,13 +431,13 @@ mono_class_static_field_address (MonoDomain *domain, MonoClassField *field) } static gpointer -mono_ldtoken_wrapper (MonoImage *image, int token) +mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context) { MonoClass *handle_class; gpointer res; MONO_ARCH_SAVE_REGS; - res = mono_ldtoken (image, token, &handle_class); + res = mono_ldtoken (image, token, &handle_class, context); mono_class_init (handle_class); return res; @@ -395,7 +446,6 @@ mono_ldtoken_wrapper (MonoImage *image, int token) static guint64 mono_fconv_u8 (double v) { - /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/ return (guint64)v; } @@ -415,6 +465,17 @@ mono_fconv_u4 (double v) return (guint32)v; } +#ifndef HAVE_TRUNC +/* Solaris doesn't have trunc */ +#ifdef HAVE_AINTL +extern long double aintl (long double); +#define trunc aintl +#else +/* FIXME: This means we will never throw overflow exceptions */ +#define trunc(v) res +#endif +#endif /* HAVE_TRUNC */ + static gint64 mono_fconv_ovf_i8 (double v) { @@ -424,7 +485,7 @@ mono_fconv_ovf_i8 (double v) res = (gint64)v; - if (isnan(v) || v != res) { + if (isnan(v) || trunc (v) != res) { mono_raise_exception (mono_get_exception_overflow ()); } return res; @@ -439,7 +500,7 @@ mono_fconv_ovf_u8 (double v) res = (guint64)v; - if (isnan(v) || v != res) { + if (isnan(v) || trunc (v) != res) { mono_raise_exception (mono_get_exception_overflow ()); } return res; @@ -453,6 +514,22 @@ mono_lconv_to_r8 (gint64 a) } #endif +#ifdef MONO_ARCH_EMULATE_LCONV_TO_R4 +static float +mono_lconv_to_r4 (gint64 a) +{ + return (float)a; +} +#endif + +#ifdef MONO_ARCH_EMULATE_CONV_R8_UN +static double +mono_conv_to_r8_un (guint32 a) +{ + return (double)a; +} +#endif + #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN static double mono_lconv_to_r8_un (guint64 a) @@ -461,3 +538,16 @@ mono_lconv_to_r8_un (guint64 a) } #endif +static gpointer +helper_compile_generic_method (MonoObject *obj, MonoMethod *method, MonoGenericContext *context) +{ + MonoMethod *vmethod, *inflated; + gpointer addr; + + vmethod = mono_object_get_virtual_method (obj, method); + inflated = mono_class_inflate_generic_method (vmethod, context, NULL); + inflated = mono_get_inflated_method (inflated); + addr = mono_compile_method (inflated); + + return addr; +}