diff options
author | k0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-04 07:04:28 +0000 |
---|---|---|
committer | k0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2018-03-04 07:04:28 +0000 |
commit | 33949a03203c7d0235ec1823b3827618237057a1 (patch) | |
tree | c79d8cfb6f12c59243a4e1bc03dfbf0e15ab0594 | |
parent | ae34216021b1f627f99f8845c8376ad54ccdfa08 (diff) | |
download | bundler-33949a03203c7d0235ec1823b3827618237057a1.tar.gz |
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.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62654 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | compile.c | 49 | ||||
-rw-r--r-- | iseq.c | 1 | ||||
-rw-r--r-- | vm_core.h | 1 |
3 files changed, 51 insertions, 0 deletions
@@ -1254,6 +1254,53 @@ new_child_iseq_ifunc(rb_iseq_t *iseq, const struct vm_ifunc *ifunc, 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 *const anchor) 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)); @@ -1809,6 +1809,7 @@ rb_iseq_disasm(const rb_iseq_t *iseq) 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); @@ -424,6 +424,7 @@ struct rb_iseq_constant_body { 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 */ |