If I define a function
inc = function(x) { return x + 1 }
and make a nested invocation of it
inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(inc(1)))))))))))))))))))))
this will result in the value 22
. If I revise the nested expression to instead make use of call
, passing in null
for this
, as
inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, 1)))))))))))))))))))))
this will also produce the value 22
.
But, on JavaScriptCore this second form appears to consume O(2^n) memory, where n is the number of nested calls. This is not the case if I try this JavaScript in Firefox or Chrome so it seems to be isolated to JavaScriptCore.
I have very little JavaScript experience (almost none). I don't have a feel for the tradeoffs that various JavaScript implementations might make, nor whether it is reasonable for the example code to be expensive in some implementations (providing generic support for closures or some such), while efficient in others.
My question is: Is this code inherently problematic? Should it be rewritten to be structured in a different way? Or is the code fine—does JavaScriptCore simply have a bug?
I've done some experimentation where refactoring a few of the inner calls to temporaries will "truncate" the memory doubling behavior
var temp1 = inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, 1))))))); var temp2 = inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, temp1))))))); inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, inc.call(null, temp2)))))));
Based on comments on this question, the consensus is that there is no fundamental problem with the code as written, but that instead this is a bug in JavaScriptCore.
For the ticket filed, it has been confirmed as reproducible and has been imported into Apple's Radar system.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With