Unverified Commit f467b02d authored by dearblue's avatar dearblue Committed by Yukihiro "Matz" Matsumoto

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`.
parent a54a3df3
......@@ -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)) |
......
......@@ -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)) */
......
......@@ -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();
......
......@@ -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);
......
......@@ -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) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment