Hacker News new | ask | show | jobs
by vidarh 2445 days ago
This is also true for languages like Self as well which pioneered inline (and polymorphic) caches in the first place. Self did it using JITs, but you "only" need a sufficient hit rate to make up for the check+branch to justify inlining the most likely option(s) at compile time.

The interesting thing is that by inlining, for the inline case you will often gain additional type information. E.g. to take an example from Ruby, since I don't know Objective C very well. In isolation you have no way of telling what type "foo + 1 + 2 + 3" will return, as it depends entirely on "foo". But lets say most call-sites calling the method where this expression is found passes an integer.

If I can guarantee that "foo + 1" is an Integer addition, then I know it will return an Integer, and so I know the same addition method will be used for the next addition (and by extension the next as well), so I can turn the above into the following Ruby-ish pseudo-code instead:

    if foo.is_a?(Integer)
        # By recursively inlining, I know not just the type of foo, but the type of the full expression.
        inlined foo + 1 + 2 + 3
    else
        foo.send(:+, 1).send(:+, 2).send(:+, 3)
    end
Even when you can't safely inline the actual calls, you can often elide checks or resort to more specialized method caching.
1 comments

Yes, of course with a JIT you can do much better than an AOT compiler, and for dynamic languages is pretty much required to get reasonable performance.
Well, compared to profile guided optimization as mentioned by the other commenter earlier, that's really only the case if the profile of called methods vary greatly between runs.

The polymorphic inline caching from Self for example is guided by collecting simple stats. Tracing does the same. A JIT ensures those stats are always completely up to date, but nothing stops you from saving it and using it for an AOT compiler as well.

But often even that is overkill, as you can often statically deduce a lot about the types a method is likely to get called with by simply looking at the call sites, and most programs have very static call profiles.