That's what I referred to with "inline caches". The problem is that for Ruby you need fully polymorphic inline caches, with guards all over the place, because unless you do tons of analysis upfront, you will have problems knowing whether or not the world has totally changed on you after any method call, and almost anything is a method call. (call into code you have not verified can't possibly call "eval", and you might find that adding two integers afterwards does in fact not add them, but returns a string and changes global variables, and what-not)
The upshot, is that compared to vtables, you're not actually saving all that much. E.g., take "1 + 2 - 3". You could inline Fixnum#+ (and could reasonably do so with an AOT compiler too). But you need to add a type guard before the inlined fragment to verify that Fixnum#+ still is the Fixnum#+ you inlined, which at the minimum costs you a comparison and a branch or you need to record every call-site with inlined code and be prepared to overwrite it with fixups if the implementation changes.
And if Fixnum#+ has been overridden, or the Fixnum#+ implementation has method calls, chances are you will need another guard before "-" too, because you might not even know for sure whether or not the object returned from "1 + 2" will be a Fixnum, so you might find that the inlined method suddenly is for the wrong class.
I'm planning on benchmarking inline caching for my compiler against vtables, but absent evidence to the contrary I'm expecting that there will be a very substantial number of cases where the complexity isn't worth it, or where they might even turn out to be slower.
> Something possible in AOT as well to certain extent, but it requires a mix of profile guided optimizations coupled with whole programm analysis.
It does if you want to do everything upfront, but you can pull things into inline caches with a mostly-AOT compiler relatively easily with just a little bit of extra information, and a few guards thrown in to do some basic tracing.