Merge pull request #3100 from lambdageek/dev/monoerror-exns
[mono.git] / mono / mini / jit-icalls.c
index 83603d75367601a16901b5f5b46e19451d7c6488..8651aa25ec497c574a6d492e6ae6e9b324be8e14 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>
@@ -18,6 +19,9 @@
 
 #include "jit-icalls.h"
 #include <mono/utils/mono-error-internals.h>
+#include <mono/metadata/exception-internals.h>
+#include <mono/metadata/threads-types.h>
+#include <mono/metadata/reflection-internals.h>
 
 #ifdef ENABLE_LLVM
 #include "mini-llvm-cpp.h"
@@ -27,11 +31,13 @@ void*
 mono_ldftn (MonoMethod *method)
 {
        gpointer addr;
+       MonoError error;
 
        if (mono_llvm_only) {
                // FIXME: No error handling
 
-               addr = mono_compile_method (method);
+               addr = mono_compile_method_checked (method, &error);
+               mono_error_assert_ok (&error);
                g_assert (addr);
 
                if (mono_method_needs_static_rgctx_invoke (method, FALSE))
@@ -42,8 +48,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);
 }
 
@@ -96,11 +105,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;
        }
@@ -694,7 +706,11 @@ mono_array_new_va (MonoMethod *cm, ...)
        va_end(ap);
 
        arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        return arr;
 }
@@ -726,7 +742,11 @@ mono_array_new_1 (MonoMethod *cm, guint32 length)
        }
 
        arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        return arr;
 }
@@ -758,7 +778,11 @@ mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
        }
 
        arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        return arr;
 }
@@ -791,7 +815,11 @@ mono_array_new_3 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 leng
        }
 
        arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        return arr;
 }
@@ -825,7 +853,11 @@ mono_array_new_4 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 leng
        }
 
        arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
-       mono_error_raise_exception (&error); /* FIXME don't raise here */
+
+       if (!mono_error_ok (&error)) {
+               mono_error_set_pending_exception (&error);
+               return NULL;
+       }
 
        return arr;
 }
@@ -833,6 +865,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;
        
@@ -840,9 +873,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);
 
@@ -1055,6 +1096,7 @@ mono_fmod(double a, double b)
 gpointer
 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
 {
+       MonoError error;
        MonoMethod *vmethod;
        gpointer addr;
        MonoGenericContext *context = mono_method_get_context (method);
@@ -1070,7 +1112,9 @@ mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointe
        g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
        g_assert (!context->method_inst || !context->method_inst->is_open);
 
-       addr = mono_compile_method (vmethod);
+       addr = mono_compile_method_checked (vmethod, &error);
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
 
        addr = mini_add_method_trampoline (vmethod, addr, mono_method_needs_static_rgctx_invoke (vmethod, FALSE), FALSE);
 
@@ -1083,16 +1127,31 @@ mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointe
        return addr;
 }
 
+MonoString*
+ves_icall_mono_ldstr (MonoDomain *domain, MonoImage *image, guint32 idx)
+{
+       MonoError error;
+       MonoString *result = mono_ldstr_checked (domain, image, idx, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
+}
+
 MonoString*
 mono_helper_ldstr (MonoImage *image, guint32 idx)
 {
-       return mono_ldstr (mono_domain_get (), image, idx);
+       MonoError error;
+       MonoString *result = mono_ldstr_checked (mono_domain_get (), image, idx, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 MonoString*
 mono_helper_ldstr_mscorlib (guint32 idx)
 {
-       return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
+       MonoError error;
+       MonoString *result = mono_ldstr_checked (mono_domain_get (), mono_defaults.corlib, idx, &error);
+       mono_error_set_pending_exception (&error);
+       return result;
 }
 
 MonoObject*
@@ -1106,7 +1165,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;
 }
 
 /*
@@ -1128,18 +1190,27 @@ mono_create_corlib_exception_0 (guint32 token)
 MonoException *
 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
 {
-       return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
+       MonoError error;
+       MonoException *ret = mono_exception_from_token_two_strings_checked (
+               mono_defaults.corlib, token, arg, NULL, &error);
+       mono_error_set_pending_exception (&error);
+       return ret;
 }
 
 MonoException *
 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
 {
-       return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
+       MonoError error;
+       MonoException *ret = mono_exception_from_token_two_strings_checked (
+               mono_defaults.corlib, token, arg1, arg2, &error);
+       mono_error_set_pending_exception (&error);
+       return ret;
 }
 
 MonoObject*
 mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
 {
+       MonoError error;
        MonoJitTlsData *jit_tls = NULL;
        MonoClass *oklass;
 
@@ -1154,8 +1225,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;
@@ -1171,6 +1244,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;
 
@@ -1188,10 +1262,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;
@@ -1207,6 +1283,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)
@@ -1219,10 +1296,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;
@@ -1232,6 +1311,7 @@ mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cach
 gpointer
 mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpointer func)
 {
+       MonoError error;
        MonoMarshalSpec **mspecs;
        MonoMethodPInvoke piinfo;
        MonoMethod *m;
@@ -1241,15 +1321,19 @@ mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpoin
 
        m = mono_marshal_get_native_func_wrapper (image, sig, &piinfo, mspecs, func);
 
-       return mono_compile_method (m);
+       gpointer compiled_ptr = mono_compile_method_checked (m, &error);
+       mono_error_set_pending_exception (&error);
+       return compiled_ptr;
 }
 
 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;
 
@@ -1282,7 +1366,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
@@ -1300,16 +1384,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) {
@@ -1322,7 +1413,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
@@ -1334,22 +1432,59 @@ 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);
+}
+
+void
+ves_icall_mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr)
+{
+       MonoError error;
+       mono_delegate_ctor (this_obj, target, addr, &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;
 }
 
 /*
@@ -1361,7 +1496,7 @@ mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index)
  * out parameter.
  */
 static gpointer
-resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt)
+resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt, MonoError *error)
 {
        MonoVTable *vt;
        gpointer *imt, *vtable_slot;
@@ -1369,6 +1504,7 @@ resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method,
        gpointer addr, compiled_method, aot_addr;
        gboolean need_rgctx_tramp = FALSE, need_unbox_tramp = FALSE;
 
+       mono_error_init (error);
        if (!this_obj)
                /* The caller will handle it */
                return NULL;
@@ -1376,10 +1512,12 @@ resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method,
        vt = this_obj->vtable;
        imt = (gpointer*)vt - MONO_IMT_SIZE;
 
-       vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface);
+       vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface, error);
+       return_val_if_nok (error, NULL);
 
        // FIXME: This can throw exceptions
-       addr = compiled_method = mono_compile_method (impl_method);
+       addr = compiled_method = mono_compile_method_checked (impl_method, error);
+       mono_error_assert_ok (error);
        g_assert (addr);
 
        if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst)
@@ -1409,7 +1547,13 @@ resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method,
 gpointer
 mono_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg)
 {
-       return resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE);
+       MonoError error;
+       gpointer res = resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE, &error);
+       if (!is_ok (&error)) {
+               MonoException *ex = mono_error_convert_to_exception (&error);
+               mono_llvm_throw_exception ((MonoObject*)ex);
+       }
+       return res;
 }
 
 static gboolean
@@ -1438,23 +1582,24 @@ is_generic_method_definition (MonoMethod *m)
  * out parameter.
  */
 static gpointer
-resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt)
+resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt, MonoError *error)
 {
        MonoMethod *m, *generic_virtual = NULL;
        gpointer addr, compiled_method;
        gboolean need_unbox_tramp = FALSE;
 
+       mono_error_init (error);
        /* Same as in common_call_trampoline () */
 
        /* Avoid loading metadata or creating a generic vtable if possible */
-       addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot);
+       addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot, error);
+       return_val_if_nok (error, NULL);
        if (addr && !vt->klass->valuetype)
                return mono_create_ftnptr (mono_domain_get (), addr);
 
        m = mono_class_get_vtable_entry (vt->klass, slot);
 
        if (is_generic_method_definition (m)) {
-               MonoError error;
                MonoGenericContext context = { NULL, NULL };
                MonoMethod *declaring;
 
@@ -1473,8 +1618,8 @@ resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_a
                g_assert (generic_virtual->is_inflated);
                context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
 
-               m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
-               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+               m = mono_class_inflate_generic_method_checked (declaring, &context, error);
+               mono_error_assert_ok (error); /* FIXME don't swallow the error */
        }
 
        if (generic_virtual) {
@@ -1486,7 +1631,8 @@ resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_a
        }
 
        // FIXME: This can throw exceptions
-       addr = compiled_method = mono_compile_method (m);
+       addr = compiled_method = mono_compile_method_checked (m, error);
+       mono_error_assert_ok (error);
        g_assert (addr);
 
        addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg);
