Thanks Leszek for the thoughtful response! I really like the minimorphic idea; it's simple and would provide a lot of benefit. I'd be interested to hear more about the other options you mentioned that aren't in that document, if you ever happen to come across other documents that might be relevant.
A few months ago I tried a prototype that added a new feedback sentinel state I called "single successor", meaning "for all of the maps seen, we've followed the only transition option and added a data property". This is the common case in constructors. It ended up about the same speed as a hit in the megamorphic stub cache, because it still requires several loads (get the successor, check that it's not deprecated, get its instance descriptors, and check that the property at the index we're adding is actually the right property). I guess maybe there's some value in not polluting the megamorphic stub cache, but it seemed to me at the time that the extra complexity wasn't worthwhile. The crucial thing that was lacking compared to the polymorphic case was that in a polymorphic constructor, TurboFan can do a great job of propagating type information around to avoid re-checking things that it already knows. There's just a single polymorphic switch at the beginning of the function, followed by simple straight-line code that sets a bunch of properties in a row. This budget-theft idea is my attempt to get back that simple straight-line code in more cases. A couple of other ideas for constructors that are less fully formed: - Just inline super-constructor calls much more aggressively than other calls. This would allow TurboFan to propagate the types through and likely turn a lot of those megamorphic stores into monomorphic in the generated code. - Track whether prototypes have setters (or interceptors, proxies, etc.) with a bit on the map. Then, if a function is only called with "new", we know that "this" didn't escape before function invocation (thanks ES spec for not letting child constructors touch "this" before calling "super"), and setting properties on "this" also doesn't cause it to escape. So until we do something else with "this" (return it, pass it to another function, or fetch a property from it), we can temporarily set this.__proto__ to be the current constructor's prototype, not the most-derived prototype. This would make a simple constructor (even one with many subtypes) act monomorphic. We'd have to reset this.__proto__ to the right thing when deopting, and there are probably a lot of other considerations that I'm not taking into account. Also, this would punish anybody who likes using setters, but if we follow the C++ mantra of "only pay for what you use", then this means folks who don't use setters don't have to pay for the fact that every line of their constructors are essentially virtual method calls. Thanks, Seth On Wednesday, December 18, 2019 at 1:25:52 AM UTC-8, Leszek Swirski wrote: > > Hi Seth, > > Thanks for the doc and the in-depth analysis. I think the approach you're > proposing is a clever low-memory-cost extension of the current IC > mechanism, but I'm not sure it's more than a patch over a system that needs > to be more fundamentally re-thought for things like constructors and a > general increase in hierarchic polymorphism. > > We've been brainstorming a bit on-and-off over the last few years about > more radical solutions to this problem, such as "minimorphic" feedback > (storing a set of maps that all share the same handler), storing (something > like) descriptor arrays rather than maps, storing feedback along the lines > of "I know it's an own property", embedding full v-tables into objects, or > even having different feedback for different constructors (with call-site > specific feedback or some other similar feedback forking mechanism). > bit.ly/v8-investigation-of-class-performance summarises a few of these > options, others are scattered around other docs or in people's heads. > > - Leszek > > On Tue, Dec 17, 2019 at 9:55 PM 'Seth Brenith' via v8-dev < > [email protected] <javascript:>> wrote: > >> Hi everyone, >> >> I'd appreciate any feedback on the document linked below. It outlines an >> idea I've been kicking around for a while, which I hope could reduce the >> polymorphic->megamorphic performance cliff in some cases. >> >> >> https://docs.google.com/document/d/1j9uXBT_wudNjM1wobHt2KxxjwwgRcAjsTNs5y_0GwpM/edit?usp=sharing >> >> Thanks! >> >> -- >> -- >> v8-dev mailing list >> [email protected] <javascript:> >> http://groups.google.com/group/v8-dev >> --- >> You received this message because you are subscribed to the Google Groups >> "v8-dev" group. >> To unsubscribe from this group and stop receiving emails from it, send an >> email to [email protected] <javascript:>. >> To view this discussion on the web visit >> https://groups.google.com/d/msgid/v8-dev/02852c79-6e06-4c4c-aee5-d1327d7521d5%40googlegroups.com >> >> <https://groups.google.com/d/msgid/v8-dev/02852c79-6e06-4c4c-aee5-d1327d7521d5%40googlegroups.com?utm_medium=email&utm_source=footer> >> . >> > -- -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev --- You received this message because you are subscribed to the Google Groups "v8-dev" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/v8-dev/caaf2c48-6388-48c1-a69e-68312755609c%40googlegroups.com.
