[llvmonly] Fix the catching of exceptions of open types in shared methods by passing...
authorZoltan Varga <vargaz@gmail.com>
Mon, 18 Jan 2016 19:02:29 +0000 (14:02 -0500)
committerZoltan Varga <vargaz@gmail.com>
Mon, 18 Jan 2016 19:02:29 +0000 (14:02 -0500)
mono/mini/generics.cs
mono/mini/mini-exceptions.c
mono/mini/mini-llvm.c
mono/mini/mini-llvm.h
mono/mini/mini.h

index bf1353f8eed6f5cc3a0928e1c59594f0391884d3..1284cb292ae733f3f58dc8b78c5a07d72d31e488 100644 (file)
@@ -999,7 +999,6 @@ class Tests
        public static int test_0_fullaot_variant_iface () {
                var arr = new BClass [10];
                var enumerable = (IEnumerable<AClass>)arr;
-               Console.WriteLine (enumerable);
                enumerable.GetEnumerator ();
                return 0;
        }
@@ -1245,6 +1244,34 @@ class Tests
                test("a", "b", "c", "d", "e", "f", "g", "h");
                return delegate_8_args_res == "h" ? 0 : 1;
        }
+
+       static void throw_catch_t<T> () where T: Exception {
+               try {
+                       throw new NotSupportedException ();
+               } catch (T) {
+               }
+       }
+
+       public static int test_0_gshared_catch_open_type () {
+               throw_catch_t<NotSupportedException> ();
+               return 0;
+       }
+
+       class ThrowClass<T> where T: Exception {
+               public void throw_catch_t () {
+                       try {
+                               throw new NotSupportedException ();
+                       } catch (T) {
+                       }
+               }
+       }
+
+       public static int test_0_gshared_catch_open_type_instance () {
+               var c = new ThrowClass<NotSupportedException> ();
+               c.throw_catch_t ();
+               return 0;
+       }
+
 }
 
 #if !__MOBILE__
index 6430539bb672f2220073032433161c989af14fd6..b575a2ccb67fd6064aacb8de27e6e00af134bafd 100644 (file)
@@ -519,17 +519,22 @@ get_generic_info_from_stack_frame (MonoJitInfo *ji, MonoContext *ctx)
 
        method = jinfo_get_method (ji);
        if (mono_method_get_context (method)->method_inst) {
+               /* A MonoMethodRuntimeGenericContext* */
                return info;
        } else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype) {
+               /* A MonoVTable* */
                return info;
        } else {
                /* Avoid returning a managed object */
                MonoObject *this_obj = (MonoObject *)info;
 
-               return this_obj->vtable->klass;
+               return this_obj->vtable;
        }
 }
 
+/*
+ * generic_info is either a MonoMethodRuntimeGenericContext or a MonoVTable.
+ */
 static MonoGenericContext
 get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
 {
@@ -547,12 +552,10 @@ get_generic_context_from_stack_frame (MonoJitInfo *ji, gpointer generic_info)
                klass = mrgctx->class_vtable->klass;
                context.method_inst = mrgctx->method_inst;
                g_assert (context.method_inst);
-       } else if ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype) {
+       } else {
                MonoVTable *vtable = (MonoVTable *)generic_info;
 
                klass = vtable->klass;
-       } else {
-               klass = (MonoClass *)generic_info;
        }
 
        //g_assert (!method->klass->generic_container);
@@ -2884,7 +2887,7 @@ mono_llvm_clear_exception (void)
  * the current exception.
  */
 gint32
-mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end)
+mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj)
 {
        MonoJitTlsData *jit_tls = mono_get_jit_tls ();
        MonoObject *exc;
@@ -2894,12 +2897,25 @@ mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 reg
        exc = mono_gchandle_get_target (jit_tls->thrown_exc);
        for (int i = 0; i < jinfo->num_clauses; i++) {
                MonoJitExceptionInfo *ei = &jinfo->clauses [i];
+               MonoClass *catch_class;
 
                if (! (ei->try_offset == region_start && ei->try_offset + ei->try_len == region_end) )
                        continue;
 
+               catch_class = ei->data.catch_class;
+               if (catch_class->byval_arg.type == MONO_TYPE_VAR || catch_class->byval_arg.type == MONO_TYPE_MVAR || catch_class->byval_arg.type == MONO_TYPE_GENERICINST) {
+                       MonoGenericContext context;
+                       MonoType *inflated_type;
+
+                       g_assert (rgctx || this_obj);
+                       context = get_generic_context_from_stack_frame (jinfo, rgctx ? rgctx : this_obj->vtable);
+                       inflated_type = mono_class_inflate_generic_type (&catch_class->byval_arg, &context);
+                       catch_class = mono_class_from_mono_type (inflated_type);
+                       mono_metadata_free_type (inflated_type);
+               }
+
                // FIXME: Handle edge cases handled in get_exception_catch_class
-               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (exc, ei->data.catch_class)) {
+               if (ei->flags == MONO_EXCEPTION_CLAUSE_NONE && mono_object_isinst (exc, catch_class)) {
                        index = ei->clause_index;
                        break;
                } else if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
index 0189b4a470dda961f22c802e04150477b5d86ea9..d5f935fe86ca57cfe91d7c9dc21a9d26347cdbce 100644 (file)
@@ -1499,6 +1499,26 @@ LLVMFunctionType3 (LLVMTypeRef ReturnType,
        return LLVMFunctionType (ReturnType, param_types, 3, IsVarArg);
 }
 
+static G_GNUC_UNUSED LLVMTypeRef
+LLVMFunctionType5 (LLVMTypeRef ReturnType,
+                                  LLVMTypeRef ParamType1,
+                                  LLVMTypeRef ParamType2,
+                                  LLVMTypeRef ParamType3,
+                                  LLVMTypeRef ParamType4,
+                                  LLVMTypeRef ParamType5,
+                                  int IsVarArg)
+{
+       LLVMTypeRef param_types [5];
+
+       param_types [0] = ParamType1;
+       param_types [1] = ParamType2;
+       param_types [2] = ParamType3;
+       param_types [3] = ParamType4;
+       param_types [4] = ParamType5;
+
+       return LLVMFunctionType (ReturnType, param_types, 5, IsVarArg);
+}
+
 /*
  * create_builder:
  *
@@ -3548,13 +3568,24 @@ mono_llvm_emit_match_exception_call (EmitContext *ctx, LLVMBuilderRef builder, g
 
        ctx->builder = builder;
 
-       const int num_args = 3;
+       const int num_args = 5;
        LLVMValueRef args [num_args];
        args [0] = convert (ctx, get_aotconst (ctx, MONO_PATCH_INFO_AOT_JIT_INFO, GINT_TO_POINTER (ctx->cfg->method_index)), IntPtrType ());
        args [1] = LLVMConstInt (LLVMInt32Type (), region_start, 0);
        args [2] = LLVMConstInt (LLVMInt32Type (), region_end, 0);
+       if (ctx->cfg->rgctx_var) {
+               LLVMValueRef rgctx_alloc = ctx->addresses [ctx->cfg->rgctx_var->dreg];
+               g_assert (rgctx_alloc);
+               args [3] = LLVMBuildLoad (builder, convert (ctx, rgctx_alloc, LLVMPointerType (IntPtrType (), 0)), "");
+       } else {
+               args [3] = LLVMConstInt (IntPtrType (), 0, 0);
+       }
+       if (ctx->this_arg)
+               args [4] = convert (ctx, ctx->this_arg, IntPtrType ());
+       else
+               args [4] = LLVMConstInt (IntPtrType (), 0, 0);
 
-       LLVMTypeRef match_sig = LLVMFunctionType3 (LLVMInt32Type (), IntPtrType (), LLVMInt32Type (), LLVMInt32Type (), FALSE);
+       LLVMTypeRef match_sig = LLVMFunctionType5 (LLVMInt32Type (), IntPtrType (), LLVMInt32Type (), LLVMInt32Type (), IntPtrType (), IntPtrType (), FALSE);
        LLVMValueRef callee = ctx->module->match_exc;
 
        if (!callee) {
index b7ec0167d226bbfb142375f3d578fbe32ead03a4..027a16fa3c75ec9a48dcede0540f1996e42c2c48 100644 (file)
@@ -17,15 +17,6 @@ void     mono_llvm_check_method_supported   (MonoCompile *cfg) MONO_LLVM_INTERNA
 void     mono_llvm_free_domain_info         (MonoDomain *domain) MONO_LLVM_INTERNAL;
 MONO_API void mono_personality              (void);
 int      mono_llvm_load                     (const char* bpath);
-void     mono_llvm_rethrow_exception (MonoObject *ex);
-void     mono_llvm_throw_exception (MonoObject *ex);
-void     mono_llvm_throw_corlib_exception (guint32 ex_token_index);
-void     mono_llvm_resume_exception (void);
-gint32   mono_llvm_match_exception (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end);
-void     mono_llvm_clear_exception (void);
-MonoObject *mono_llvm_load_exception (void);
-void     mono_llvm_reset_exception (void);
-void     mono_llvm_raise_exception (MonoException *e);
 void     mono_llvm_create_vars (MonoCompile *cfg) MONO_LLVM_INTERNAL;
 
 gboolean mini_llvm_init                     (void);
index 3d029d740d80a398596ab0c542f4367ef3402cb0..6cd3b72bfdba0998db5e69b3a7931f61f6821152 100644 (file)
@@ -2800,6 +2800,15 @@ MONO_API gboolean mono_exception_walk_trace     (MonoException *ex, MonoExceptio
 void mono_restore_context                       (MonoContext *ctx);
 guint8* mono_jinfo_get_unwind_info              (MonoJitInfo *ji, guint32 *unwind_info_len);
 int  mono_jinfo_get_epilog_size                 (MonoJitInfo *ji);
+void     mono_llvm_rethrow_exception            (MonoObject *ex);
+void     mono_llvm_throw_exception              (MonoObject *ex);
+void     mono_llvm_throw_corlib_exception       (guint32 ex_token_index);
+void     mono_llvm_resume_exception             (void);
+void     mono_llvm_clear_exception              (void);
+MonoObject *mono_llvm_load_exception            (void);
+void     mono_llvm_reset_exception              (void);
+void     mono_llvm_raise_exception              (MonoException *e);
+gint32 mono_llvm_match_exception                (MonoJitInfo *jinfo, guint32 region_start, guint32 region_end, gpointer rgctx, MonoObject *this_obj);
 
 gboolean
 mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,