diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-03-19 18:42:53 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-03-19 18:42:53 +0900 |
| commit | 4cf38eb9032ab70544f940941703a0c09529539f (patch) | |
| tree | e7e8343d7eaf22483985283eeeefefe15e09a323 | |
| parent | d01118d2617ea6a0c6f32789cee072eb3dbf42ee (diff) | |
| download | mruby-4cf38eb9032ab70544f940941703a0c09529539f.tar.gz mruby-4cf38eb9032ab70544f940941703a0c09529539f.zip | |
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
```
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 7 |
1 files changed, 2 insertions, 5 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index dbf9dcd39..1ca86761c 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/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; @@ -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; |
