|
|
|
|
|
by olliej
1355 days ago
|
|
This would only be relevant if you're doing something like var theFunction = condition ? "querySelector" : "getElementById";
...
document[theFunction](...)
it won't apply to if (condition)
document.querySelector(...)
else
document.getElementById(...)
As from the point of view of the runtime the latter has two call sites, and each one is monomorphic and will very quickly (first layer of the JIT tower generally) become a Structure/Shape/HiddenClass check on `document` followed by a direct call to the host environment's implementation function (or more likely the argument checking and marshaling function before the actual internal implementation).It is possible that the higher level JITs pay attention to the branch counts on conditions or use other side channels for the deopt, but for host functions it's generally not something that will happen as the JITs see natively implemented functions as largely opaque barriers - they only have a few internal (to the runtime itself) cases where they make any assumptions about the behaviour of host functions. |
|
I expected that to be the case but I’ve actually measured it and it’s not always. It is, when the object being accessed has a consistent shape/hidden class, as you mention, but a lot of times they don’t. A weird case is native interfaces because while the host functions are opaque and you’d expect they have a stable shape the interfaces themselves are often mutable either for historical reasons or shortcuts taken in newer proposals/implementations. Accessing document.foo isn’t and can’t be monomorphic in many cases, even if it can be treated that way speculatively. But branchy code can throw out all sorts of speculation of that sort. I don’t know which level of the JIT this occurs at, I’m just speaking from having measured it as a user of the APIs.