- Traces and JITs
- Speculative Inlining
- The Problem of Numbers
- Summary
Speculative Inlining
One of the simplest optimizations you can do with a static language like C is to inline a function. Inlining a function means copying the function body into the place where it's called. This isn't possible with a JavaScript method, because you don't know the method that will really be called. A lot of the time, however, you can make a good guess. If you're right most of the time, and it still works in the cases where you're wrong, then you win overall. You still need to perform the lookup to see whether the inlined method is the one being called. There are two ways in JavaScript that this can be wrong: if the method is replaced by another one in the (hidden) class, or the object is a member of a different class.
When we looked at inline caching in part 1 of this series, we ignored the fact that methods can be replaced, and didn't look at methods for invalidating the cache at all. One way to do this is to keep a version with each mapping and increment it in the structure referenced by the cache, invalidating the cache when the mapping is updated. This is only really needed for statically compiled code, however. With a virtual machine, you can keep track of where a particular lookup is cached and invalidate it explicitly.
Speculative inlining is one of a group of fairly common techniques for optimizing dynamic languages, based around the "guess and hope" approach. As some Smalltalk implementer said, "People expect compiler writers to cheat, and it's fine as long as they don't get caught."
In a lot of cases, you can make a very good guess about which version of a method might be called. If you only have one method with a particular name, there's a good chance that this method is the one that will be called. Similarly, if the method lookup always returned the same value for a given call site while you were running a function in the interpreter, you can be fairly sure which method will usually be called.
This is one place where hidden class transforms really help; they make it a lot easier to find unique methods, especially when the transform is performed at compile time.