K. Gadd (2013-07-12T20:12:58.000Z)
forbes at lindesay.co.uk (2013-07-12T20:36:28.956Z)
I've had some back and forth with v8 devs about this since it affects my compiler. I believe they already have open issues about it but I don't know the bug #s. In general, the problem seems to be that Function.bind creates functions that have different type information from normal functions you wrote in pure JS; they're 'special' native functions in the same fashion as say, a DOM API: ``` > document.createElement function createElement() { [native code] } > function f () {} > f function f() {} > f.bind(null) function () { [native code] } ``` This is important because v8 tries to gather information about callees at various call sites. Having a mix of these special and non-special functions means that the JIT is not able to make safe optimizations based on all the callers being the same type. IIRC there are also some other problems specific to v8, like it only being able to optimize Function.apply and Function.call if the .apply/.call methods are the implementations used for pure-JS functions (so bind breaks those too). I can't comment on why it's slow in SpiderMonkey (I've never asked... I should file a bug) but it is indeed the case that f.bind(null) produces a 'native code' function in SpiderMonkey, so I expect some of the same optimization consequences apply. I also expect that it is much harder for v8 and spidermonkey to inline a function that contains native code, if not entirely impossible. All of these problems, as I understand them, are completely fixable. It might be as simple as making bind return a pure-JS function instead of a native function. This is supported by the fact that a pure-JS polyfill for .bind is usually faster in my tests. In general VM authors are much more helpful when shown real world applications affected by these issues, based on my experience. They tend to ignore jsperf microbenchmarks, etc. I don't know that this could be addressed at all from a specification perspective. The only thing I can think of would be specifying that the result of Function.bind should somehow be indistinguishable from a hand-written JS function (no 'native code' in tostring, etc) but I don't think that sort of spec requirement would actually prevent any of these performance traps. Hope this helps,