[aot] Avoid raising exceptions in the AOT runtime. (#3043)
authorZoltan Varga <vargaz@gmail.com>
Wed, 25 May 2016 16:35:39 +0000 (12:35 -0400)
committerZoltan Varga <vargaz@gmail.com>
Wed, 25 May 2016 16:35:39 +0000 (12:35 -0400)
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/driver.c
mono/mini/jit-icalls.c
mono/mini/jit.h
mono/mini/mini-trampolines.c
mono/mini/mini.h

index 2078e8ef8543dc8da7291bd9306b1f8021552522..2ebae1f232242f94400f0dba9350a546e639be73 100644 (file)
@@ -2400,9 +2400,8 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin
 }      
 
 gpointer
-mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot, MonoError *error)
 {
-       MonoError error;
        int i;
        MonoClass *klass = vtable->klass;
        MonoAotModule *amodule = (MonoAotModule *)klass->image->aot_module;
@@ -2412,6 +2411,8 @@ mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int sl
        MethodRef ref;
        gboolean res;
 
+       mono_error_init (error);
+
        if (MONO_CLASS_IS_INTERFACE (klass) || klass->rank || !amodule)
                return NULL;
 
@@ -2423,12 +2424,12 @@ mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int sl
                return NULL;
 
        for (i = 0; i < slot; ++i) {
-               decode_method_ref (amodule, &ref, p, &p, &error);
-               mono_error_cleanup (&error); /* FIXME don't swallow the error */
+               decode_method_ref (amodule, &ref, p, &p, error);
+               mono_error_cleanup (error); /* FIXME don't swallow the error */
        }
 
-       res = decode_method_ref (amodule, &ref, p, &p, &error);
-       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+       res = decode_method_ref (amodule, &ref, p, &p, error);
+       mono_error_cleanup (error); /* FIXME don't swallow the error */
        if (!res)
                return NULL;
        if (ref.no_aot_trampoline)
@@ -2437,7 +2438,7 @@ mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int sl
        if (mono_metadata_token_index (ref.token) == 0 || mono_metadata_token_table (ref.token) != MONO_TABLE_METHOD)
                return NULL;
 
-       return mono_aot_get_method_from_token (domain, ref.image, ref.token);
+       return mono_aot_get_method_from_token (domain, ref.image, ref.token, error);
 }
 
 gboolean
@@ -4254,28 +4255,36 @@ init_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, M
        return FALSE;
 }
 
