Merge pull request #2748 from lambdageek/dev/monoerror-mono_value_box
[mono.git] / mono / mini / jit-icalls.c
index 6b8adcf58af1aa9d45b12def2b7e5efb9a96826a..38b668e8ae9ec3b0cdacad753bab753be14a9535 100644 (file)
@@ -18,6 +18,8 @@
 
 #include "jit-icalls.h"
 #include <mono/utils/mono-error-internals.h>
+#include <mono/metadata/threads-types.h>
+#include <mono/metadata/reflection-internals.h>
 
 #ifdef ENABLE_LLVM
 #include "mini-llvm-cpp.h"
@@ -27,6 +29,7 @@ void*
 mono_ldftn (MonoMethod *method)
 {
        gpointer addr;
+       MonoError error;
 
        if (mono_llvm_only) {
                // FIXME: No error handling
@@ -42,8 +45,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);
 }
 
@@ -658,6 +664,8 @@ mono_fload_r4_arg (double val)
 MonoArray *
 mono_array_new_va (MonoMethod *cm, ...)
 {
+       MonoError error;
+       MonoArray *arr;
        MonoDomain *domain = mono_domain_get ();
        va_list ap;
        uintptr_t *lengths;
@@ -691,13 +699,22 @@ mono_array_new_va (MonoMethod *cm, ...)
        }
        va_end(ap);
 
-       return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
+       arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
+       return arr;
 }
 
 /* Specialized version of mono_array_new_va () which avoids varargs */
 MonoArray *
 mono_array_new_1 (MonoMethod *cm, guint32 length)
 {
+       MonoError error;
+       MonoArray *arr;
        MonoDomain *domain = mono_domain_get ();
        uintptr_t lengths [1];
        intptr_t *lower_bounds;
@@ -718,12 +735,21 @@ mono_array_new_1 (MonoMethod *cm, guint32 length)
                lower_bounds = NULL;
        }
 
-       return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
+       arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
+       return arr;
 }
 
 MonoArray *
 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
 {
+       MonoError error;
+       MonoArray *arr;
        MonoDomain *domain = mono_domain_get ();
        uintptr_t lengths [2];
        intptr_t *lower_bounds;
@@ -745,12 +771,21 @@ mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
                lower_bounds = NULL;
        }
 
-       return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
+       arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
+       return arr;
 }
 
 MonoArray *
 mono_array_new_3 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3)
 {
+       MonoError error;
+       MonoArray *arr;
        MonoDomain *domain = mono_domain_get ();
        uintptr_t lengths [3];
        intptr_t *lower_bounds;
@@ -773,12 +808,21 @@ mono_array_new_3 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 leng
                lower_bounds = NULL;
        }
 
-       return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
+       arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
+       return arr;
 }
 
 MonoArray *
 mono_array_new_4 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3, guint32 length4)
 {
+       MonoError error;
+       MonoArray *arr;
        MonoDomain *domain = mono_domain_get ();
        uintptr_t lengths [4];
        intptr_t *lower_bounds;
@@ -802,12 +846,20 @@ mono_array_new_4 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 leng
                lower_bounds = NULL;
        }
 
-       return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
+       arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
+       return arr;
 }
 
 gpointer
 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
 {
+       MonoError error;
        MonoVTable *vtable;
        gpointer addr;
        
@@ -815,9 +867,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);
 
@@ -1081,7 +1141,10 @@ mono_helper_newobj_mscorlib (guint32 idx)
                return NULL;
        }
 
-       return mono_object_new (mono_domain_get (), klass);
+       MonoObject *obj = mono_object_new_checked (mono_domain_get (), klass, &error);
+       if (!mono_error_ok (&error))
+               mono_error_set_pending_exception (&error);
+       return obj;
 }
 
 /*
@@ -1220,11 +1283,13 @@ mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpoin
 }
 
 static MonoMethod*
-constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg)
+constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg, MonoError *error)
 {
        MonoMethod *m;
        int vt_slot, iface_offset;
 
+       mono_error_init (error);
+
        if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
                MonoObject *this_obj;
 
@@ -1257,7 +1322,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
@@ -1275,16 +1340,23 @@ constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *k
  * 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 ().
+ * the arguments to the method in the format used by mono_runtime_invoke_checked ().
  */
 MonoObject*
 mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
 {
+       MonoError error;
+       MonoObject *o;
        MonoMethod *m;
        gpointer this_arg;
        gpointer new_args [16];
 
-       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg);
+       m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg, &error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
        if (!m)
                return NULL;
        if (args && deref_arg) {
@@ -1297,7 +1369,14 @@ mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *kl
                args [0] = this_arg;
                this_arg = NULL;
        }
