Permalink
Browse files

Generate new OP_RESCUE; fix #3487

The old OP_RESCUE took one operand A, which specifies a class
to match with the exception. The new OP_RESCUE takes tree operands:

A: the register to hold exception
B: the matching exception; the match result will be stored here.
C: the continuation; if C is zero, the exception will be stored to R(A)
   otherwise, the value from R(A) is used as a exception.

Thus,
```ruby
begin
  raise "a"
rescue TypeError
  p 1
rescue RuntimeError
  p 2
end
```
will be compiled as
```
irep 0x557a06667aa0 nregs=4 nlocals=1 pools=1 syms=4 reps=0
file: /tmp/e.rb
2 000 OP_ONERR  005
2 001 OP_LOADSELF R1
2 002 OP_STRING R2  L(0)  ; "a"
2 003 OP_SEND R1  :raise  1
2 004 OP_JMP  022
3 005 OP_GETCONST R2  :TypeError
3 006 OP_RESCUE R1  R2
3 007 OP_JMPIF  R2  009
3 008 OP_JMP  013
4 009 OP_LOADSELF R1
4 010 OP_LOADI  R2  1
4 011 OP_SEND R1  :p  1
4 012 OP_JMP  023
5 013 OP_GETCONST R2 :RuntimeError
5 014 OP_RESCUE R1 R2  cont
5 015 OP_JMPIF  R2  017
5 016 OP_JMP  021
6 017 OP_LOADSELF R1
6 018 OP_LOADI  R2  2
6 019 OP_SEND R1  :p  1
6 020 OP_JMP  023
6 021 OP_RAISE  R1
6 022 OP_POPERR 1
6 023 OP_STOP
```

The new VM can accept old OP_RESCUE. The mruby compatible VM (namely
mruby/c) should be updated to support the new OP_RESCUE behavior.
  • Loading branch information...
matz committed Mar 11, 2017
1 parent 92f5bec commit 916b8ed5c8b6f7a0b6532604a42dc7c9584426f1
Showing with 17 additions and 15 deletions.
  1. +17 −15 mrbgems/mruby-compiler/core/codegen.c
@@ -1293,8 +1293,8 @@ codegen(codegen_scope *s, node *tree, int val)
if (tree->car) {
node *n2 = tree->car;
int exc = cursp();
int cnt = 0;
genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
push();
while (n2) {
node *n3 = n2->car;
@@ -1303,20 +1303,26 @@ codegen(codegen_scope *s, node *tree, int val)
if (pos1) dispatch(s, pos1);
pos2 = 0;
do {
if (n4) {
codegen(s, n4->car, VAL);
}
else {
genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
push();
}
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
pop();
if (n4 && n4->car && (intptr_t)n4->car->car == NODE_SPLAT) {
if (cnt == 0) {
genop(s, MKOP_ABC(OP_RESCUE, exc, 0, cnt)); cnt = 1;
}
genop(s, MKOP_AB(OP_MOVE, cursp(), exc));
push();
codegen(s, n4->car, VAL);
pop_n(2);
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "__case_eqq")), 1));
}
else {
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "===")), 1));
if (n4) {
codegen(s, n4->car, VAL);
}
else {
genop(s, MKOP_ABx(OP_GETCONST, cursp(), new_msym(s, mrb_intern_lit(s->mrb, "StandardError"))));
push();
}
pop();
genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), cnt)); cnt = 1;
}
tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
@@ -1788,11 +1794,7 @@ codegen(codegen_scope *s, node *tree, int val)
genop(s, MKOP_A(OP_POPERR, 1));
noexc = genop(s, MKOP_Bx(OP_JMP, 0));
dispatch(s, onerr);
<<<<<<< HEAD
genop(s, MKOP_AB(OP_RESCUE, exc, 0));
=======
genop(s, MKOP_ABC(OP_RESCUE, exc, 0, 0));
>>>>>>> 55d89bd... Enhance OP_RESCUE to take B operand fas matching exception; ref #3487
genop(s, MKOP_A(OP_LOADF, exc));
dispatch(s, noexc);
loop_pop(s, NOVAL);

0 comments on commit 916b8ed

Please sign in to comment.