-void
-mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
+static void
+init_llvmonly_method (MonoAotModule *amodule, guint32 method_index, MonoMethod *method, MonoClass *init_class, MonoGenericContext *context)
 {
-       MonoAotModule *amodule = (MonoAotModule *)aot_module;
        gboolean res;
        MonoError error;
 
-       res = init_method (amodule, method_index, NULL, NULL, NULL, &error);
-       // FIXME: Pass the exception up to the caller ?
+       res = init_method (amodule, method_index, method, init_class, context, &error);
        /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       if (!is_ok (&error)) {
+               MonoException *ex = mono_error_convert_to_exception (&error);
+               if (ex)
+                       mono_llvm_throw_exception ((MonoObject*)ex);
+       }
+}
+
+void
+mono_aot_init_llvm_method (gpointer aot_module, guint32 method_index)
+{
+       MonoAotModule *amodule = (MonoAotModule *)aot_module;
+
+       init_llvmonly_method (amodule, method_index, NULL, NULL, NULL);
 }
 
 void
 mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, MonoObject *this_obj)
 {
        MonoAotModule *amodule = (MonoAotModule *)aot_module;
-       gboolean res;
        MonoClass *klass;
        MonoGenericContext *context;
        MonoMethod *method;
-       MonoError error;
 
        // FIXME:
        g_assert (this_obj);
@@ -4289,19 +4298,15 @@ mono_aot_init_gshared_method_this (gpointer aot_module, guint32 method_index, Mo
        context = mono_method_get_context (method);
        g_assert (context);
 
-       res = init_method (amodule, method_index, NULL, klass, context, &error);
-       /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       init_llvmonly_method (amodule, method_index, NULL, klass, context);
 }
 
 void
 mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index, MonoMethodRuntimeGenericContext *rgctx)
 {
        MonoAotModule *amodule = (MonoAotModule *)aot_module;
-       gboolean res;
        MonoGenericContext context = { NULL, NULL };
        MonoClass *klass = rgctx->class_vtable->klass;
-       MonoError error;
 
        if (klass->generic_class)
                context.class_inst = klass->generic_class->context.class_inst;
@@ -4309,20 +4314,16 @@ mono_aot_init_gshared_method_mrgctx (gpointer aot_module, guint32 method_index,
                context.class_inst = klass->generic_container->context.class_inst;
        context.method_inst = rgctx->method_inst;
 
-       res = init_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context, &error);
-       /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       init_llvmonly_method (amodule, method_index, NULL, rgctx->class_vtable->klass, &context);
 }
 
 void
 mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index, MonoVTable *vtable)
 {
        MonoAotModule *amodule = (MonoAotModule *)aot_module;
-       gboolean res;
        MonoClass *klass;
        MonoGenericContext *context;
        MonoMethod *method;
-       MonoError error;
 
        klass = vtable->klass;
 
@@ -4334,9 +4335,7 @@ mono_aot_init_gshared_method_vtable (gpointer aot_module, guint32 method_index,
        context = mono_method_get_context (method);
        g_assert (context);
 
-       res = init_method (amodule, method_index, NULL, klass, context, &error);
-       /* Its okay to raise in llvmonly mode */
-       mono_error_raise_exception (&error);
+       init_llvmonly_method (amodule, method_index, NULL, klass, context);
 }
 
 /*
@@ -4389,7 +4388,7 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
         * remoting.
         */
        if (mono_aot_only && method->wrapper_type == MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK)
-               return mono_aot_get_method (domain, mono_marshal_method_from_wrapper (method));
+               return mono_aot_get_method_checked (domain, mono_marshal_method_from_wrapper (method), error);
 
        g_assert (klass->inited);
 
@@ -4429,9 +4428,11 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED && method->klass->rank && strstr (method->name, "System.Collections.Generic")) {
                        MonoMethod *m = mono_aot_get_array_helper_from_wrapper (method);
 
-                       code = (guint8 *)mono_aot_get_method (domain, m);
+                       code = (guint8 *)mono_aot_get_method_checked (domain, m, error);
                        if (code)
                                return code;
+                       if (!is_ok (error))
+                               return NULL;
                }
 
                /*
@@ -4440,7 +4441,6 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                 * an out parameter, so the managed-to-native wrappers can share the same code.
                 */
                if (method_index == 0xffffff && method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE && method->klass == mono_defaults.array_class && !strcmp (method->name, "GetGenericValueImpl")) {
-                       MonoError error;
                        MonoMethod *m;
                        MonoGenericContext ctx;
                        MonoType *args [16];
@@ -4456,17 +4456,19 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                        args [0] = &mono_defaults.object_class->byval_arg;
                        ctx.method_inst = mono_metadata_get_generic_inst (1, args);
 
-                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, error), TRUE, TRUE);
                        if (!m)
-                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (error)); /* FIXME don't swallow the error */
 
                        /* 
                         * Get the code for the <object> instantiation which should be emitted into
                         * the mscorlib aot image by the AOT compiler.
                         */
-                       code = (guint8 *)mono_aot_get_method (domain, m);
+                       code = (guint8 *)mono_aot_get_method_checked (domain, m, error);
                        if (code)
                                return code;
+                       if (!is_ok (error))
+                               return NULL;
                }
 
                /* Same for CompareExchange<T> and Exchange<T> */
@@ -4475,7 +4477,6 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                        ((!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Interlocked") && (!strcmp (method->name, "CompareExchange") || !strcmp (method->name, "Exchange")) && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1]))) ||
                         (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Read") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->ret)))) ||
                         (!strcmp (method->klass->name_space, "System.Threading") && !strcmp (method->klass->name, "Volatile") && (!strcmp (method->name, "Write") && MONO_TYPE_IS_REFERENCE (mini_type_get_underlying_type (mono_method_signature (method)->params [1])))))) {
-                       MonoError error;
                        MonoMethod *m;
                        MonoGenericContext ctx;
                        MonoType *args [16];
@@ -4491,9 +4492,9 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                        args [0] = &mono_defaults.object_class->byval_arg;
                        ctx.method_inst = mono_metadata_get_generic_inst (1, args);
 
-                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, &error), TRUE, TRUE);
+                       m = mono_marshal_get_native_wrapper (mono_class_inflate_generic_method_checked (m, &ctx, error), TRUE, TRUE);
                        if (!m)
-                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (&error)); /* FIXME don't swallow the error */
+                               g_error ("AOT runtime could not load method due to %s", mono_error_get_message (error)); /* FIXME don't swallow the error */
 
                        /* Avoid recursion */
                        if (method == m)
@@ -4503,9 +4504,11 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
                         * Get the code for the <object> instantiation which should be emitted into
                         * the mscorlib aot image by the AOT compiler.
                         */
-                       code = (guint8 *)mono_aot_get_method (domain, m);
+                       code = (guint8 *)mono_aot_get_method_checked (domain, m, error);
                        if (code)
                                return code;