-       return mono_runtime_invoke (m, this_arg, args, NULL);
+
+       o = mono_runtime_invoke_checked (m, this_arg, args, &error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+
+       return o;
 }
 
 void
@@ -1309,22 +1388,51 @@ 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
 mono_fill_class_rgctx (MonoVTable *vtable, int index)
 {
-       return mono_class_fill_runtime_generic_context (vtable, index);
+       MonoError error;
+       gpointer res;
+
+       res = mono_class_fill_runtime_generic_context (vtable, index, &error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+       return res;
 }
 
 gpointer
 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index)
 {
-       return mono_method_fill_runtime_generic_context (mrgctx, index);
+       MonoError error;
+       gpointer res;
+
+       res = mono_method_fill_runtime_generic_context (mrgctx, index, &error);
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
+       return res;
 }
 
 /*
@@ -1618,13 +1726,29 @@ mono_init_vtable_slot (MonoVTable *vtable, int slot)
  * Similar to mono_delegate_ctor ().
  */
 void
-mono_llvmonly_init_delegate (MonoDelegate *del, MonoObject *target, MonoMethod *method)
+mono_llvmonly_init_delegate (MonoDelegate *del)
 {
-       MONO_OBJECT_SETREF (del, target, target);
-       del->method = method;
-       del->method_ptr = mono_compile_method (method);
+       MonoFtnDesc *ftndesc = *(MonoFtnDesc**)del->method_code;
 
-       mini_init_delegate (del);
+       /*
+        * We store a MonoFtnDesc in del->method_code.
+        * It would be better to store an ftndesc in del->method_ptr too,
+        * but we don't have a a structure which could own its memory.
+        */
+       if (G_UNLIKELY (!ftndesc)) {
+               gpointer addr = mono_compile_method (del->method);
+
+               if (del->method->klass->valuetype && mono_method_signature (del->method)->hasthis)
+                   addr = mono_aot_get_unbox_trampoline (del->method);
+
+               gpointer arg = mini_get_delegate_arg (del->method, addr);
+
+               ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
+               mono_memory_barrier ();
+               *del->method_code = (gpointer)ftndesc;
+       }
+       del->method_ptr = ftndesc->addr;
+       del->extra_arg = ftndesc->arg;
 }
 
 void
@@ -1634,23 +1758,32 @@ mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, Mono
 
        method = mono_object_get_virtual_method (target, method);
 
-       MONO_OBJECT_SETREF (del, target, target);
        del->method = method;
        del->method_ptr = mono_compile_method (method);
-
-       mini_init_delegate (del);
+       if (method->klass->valuetype)
+               del->method_ptr = mono_aot_get_unbox_trampoline (method);
+       del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
 }
 
 MonoObject*
 mono_get_assembly_object (MonoImage *image)
 {
-       return (MonoObject*)mono_assembly_get_object (mono_domain_get (), image->assembly);
+       MonoError error;
+       MonoObject *result;
+       result = (MonoObject*)mono_assembly_get_object_checked (mono_domain_get (), image->assembly, &error);
+       if (!result)
+               mono_error_set_pending_exception (&error);
+       return result;
 }
 
 MonoObject*
 mono_get_method_object (MonoMethod *method)
 {
-       return (MonoObject*)mono_method_get_object (mono_domain_get (), method, method->klass);
+       MonoError error;
+       MonoObject * result;
+       result = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), method, method->klass, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 double
@@ -1661,24 +1794,21 @@ mono_ckfinite (double d)
        return d;
 }
 
+/*
+ * mono_interruption_checkpoint_from_trampoline:
+ *
+ *   Check whenever the thread has a pending exception, and throw it
+ * if needed.
+ * Architectures should move away from calling this function and
+ * instead call mono_thread_force_interruption_checkpoint_noraise (),
+ * rewrind to the parent frame, and throw the exception normally.
+ */
 void
-mono_llvmonly_set_calling_assembly (MonoImage *image)
+mono_interruption_checkpoint_from_trampoline (void)
 {
-       MonoJitTlsData *jit_tls = NULL;
-
-       jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
-       g_assert (jit_tls);
-       jit_tls->calling_image = image;
-}
-
-MonoObject*
-mono_llvmonly_get_calling_assembly (void)
-{
-       MonoJitTlsData *jit_tls = NULL;
+       MonoException *ex;
 
-       jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
-       g_assert (jit_tls);
-       if (!jit_tls->calling_image)
-               mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
-       return (MonoObject*)mono_assembly_get_object (mono_domain_get (), jit_tls->calling_image->assembly);
+       ex = mono_thread_force_interruption_checkpoint_noraise ();
+       if (ex)
+               mono_raise_exception (ex);
 }