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. ...@@ -66,7 +66,7 @@ sign) of operands.
| OP_EXCEPT | B | R(a) = exc | | OP_EXCEPT | B | R(a) = exc |
| OP_RESCUE | BB | R(b) = R(a).isa?(R(b)) | | OP_RESCUE | BB | R(b) = R(a).isa?(R(b)) |
| OP_POPERR | B | a.times{rescue_pop()} | | 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_EPUSH | B | ensure_push(SEQ[a]) |
| OP_EPOP | B | A.times{ensure_pop().call} | | OP_EPOP | B | A.times{ensure_pop().call} |
| OP_SENDV | BB | R(a) = call(R(a),Syms(b),*R(a+1)) | | OP_SENDV | BB | R(a) = call(R(a),Syms(b),*R(a+1)) |
......
...@@ -53,7 +53,7 @@ OPCODE(ONERR, S) /* rescue_push(a) */ ...@@ -53,7 +53,7 @@ OPCODE(ONERR, S) /* rescue_push(a) */
OPCODE(EXCEPT, B) /* R(a) = exc */ OPCODE(EXCEPT, B) /* R(a) = exc */
OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */ OPCODE(RESCUE, BB) /* R(b) = R(a).isa?(R(b)) */
OPCODE(POPERR, B) /* a.times{rescue_pop()} */ 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(EPUSH, B) /* ensure_push(SEQ[a]) */
OPCODE(EPOP, B) /* A.times{ensure_pop().call} */ OPCODE(EPOP, B) /* A.times{ensure_pop().call} */
OPCODE(SENDV, BB) /* R(a) = call(R(a),Syms(b),*R(a+1)) */ 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) ...@@ -1533,7 +1533,7 @@ codegen(codegen_scope *s, node *tree, int val)
} }
if (pos1) { if (pos1) {
dispatch(s, pos1); dispatch(s, pos1);
genop_1(s, OP_RAISE, exc); genop_1(s, OP_RAISEIF, exc);
} }
} }
pop(); pop();
......
...@@ -507,8 +507,8 @@ codedump(mrb_state *mrb, const mrb_irep *irep) ...@@ -507,8 +507,8 @@ codedump(mrb_state *mrb, const mrb_irep *irep)
printf("OP_RESCUE\tR%d\tR%d", a, b); printf("OP_RESCUE\tR%d\tR%d", a, b);
print_lv_ab(mrb, irep, a, b); print_lv_ab(mrb, irep, a, b);
break; break;
CASE(OP_RAISE, B); CASE(OP_RAISEIF, B);
printf("OP_RAISE\tR%d\t\t", a); printf("OP_RAISEIF\tR%d\t\t", a);
print_lv_a(mrb, irep, a); print_lv_a(mrb, irep, a);
break; break;
CASE(OP_POPERR, B); CASE(OP_POPERR, B);
......
...@@ -1255,8 +1255,24 @@ RETRY_TRY_BLOCK: ...@@ -1255,8 +1255,24 @@ RETRY_TRY_BLOCK:
} }
CASE(OP_EXCEPT, B) { CASE(OP_EXCEPT, B) {
mrb_value exc = mrb_obj_value(mrb->exc); mrb_value exc;
mrb->exc = 0;
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; regs[a] = exc;
NEXT; NEXT;
} }
...@@ -1289,9 +1305,17 @@ RETRY_TRY_BLOCK: ...@@ -1289,9 +1305,17 @@ RETRY_TRY_BLOCK:
NEXT; NEXT;
} }
CASE(OP_RAISE, B) { CASE(OP_RAISEIF, B) {
mrb_exc_set(mrb, regs[a]); mrb_value exc = regs[a];
goto L_RAISE; 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) { 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