Bug #8484
Updated by nobu (Nobuyoshi Nakada) over 10 years ago
r41041 で、ブロック呼び出し前の VM 内の処理中に Ruby のメソッドが何らかの理由で呼ばれると argv が壊れるという問題を直しました。 具体的には、 ~~~ruby y = Object.new def y.s(a) yield(a) end m = Object.new def m.method_missing(*a) super end assert_equal [m, nil], y.s(m){|a,b|[a,b]} ~~~ のようなコードの場合、 * `y.s` y.s に `m` m と `block` block が渡される * `y.s` y.s で `yield(a)` yield(a) が呼ばれる * `argv`が設定される argvが設定される * `vm_invoke_block` vm_invoke_block 内の `VALUE VALUE * const rsp = GET_SP() - ci->argc; SET_SP(rsp);` SET_SP(rsp); で `argv` argv の先頭に `sp` sp が設定される * `vm_yield_setup_args` vm_yield_setup_args * `vm_yield_setup_block_args` vm_yield_setup_block_args * `y.s` のブロックパラメータは2つなのに、引数は一つなので、`a.to_ary` y.s のブロックパラメータは2つなのに、引数は一つなので、a.to_ary が呼ばれる (`rb_check_array_type(arg0)`) (rb_check_array_type(arg0)) * `method_missing` method_missing が呼ばれる * `super` super が呼ばれる (このへんで `vm _push_frame` vm _push_frame が呼ばれる) * `vm_push_frame`のinitialize vm_push_frameのinitialize local variablesのところで`argv`に`nil`が代入されて破壊される variablesのところでargvにnilが代入されて破壊される で、これ自体は `argv` argv を対比しておいて戻せばよいです。 また、`SET_SP(rsp)`のあたりは、ささださん曰く「 `argv` また、SET_SP(rsp)のあたりは、ささださん曰く「 argv に書き込みがない、という前提でそこは作ってるんだよね」だそうな。 しかし、「そんな前提わかるかっ」ですし、 methodの方は `SAVE_RESTORE_CI(tmp SAVE_RESTORE_CI(tmp = rb_check_convert_type(ary, T_ARRAY, "Array", "to_a"), ci);` ci); ともうちょっとわかりやすく書いてあるので、 「頂いた問題点を元に、一度全部総点検が必要そうです」とのことですので、お願いします。