Module style::sharing [] [src]

Code related to the style sharing cache, an optimization that allows similar nodes to share style without having to run selector matching twice.

The basic setup is as follows. We have an LRU cache of style sharing candidates. When we try to style a target element, we first check whether we can quickly determine that styles match something in this cache, and if so we just use the cached style information. This check is done with a StyleBloom filter set up for the target element, which may not be a correct state for the cached candidate element if they're cousins instead of siblings.

The complicated part is determining that styles match. This is subject to the following constraints:

1) The target and candidate must be inheriting the same styles. 2) The target and candidate must have exactly the same rules matching them. 3) The target and candidate must have exactly the same non-selector-based style information (inline styles, presentation hints). 4) The target and candidate must have exactly the same rules matching their pseudo-elements, because an element's style data points to the style data for its pseudo-elements.

These constraints are satisfied in the following ways:

The actual checks that ensure that elements match the same rules are conceptually split up into two pieces. First, we do various checks on elements that make sure that the set of possible rules in all selector maps in the stylist (for normal styling and for pseudo-elements) that might match the two elements is the same. For example, we enforce that the target and candidate must have the same localname and namespace. Second, we have a selector map of "revalidation selectors" that the stylist maintains that we actually match against the target and candidate and then check whether the two sets of results were the same. Due to the up-front selector map checks, we know that the target and candidate will be matched against the same exact set of revalidation selectors, so the match result arrays can be compared directly.

It's very important that a selector be added to the set of revalidation selectors any time there are two elements that could pass all the up-front checks but match differently against some ComplexSelector in the selector. If that happens, then they can have descendants that might themselves pass the up-front checks but would have different matching results for the selector in question. In this case, "descendants" includes pseudo-elements, so there is a single selector map of revalidation selectors that includes both selectors targeting elements and selectors targeting pseudo-element originating elements. We ensure that the pseudo-element parts of all these selectors are effectively stripped off, so that matching them all against elements makes sense.

Structs

OpaqueComputedValues

Opaque pointer type to compare ComputedValues identities.

StyleSharingCache

An LRU cache of the last few nodes seen, so that we can aggressively try to reuse their styles.

StyleSharingCandidate

Information regarding a style sharing candidate, that is, an entry in the style sharing cache.

StyleSharingTarget

An element we want to test against the style sharing cache.

ValidationData

Some data we want to avoid recomputing all the time while trying to share style.

Enums

StyleSharingBehavior

Controls whether the style sharing cache is used.

Constants

SHARING_CACHE_SIZE

The amount of nodes that the style sharing candidate cache should hold at most. We'd somewhat like 32, but ArrayDeque only implements certain backing store sizes. A cache size of 32 would mean a backing store of 33, but that's not an implemented size: we can do 32 or 40.