@@ -1508,7 +1654,13 @@ mono_resolve_vcall_gsharedvt (MonoObject *this_obj, int slot, MonoMethod *imt_me
 {
        g_assert (this_obj);
 
-       return resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE);
+       MonoError error;
+       gpointer result = resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE, &error);
+       if (!is_ok (&error)) {
+               MonoException *ex = mono_error_convert_to_exception (&error);
+               mono_llvm_throw_exception ((MonoObject*)ex);
+       }
+       return result;
 }
 
 /*
@@ -1552,7 +1704,8 @@ mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic
                need_unbox_tramp = TRUE;
 
        // FIXME: This can throw exceptions
-       addr = compiled_method = mono_compile_method (m);
+       addr = compiled_method = mono_compile_method_checked (m, &error);
+       mono_error_assert_ok (&error);
        g_assert (addr);
 
        addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
@@ -1579,6 +1732,7 @@ mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic
 MonoFtnDesc*
 mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *generic_virtual)
 {
+       MonoError error;
        MonoMethod *m, *variant_iface;
        gpointer addr, aot_addr, compiled_method;
        gboolean need_unbox_tramp = FALSE;
@@ -1588,13 +1742,18 @@ mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMetho
 
        imt = (gpointer*)vt - MONO_IMT_SIZE;
 
-       mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface);
+       mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface, &error);
+       if (!is_ok (&error)) {
+               MonoException *ex = mono_error_convert_to_exception (&error);
+               mono_llvm_throw_exception ((MonoObject*)ex);
+       }
 
        if (vt->klass->valuetype)
                need_unbox_tramp = TRUE;
 
        // FIXME: This can throw exceptions
-       addr = compiled_method = mono_compile_method (m);
+       addr = compiled_method = mono_compile_method_checked (m, &error);
+       mono_error_assert_ok (&error);
        g_assert (addr);
 
        addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
@@ -1621,11 +1780,14 @@ mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMetho
 gpointer
 mono_init_vtable_slot (MonoVTable *vtable, int slot)
 {
+       MonoError error;
        gpointer arg = NULL;
        gpointer addr;
        gpointer *ftnptr;
 
-       addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE);
+       addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE, &error);
+       if (mono_error_set_pending_exception (&error))
+               return NULL;
        ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer));
        ftnptr [0] = addr;
        ftnptr [1] = arg;
@@ -1645,6 +1807,7 @@ mono_init_vtable_slot (MonoVTable *vtable, int slot)
 void
 mono_llvmonly_init_delegate (MonoDelegate *del)
 {
+       MonoError error;
        MonoFtnDesc *ftndesc = *(MonoFtnDesc**)del->method_code;
 
        /*
@@ -1653,7 +1816,13 @@ mono_llvmonly_init_delegate (MonoDelegate *del)
         * but we don't have a a structure which could own its memory.
         */
        if (G_UNLIKELY (!ftndesc)) {
-               gpointer addr = mono_compile_method (del->method);
+               gpointer addr = mono_compile_method_checked (del->method, &error);
+               if (mono_error_set_pending_exception (&error))
+                       return;
+
+               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);
@@ -1667,25 +1836,40 @@ mono_llvmonly_init_delegate (MonoDelegate *del)
 void
 mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
 {
+       MonoError error;
+
        g_assert (target);
 
        method = mono_object_get_virtual_method (target, method);
 
        del->method = method;
-       del->method_ptr = mono_compile_method (method);
+       del->method_ptr = mono_compile_method_checked (method, &error);
+       if (mono_error_set_pending_exception (&error))
+               return;
+       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
@@ -1696,24 +1880,35 @@ 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;
+       MonoException *ex;
 
-       jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
-       g_assert (jit_tls);
-       jit_tls->calling_image = image;
+       ex = mono_thread_force_interruption_checkpoint_noraise ();
+       if (ex)
+               mono_raise_exception (ex);
 }
 
-MonoObject*
-mono_llvmonly_get_calling_assembly (void)
+void
+mono_throw_method_access (MonoMethod *callee, MonoMethod *caller)
 {
-       MonoJitTlsData *jit_tls = NULL;
+       char *callee_name = mono_method_full_name (callee, 1);
+       char *caller_name = mono_method_full_name (caller, 1);
+       MonoError error;
 
-       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);
+       mono_error_init (&error);
+       mono_error_set_generic_error (&error, "System", "MethodAccessException", "Method `%s' is inaccessible from method `%s'\n", callee_name, caller_name);
+       mono_error_set_pending_exception (&error);
+       g_free (callee_name);
+       g_free (caller_name);
 }