Vyacheslav Egorov
Jun 23, 2016 · 1 min read

Regarding the bug itself. There is a code in Crankshaft that looks at typeof x == “…” and typeof x === “…” and tries to figure out if they always evaluate to true or false (see HTypeofIsAndBranch::KnownSuccessorBlock). For example if x is a constant it just computes typeof x and compares it with right hand side in compile time. However Crankshaft does not actually call to the same typeof implementation that normal JavaScript uses. For unknown reasons (probably because Crankshaft optimization passes can run in a background compiler thread) it has a its own implementation of typeof (see TypeOfString function). This implementation got out of sync when V8 folks were refactoring stuff related to an obscure thing called “undetectable objects” — null got marked as undetectable object for Crankshaft in this change but TypeOfString implementation was not aligned with this change.

Note: that TypeOfString was only ever used to fold constant HTypeOfIsAndBranch instructions and was never used to constant fold standalone typeof Const which did not participate in typeof x == “…” like pattern. That’s why things like (0, typeof null) == ‘undefined’ work around this bug — because they break recognition of this pattern.

Regarding let vs var. If you bump iteration limit for the `var` case to 20000 you will see it hit the bug. The reason for this is that for loop with `let`-binding gets desugared in a very baroque way in V8 — which causes it to be optimized earlier than for loop with `var`-binding.

    Vyacheslav Egorov

    Written by

    crazy Russian compiler engineer.