ext Oliver Hunt wrote:
It is not possible to optimise inside a |with| block -- we can't prove in advance that you will be using a inextensible object as your scope object so the fact that you can't add new properties to it is irrelevant, we have to assume that the object may change, and deoptimise accordingly.
Right, except in the benchmark I posted, a closure is created inside the with block. When the resulting function is compiled, the compiler has the scope object available and could query it. The compiler already does this for instances of JSVariableObject via isDynamicScope(). isDynamicScope() would have to be moved to JSObject, be renamed and rather return an enum with entries StaticScope, DynamicScope, and SemiStaticScope, so that the compiler could apply scope optimizations to a wider range of objects.
That said |with| has a significant amount of baggage that leads to unexpected semantic behaviour, enough to make ES5 strict mode disallow |with| entirely. Good JS should never use |with| so there's no point in trying to optimise it.
Yeah. :)
A better example of something where we currently don't optimise but _could_ is cross scope look up with dynamic insertion -- eg. optimising access to the global object from a function that uses eval.
Like the following? a = 123; (function() { var i; eval("1"); for (i = 0; i < 100000; ++i) { a; a; a; a; a; a; } })(); I see it's generating op_resolve instead of op_resolve_global now. That causes a 4x slowdown. Similarly for this one: a = 123; (function() { eval("1"); (function() { for (var i = 0; i < 100000; ++i) { a; a; a; a; a; a; a; a; } })(); })(); With V8 version 2.2.3.2 the eval doesn't have any performance impact. Any suggestions on how to approach this optimization? I'm guessing this is the case that would still need to work: a = 2; (function(code) { eval(code); return a + a; })("var a = 4"); // must return 8, not 4 So "a" is not going to be in the symbol table at function compile time, but the eval could introduce it... How about a bytecode that does a dynamic lookup the first time, but patches itself to become e.g. resolve_global if appropriate? It would potentially have to be un-patched again after a subsequent eval, though... I created https://bugs.webkit.org/show_bug.cgi?id=38644. Regards, Kent