I'd like to dredge up this topic and resolve it once and for all. Please
see bug 912303 for why I'm bringing this up now:
https://bugzilla.mozilla.org/show_bug.cgi?id=912303
As it stands, our current JITs (neither Ion nor Baseline, nor Jaeger
before that) do not respect __noSuchMethod__ semantics, and the fix for
this bug will be painful and unnecessarily complex and heavyweight.
__noSuchMethod__ hurts us in ways that we can't defend against with the
usual techniques. Let me explain in more detail.
Whenever we attach an optimized stub (either Baseline or Ion) for any
CALLELEM or CALLPROP operation, we MUST check the result to see if it's
a primitive, and MUST jump to a slowpath to make a VM-call to run
|OnUnknownMethod|. This is the _best_ possible solution, and it
involves at the minimum the insertion of a likely-to-fail
primitive-value check into property-access hot paths, and a whole lot of
complexity (and bloat) to every IC stub that does property accesses.
"But wait!" you say, "why don't we just not attach stubs when we know
that __onUnknownMethod__ may need to be called?". Well, we can't do
that, because we don't know when __onUnknownMethod__ will be bound on an
ancestral prototype of the holder object of the property being
retrieved. We could generate an optimized stub, and then later an
ancestral prototype object modified to bind __onUnknownMethod__, and the
optimized stub would have no way of knowing, short of always guarding
against all shapes in the proto chain of every CALLPROP/CALLELEM, which
is worse than the primitive-value check described previously.
This is a huge amount of pain and complexity for handling a very rare
corner case. Unlike most corner cases which can be easily guarded
against, this feature forces additional checks in common hot-paths, and
there's no way around it. Baseline has several GetProp and GetElem
stubs that would need to be modified in this way. Ion has several
variants of each as well.
This pain can be reduced by either removing __noSuchMethod__ entirely,
or by reducing its scope so that it only gets called for nonexistant
properties (as opposed to getting called for both nonexistant and
primitive-valued properties).
Combining the above argument with previously presented arguments, the
reasons for removal are:
1. It's a non-standard extension and it's not going to get standardized.
2. A good amount of its functionality can be implemented using
Object.prototype.__proto__ = new Proxy(...), which has the additional
boon of being standardized.
3. It adds a lot of unnecessary complexity to the JITS, bloats the
generated jitcode, and slows down hot paths.
I'm open to either removal or limiting its behaviour to only
non-existant properties, but I want to get moving ahead with at least
one of those two options.
My vote is for removal.
Cheers.
Kannan
_______________________________________________
dev-tech-js-engine-internals mailing list
[email protected]
https://lists.mozilla.org/listinfo/dev-tech-js-engine-internals