[interp] Implement CEE_RETHROW properly by allocating a separate exception variable...
authorZoltan Varga <vargaz@gmail.com>
Fri, 16 Jun 2017 20:01:38 +0000 (16:01 -0400)
committerGitHub <noreply@github.com>
Fri, 16 Jun 2017 20:01:38 +0000 (16:01 -0400)
mono/mini/exceptions.cs
mono/mini/interp/interp-internals.h
mono/mini/interp/interp.c
mono/mini/interp/mintops.def
mono/mini/interp/transform.c

index 07f498e628ba1812082dbf0cb1d3a12b2d86245d..3251985e4d702f02e7b58499dc727b99bc4949f2 100644 (file)
@@ -2316,7 +2316,6 @@ class Tests
                Console.WriteLine ();
        }
 
-       [Category ("!INTERPRETER")]
        [Category ("!BITCODE")]
        public static int test_0_rethrow_stacktrace () {
                // Check that rethrowing an exception preserves the original stack trace
index 895ea8242bacaa448fb3195fe3230fbcb3d1cdcd..60d91afd44426284352754e64eef1793af91821f 100644 (file)
@@ -85,6 +85,7 @@ typedef struct _RuntimeMethod
        int transformed;
        guint32 *arg_offsets;
        guint32 *local_offsets;
+       guint32 *exvar_offsets;
        unsigned int param_count;
        unsigned int hasthis;
        gpointer jit_wrapper;
index a103ed22b6a851c332eed65ef8484189bd284847..556595081a57d99332cef860c693a0721903fe95 100644 (file)
@@ -596,14 +596,18 @@ fill_in_trace (MonoException *exception, MonoInvocation *frame)
 
 #define FILL_IN_TRACE(exception, frame) fill_in_trace(exception, frame)
 
-#define THROW_EX(exception,ex_ip)      \
+#define THROW_EX_GENERAL(exception,ex_ip,rethrow)              \
        do {\
                frame->ip = (ex_ip);            \
                frame->ex = (MonoException*)(exception);        \
-               FILL_IN_TRACE(frame->ex, frame); \
+               if (!rethrow) { \
+                       FILL_IN_TRACE(frame->ex, frame);        \
+               } \
                goto handle_exception;  \
        } while (0)
 
+#define THROW_EX(exception,ex_ip) THROW_EX_GENERAL ((exception), (ex_ip), FALSE)
+
 static MonoObject*
 ves_array_create (MonoInvocation *frame, MonoDomain *domain, MonoClass *klass, MonoMethodSignature *sig, stackval *values)
 {
@@ -4974,7 +4978,7 @@ array_constructed:
                        ip += 2;
                        MINT_IN_BREAK;
 #endif
-               MINT_IN_CASE(MINT_RETHROW)
+          MINT_IN_CASE(MINT_RETHROW) {
                        /* 
                         * need to clarify what this should actually do:
                         * start the search from the last found handler in
@@ -4985,9 +4989,11 @@ array_constructed:
                         * We need to NULL frame->ex_handler for the later code to
                         * actually run the new found handler.
                         */
+                       int exvar_offset = *(guint16*)(ip + 1);
                        frame->ex_handler = NULL;
-                       THROW_EX (frame->ex, ip - 1);
+                       THROW_EX_GENERAL (*(MonoException**)(frame->locals + exvar_offset), ip - 1, TRUE);
                        MINT_IN_BREAK;
+          }
                MINT_IN_DEFAULT
                        g_print ("Unimplemented opcode: %04x %s at 0x%x\n", *ip, mono_interp_opname[*ip], ip-rtm->code);
                        THROW_EX (mono_get_exception_execution_engine ("Unimplemented opcode"), ip);
@@ -5055,6 +5061,7 @@ array_constructed:
                                                        g_print ("* Matched Filter at '%s'\n", method->name);
 #endif
                                                inv->ex_handler = clause;
+                                               *(MonoException**)(inv->locals + inv->runtime_method->exvar_offsets [i]) = frame->ex;
                                                goto handle_finally;
                                        }
                                } else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
