1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
k0kubun 2018-03-04 07:04:28 +00:00
parent ae34216021
commit 33949a0320
3 changed files with 51 additions and 0 deletions

View file

@ -1254,6 +1254,53 @@ new_child_iseq_ifunc(rb_iseq_t *iseq, const struct vm_ifunc *ifunc,
return ret_iseq; 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 static int
iseq_setup(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) 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"); debugs("[compile step 5 (iseq_translate_threaded_code)] \n");
if (!rb_iseq_translate_threaded_code(iseq)) return COMPILE_NG; if (!rb_iseq_translate_threaded_code(iseq)) return COMPILE_NG;
update_catch_except_flags(iseq->body);
if (compile_debug > 1) { if (compile_debug > 1) {
VALUE str = rb_iseq_disasm(iseq); VALUE str = rb_iseq_disasm(iseq);
printf("%s\n", StringValueCStr(str)); printf("%s\n", StringValueCStr(str));

1
iseq.c
View file

@ -1809,6 +1809,7 @@ rb_iseq_disasm(const rb_iseq_t *iseq)
rb_str_cat2(str, "== disasm: "); rb_str_cat2(str, "== disasm: ");
rb_str_concat(str, iseq_inspect(iseq)); 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) { if ((l = RSTRING_LEN(str)) < header_minlen) {
rb_str_resize(str, header_minlen); rb_str_resize(str, header_minlen);
memset(RSTRING_PTR(str) + l, '=', header_minlen - l); memset(RSTRING_PTR(str) + l, '=', header_minlen - l);

View file

@ -424,6 +424,7 @@ struct rb_iseq_constant_body {
struct rb_control_frame_struct *); /* function pointer for loaded native code */ struct rb_control_frame_struct *); /* function pointer for loaded native code */
long unsigned total_calls; /* number of total calls with `mjit_exec()` */ long unsigned total_calls; /* number of total calls with `mjit_exec()` */
struct rb_mjit_unit *jit_unit; struct rb_mjit_unit *jit_unit;
char catch_except_p; /* If a frame of this ISeq may catch exception, set TRUE */
}; };
/* T_IMEMO/iseq */ /* T_IMEMO/iseq */