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

Reply via email to