layout: Stop mutating the style data from layout.

This is part of #16982.

Right now we have some code that tries to cache stuff in the style data during
layout.

This code is extremely rarely executed, only for `<details>` and `<summary>`.

I think if we really really want to cache these, we should find a place in the
layout data for it.

For now, let's move it away (and all the other layout code) from mutating the
style data from layout.
This commit is contained in:
Emilio Cobos Álvarez 2017-05-21 17:35:47 +02:00
parent 3d40b516c8
commit a8fe5d65d4
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
2 changed files with 32 additions and 47 deletions

View file

@ -30,7 +30,7 @@
#![allow(unsafe_code)] #![allow(unsafe_code)]
use atomic_refcell::AtomicRefCell; use atomic_refcell::{AtomicRef, AtomicRefCell};
use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId}; use dom::bindings::inheritance::{CharacterDataTypeId, ElementTypeId};
use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId}; use dom::bindings::inheritance::{HTMLElementTypeId, NodeTypeId};
use dom::bindings::js::LayoutJS; use dom::bindings::js::LayoutJS;
@ -1092,8 +1092,10 @@ impl<'le> ThreadSafeLayoutElement for ServoThreadSafeLayoutElement<'le> {
self.element.get_attr(namespace, name) self.element.get_attr(namespace, name)
} }
fn get_style_data(&self) -> Option<&AtomicRefCell<ElementData>> { fn style_data(&self) -> AtomicRef<ElementData> {
self.element.get_data() self.element.get_data()
.expect("Unstyled layout node?")
.borrow()
} }
} }

View file

