summaryrefslogtreecommitdiff
path: root/compile.c
diff options
context:
space:
mode:
author卜部昌平 <shyouhei@ruby-lang.org>2020-06-11 15:18:42 +0900
committer卜部昌平 <shyouhei@ruby-lang.org>2020-06-29 11:05:41 +0900
commitcc1e9b8e1178cf4284fbcae1a94950e580491a05 (patch)
tree88cc45dd2347762f18c39ee4bf5c45be726bae69 /compile.c
parent1f90690a1d2931e960a54056de089d163b689ed4 (diff)
compile_break: do not goto into a branch
I'm not necessarily against every goto in general, but jumping into a branch is definitely a bad idea. Better refactor.
Notes
Notes: Merged: https://github.com/ruby/ruby/pull/3247
Diffstat (limited to 'compile.c')
-rw-r--r--compile.c34
1 files changed, 15 insertions, 19 deletions
diff --git a/compile.c b/compile.c
index 48b3afd2d7..5bf72e1ec0 100644
--- a/compile.c
+++ b/compile.c
@@ -6579,22 +6579,8 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_INSN(ret, line, putnil);
}
}
- else if (iseq->body->type == ISEQ_TYPE_BLOCK) {
- break_by_insn:
- /* escape from block */
- CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
- ADD_INSN1(ret, line, throw, INT2FIX(throw_flag | TAG_BREAK));
- if (popped) {
- ADD_INSN(ret, line, pop);
- }
- }
- else if (iseq->body->type == ISEQ_TYPE_EVAL) {
- break_in_eval:
- COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
- return COMPILE_NG;
- }
else {
- const rb_iseq_t *ip = iseq->body->parent_iseq;
+ const rb_iseq_t *ip = iseq;
while (ip) {
if (!ISEQ_COMPILE_DATA(ip)) {
@@ -6604,16 +6590,26 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
if (ISEQ_COMPILE_DATA(ip)->redo_label != 0) {
throw_flag = VM_THROW_NO_ESCAPE_FLAG;
- goto break_by_insn;
}
else if (ip->body->type == ISEQ_TYPE_BLOCK) {
- goto break_by_insn;
+ throw_flag = 0;
}
else if (ip->body->type == ISEQ_TYPE_EVAL) {
- goto break_in_eval;
+ COMPILE_ERROR(ERROR_ARGS "Can't escape from eval with break");
+ return COMPILE_NG;
}
+ else {
+ ip = ip->body->parent_iseq;
+ continue;
+ }
- ip = ip->body->parent_iseq;
+ /* escape from block */
+ CHECK(COMPILE(ret, "break val (block)", node->nd_stts));
+ ADD_INSN1(ret, line, throw, INT2FIX(throw_flag | TAG_BREAK));
+ if (popped) {
+ ADD_INSN(ret, line, pop);
+ }
+ return COMPILE_OK;
}
COMPILE_ERROR(ERROR_ARGS "Invalid break");
return COMPILE_NG;