+                       if (!is_ok (error))
+                               return NULL;
                }
 
                /* For ARRAY_ACCESSOR wrappers with reference types, use the <object> instantiation saved in corlib */
@@ -4521,9 +4524,11 @@ mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *
 
                                        m = mono_marshal_get_array_accessor_wrapper (m);
                                        if (m != method) {
-                                               code = (guint8 *)mono_aot_get_method (domain, m);
+                                               code = (guint8 *)mono_aot_get_method_checked (domain, m, error);
                                                if (code)
                                                        return code;
+                                               if (!is_ok (error))
+                                                       return NULL;
                                        }
                                }
                        }
@@ -4596,6 +4601,7 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
        MonoError error;
 
        gpointer res = mono_aot_get_method_checked (domain, method, &error);
+       /* This is a public api function so it can raise exceptions */
        mono_error_raise_exception (&error);
        return res;
 }
@@ -4605,20 +4611,20 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
  * method.
  */
 gpointer
-mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
+mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token, MonoError *error)
 {
        MonoAotModule *aot_module = (MonoAotModule *)image->aot_module;
        int method_index;
-       MonoError error;
        gpointer res;
 
+       mono_error_init (error);
+
        if (!aot_module)
                return NULL;
 
        method_index = mono_metadata_token_index (token) - 1;
 
-       res = load_method (domain, aot_module, image, NULL, token, method_index, &error);
-       mono_error_raise_exception (&error); /* FIXME: Don't raise here */
+       res = load_method (domain, aot_module, image, NULL, token, method_index, error);
        return res;
 }
 
@@ -5825,6 +5831,12 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method)
        return NULL;
 }
 
+gpointer
+mono_aot_get_method_checked (MonoDomain *domain, MonoMethod *method, MonoError *error)
+{
+       return NULL;
+}
+
 gboolean
 mono_aot_is_got_entry (guint8 *code, guint8 *addr)
 {
@@ -5850,7 +5862,7 @@ mono_aot_find_jit_info (MonoDomain *domain, MonoImage *image, gpointer addr)
 }
 
 gpointer
-mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token)
+mono_aot_get_method_from_token (MonoDomain *domain, MonoImage *image, guint32 token, MonoError *error)
 {
        return NULL;
 }
@@ -5873,7 +5885,7 @@ mono_aot_patch_plt_entry (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_
 }
 
 gpointer
-mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot)
+mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot, MonoError *error)
 {
        return NULL;
 }
index 21fa1d4fc8ffa6b08cb2a41c8fba72e525984030..f0a4f49dd7fce66daa38936e06948b3896b1ca6b 100644 (file)
@@ -4320,8 +4320,10 @@ set_bp_in_method (MonoDomain *domain, MonoMethod *method, MonoSeqPointInfo *seq_
 
        code = mono_jit_find_compiled_method_with_jit_info (domain, method, &ji);
        if (!code) {
+               MonoError error;
+
                /* Might be AOTed code */
-               code = mono_aot_get_method (domain, method);
+               code = mono_aot_get_method_checked (domain, method, &error);
                g_assert (code);
                ji = mono_jit_info_table_find (domain, (char *)code);
                g_assert (ji);
index aa80289292431607f3c68cb9b344b3e5fa7fea28..7b37da2a67705dae962975399db081541af1392f 100644 (file)
@@ -399,7 +399,7 @@ mini_regression_step (MonoImage *image, int verbose, int *total_run, int *total,
                                if (verbose >= 2)
                                        g_print ("Running '%s' ...\n", method->name);
 #ifdef MONO_USE_AOT_COMPILER
-                               if ((func = (TestMethod)mono_aot_get_method (mono_get_root_domain (), method)))
+                               if ((func = (TestMethod)mono_aot_get_method_checked (mono_get_root_domain (), method, &error)))
                                        ;
                                else
 #endif
index 1c365d577b8fac4b4cc97e16d56318a771b19f99..5852061fcd8c4a649bd8a6dbb8e1097eb24bbcc1 100644 (file)
@@ -1576,7 +1576,8 @@ resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_a
        /* 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);
+       mono_error_assert_ok (&error); /* FIXME don't swallow the error */
        if (addr && !vt->klass->valuetype)
                return mono_create_ftnptr (mono_domain_get (), addr);
 
index f2dc914e374aaf959ca6cbb97336efe5bb72ab6c..6d528eb651c88b7375f6521083809f624422006d 100644 (file)
@@ -88,7 +88,7 @@ MONO_API char*       mono_get_runtime_build_info    (void);
 MONO_API MonoJitInfo *
 mono_get_jit_info_from_method (MonoDomain *domain, MonoMethod *method);
 
-MONO_API void *
+MONO_RT_EXTERNAL_ONLY MONO_API void *
 mono_aot_get_method (MonoDomain *domain, MonoMethod *method);
 
 MONO_END_DECLS
index 9a71893c239fa4137906d382c43df066c9b1ebde..69a76c19afec5f1c9f865649b3451dec0f345c80 100644 (file)
@@ -203,11 +203,14 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
                impl = mono_class_inflate_generic_method_checked (impl, &context, &error);
                g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
        } else {
+               MonoError error;
                /* Avoid loading metadata or creating a generic vtable if possible */
-               if (lookup_aot && !vt->klass->valuetype)
-                       aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method));
-               else
+               if (lookup_aot && !vt->klass->valuetype) {
+                       aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method), &error);
+                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+               } else {
                        aot_addr = NULL;
+               }
                if (aot_addr)
                        impl = NULL;
                else
