зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #8029 - Some cleanup in layout (from Ms2ger:cleanup-layout); r=pcwalton
Source-Repo: https://github.com/servo/servo Source-Revision: e0c8a88410277843714a20d5fced73a392fad861
This commit is contained in:
Родитель
cfc0603fb6
Коммит
8be0065221
|
@ -363,14 +363,30 @@ impl StyleSharingCandidateCache {
|
||||||
|
|
||||||
/// The results of attempting to share a style.
|
/// The results of attempting to share a style.
|
||||||
pub enum StyleSharingResult {
|
pub enum StyleSharingResult {
|
||||||
/// We didn't find anybody to share the style with. The boolean indicates whether the style
|
/// We didn't find anybody to share the style with.
|
||||||
/// is shareable at all.
|
CannotShare,
|
||||||
CannotShare(bool),
|
|
||||||
/// The node's style can be shared. The integer specifies the index in the LRU cache that was
|
/// The node's style can be shared. The integer specifies the index in the LRU cache that was
|
||||||
/// hit and the damage that was done.
|
/// hit and the damage that was done.
|
||||||
StyleWasShared(usize, RestyleDamage),
|
StyleWasShared(usize, RestyleDamage),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait ElementMatchMethods {
|
||||||
|
fn match_element(&self,
|
||||||
|
stylist: &Stylist,
|
||||||
|
parent_bf: Option<&BloomFilter>,
|
||||||
|
applicable_declarations: &mut ApplicableDeclarations)
|
||||||
|
-> bool;
|
||||||
|
|
||||||
|
/// Attempts to share a style with another node. This method is unsafe because it depends on
|
||||||
|
/// the `style_sharing_candidate_cache` having only live nodes in it, and we have no way to
|
||||||
|
/// guarantee that at the type system level yet.
|
||||||
|
unsafe fn share_style_if_possible(&self,
|
||||||
|
style_sharing_candidate_cache:
|
||||||
|
&mut StyleSharingCandidateCache,
|
||||||
|
parent: Option<LayoutNode>)
|
||||||
|
-> StyleSharingResult;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait MatchMethods {
|
pub trait MatchMethods {
|
||||||
/// Inserts and removes the matching `Descendant` selectors from a bloom
|
/// Inserts and removes the matching `Descendant` selectors from a bloom
|
||||||
/// filter. This is used to speed up CSS selector matching to remove
|
/// filter. This is used to speed up CSS selector matching to remove
|
||||||
|
@ -385,21 +401,6 @@ pub trait MatchMethods {
|
||||||
/// called to reset the bloom filter after an `insert`.
|
/// called to reset the bloom filter after an `insert`.
|
||||||
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter);
|
fn remove_from_bloom_filter(&self, bf: &mut BloomFilter);
|
||||||
|
|
||||||
fn match_node(&self,
|
|
||||||
stylist: &Stylist,
|
|
||||||
parent_bf: Option<&BloomFilter>,
|
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
|
||||||
shareable: &mut bool);
|
|
||||||
|
|
||||||
/// Attempts to share a style with another node. This method is unsafe because it depends on
|
|
||||||
/// the `style_sharing_candidate_cache` having only live nodes in it, and we have no way to
|
|
||||||
/// guarantee that at the type system level yet.
|
|
||||||
unsafe fn share_style_if_possible(&self,
|
|
||||||
style_sharing_candidate_cache:
|
|
||||||
&mut StyleSharingCandidateCache,
|
|
||||||
parent: Option<LayoutNode>)
|
|
||||||
-> StyleSharingResult;
|
|
||||||
|
|
||||||
unsafe fn cascade_node(&self,
|
unsafe fn cascade_node(&self,
|
||||||
layout_context: &SharedLayoutContext,
|
layout_context: &SharedLayoutContext,
|
||||||
parent: Option<LayoutNode>,
|
parent: Option<LayoutNode>,
|
||||||
|
@ -420,7 +421,9 @@ trait PrivateMatchMethods {
|
||||||
shareable: bool,
|
shareable: bool,
|
||||||
animate_properties: bool)
|
animate_properties: bool)
|
||||||
-> RestyleDamage;
|
-> RestyleDamage;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait PrivateElementMatchMethods {
|
||||||
fn share_style_with_candidate_if_possible(&self,
|
fn share_style_with_candidate_if_possible(&self,
|
||||||
parent_node: Option<LayoutNode>,
|
parent_node: Option<LayoutNode>,
|
||||||
candidate: &StyleSharingCandidate)
|
candidate: &StyleSharingCandidate)
|
||||||
|
@ -504,13 +507,13 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
*style = Some(this_style);
|
*style = Some(this_style);
|
||||||
damage
|
damage
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ln> PrivateElementMatchMethods for LayoutElement<'ln> {
|
||||||
fn share_style_with_candidate_if_possible(&self,
|
fn share_style_with_candidate_if_possible(&self,
|
||||||
parent_node: Option<LayoutNode>,
|
parent_node: Option<LayoutNode>,
|
||||||
candidate: &StyleSharingCandidate)
|
candidate: &StyleSharingCandidate)
|
||||||
-> Option<Arc<ComputedValues>> {
|
-> Option<Arc<ComputedValues>> {
|
||||||
let element = self.as_element().unwrap();
|
|
||||||
|
|
||||||
let parent_node = match parent_node {
|
let parent_node = match parent_node {
|
||||||
Some(ref parent_node) if parent_node.as_element().is_some() => parent_node,
|
Some(ref parent_node) if parent_node.as_element().is_some() => parent_node,
|
||||||
Some(_) | None => return None,
|
Some(_) | None => return None,
|
||||||
|
@ -528,7 +531,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check tag names, classes, etc.
|
// Check tag names, classes, etc.
|
||||||
if !candidate.can_share_style_with(&element) {
|
if !candidate.can_share_style_with(self) {
|
||||||
return None
|
return None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -541,35 +544,34 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ln> MatchMethods for LayoutNode<'ln> {
|
impl<'ln> ElementMatchMethods for LayoutElement<'ln> {
|
||||||
fn match_node(&self,
|
fn match_element(&self,
|
||||||
stylist: &Stylist,
|
stylist: &Stylist,
|
||||||
parent_bf: Option<&BloomFilter>,
|
parent_bf: Option<&BloomFilter>,
|
||||||
applicable_declarations: &mut ApplicableDeclarations,
|
applicable_declarations: &mut ApplicableDeclarations)
|
||||||
shareable: &mut bool) {
|
-> bool {
|
||||||
let element = self.as_element().unwrap();
|
let style_attribute = self.style_attribute().as_ref();
|
||||||
let style_attribute = element.style_attribute().as_ref();
|
|
||||||
|
|
||||||
applicable_declarations.normal_shareable =
|
applicable_declarations.normal_shareable =
|
||||||
stylist.push_applicable_declarations(&element,
|
stylist.push_applicable_declarations(self,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
style_attribute,
|
style_attribute,
|
||||||
None,
|
None,
|
||||||
&mut applicable_declarations.normal);
|
&mut applicable_declarations.normal);
|
||||||
stylist.push_applicable_declarations(&element,
|
stylist.push_applicable_declarations(self,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
None,
|
None,
|
||||||
Some(PseudoElement::Before),
|
Some(PseudoElement::Before),
|
||||||
&mut applicable_declarations.before);
|
&mut applicable_declarations.before);
|
||||||
stylist.push_applicable_declarations(&element,
|
stylist.push_applicable_declarations(self,
|
||||||
parent_bf,
|
parent_bf,
|
||||||
None,
|
None,
|
||||||
Some(PseudoElement::After),
|
Some(PseudoElement::After),
|
||||||
&mut applicable_declarations.after);
|
&mut applicable_declarations.after);
|
||||||
|
|
||||||
*shareable = applicable_declarations.normal_shareable &&
|
applicable_declarations.normal_shareable &&
|
||||||
applicable_declarations.before.is_empty() &&
|
applicable_declarations.before.is_empty() &&
|
||||||
applicable_declarations.after.is_empty()
|
applicable_declarations.after.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn share_style_if_possible(&self,
|
unsafe fn share_style_if_possible(&self,
|
||||||
|
@ -578,25 +580,22 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
parent: Option<LayoutNode>)
|
parent: Option<LayoutNode>)
|
||||||
-> StyleSharingResult {
|
-> StyleSharingResult {
|
||||||
if opts::get().disable_share_style_cache {
|
if opts::get().disable_share_style_cache {
|
||||||
return StyleSharingResult::CannotShare(false)
|
return StyleSharingResult::CannotShare
|
||||||
}
|
}
|
||||||
let ok = {
|
|
||||||
if let Some(element) = self.as_element() {
|
if self.style_attribute().is_some() {
|
||||||
element.style_attribute().is_none() &&
|
return StyleSharingResult::CannotShare
|
||||||
element.get_attr(&ns!(""), &atom!("id")).is_none()
|
}
|
||||||
} else {
|
if self.get_attr(&ns!(""), &atom!("id")).is_some() {
|
||||||
false
|
return StyleSharingResult::CannotShare
|
||||||
}
|
|
||||||
};
|
|
||||||
if !ok {
|
|
||||||
return StyleSharingResult::CannotShare(false)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, &(ref candidate, ())) in style_sharing_candidate_cache.iter().enumerate() {
|
for (i, &(ref candidate, ())) in style_sharing_candidate_cache.iter().enumerate() {
|
||||||
match self.share_style_with_candidate_if_possible(parent.clone(), candidate) {
|
match self.share_style_with_candidate_if_possible(parent.clone(), candidate) {
|
||||||
Some(shared_style) => {
|
Some(shared_style) => {
|
||||||
// Yay, cache hit. Share the style.
|
// Yay, cache hit. Share the style.
|
||||||
let mut layout_data_ref = self.mutate_layout_data();
|
let node = self.as_node();
|
||||||
|
let mut layout_data_ref = node.mutate_layout_data();
|
||||||
let shared_data = &mut layout_data_ref.as_mut().unwrap().shared_data;
|
let shared_data = &mut layout_data_ref.as_mut().unwrap().shared_data;
|
||||||
let style = &mut shared_data.style;
|
let style = &mut shared_data.style;
|
||||||
let damage = incremental::compute_damage(style, &*shared_style);
|
let damage = incremental::compute_damage(style, &*shared_style);
|
||||||
|
@ -607,9 +606,11 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
StyleSharingResult::CannotShare(true)
|
StyleSharingResult::CannotShare
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
// The below two functions are copy+paste because I can't figure out how to
|
// The below two functions are copy+paste because I can't figure out how to
|
||||||
// write a function which takes a generic function. I don't think it can
|
// write a function which takes a generic function. I don't think it can
|
||||||
// be done.
|
// be done.
|
||||||
|
|
|
@ -165,21 +165,18 @@ trait ParallelPostorderDomTraversal : PostorderDomTraversal {
|
||||||
/// The only communication between siblings is that they both
|
/// The only communication between siblings is that they both
|
||||||
/// fetch-and-subtract the parent's children count.
|
/// fetch-and-subtract the parent's children count.
|
||||||
fn run_parallel(&self,
|
fn run_parallel(&self,
|
||||||
mut unsafe_node: UnsafeLayoutNode,
|
unsafe_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>) {
|
proxy: &mut WorkerProxy<SharedLayoutContext, UnsafeLayoutNodeList>) {
|
||||||
|
// Get a real layout node.
|
||||||
|
let mut node: LayoutNode = unsafe {
|
||||||
|
layout_node_from_unsafe_layout_node(&unsafe_node)
|
||||||
|
};
|
||||||
loop {
|
loop {
|
||||||
// Get a real layout node.
|
|
||||||
let node: LayoutNode = unsafe {
|
|
||||||
layout_node_from_unsafe_layout_node(&unsafe_node)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Perform the appropriate operation.
|
// Perform the appropriate operation.
|
||||||
self.process(node);
|
self.process(node);
|
||||||
|
|
||||||
let shared_layout_context = proxy.user_data();
|
let shared_layout_context = proxy.user_data();
|
||||||
let layout_context = LayoutContext::new(shared_layout_context);
|
let parent = match node.layout_parent_node(shared_layout_context) {
|
||||||
|
|
||||||
let parent = match node.layout_parent_node(layout_context.shared) {
|
|
||||||
None => break,
|
None => break,
|
||||||
Some(parent) => parent,
|
Some(parent) => parent,
|
||||||
};
|
};
|
||||||
|
@ -188,18 +185,18 @@ trait ParallelPostorderDomTraversal : PostorderDomTraversal {
|
||||||
&*parent.borrow_layout_data_unchecked()
|
&*parent.borrow_layout_data_unchecked()
|
||||||
};
|
};
|
||||||
let parent_layout_data = parent_layout_data.as_ref().expect("no layout data");
|
let parent_layout_data = parent_layout_data.as_ref().expect("no layout data");
|
||||||
unsafe_node = layout_node_to_unsafe_layout_node(&parent);
|
|
||||||
|
|
||||||
if parent_layout_data
|
if parent_layout_data
|
||||||
.data
|
.data
|
||||||
.parallel
|
.parallel
|
||||||
.children_count
|
.children_count
|
||||||
.fetch_sub(1, Ordering::Relaxed) == 1 {
|
.fetch_sub(1, Ordering::Relaxed) != 1 {
|
||||||
// We were the last child of our parent. Construct flows for our parent.
|
|
||||||
} else {
|
|
||||||
// Get out of here and find another node to work on.
|
// Get out of here and find another node to work on.
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We were the last child of our parent. Construct flows for our parent.
|
||||||
|
node = parent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
use construct::FlowConstructor;
|
use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use css::matching::{ApplicableDeclarations, MatchMethods, StyleSharingResult};
|
use css::matching::{ApplicableDeclarations, ElementMatchMethods, MatchMethods, StyleSharingResult};
|
||||||
use flow::{MutableFlowUtils, PostorderFlowTraversal, PreorderFlowTraversal};
|
use flow::{MutableFlowUtils, PostorderFlowTraversal, PreorderFlowTraversal};
|
||||||
use flow::{self, Flow};
|
use flow::{self, Flow};
|
||||||
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
||||||
|
@ -165,26 +165,42 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> {
|
||||||
// Check to see whether we can share a style with someone.
|
// Check to see whether we can share a style with someone.
|
||||||
let style_sharing_candidate_cache =
|
let style_sharing_candidate_cache =
|
||||||
&mut self.layout_context.style_sharing_candidate_cache();
|
&mut self.layout_context.style_sharing_candidate_cache();
|
||||||
let sharing_result = unsafe {
|
|
||||||
node.share_style_if_possible(style_sharing_candidate_cache,
|
let sharing_result = match node.as_element() {
|
||||||
parent_opt.clone())
|
Some(element) => {
|
||||||
|
unsafe {
|
||||||
|
element.share_style_if_possible(style_sharing_candidate_cache,
|
||||||
|
parent_opt.clone())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => StyleSharingResult::CannotShare,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Otherwise, match and cascade selectors.
|
// Otherwise, match and cascade selectors.
|
||||||
match sharing_result {
|
match sharing_result {
|
||||||
StyleSharingResult::CannotShare(mut shareable) => {
|
StyleSharingResult::CannotShare => {
|
||||||
let mut applicable_declarations = ApplicableDeclarations::new();
|
let mut applicable_declarations = ApplicableDeclarations::new();
|
||||||
|
|
||||||
if node.as_element().is_some() {
|
let shareable_element = match node.as_element() {
|
||||||
// Perform the CSS selector matching.
|
Some(element) => {
|
||||||
let stylist = unsafe { &*self.layout_context.shared.stylist };
|
// Perform the CSS selector matching.
|
||||||
node.match_node(stylist,
|
let stylist = unsafe { &*self.layout_context.shared.stylist };
|
||||||
Some(&*bf),
|
if element.match_element(stylist,
|
||||||
&mut applicable_declarations,
|
Some(&*bf),
|
||||||
&mut shareable);
|
&mut applicable_declarations) {
|
||||||
} else if node.has_changed() {
|
Some(element)
|
||||||
ThreadSafeLayoutNode::new(&node).set_restyle_damage(
|
} else {
|
||||||
incremental::rebuild_and_reflow())
|
None
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
if node.has_changed() {
|
||||||
|
ThreadSafeLayoutNode::new(&node).set_restyle_damage(
|
||||||
|
incremental::rebuild_and_reflow())
|
||||||
|
}
|
||||||
|
None
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Perform the CSS cascade.
|
// Perform the CSS cascade.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -196,10 +212,8 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ourselves to the LRU cache.
|
// Add ourselves to the LRU cache.
|
||||||
if shareable {
|
if let Some(element) = shareable_element {
|
||||||
if let Some(element) = node.as_element() {
|
style_sharing_candidate_cache.insert_if_possible(&element);
|
||||||
style_sharing_candidate_cache.insert_if_possible(&element);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StyleSharingResult::StyleWasShared(index, damage) => {
|
StyleSharingResult::StyleWasShared(index, damage) => {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче