diff options
| author | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-03-12 00:22:12 +0900 |
|---|---|---|
| committer | Yukihiro "Matz" Matsumoto <[email protected]> | 2017-03-12 01:10:20 +0900 |
| commit | 916b8ed5c8b6f7a0b6532604a42dc7c9584426f1 (patch) | |
| tree | dc0fc38fe0067ee9a059864b4f5748aaf69e27bf /mrbgems/mruby-compiler/core/codegen.c | |
| parent | 92f5becabe9db34e51fa917f3095b1f90869a1a5 (diff) | |
| download | mruby-916b8ed5c8b6f7a0b6532604a42dc7c9584426f1.tar.gz mruby-916b8ed5c8b6f7a0b6532604a42dc7c9584426f1.zip | |
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.
Diffstat (limited to 'mrbgems/mruby-compiler/core/codegen.c')
| -rw-r--r-- | mrbgems/mruby-compiler/core/codegen.c | 32 |
1 files changed, 17 insertions, 15 deletions
diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index 31d66d22c..dbf9dcd39 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; @@ -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); |