@@ -870,7 +873,11 @@ mono_vcall_trampoline (mgreg_t *regs, guint8 *code, int slot, guint8 *tramp)
                vtable_slot = &(vt->vtable [slot]);
 
                /* 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);
+               if (!is_ok (&error)) {
+                       mono_error_set_pending_exception (&error);
+                       return NULL;
+               }
                if (addr && !vt->klass->valuetype) {
                        if (mono_domain_owns_vtable_slot (mono_domain_get (), vtable_slot))
                                *vtable_slot = addr;
@@ -968,6 +975,7 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info,
        MonoMethod *method = NULL;
        gpointer addr;
        guint8 *plt_entry;
+       MonoError error;
 
        trampoline_calls ++;
 
@@ -975,12 +983,13 @@ mono_aot_trampoline (mgreg_t *regs, guint8 *code, guint8 *token_info,
        token_info += sizeof (gpointer);
        token = *(guint32*)(gpointer)token_info;
 
-       addr = mono_aot_get_method_from_token (mono_domain_get (), image, token);
+       addr = mono_aot_get_method_from_token (mono_domain_get (), image, token, &error);
        if (!addr) {
-               MonoError error;
+               if (!is_ok (&error))
+                       g_error ("Could not load AOT method due to %s", mono_error_get_message (&error));
                method = mono_get_method_checked (image, token, NULL, NULL, &error);
                if (!method)
-                       g_error ("Could not load AOT trampoline due to %s", mono_error_get_message (&error));
+                       g_error ("Could not load AOT method due to %s", mono_error_get_message (&error));
 
                /* Use the generic code */
                return mono_magic_trampoline (regs, code, method, tramp);
index 4ad70f762bf8203405acc2b2293c8d84d4365ef0..1f2d43208115b5dd6122a86d26abc944861961d7 100644 (file)
@@ -2455,11 +2455,9 @@ jinfo_get_method (MonoJitInfo *ji)
 /* AOT */
 void      mono_aot_init                     (void);
 void      mono_aot_cleanup                  (void);
-gpointer  mono_aot_get_method               (MonoDomain *domain,
-                                                                                        MonoMethod *method);
 gpointer  mono_aot_get_method_checked       (MonoDomain *domain,
                                                                                         MonoMethod *method, MonoError *error);
-gpointer  mono_aot_get_method_from_token    (MonoDomain *domain, MonoImage *image, guint32 token);
+gpointer  mono_aot_get_method_from_token    (MonoDomain *domain, MonoImage *image, guint32 token, MonoError *error);
 gboolean  mono_aot_is_got_entry             (guint8 *code, guint8 *addr);
 guint8*   mono_aot_get_plt_entry            (guint8 *code);
 guint32   mono_aot_get_plt_info_offset      (mgreg_t *regs, guint8 *code);
@@ -2468,7 +2466,7 @@ gboolean  mono_aot_get_class_from_name      (MonoImage *image, const char *name_
 MonoJitInfo* mono_aot_find_jit_info         (MonoDomain *domain, MonoImage *image, gpointer addr);
 gpointer mono_aot_plt_resolve               (gpointer aot_module, guint32 plt_info_offset, guint8 *code, MonoError *error);
 void     mono_aot_patch_plt_entry           (guint8 *code, guint8 *plt_entry, gpointer *got, mgreg_t *regs, guint8 *addr);
-gpointer mono_aot_get_method_from_vt_slot   (MonoDomain *domain, MonoVTable *vtable, int slot);
+gpointer mono_aot_get_method_from_vt_slot   (MonoDomain *domain, MonoVTable *vtable, int slot, MonoError *error);
 gpointer mono_aot_create_specific_trampoline   (MonoImage *image, gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len);
 gpointer mono_aot_get_trampoline            (const char *name);
 gpointer mono_aot_get_trampoline_full       (const char *name, MonoTrampInfo **out_tinfo);