@ -8,7 +8,7 @@ use HTMLCanvasData;
use LayoutNodeType; use LayoutNodeType;
use OpaqueStyleAndLayoutData; use OpaqueStyleAndLayoutData;
use SVGSVGData; use SVGSVGData;
use atomic_refcell::AtomicRefCell; use atomic_refcell::AtomicRef;
use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type}; use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type};
use html5ever::{Namespace, LocalName}; use html5ever::{Namespace, LocalName};
use msg::constellation_msg::{BrowsingContextId, PipelineId}; use msg::constellation_msg::{BrowsingContextId, PipelineId};
@ -338,18 +338,14 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
fn get_attr_enum(&self, namespace: &Namespace, name: &LocalName) -> Option<&AttrValue>; fn get_attr_enum(&self, namespace: &Namespace, name: &LocalName) -> Option<&AttrValue>;
fn get_style_data(&self) -> Option<&AtomicRefCell<ElementData>>; fn style_data(&self) -> AtomicRef<ElementData>;
#[inline] #[inline]
fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>>; fn get_pseudo_element_type(&self) -> PseudoElementType<Option<display::T>>;
#[inline] #[inline]
fn get_before_pseudo(&self) -> Option<Self> { fn get_before_pseudo(&self) -> Option<Self> {
if self.get_style_data() if self.style_data().styles().pseudos.has(&PseudoElement::Before) {
.unwrap()
.borrow()
.styles().pseudos
.has(&PseudoElement::Before) {
Some(self.with_pseudo(PseudoElementType::Before(None))) Some(self.with_pseudo(PseudoElementType::Before(None)))
} else { } else {
None None
@ -358,11 +354,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
#[inline] #[inline]
fn get_after_pseudo(&self) -> Option<Self> { fn get_after_pseudo(&self) -> Option<Self> {
if self.get_style_data() if self.style_data().styles().pseudos.has(&PseudoElement::After) {
.unwrap()
.borrow()
.styles().pseudos
.has(&PseudoElement::After) {
Some(self.with_pseudo(PseudoElementType::After(None))) Some(self.with_pseudo(PseudoElementType::After(None)))
} else { } else {
None None
@ -400,50 +392,41 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
/// Unlike the version on TNode, this handles pseudo-elements. /// Unlike the version on TNode, this handles pseudo-elements.
#[inline] #[inline]
fn style(&self, context: &SharedStyleContext) -> Arc<ServoComputedValues> { fn style(&self, context: &SharedStyleContext) -> Arc<ServoComputedValues> {
let data = self.style_data();
match self.get_pseudo_element_type() { match self.get_pseudo_element_type() {
PseudoElementType::Normal => self.get_style_data().unwrap().borrow() PseudoElementType::Normal => {
.styles().primary.values().clone(), data.styles().primary.values().clone()
},
other => { other => {
// Precompute non-eagerly-cascaded pseudo-element styles if not // Precompute non-eagerly-cascaded pseudo-element styles if not
// cached before. // cached before.
let style_pseudo = other.style_pseudo_element(); let style_pseudo = other.style_pseudo_element();
let mut data = self.get_style_data().unwrap().borrow_mut();
match style_pseudo.cascade_type() { match style_pseudo.cascade_type() {
// Already computed during the cascade. // Already computed during the cascade.
PseudoElementCascadeType::Eager => { PseudoElementCascadeType::Eager => {
data.styles().pseudos.get(&style_pseudo) self.style_data()
.styles().pseudos.get(&style_pseudo)
.unwrap().values().clone() .unwrap().values().clone()
}, },
PseudoElementCascadeType::Precomputed => { PseudoElementCascadeType::Precomputed => {
if !data.styles().cached_pseudos.contains_key(&style_pseudo) { context.stylist.precomputed_values_for_pseudo(
let new_style = &context.guards,
context.stylist.precomputed_values_for_pseudo( &style_pseudo,
&context.guards, Some(data.styles().primary.values()),
&style_pseudo, CascadeFlags::empty(),
Some(data.styles().primary.values()), &ServoMetricsProvider)
CascadeFlags::empty(), .values().clone()
&ServoMetricsProvider);
data.styles_mut().cached_pseudos
.insert(style_pseudo.clone(), new_style);
}
data.styles().cached_pseudos.get(&style_pseudo)
.unwrap().values().clone()
} }
PseudoElementCascadeType::Lazy => { PseudoElementCascadeType::Lazy => {
if !data.styles().cached_pseudos.contains_key(&style_pseudo) { context.stylist
let new_style = .lazily_compute_pseudo_element_style(
context.stylist &context.guards,
.lazily_compute_pseudo_element_style( unsafe { &self.unsafe_get() },
&context.guards, &style_pseudo,
unsafe { &self.unsafe_get() }, data.styles().primary.values(),
&style_pseudo, &ServoMetricsProvider)
data.styles().primary.values(), .unwrap()
&ServoMetricsProvider); .values().clone()
data.styles_mut().cached_pseudos
.insert(style_pseudo.clone(), new_style.unwrap());
}
data.styles().cached_pseudos.get(&style_pseudo)
.unwrap().values().clone()
} }
} }
} }
@ -452,7 +435,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
#[inline] #[inline]
fn selected_style(&self) -> Arc<ServoComputedValues> { fn selected_style(&self) -> Arc<ServoComputedValues> {
let data = self.get_style_data().unwrap().borrow(); let data = self.style_data();
data.styles().pseudos data.styles().pseudos
.get(&PseudoElement::Selection).map(|s| s) .get(&PseudoElement::Selection).map(|s| s)
.unwrap_or(&data.styles().primary) .unwrap_or(&data.styles().primary)
@ -468,7 +451,7 @@ pub trait ThreadSafeLayoutElement: Clone + Copy + Sized + Debug +
/// element style is precomputed, not from general layout itself. /// element style is precomputed, not from general layout itself.
#[inline] #[inline]
fn resolved_style(&self) -> Arc<ServoComputedValues> { fn resolved_style(&self) -> Arc<ServoComputedValues> {
let data = self.get_style_data().unwrap().borrow(); let data = self.style_data();
match self.get_pseudo_element_type() { match self.get_pseudo_element_type() {
PseudoElementType::Normal PseudoElementType::Normal
=> data.styles().primary.values().clone(), => data.styles().primary.values().clone(),