• Yukihiro "Matz" Matsumoto's avatar
    Fixed OP_RESCUE code generation bug; fix #3519 · 4cf38eb9
    Yukihiro "Matz" Matsumoto authored
    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
    ```
    4cf38eb9
codegen.c 69.3 KB