@@ -5070,6 +5077,7 @@ array_constructed:
                                                        g_print ("* Found handler at '%s'\n", method->name);
 #endif
                                                inv->ex_handler = clause;
+                                               *(MonoException**)(inv->locals + inv->runtime_method->exvar_offsets [i]) = frame->ex;
                                                goto handle_finally;
                                        }
                                }
index 647e5838607a5b02433365592919a620f745feb6..fec89d9cd28a6a6a9ba8461dc80c0ba11c1fc0d5 100644 (file)
@@ -171,7 +171,7 @@ OPDEF(MINT_BR_S, "br.s", 2, MintOpShortBranch)
 OPDEF(MINT_LEAVE_S, "leave.s", 2, MintOpShortBranch)
 
 OPDEF(MINT_THROW, "throw", 1, MintOpNoArgs)
-OPDEF(MINT_RETHROW, "rethrow", 1, MintOpNoArgs)
+OPDEF(MINT_RETHROW, "rethrow", 2, MintOpUShortInt)
 OPDEF(MINT_ENDFINALLY, "endfinally", 2, MintOpNoArgs)
 
 OPDEF(MINT_BRFALSE_I4, "brfalse.i4", 3, MintOpBranch)
index 57b50650a7bd6525d669d4616715d2470b692e0a..21bbecf8e50f5af0d1e4d2d56da8b97bcc63b463 100644 (file)
@@ -1461,11 +1461,9 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                        td.stack_state [c->data.filter_offset][0].klass = NULL; /*FIX*/
                }
 
-               if ((c->flags & MONO_EXCEPTION_CLAUSE_FINALLY) || (c->flags & MONO_EXCEPTION_CLAUSE_FAULT)) {
-                       for (int j = c->handler_offset; j < c->handler_offset + c->handler_len; ++j) {
-                               if (td.clause_indexes [j] == -1)
-                                       td.clause_indexes [j] = i;
-                       }
+               for (int j = c->handler_offset; j < c->handler_offset + c->handler_len; ++j) {
+                       if (td.clause_indexes [j] == -1)
+                               td.clause_indexes [j] = i;
                }
        }
 
@@ -3743,10 +3741,14 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                ip += 2;
                                break;
 #endif
-                       case CEE_RETHROW:
+                       case CEE_RETHROW: {
+                               int clause_index = td.clause_indexes [in_offset];
+                               g_assert (clause_index != -1);
                                SIMPLE_OP (td, MINT_RETHROW);
+                               ADD_CODE (&td, rtm->exvar_offsets [clause_index]);
                                generating_code = 0;
                                break;
+                       }
                        case CEE_SIZEOF: {
                                gint32 size;
                                token = read32 (td.ip + 1);
@@ -3877,7 +3879,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                ei->try_start = (guint8*)(rtm->code + c->try_offset);
                ei->try_end = (guint8*)(rtm->code + c->try_offset + c->try_len);
                ei->handler_start = (guint8*)(rtm->code + c->handler_offset);
-               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
+               ei->exvar_offset = rtm->exvar_offsets [i];
+               if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+                       ei->data.filter = (guint8*)(rtm->code + c->data.filter_offset);
+               } else if (ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
                } else {
                        ei->data.catch_class = c->data.catch_class;
                }
@@ -4160,6 +4165,14 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                offset += size;
        }
        offset = (offset + 7) & ~7;
+
+       runtime_method->exvar_offsets = g_malloc (header->num_clauses * sizeof (guint32));
+       for (i = 0; i < header->num_clauses; i++) {
+               offset += sizeof (MonoObject*);
+               runtime_method->exvar_offsets [i] = offset;
+       }
+       offset = (offset + 7) & ~7;
+
        runtime_method->locals_size = offset;
        g_assert (runtime_method->locals_size < 65536);
        offset = 0;