summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authordearblue <[email protected]>2020-05-24 11:44:31 +0900
committerYukihiro "Matz" Matsumoto <[email protected]>2020-10-12 16:21:32 +0900
commitf467b02d4598ab64d98727348e8a9c4f04fc9b83 (patch)
treeb5c4fdda5178b33ce9014054df0c0ec4b6caa93a
parenta54a3df32c379a6953664f1d9241c731066915ec (diff)
downloadmruby-f467b02d4598ab64d98727348e8a9c4f04fc9b83.tar.gz
mruby-f467b02d4598ab64d98727348e8a9c4f04fc9b83.zip
Extended `OP_EXCEPT` and `OP_RAISE` (`OP_RAISEIF`) instructions
- `OP_EXCEPT` checks if `mrb->exc` is `NULL`, `MRB_TT_EXCEPTION` or `MRB_TT_BREAK`. If `mrb->exc` is `NULL`, it will be replaced with `nil`. - If `OP_RAISE` is `nil`, it does nothing and the immediately following instruction is executed (like `OP_NOP`). Also, in case of `RBreak` object, it moves to the processing for `break`. With this change, the instruction name is changed from `OP_RAISE` to `OP_RAISEIF`.
-rw-r--r--doc/opcode.md2
-rw-r--r--include/mruby/ops.h2
-rw-r--r--mrbgems/mruby-compiler/core/codegen.c2
-rw-r--r--src/codedump.c4
-rw-r--r--src/vm.c34
5 files changed, 34 insertions, 10 deletions
diff --git a/doc/opcode.md b/doc/opcode.md
index 98d29cdc0..d7e620350 100644
--- a/doc/opcode.md
+++ b/doc/opcode.md
@@ -66,7 +66,7 @@ sign) of operands.
| OP_EXCEPT | B | R(a) = exc |
| OP_RESCUE | BB | R(b) = R(a).isa?(R(b)) |
| OP_POPERR | B | a.times{rescue_pop()} |
-| OP_RAISE | B | raise(R(a)) |
+| OP_RAISEIF | B | raise(R(a)) if R(a) |
| OP_EPUSH | B | ensure_push(SEQ[a]) |
| OP_EPOP | B | A.times{ensure_pop().call} |
| OP_SENDV | BB | R(a) = call(R(a),Syms(b),*R(a+1)) |
diff --git a/include/mruby/ops.h b/include/mruby/ops.h
index 7d20ac0ad..45397e2ed 100644
--- a/include/mruby/ops.h
+++ b/include/mruby/ops.h
@@ -53,7 +53,7 @@ OPCODE(ONERR, S) /* rescue_push(a) */
OPCODE(EXCEPT, B) /* R(a) = exc */
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
OPCODE(POPERR, B) /* a.times{rescue_pop()} */
-OPCODE(RAISE, B) /* raise(R(a)) */
+OPCODE(RAISEIF, B) /* raise(R(a)) if R(a) */
OPCODE(EPUSH, B) /* ensure_push(SEQ[a]) */
OPCODE(EPOP, B) /* A.times{ensure_pop().call} */
OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c
index e55b6791d..7911ecb36 100644
--- a/mrbgems/mruby-compiler/core/codegen.c
+++ b/mrbgems/mruby-compiler/core/codegen.c
@@ -1533,7 +1533,7 @@ codegen(codegen_scope *s, node *tree, int val)
}
if (pos1) {
dispatch(s, pos1);
- genop_1(s, OP_RAISE, exc);
+ genop_1(s, OP_RAISEIF, exc);
}
}
pop();
diff --git a/src/codedump.c b/src/codedump.c
index a19d60708..2225da4ce 100644
--- a/src/codedump.c
+++ b/src/codedump.c
@@ -507,8 +507,8 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
printf("OP_RESCUE\tR%d\tR%d", a, b);
print_lv_ab(mrb, irep, a, b);
break;
- CASE(OP_RAISE, B);
- printf("OP_RAISE\tR%d\t\t", a);
+ CASE(OP_RAISEIF, B);
+ printf("OP_RAISEIF\tR%d\t\t", a);
print_lv_a(mrb, irep, a);
break;
CASE(OP_POPERR, B);
diff --git a/src/vm.c b/src/vm.c
index 3faecfaf2..2dbbe85f8 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -1255,8 +1255,24 @@ RETRY_TRY_BLOCK:
}
CASE(OP_EXCEPT, B) {
- mrb_value exc = mrb_obj_value(mrb->exc);
- mrb->exc = 0;
+ mrb_value exc;
+
+ if (mrb->exc == NULL) {
+ exc = mrb_nil_value();
+ }
+ else {
+ switch (mrb->exc->tt) {
+ case MRB_TT_BREAK:
+ case MRB_TT_EXCEPTION:
+ exc = mrb_obj_value(mrb->exc);
+ break;
+ default:
+ mrb_assert(!"bad mrb_type");
+ exc = mrb_nil_value();
+ break;
+ }
+ mrb->exc = NULL;
+ }
regs[a] = exc;
NEXT;
}
@@ -1289,9 +1305,17 @@ RETRY_TRY_BLOCK:
NEXT;
}
- CASE(OP_RAISE, B) {
- mrb_exc_set(mrb, regs[a]);
- goto L_RAISE;
+ CASE(OP_RAISEIF, B) {
+ mrb_value exc = regs[a];
+ if (mrb_break_p(exc)) {
+ mrb->exc = mrb_obj_ptr(exc);
+ goto L_BREAK;
+ }
+ mrb_exc_set(mrb, exc);
+ if (mrb->exc) {
+ goto L_RAISE;
+ }
+ NEXT;
}
CASE(OP_EPUSH, B) {