I started this post in October 2013 (!) but never finished it. But it seems like something other folks might find interesting, so, here goes.
I was fiddling with
Tracepoint and I could see an event for
Incidentally, did you know that calling
Array#select without a block returns an
I didn't. Anyhow, a
TracePoint event doesn't get fired for
#length, but one does for
send(:length) triggers one:
Seems weird, since
#length is a C function for which
#size is an alias:
So why doesn't a plain old
#length invocation result in a tracepoint event? I asked Pat Shaughnessy about it on the twitters and he pointed out that it's because
size is implemented - wait for it - as a YARV instruction! Sure enough, in
opt_size, and if I add a
printf('heyo\n'); to the part of that definition that's handling arrays (via
RBASIC_CLASS(recv) == rb_cArray) and run
ruby -e ".size", there appears a flurry of heyos.
Kashap Kondamudi does a fine job of explaining the Ruby execution process so I won't repeat all that here. The short version, though, is that disassembling a
size method invocation shows that it's using a specialized
whereas disassembling a
select invocation shows that it's using a more general instruction:
and the implementation for
opt_send_without_block presumably is also firing tracepoint events. I poked around a bit and it seems like that instruction uses the
CALL_METHOD macro which looks up the appropriate method and invokes it. That's not a great explanation because I didn't follow the flow there; maybe someone on the internet will fill in the missing pieces for me here.
Anyhow, takeaway is that Pat is a smart fella and everyone should buy a second copy of Ruby Under a Microscope, and also that when digging around in stuff like this, don't forget about the YARV instruction definitions!