たなけんのやつ


なんだよぉ、そんくらいすぐわかるだろぉ・・・と昨夜ソース調べたり、YARV調べても、全然わからなくて、朝起きても悔しかったから、結局gdbで調べる羽目になった。

つまるところ a = 10 の戻り値は引数って話がどっかに定義されているとは思う。

Rubyのビルド、安定してて最高ですね。

$ ./autogen.sh
$ ./configure optflags="-O0"
$ make

ただgdbで闇雲にやるには、Rubyの内部実装を知らなすぎるので、例のやつ。

これであたりがついたので、

% gdb --args ./ruby ./tanaken_wowwow.rb
(gdb) b vm_setivar
Breakpoint 1 at 0x223370: file /home/pyama/src/github.com/ruby/ruby/vm_insnhelper.c, line 1440.
(gdb) run
Starting program: /home/pyama/src/github.com/ruby/ruby/ruby ./tanaken_wowwow.rb
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, vm_setivar (obj=140737345398560, id=45203, val=21, dest_shape_id=4294967295, index=4294967295) at /home/py
ama/src/github.com/ruby/ruby/vm_insnhelper.c:1440
1440        switch (BUILTIN_TYPE(obj)) {
(gdb) call rb_p(obj)
#<Bar:0x00007ffff77aa720>
(gdb) call rb_p(val)
10

で、実装をみると、

static VALUE
vm_setivar_default(VALUE obj, ID id, VALUE val, shape_id_t dest_shape_id, attr_index_t index)
{
#if SHAPE_IN_BASIC_FLAGS
    shape_id_t shape_id = RBASIC_SHAPE_ID(obj);
#else
    shape_id_t shape_id = rb_generic_shape_id(obj);
#endif

    struct gen_ivtbl *ivtbl = 0;

    // Cache hit case
    if (shape_id == dest_shape_id) {
        RUBY_ASSERT(dest_shape_id != INVALID_SHAPE_ID && shape_id != INVALID_SHAPE_ID);

        // Just get the IV table
        rb_gen_ivtbl_get(obj, 0, &ivtbl);
    }
    else if (dest_shape_id != INVALID_SHAPE_ID) {
        rb_shape_t * dest_shape = rb_shape_get_shape_by_id(dest_shape_id);
        shape_id_t source_shape_id = dest_shape->parent_id;

        if (shape_id == source_shape_id && dest_shape->edge_name == id && dest_shape->type == SHAPE_IVAR) {
            ivtbl = rb_ensure_generic_iv_list_size(obj, dest_shape, index + 1);
#if SHAPE_IN_BASIC_FLAGS
            RBASIC_SET_SHAPE_ID(obj, dest_shape_id);
#else
            RUBY_ASSERT(ivtbl->shape_id == dest_shape_id);
#endif
        }
        else {
            return Qundef;
        }
    }
    else {
        return Qundef;
    }

    VALUE *ptr = ivtbl->ivptr;

    RB_OBJ_WRITE(obj, &ptr[index], val);

    RB_DEBUG_COUNTER_INC(ivar_set_ic_hit);

    return val;
}

ちゃんとvalが返却されてるのが確認できました。最初、闇雲にソースを眺めていたのですが、最初からGPTに聞けばよかった。便利便利。