Fixed OP_RESCUE code generation bug; fix #3519

916b8e let code executed with mrb->exc set, and may cause a crash
like #3519. Instead modified OP_RESCUE again. To retrieve the exception
object, we use `OP_RESCUE R(A), 0, 0` (old behavior). To compare the
exception object and the class, we use `OP_RESCUE R(A), R(B), 1`.

The reason we use OP_RESCUE for two instruction switched by operand
C is to save the instruction space.

As a result, the following code:
```ruby
begin
  raise "a"
rescue TypeError
  p 1
rescue RuntimeError
  p 2
end
```
will be compiled as:
```
irep 0x55cd1f565cb0 nregs=4 nlocals=1 pools=1 syms=4 reps=0
file: -
    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	023
    2 005 OP_RESCUE	R1
    3 006 OP_GETCONST	R2	:TypeError
    3 007 OP_RESCUE	R1	R2	cont
    3 008 OP_JMPIF	R2	010
    3 009 OP_JMP	014
    4 010 OP_LOADSELF	R1
    4 011 OP_LOADI	R2	1
    4 012 OP_SEND	R1	:p	1
    4 013 OP_JMP	024
    5 014 OP_GETCONST	R2	:RuntimeError
    5 015 OP_RESCUE	R1	R2	cont
    5 016 OP_JMPIF	R2	018
    5 017 OP_JMP	022
    6 018 OP_LOADSELF	R1
    6 019 OP_LOADI	R2	2
    6 020 OP_SEND	R1	:p	1
    6 021 OP_JMP	024
    6 022 OP_RAISE	R1
    6 023 OP_POPERR	1
    6 024 OP_STOP
```
parent d01118d2
......@@ -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;
......@@ -1304,9 +1304,6 @@ codegen(codegen_scope *s, node *tree, int val)
pos2 = 0;
do {
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);
......@@ -1322,7 +1319,7 @@ codegen(codegen_scope *s, node *tree, int val)
push();
}
pop();
genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), cnt)); cnt = 1;
genop(s, MKOP_ABC(OP_RESCUE, exc, cursp(), 1));
}
tmp = genop(s, MKOP_AsBx(OP_JMPIF, cursp(), pos2));
pos2 = tmp;
......
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