Closed Bug 1799028 Opened 2 years ago Closed 2 years ago

Cache for-in iterators on the Shape

Categories

(Core :: JavaScript Engine, task, P1)

task

Tracking

()

RESOLVED FIXED
109 Branch
Tracking Status
firefox109 --- fixed

People

(Reporter: iain, Assigned: iain)

References

(Blocks 2 open bugs)

Details

(Whiteboard: [sp3])

Attachments

(6 files)

Looking at Speedometer profiles, Jan noticed that retrieving iterators from the cache in for-in loops was a performance hotspot. For example this is one of the hottest functions in the elm subbenchmark.

We can make it faster to retrieve the iterator by caching it on the shape. In particular, we already have ShapeCachePtr, which can cache several different things; it seems reasonable to reuse it here.

I've left the existing caching mechanism in place for now, and added the shape-based caching on top of that. We can consider removing the existing iterator cache in a follow-up.

The next patch adds a CacheIR op to get the iterator from the shape cache, which also needs to activate iterators.

The only difference between the two implementations of GuardAndGetIterator was how we load the enumerators. Making this shared also lets us share the code in the next patch.

Depends on D162048

Depends on D162049

Depends on D162050

This makes it possible for us to bake the address of the active iterator list into stub data. If it's per-realm, then we can't assume that all objects reaching a given stub should be added to the same list. With a per-compartment list, we can be sure every object reaching a given stub shares the compartment (even if it's a CCW representing an object from another compartment).

While moving this, I also changed it from being a pointer to a NativeIterator to embedding a NativeIterator directly. This saves an indirection, makes some previous fallible code infallible, and makes everything a little simpler.

Depends on D162051

We were sometimes asserting when deleting compartments because the GCPtr destructor for the unused fields of the iterator sentinel saw that they were being destroyed outside of a GC. This wasn't a problem when the sentinel was heap-allocated because we used a UniquePtr with FreePolicy instead of DeletePolicy, so the destructor never ran.

I think the best fix is to avoid storing those unused fields in the first place by splitting out a superclass.

Pushed by iireland@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/cd5d3f62e4da Cache iterator in shape r=jandem https://hg.mozilla.org/integration/autoland/rev/97d6a930de1b Factor out iterator activation and share implementation of GuardAndGetIterator r=jandem https://hg.mozilla.org/integration/autoland/rev/471e76800bc3 Add ObjectToIteratorResult r=jandem https://hg.mozilla.org/integration/autoland/rev/3e245a08238b Transpile ObjectToIteratorResult r=jandem https://hg.mozilla.org/integration/autoland/rev/b0dc5f1fd855 Move enumerators from Realm to Compartment r=jandem https://hg.mozilla.org/integration/autoland/rev/ba555724d7cb Refactor iterator sentinel r=jandem

Some improvements on the following Speedometer tests:

Elm-TodoMVC/*
React-Redux-TodoMVC/*
and maybe Preact also

I measured about a 7% improvement on Elm while developing this patch. The React numbers weren't significant in my sample size but also looked like there might be a small win.

Whiteboard: [sp3]
Regressions: 1824123
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: