Merge pull request #1419 from directhex/bump_msvc_VERSION
[mono.git] / mono / mini / jit-icalls.c
index 8822b8026e78b85c0b2d83210734b35bd216e0e9..fcfcf4f3cd16160c56f2bfacc12e51b9850d1b41 100644 (file)
@@ -17,7 +17,7 @@
 #endif
 
 #include "jit-icalls.h"
-
+#include <mono/utils/mono-error-internals.h>
 void*
 mono_ldftn (MonoMethod *method)
 {
@@ -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)
@@ -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;
 }
 
@@ -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)
@@ -1016,9 +1022,9 @@ mono_helper_ldstr_mscorlib (guint32 idx)
 MonoObject*
 mono_helper_newobj_mscorlib (guint32 idx)
 {
-       MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx);
-       
-       g_assert (klass);
+       MonoError error;
+       MonoClass *klass = mono_class_get_checked (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx, &error);
+       mono_error_raise_exception (&error);
 
        return mono_object_new (mono_domain_get (), klass);
 }
@@ -1052,9 +1058,10 @@ 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;
+       MonoClass *oklass;
 
        if (mini_get_debug_options ()->better_cast_details) {
                jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
@@ -1064,11 +1071,14 @@ mono_object_castclass (MonoObject *obj, MonoClass *klass)
        if (!obj)
                return NULL;
 
+       oklass = obj->vtable->klass;
+       if ((klass->enumtype && oklass == klass->element_class) || (oklass->enumtype && klass == oklass->element_class))
+               return obj;
        if (mono_object_isinst (obj, klass))
                return obj;
 
        if (mini_get_debug_options ()->better_cast_details) {
-               jit_tls->class_cast_from = obj->vtable->klass;
+               jit_tls->class_cast_from = oklass;
                jit_tls->class_cast_to = klass;
        }
 
@@ -1160,11 +1170,26 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
        MonoMethod *m;
        int vt_slot;
 
-       /* 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->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.
@@ -1183,46 +1208,31 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
        return m;
 }
 
+/*
+ * 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_object_tostring_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
-{
-       MonoMethod *m;
-       gpointer this_arg;
-
-       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
-       return mono_runtime_invoke (m, this_arg, NULL, NULL);
-}
-
-int
-mono_object_gethashcode_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass)
+mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
 {
        MonoMethod *m;
        gpointer this_arg;
-       MonoObject *res;
-       gpointer p;
+       gpointer new_args [16];
 
        m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
-       // FIXME: This boxes the result
-       res = mono_runtime_invoke (m, this_arg, NULL, NULL);
-       p = mono_object_unbox (res);
-       return *(int*)p;
-}
-
-MonoBoolean
-mono_object_equals_gsharedvt (gpointer mp, MonoMethod *cmethod, MonoClass *klass, MonoObject *arg)
-{
-       MonoMethod *m;
-       gpointer this_arg;
-       MonoObject *res;
-       gpointer p;
-       void **args;
-
-       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
-       // FIXME: This boxes the result
-       args = (void**)&arg;
-       res = mono_runtime_invoke (m, this_arg, args, NULL);
-       p = mono_object_unbox (res);
-       return *(MonoBoolean*)p;
+       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