[前][次][番号順一覧][スレッド一覧]

ruby-changes:50518

From: k0kubun <ko1@a...>
Date: Sun, 4 Mar 2018 16:04:34 +0900 (JST)
Subject: [ruby-changes:50518] k0kubun:r62654 (trunk): compile.c: set catch_except_p flag

k0kubun	2018-03-04 16:04:28 +0900 (Sun, 04 Mar 2018)

  New Revision: 62654

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62654

  Log:
    compile.c: set catch_except_p flag
    
    to be used for MJIT's optimization. It's not used for optimization
    in this commit yet.
    
    vm_core.h: added catch_except_p field.
    
    iseq.c: show the flag in ISeq disasm for debugging.

  Modified files:
    trunk/compile.c
    trunk/iseq.c
    trunk/vm_core.h
Index: vm_core.h
===================================================================
--- vm_core.h	(revision 62653)
+++ vm_core.h	(revision 62654)
@@ -424,6 +424,7 @@ struct rb_iseq_constant_body { https://github.com/ruby/ruby/blob/trunk/vm_core.h#L424
                       struct rb_control_frame_struct *); /* function pointer for loaded native code */
     long unsigned total_calls; /* number of total calls with `mjit_exec()` */
     struct rb_mjit_unit *jit_unit;
+    char catch_except_p; /* If a frame of this ISeq may catch exception, set TRUE */
 };
 
 /* T_IMEMO/iseq */
Index: compile.c
===================================================================
--- compile.c	(revision 62653)
+++ compile.c	(revision 62654)
@@ -1254,6 +1254,53 @@ new_child_iseq_ifunc(rb_iseq_t *iseq, co https://github.com/ruby/ruby/blob/trunk/compile.c#L1254
     return ret_iseq;
 }
 
+/* Set body->catch_except_p to TRUE if the ISeq may catch an exception. If it is FALSE,
+   JIT-ed code may be optimized.  If we are extremely conservative, we should set TRUE
+   if catch table exists.  But we want to optimize while loop, which always has catch
+   table entries for break/next/redo.
+
+   So this function sets TRUE for limited ISeqs with break/next/redo catch table entries
+   whose child ISeq would really raise an exception. */
+static void
+update_catch_except_flags(struct rb_iseq_constant_body *body)
+{
+    unsigned int pos;
+    size_t i;
+    int insn;
+    const struct iseq_catch_table *ct = body->catch_table;
+
+    /* This assumes that a block has parent_iseq which may catch an exception from the block, and that
+       BREAK/NEXT/REDO catch table entries are used only when `throw` insn is used in the block. */
+    if (body->parent_iseq != NULL) {
+        pos = 0;
+        while (pos < body->iseq_size) {
+#if OPT_DIRECT_THREADED_CODE || OPT_CALL_THREADED_CODE
+            insn = rb_vm_insn_addr2insn((void *)body->iseq_encoded[pos]);
+#else
+            insn = (int)body->iseq_encoded[pos];
+#endif
+            if (insn == BIN(throw)) {
+                struct rb_iseq_constant_body *parent_body = body->parent_iseq->body;
+                parent_body->catch_except_p = TRUE;
+            }
+            pos += insn_len(insn);
+        }
+    }
+
+    if (ct == NULL)
+        return;
+
+    for (i = 0; i < ct->size; i++) {
+        const struct iseq_catch_table_entry *entry = &ct->entries[i];
+        if (entry->type != CATCH_TYPE_BREAK
+            && entry->type != CATCH_TYPE_NEXT
+            && entry->type != CATCH_TYPE_REDO) {
+            body->catch_except_p = TRUE;
+            break;
+        }
+    }
+}
+
 static int
 iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor)
 {
@@ -1299,6 +1346,8 @@ iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR https://github.com/ruby/ruby/blob/trunk/compile.c#L1346
     debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
     if (!rb_iseq_translate_threaded_code(iseq)) return COMPILE_NG;
 
+    update_catch_except_flags(iseq->body);
+
     if (compile_debug > 1) {
 	VALUE str = rb_iseq_disasm(iseq);
 	printf("%s\n", StringValueCStr(str));
Index: iseq.c
===================================================================
--- iseq.c	(revision 62653)
+++ iseq.c	(revision 62654)
@@ -1809,6 +1809,7 @@ rb_iseq_disasm(const rb_iseq_t *iseq) https://github.com/ruby/ruby/blob/trunk/iseq.c#L1809
     rb_str_cat2(str, "== disasm: ");
 
     rb_str_concat(str, iseq_inspect(iseq));
+    rb_str_catf(str, " (catch: %s)", iseq->body->catch_except_p ? "TRUE" : "FALSE");
     if ((l = RSTRING_LEN(str)) < header_minlen) {
 	rb_str_resize(str, header_minlen);
 	memset(RSTRING_PTR(str) + l, '=', header_minlen - l);

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]