Merge pull request #3104 from lambdageek/dev/monoerror-resolve_vcall
authorAleksey Kliger (λgeek) <akliger@gmail.com>
Mon, 6 Jun 2016 18:01:44 +0000 (14:01 -0400)
committerAleksey Kliger (λgeek) <akliger@gmail.com>
Mon, 6 Jun 2016 18:01:44 +0000 (14:01 -0400)
[llvm] Raise MonoError using mono_llvm_throw_exception

mono/mini/jit-icalls.c
mono/mini/mini-trampolines.c
mono/mini/mini.h

index 39abeb285497461e407cb5f3f1bfb3dd0fa96d7b..e648c4128ce088a982b7ed81bd18c3557be1efe0 100644 (file)
@@ -1487,15 +1487,15 @@ 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)
 {
-       MonoError error;
        MonoVTable *vt;
        gpointer *imt, *vtable_slot;
        MonoMethod *impl_method, *generic_virtual = NULL, *variant_iface = NULL;
        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;
@@ -1503,11 +1503,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_checked (impl_method, &error);
-       mono_error_assert_ok (&error);
+       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)
@@ -1537,7 +1538,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
@@ -1566,18 +1573,18 @@ 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)
 {
-       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, &error);
-       mono_error_raise_exception (&error); // FIXME: Don't raise here
+       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);
 
@@ -1602,8 +1609,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);
-               mono_error_assert_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) {
@@ -1615,8 +1622,8 @@ resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_a
        }
 
        // FIXME: This can throw exceptions
-       addr = compiled_method = mono_compile_method_checked (m, &error);
-       mono_error_assert_ok (&error);
+       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);
@@ -1638,7 +1645,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;
 }
 
 /*
@@ -1720,7 +1733,11 @@ 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;
@@ -1754,11 +1771,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;
index 68b5a8b0a47b5efbfa8421bb212c0f8d014e905a..27820c19f9fa6c19c7af17e34955d16675120698 100644 (file)
@@ -154,7 +154,7 @@ mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr)
  * Either IMPL_METHOD or OUT_AOT_ADDR will be set on return.
  */
 gpointer*
-mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr, gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface)
+mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr, gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface, MonoError *error)
 {
        MonoMethod *impl = NULL, *generic_virtual = NULL;
        gboolean lookup_aot, variance_used = FALSE, need_rgctx_tramp = FALSE;
@@ -166,6 +166,7 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
 
        g_assert (imt_slot < MONO_IMT_SIZE);
 
+       mono_error_init (error);
        /* This has to be variance aware since imt_method can be from an interface that vt->klass doesn't directly implement */
        interface_offset = mono_class_interface_offset_with_variance (vt->klass, imt_method->klass, &variance_used);
        if (interface_offset < 0)
@@ -188,7 +189,6 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
                mono_vtable_build_imt_slot (vt, mono_method_get_imt_slot (imt_method));
 
        if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst) {
-               MonoError error;
                MonoGenericContext context = { NULL, NULL };
 
                /*
@@ -201,15 +201,14 @@ mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_
                if (impl->klass->generic_class)
                        context.class_inst = impl->klass->generic_class->context.class_inst;
                context.method_inst = ((MonoMethodInflated*)imt_method)->context.method_inst;
-               impl = mono_class_inflate_generic_method_checked (impl, &context, &error);
-               g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+               impl = mono_class_inflate_generic_method_checked (impl, &context, error);
+               mono_error_assert_ok (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), &error);
-                       mono_error_raise_exception (&error); // FIXME: Don't raise here
+                       aot_addr = (guint8 *)mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, interface_offset + mono_method_get_vtable_slot (imt_method), error);
+                       return_val_if_nok (error, NULL);
                } else {
                        aot_addr = NULL;
                }
@@ -562,7 +561,9 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                                need_rgctx_tramp = TRUE;
                        }
 
-                       vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface);
+                       vtable_slot = mini_resolve_imt_method (vt, vtable_slot, imt_method, &impl_method, &addr, &need_rgctx_tramp, &variant_iface, error);
+                       return_val_if_nok (error, NULL);
+
                        /* This is the vcall slot which gets called through the IMT thunk */
                        vtable_slot_to_patch = vtable_slot;
 
@@ -585,7 +586,6 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
         * return TRUE for methods used in IMT calls too.
         */
        if (virtual_ && is_generic_method_definition (m)) {
-               MonoError error;
                MonoGenericContext context = { NULL, NULL };
                MonoMethod *declaring;
 
@@ -604,8 +604,8 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                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: only do this if the method is sharable */
                need_rgctx_tramp = TRUE;
        } else if ((context_used = mono_method_check_context_used (m))) {
@@ -658,7 +658,6 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                }
 
                if (method_inst || m->wrapper_type) {
-                       MonoError error;
                        MonoGenericContext context = { NULL, NULL };
 
                        if (m->is_inflated)
@@ -672,8 +671,8 @@ common_call_trampoline (mgreg_t *regs, guint8 *code, MonoMethod *m, MonoVTable *
                                context.class_inst = klass->generic_container->context.class_inst;
                        context.method_inst = method_inst;
 
-                       actual_method = mono_class_inflate_generic_method_checked (declaring, &context, &error);
-                       g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
+                       actual_method = mono_class_inflate_generic_method_checked (declaring, &context, error);
+                       mono_error_assert_ok (error);
                } else {
                        actual_method = mono_class_get_method_generic (klass, m);
                }
index f0f76b0a6710ccd89eb0158dda78e298a5866430..48729fc2eeeac4601b3a06e59a30d06c120fabf4 100644 (file)
@@ -2572,7 +2572,8 @@ gpointer          mini_add_method_trampoline (MonoMethod *m, gpointer compiled_m
 gpointer          mini_add_method_wrappers_llvmonly (MonoMethod *m, gpointer compiled_method, gboolean caller_gsharedvt, gboolean add_unbox_tramp, gpointer *out_arg);
 gboolean          mini_jit_info_is_gsharedvt (MonoJitInfo *ji);
 gpointer*         mini_resolve_imt_method (MonoVTable *vt, gpointer *vtable_slot, MonoMethod *imt_method, MonoMethod **impl_method, gpointer *out_aot_addr,
-                                                                                  gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface);
+                                          gboolean *out_need_rgctx_tramp, MonoMethod **variant_iface,
+                                          MonoError *error);
 MonoFtnDesc      *mini_create_llvmonly_ftndesc (MonoDomain *domain, gpointer addr, gpointer arg);
 
 gboolean          mono_running_on_valgrind (void);