summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
authork0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-10 14:52:12 +0000
committerk0kubun <k0kubun@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-10 14:52:12 +0000
commit724878c9139715fea803690cfd2a0687abbd7242 (patch)
tree53bf906732f19773161fa1c893af508017ac8232 /compile.c
parentcfcf1d1a1aaf3eb4525d10e19b0d19cbd84ccd2b (diff)
compile.c: mark all ISeq ancestors as catch_except_p
This change assumes that continuously reading `parent_iseq` from block ISeq would reach non-block ISeq finally. test/ruby/test_jit.rb: add test that catches 2-depth exception Combination of r62654 and r62678 caused following error in this test. -e:12:in `wrapper': Stack consistency error (sp: 14, bp: 13) (fatal) == disasm: #<ISeq:wrapper@-e:10 (10,0)-(12,3)> (catch: FALSE)=========== local table (size: 2, argc: 2 [opts: 0, rest: -1, post: 0, block: -1, kw: -1@-1, kwrest: -1]) [ 2] paths<Arg> [ 1] prefixes<Arg> 0000 putself ( 11)[LiCa] 0001 getlocal_WC_0 paths 0003 getlocal_WC_0 prefixes 0005 opt_send_without_block <callinfo!mid:catch_true, argc:2, FCALL|ARGS_SIMPLE>, <callcache> 0008 leave ( 12)[Re] As you can see, it says `catch: FALSE`, but obviously it catches exception raised from `return path`. As of r62655, it was kind of intentional because I only cared about expiration of JIT-ed frame and I've thought calling `vm_exec` is only needed once for it. So r62654 was NOT actually checking if it may catch exception. But for r62678, obviously we should set catch_except_p=TRUE for all ISeqs which may catch exception. Otherwise catch table lookup would fail. With this bugfix, code generated by r62655 might be worse, but at least while loop can be marked as `catch: FALSE` as expected. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@62717 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/compile.c b/compile.c
index 7b784b8560..2c388b8a8c 100644
--- a/compile.c
+++ b/compile.c
@@ -1246,6 +1246,15 @@ new_child_iseq_ifunc(rb_iseq_t *iseq, const struct vm_ifunc *ifunc,
return ret_iseq;
}
+static void
+set_catch_except_p(struct rb_iseq_constant_body *body)
+{
+ body->catch_except_p = TRUE;
+ if (body->parent_iseq != NULL) {
+ set_catch_except_p(body->parent_iseq->body);
+ }
+}
+
/* 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
@@ -1273,7 +1282,7 @@ update_catch_except_flags(struct rb_iseq_constant_body *body)
#endif
if (insn == BIN(throw)) {
struct rb_iseq_constant_body *parent_body = body->parent_iseq->body;
- parent_body->catch_except_p = TRUE;
+ set_catch_except_p(parent_body);
}
pos += insn_len(insn);
}