Merge pull request #992 from ludovic-henry/ludovic-counters-pr1
[mono.git] / mono / mini / jit-icalls.c
index 0b1f2e2662949ab62a45cb485ffedbbdadff0e1b..45c7689a58ab09bf9e100b53049471ffabae6ab5 100644 (file)
@@ -82,7 +82,7 @@ mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
                mono_raise_exception (mono_get_exception_array_type_mismatch ());
 }
 
-#ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
+#if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
 
 gint64 
 mono_llmult (gint64 a, gint64 b)
@@ -429,7 +429,7 @@ mono_imul_ovf_un (guint32 a, guint32 b)
 }
 #endif
 
-#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
+#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
 double
 mono_fdiv (double a, double b)
 {
@@ -439,7 +439,7 @@ mono_fdiv (double a, double b)
 }
 #endif
 
-#ifdef MONO_ARCH_SOFT_FLOAT
+#ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
 
 double
 mono_fsub (double a, double b)
@@ -871,6 +871,13 @@ guint32
 mono_fconv_u4 (double v)
 {
        /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
+
+       /* MS.NET behaves like this for some reason */
+#ifdef HAVE_ISINF
+       if (isinf (v) || isnan (v))
+               return 0;
+#endif
+
        return (guint32)v;
 }
 
@@ -915,7 +922,7 @@ mono_fconv_ovf_u8 (double v)
  * 
  * To work around this issue we test for value boundaries instead. 
  */
-#if defined(__arm__) && MONO_ARCH_SOFT_FLOAT 
+#if defined(__arm__) && defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
        if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
                mono_raise_exception (mono_get_exception_overflow ());
        }
@@ -989,8 +996,7 @@ mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointe
 
        addr = mono_compile_method (vmethod);
 
-       if (mono_method_needs_static_rgctx_invoke (vmethod, FALSE))
-               addr = mono_create_static_rgctx_trampoline (vmethod, addr);
+       addr = mini_add_method_trampoline (NULL, vmethod, addr, mono_method_needs_static_rgctx_invoke (vmethod, FALSE), FALSE);
 
        /* Since this is a virtual call, have to unbox vtypes */
        if (obj->vtable->klass->valuetype)
@@ -1052,7 +1058,7 @@ mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg
 }
 
 MonoObject*
-mono_object_castclass (MonoObject *obj, MonoClass *klass)
+mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
 {
        MonoJitTlsData *jit_tls = NULL;
 
@@ -1064,6 +1070,8 @@ mono_object_castclass (MonoObject *obj, MonoClass *klass)
        if (!obj)
                return NULL;
 
+       if (klass->enumtype && obj->vtable->klass == klass->element_class)
+               return obj;
        if (mono_object_isinst (obj, klass))
                return obj;
 
@@ -1154,46 +1162,82 @@ mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpoin
        return mono_compile_method (m);
 }
 
-MonoObject*
-mono_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
+static MonoMethod*
+constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg)
 {
        MonoMethod *m;
        int vt_slot;
-       gpointer this_arg;
 
-       /* Lookup the virtual method */
-       mono_class_setup_vtable (klass);
-       g_assert (klass->vtable);
-       vt_slot = mono_method_get_vtable_slot (cmethod);
-       m = klass->vtable [vt_slot];
-       if (klass->valuetype)
-               this_arg = mp;
+       if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
+               mono_raise_exception (mono_get_exception_execution_engine ("Not yet supported."));
+
+       if (mono_method_signature (cmethod)->pinvoke) {
+               /* Object.GetType () */
+               m = mono_marshal_get_native_wrapper (cmethod, TRUE, FALSE);
+       } else {
+               /* Lookup the virtual method */
+               mono_class_setup_vtable (klass);
+               g_assert (klass->vtable);
+               vt_slot = mono_method_get_vtable_slot (cmethod);
+               if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
+                       int iface_offset;
+
+                       iface_offset = mono_class_interface_offset (klass, cmethod->klass);
+                       g_assert (iface_offset != -1);
+                       vt_slot += iface_offset;
+               }
+               m = klass->vtable [vt_slot];
+       }
+       if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
+               /*
+                * Calling a non-vtype method with a vtype receiver, has to box.
+                */
+               *this_arg = mono_value_box (mono_domain_get (), klass, mp);
+       else if (klass->valuetype)
+               /*
+                * Calling a vtype method with a vtype receiver
+                */
+               *this_arg = mp;
        else
-               this_arg = *(gpointer*)mp;
-       return mono_runtime_invoke (m, this_arg, NULL, NULL);
+               /*
+                * Calling a non-vtype method
+                */
+               *this_arg = *(gpointer*)mp;
+       return m;
 }
 
-int
-mono_object_gethashcode_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
+/*
+ * mono_gsharedvt_constrained_call:
+ *
+ *   Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
+ * the arguments to the method in the format used by mono_runtime_invoke ().
+ */
+MonoObject*
+mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
 {
        MonoMethod *m;
-       int vt_slot;
        gpointer this_arg;
-       MonoObject *res;
-       gpointer p;
-
-       /* Lookup the virtual method */
-       mono_class_setup_vtable (klass);
-       g_assert (klass->vtable);
-       vt_slot = mono_method_get_vtable_slot (cmethod);
-       m = klass->vtable [vt_slot];
+       gpointer new_args [16];
+
+       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
+       if (args && deref_arg) {
+               new_args [0] = *(gpointer*)args [0];
+               args = new_args;
+       }
+       if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+               /* Object.GetType () */
+               args = new_args;
+               args [0] = this_arg;
+               this_arg = NULL;
+       }
+       return mono_runtime_invoke (m, this_arg, args, NULL);
+}
+
+void
+mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass)
+{
        if (klass->valuetype)
-               this_arg = mp;
+               mono_value_copy (dest, src, klass);
        else
-               this_arg = *(gpointer*)mp;
-       // FIXME: This boxes the result
-       res = mono_runtime_invoke (m, this_arg, NULL, NULL);
-       p = mono_object_unbox (res);
-       return *(int*)p;
+        mono_gc_wbarrier_generic_store (dest, *(MonoObject**)src);
 }
-