Revert "Auto merge of #17701 - bholley:reuse_allocations, r=emilio"

This reverts commit ebfc8f5858, reversing
changes made to 5585ff2c44.

Animation code can reenter and create a new TLS context from the traversal
SequentialTask, so this won't work as written.
This commit is contained in:
Emilio Cobos Álvarez 2017-07-13 09:58:08 +02:00
parent 173181a491
commit a34f288b98
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
12 changed files with 39 additions and 140 deletions

View file

@ -66,7 +66,6 @@
use Atom;
use applicable_declarations::ApplicableDeclarationBlock;
use atomic_refcell::{AtomicRefCell, AtomicRefMut};
use bit_vec::BitVec;
use bloom::StyleBloom;
use cache::{LRUCache, LRUCacheMutIterator};
@ -74,15 +73,12 @@ use context::{SelectorFlagsMap, SharedStyleContext, StyleContext};
use data::{ElementData, ElementStyles};
use dom::{TElement, SendElement};
use matching::{ChildCascadeRequirement, MatchMethods};
use owning_ref::OwningHandle;
use properties::ComputedValues;
use selector_parser::RestyleDamage;
use selectors::matching::{ElementSelectorFlags, VisitedHandlingMode};
use smallvec::SmallVec;
use std::marker::PhantomData;
use std::mem;
use std::ops::Deref;
use stylearc::Arc;
use stylist::Stylist;
mod checks;
@ -97,8 +93,7 @@ mod checks;
/// improvements (e.g. 3x fewer styles having to be resolved than at size 8) and
/// slight performance improvements. Sizes larger than 32 haven't really been
/// tested.
pub const SHARING_CACHE_SIZE: usize = 31;
const SHARING_CACHE_BACKING_STORE_SIZE: usize = SHARING_CACHE_SIZE + 1;
pub const STYLE_SHARING_CANDIDATE_CACHE_SIZE: usize = 31;
/// Controls whether the style sharing cache is used.
#[derive(Clone, Copy, PartialEq)]
@ -216,21 +211,14 @@ impl ValidationData {
/// Note that this information is stored in TLS and cleared after the traversal,
/// and once here, the style information of the element is immutable, so it's
/// safe to access.
///
/// Important: If you change the members/layout here, You need to do the same for
/// FakeCandidate below.
#[derive(Debug)]
pub struct StyleSharingCandidate<E: TElement> {
/// The element.
element: E,
/// The element. We use SendElement here so that the cache may live in
/// ScopedTLS.
element: SendElement<E>,
validation_data: ValidationData,
}
struct FakeCandidate {
_element: usize,
_validation_data: ValidationData,
}
impl<E: TElement> Deref for StyleSharingCandidate<E> {
type Target = E;
@ -243,12 +231,12 @@ impl<E: TElement> Deref for StyleSharingCandidate<E> {
impl<E: TElement> StyleSharingCandidate<E> {
/// Get the classlist of this candidate.
fn class_list(&mut self) -> &[Atom] {
self.validation_data.class_list(self.element)
self.validation_data.class_list(*self.element)
}
/// Get the pres hints of this candidate.
fn pres_hints(&mut self) -> &[ApplicableDeclarationBlock] {
self.validation_data.pres_hints(self.element)
self.validation_data.pres_hints(*self.element)
}
/// Compute the bit vector of revalidation selector match results
@ -259,7 +247,7 @@ impl<E: TElement> StyleSharingCandidate<E> {
bloom: &StyleBloom<E>,
) -> &BitVec {
self.validation_data.revalidation_match_results(
self.element,
*self.element,
stylist,
bloom,
/* bloom_known_valid = */ false,
@ -469,81 +457,35 @@ pub enum StyleSharingResult {
StyleWasShared(usize, ChildCascadeRequirement),
}
/// Style sharing caches are are large allocations, so we store them in thread-local
/// storage such that they can be reused across style traversals. Ideally, we'd just
/// stack-allocate these buffers with uninitialized memory, but right now rustc can't
/// avoid memmoving the entire cache during setup, which gets very expensive. See
/// issues like [1] and [2].
///
/// Given that the cache stores entries of type TElement, we transmute to usize
/// before storing in TLS. This is safe as long as we make sure to empty the cache
/// before we let it go.
///
/// [1] https://github.com/rust-lang/rust/issues/42763
/// [2] https://github.com/rust-lang/rust/issues/13707
type SharingCacheBase<Candidate> = LRUCache<[Candidate; SHARING_CACHE_BACKING_STORE_SIZE]>;
type SharingCache<E> = SharingCacheBase<StyleSharingCandidate<E>>;
type TypelessSharingCache = SharingCacheBase<FakeCandidate>;
type StoredSharingCache = Arc<AtomicRefCell<TypelessSharingCache>>;
thread_local!(static SHARING_CACHE_KEY: StoredSharingCache =
Arc::new(AtomicRefCell::new(LRUCache::new())));
/// An LRU cache of the last few nodes seen, so that we can aggressively try to
/// reuse their styles.
///
/// Note that this cache is flushed every time we steal work from the queue, so
/// storing nodes here temporarily is safe.
pub struct StyleSharingCandidateCache<E: TElement> {
/// The LRU cache, with the type cast away to allow persisting the allocation.
cache_typeless: OwningHandle<StoredSharingCache, AtomicRefMut<'static, TypelessSharingCache>>,
/// Bind this structure to the lifetime of E, since that's what we effectively store.
marker: PhantomData<SendElement<E>>,
cache: LRUCache<[StyleSharingCandidate<E>; STYLE_SHARING_CANDIDATE_CACHE_SIZE + 1]>,
/// The DOM depth we're currently at. This is used as an optimization to
/// clear the cache when we change depths, since we know at that point
/// nothing in the cache will match.
dom_depth: usize,
}
impl<E: TElement> Drop for StyleSharingCandidateCache<E> {
fn drop(&mut self) {
self.clear();
}
}
impl<E: TElement> StyleSharingCandidateCache<E> {
fn cache(&self) -> &SharingCache<E> {
let base: &TypelessSharingCache = &*self.cache_typeless;
unsafe { mem::transmute(base) }
}
fn cache_mut(&mut self) -> &mut SharingCache<E> {
let base: &mut TypelessSharingCache = &mut *self.cache_typeless;
unsafe { mem::transmute(base) }
}
/// Create a new style sharing candidate cache.
pub fn new() -> Self {
assert_eq!(mem::size_of::<SharingCache<E>>(), mem::size_of::<TypelessSharingCache>());
assert_eq!(mem::align_of::<SharingCache<E>>(), mem::align_of::<TypelessSharingCache>());
let cache_arc = SHARING_CACHE_KEY.with(|c| c.clone());
let cache = OwningHandle::new_with_fn(cache_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut());
debug_assert_eq!(cache.num_entries(), 0);
StyleSharingCandidateCache {
cache_typeless: cache,
marker: PhantomData,
cache: LRUCache::new(),
dom_depth: 0,
}
}
/// Returns the number of entries in the cache.
pub fn num_entries(&self) -> usize {
self.cache().num_entries()
self.cache.num_entries()
}
fn iter_mut(&mut self) -> LRUCacheMutIterator<StyleSharingCandidate<E>> {
self.cache_mut().iter_mut()
self.cache.iter_mut()
}
/// Tries to insert an element in the style sharing cache.
@ -588,20 +530,20 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
self.clear();
self.dom_depth = dom_depth;
}
self.cache_mut().insert(StyleSharingCandidate {
element: *element,
self.cache.insert(StyleSharingCandidate {
element: unsafe { SendElement::new(*element) },
validation_data: validation_data,
});
}
/// Touch a given index in the style sharing candidate cache.
pub fn touch(&mut self, index: usize) {
self.cache_mut().touch(index);
self.cache.touch(index);
}
/// Clear the style sharing candidate cache.
pub fn clear(&mut self) {
self.cache_mut().evict_all()
self.cache.evict_all()
}
/// Attempts to share a style with another node.
@ -668,7 +610,7 @@ impl<E: TElement> StyleSharingCandidateCache<E> {
}
debug!("{:?} Cannot share style: {} cache entries", target.element,
self.cache().num_entries());
self.cache.num_entries());
StyleSharingResult::CannotShare
}