たなけんのやつ
なんだよぉ、そんくらいすぐわかるだろぉ・・・と昨夜ソース調べたり、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
で、実装をみると、
https://github.com/ruby/ruby/blob/648870b5c577239b3274b0b48c82fb74910dfabf/vm_insnhelper.c#L1433
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に聞けばよかった。便利便利。