> But if V8 thinks that the code is “too tricky”, it keeps it in slow but dynamic form.
The next paragraph shows what caused V8 to not optimize :
> For example, in the first set of changes I’ve used a global variable defined outside of the class, so it had an external state. In the second one, I’ve changed the class structure on the fly. As a result, V8 did not compile it to effective typed native code.
But you're right, saying "it's probably that" is not the same thing as delving in the code.
If you want gory details I recommend Vyacheslav Egorov's blog (mrale.ph). Here's an old slide of his that lists all the ways you can force an object into dictionary mode (at least ca. 2011):
Using Object.seal, Object.freeze and Object.defineProperty with writable, enumerable, configurable not set to true does not cause object named properties convertion to dictionary mode. However they still convert elements storage (one containing properties with names "0", "1", etc) to dictionary mode.
Similary accessors don't cause object properties storage conversion to dictionary mode unless there is a transition clash.
var obj = {};
obj.__defineGetter__("foo", function () { return 0; })
print(%HasFastProperties(obj)); // => true
var obj = {};
obj.__defineGetter__("foo", function () { return 0; }) // Transition clash
print(%HasFastProperties(obj)); // => false
Nothing changed with respect to `delete obj.foo`: this always converts named properties storage conversion to dictionary mode. However `delete arr[index]` doesn't (at least for arrays that were not in slow mode already), rules for objects depend on the amount of holes in the elements part of the object.The usual disclaimers of "profile it first" and "YMMV" apply, but it's useful to be aware of potential low hanging fruit when JS performance is critical to your application.