Merge pull request #2720 from mono/fix-39325
[mono.git] / mono / mini / jit-icalls.c
index 5cc3f4b89e743d9fce44363c8c39e080f36bc939..6d87c74e92d01e1fb087a6f8c19e57dc65084c08 100644 (file)
@@ -8,6 +8,7 @@
  * (C) 2002 Ximian, Inc.
  * Copyright 2003-2011 Novell Inc (http://www.novell.com)
  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 #include <config.h>
 #include <math.h>
@@ -29,6 +30,7 @@ void*
 mono_ldftn (MonoMethod *method)
 {
        gpointer addr;
+       MonoError error;
 
        if (mono_llvm_only) {
                // FIXME: No error handling
@@ -44,8 +46,11 @@ mono_ldftn (MonoMethod *method)
                return addr;
        }
 
-       addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
-
+       addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE, &error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
        return mono_create_ftnptr (mono_domain_get (), addr);
 }
 
@@ -98,11 +103,14 @@ mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method)
 void
 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
 {
+       MonoError error;
        if (!array) {
                mono_set_pending_exception (mono_get_exception_null_reference ());
                return;
        }
-       if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class)) {
+       if (val && !mono_object_isinst_checked (val, array->obj.vtable->klass->element_class, &error)) {
+               if (mono_error_set_pending_exception (&error))
+                       return;
                mono_set_pending_exception (mono_get_exception_array_type_mismatch ());
                return;
        }
@@ -855,6 +863,7 @@ mono_array_new_4 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 leng
 gpointer
 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
 {
+       MonoError error;
        MonoVTable *vtable;
        gpointer addr;
        
@@ -862,9 +871,17 @@ mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
 
        mono_class_init (field->parent);
 
-       vtable = mono_class_vtable_full (domain, field->parent, TRUE);
-       if (!vtable->initialized)
-               mono_runtime_class_init (vtable);
+       vtable = mono_class_vtable_full (domain, field->parent, &error);
+       if (!is_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+       if (!vtable->initialized) {
+               if (!mono_runtime_class_init_full (vtable, &error)) {
+                       mono_error_set_pending_exception (&error);
+                       return NULL;
+               }
+       }
 
        //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
 
@@ -1165,6 +1182,7 @@ mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg
 MonoObject*
 mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
 {
+       MonoError error;
        MonoJitTlsData *jit_tls = NULL;
        MonoClass *oklass;
 
@@ -1179,8 +1197,10 @@ mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
        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))
+       if (mono_object_isinst_checked (obj, klass, &error))
                return obj;
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
 
        if (mini_get_debug_options ()->better_cast_details) {
                jit_tls->class_cast_from = oklass;
@@ -1196,6 +1216,7 @@ mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
 MonoObject*
 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
 {
+       MonoError error;
        MonoJitTlsData *jit_tls = NULL;
        gpointer cached_vtable, obj_vtable;
 
@@ -1213,10 +1234,12 @@ mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *c
        if (cached_vtable == obj_vtable)
                return obj;
 
-       if (mono_object_isinst (obj, klass)) {
+       if (mono_object_isinst_checked (obj, klass, &error)) {
                *cache = obj_vtable;
                return obj;
        }
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
 
        if (mini_get_debug_options ()->better_cast_details) {
                jit_tls->class_cast_from = obj->vtable->klass;
@@ -1232,6 +1255,7 @@ mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *c
 MonoObject*
 mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
 {
+       MonoError error;
        size_t cached_vtable, obj_vtable;
 
        if (!obj)
@@ -1244,10 +1268,12 @@ mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cach
                return (cached_vtable & 0x1) ? NULL : obj;
        }
 
-       if (mono_object_isinst (obj, klass)) {
+       if (mono_object_isinst_checked (obj, klass, &error)) {
                *cache = (gpointer)obj_vtable;
                return obj;
        } else {
+               if (mono_error_set_pending_exception (&error))
+                       return NULL;
                /*negative cache*/
                *cache = (gpointer)(obj_vtable | 0x1);
                return NULL;
@@ -1309,7 +1335,7 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
                /*
                 * Calling a non-vtype method with a vtype receiver, has to box.
                 */
-               *this_arg = mono_value_box (mono_domain_get (), klass, mp);
+               *this_arg = mono_value_box_checked (mono_domain_get (), klass, mp, error);
        else if (klass->valuetype)
                /*
                 * Calling a vtype method with a vtype receiver
@@ -1375,10 +1401,23 @@ mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass)
         mono_gc_wbarrier_generic_store (dest, *(MonoObject**)src);
 }
 
+void
+ves_icall_runtime_class_init (MonoVTable *vtable)
+{
+       MONO_REQ_GC_UNSAFE_MODE;
+       MonoError error;
+
+       mono_runtime_class_init_full (vtable, &error);
+       mono_error_set_pending_exception (&error);
+}
+
+
 void
 mono_generic_class_init (MonoVTable *vtable)
 {
-       mono_runtime_class_init (vtable);
+       MonoError error;
+       mono_runtime_class_init_full (vtable, &error);
+       mono_error_set_pending_exception (&error);
 }
 
 gpointer