зеркало из https://github.com/mozilla/gecko-dev.git
servo: Merge #13655 - Move children_to_process to layout (from bholley:children_to_process); r=<try>
We don't need this for Gecko, and it's hard to implement in that case because there's nowhere obvious to put it (we don't plan to create TSDs for non-dirty nodes, and non-dirty nodes can have dirty children which require the children_to_process atomic). There are various solutions here, but punting is the easiest. We'll need to rethink this if/when we need to do a bottom-up traversal for Gecko. Source-Repo: https://github.com/servo/servo Source-Revision: 70dbfd28fa44b0cd89a0ea39a6bd1180611c5e66
This commit is contained in:
Родитель
a286b6fb44
Коммит
79a77ced40
|
@ -1418,7 +1418,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
let result = {
|
||||
let mut style = node.style(self.style_context());
|
||||
let mut data = node.mutate_layout_data().unwrap();
|
||||
let damage = data.restyle_damage;
|
||||
let damage = data.base.restyle_damage;
|
||||
|
||||
match *node.construction_result_mut(&mut *data) {
|
||||
ConstructionResult::None => true,
|
||||
|
|
|
@ -3,19 +3,13 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
use construct::ConstructionResult;
|
||||
use script_layout_interface::restyle_damage::RestyleDamage;
|
||||
use style::data::PersistentStyleData;
|
||||
use script_layout_interface::PartialPersistentLayoutData;
|
||||
|
||||
/// Data that layout associates with a node.
|
||||
pub struct PersistentLayoutData {
|
||||
/// Data that the style system associates with a node. When the
|
||||
/// style system is being used standalone, this is all that hangs
|
||||
/// off the node. This must be first to permit the various
|
||||
/// transmutations between PersistentStyleData and PersistentLayoutData.
|
||||
pub style_data: PersistentStyleData,
|
||||
|
||||
/// Description of how to account for recent style changes.
|
||||
pub restyle_damage: RestyleDamage,
|
||||
/// Data accessed by script_layout_interface. This must be first to allow
|
||||
/// casting between PersistentLayoutData and PartialPersistentLayoutData.
|
||||
pub base: PartialPersistentLayoutData,
|
||||
|
||||
/// The current results of flow construction for this node. This is either a
|
||||
/// flow or a `ConstructionItem`. See comments in `construct.rs` for more
|
||||
|
@ -38,8 +32,7 @@ impl PersistentLayoutData {
|
|||
/// Creates new layout data.
|
||||
pub fn new() -> PersistentLayoutData {
|
||||
PersistentLayoutData {
|
||||
style_data: PersistentStyleData::new(),
|
||||
restyle_damage: RestyleDamage::empty(),
|
||||
base: PartialPersistentLayoutData::new(),
|
||||
flow_construction_result: ConstructionResult::None,
|
||||
before_flow_construction_result: ConstructionResult::None,
|
||||
after_flow_construction_result: ConstructionResult::None,
|
||||
|
|
|
@ -54,6 +54,7 @@ use std::fmt;
|
|||
use std::marker::PhantomData;
|
||||
use std::mem::transmute;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
use string_cache::{Atom, Namespace};
|
||||
use style::atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
|
||||
use style::attr::AttrValue;
|
||||
|
@ -221,6 +222,18 @@ impl<'ln> TNode for ServoLayoutNode<'ln> {
|
|||
self.node.set_flag(CAN_BE_FRAGMENTED, value)
|
||||
}
|
||||
|
||||
fn store_children_to_process(&self, n: isize) {
|
||||
let data = self.get_partial_layout_data().unwrap().borrow();
|
||||
data.parallel.children_to_process.store(n, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
fn did_process_child(&self) -> isize {
|
||||
let data = self.get_partial_layout_data().unwrap().borrow();
|
||||
let old_value = data.parallel.children_to_process.fetch_sub(1, Ordering::Relaxed);
|
||||
debug_assert!(old_value >= 1);
|
||||
old_value - 1
|
||||
}
|
||||
|
||||
fn borrow_data(&self) -> Option<AtomicRef<PersistentStyleData>> {
|
||||
self.get_style_data().map(|d| d.borrow())
|
||||
}
|
||||
|
|
|
@ -52,12 +52,32 @@ use core::nonzero::NonZero;
|
|||
use ipc_channel::ipc::IpcSender;
|
||||
use libc::c_void;
|
||||
use restyle_damage::RestyleDamage;
|
||||
use std::sync::atomic::AtomicIsize;
|
||||
use style::atomic_refcell::AtomicRefCell;
|
||||
use style::data::PersistentStyleData;
|
||||
|
||||
pub struct PartialPersistentLayoutData {
|
||||
/// Data that the style system associates with a node. When the
|
||||
/// style system is being used standalone, this is all that hangs
|
||||
/// off the node. This must be first to permit the various
|
||||
/// transmutations between PersistentStyleData and PersistentLayoutData.
|
||||
pub style_data: PersistentStyleData,
|
||||
|
||||
/// Description of how to account for recent style changes.
|
||||
pub restyle_damage: RestyleDamage,
|
||||
|
||||
/// Information needed during parallel traversals.
|
||||
pub parallel: DomParallelInfo,
|
||||
}
|
||||
|
||||
impl PartialPersistentLayoutData {
|
||||
pub fn new() -> Self {
|
||||
PartialPersistentLayoutData {
|
||||
style_data: PersistentStyleData::new(),
|
||||
restyle_damage: RestyleDamage::empty(),
|
||||
parallel: DomParallelInfo::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, HeapSizeOf)]
|
||||
|
@ -70,6 +90,22 @@ pub struct OpaqueStyleAndLayoutData {
|
|||
#[allow(unsafe_code)]
|
||||
unsafe impl Send for OpaqueStyleAndLayoutData {}
|
||||
|
||||
/// Information that we need stored in each DOM node.
|
||||
#[derive(HeapSizeOf)]
|
||||
pub struct DomParallelInfo {
|
||||
/// The number of children remaining to process during bottom-up traversal.
|
||||
pub children_to_process: AtomicIsize,
|
||||
}
|
||||
|
||||
impl DomParallelInfo {
|
||||
pub fn new() -> DomParallelInfo {
|
||||
DomParallelInfo {
|
||||
children_to_process: AtomicIsize::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum LayoutNodeType {
|
||||
Comment,
|
||||
|
|
|
@ -9,7 +9,6 @@ use selector_impl::PseudoElement;
|
|||
use std::collections::HashMap;
|
||||
use std::hash::BuildHasherDefault;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicIsize;
|
||||
|
||||
pub struct PersistentStyleData {
|
||||
/// The results of CSS styling for this node.
|
||||
|
@ -18,9 +17,6 @@ pub struct PersistentStyleData {
|
|||
/// The results of CSS styling for each pseudo-element (if any).
|
||||
pub per_pseudo: HashMap<PseudoElement, Arc<ComputedValues>,
|
||||
BuildHasherDefault<::fnv::FnvHasher>>,
|
||||
|
||||
/// Information needed during parallel traversals.
|
||||
pub parallel: DomParallelInfo,
|
||||
}
|
||||
|
||||
impl PersistentStyleData {
|
||||
|
@ -28,22 +24,6 @@ impl PersistentStyleData {
|
|||
PersistentStyleData {
|
||||
style: None,
|
||||
per_pseudo: HashMap::with_hasher(Default::default()),
|
||||
parallel: DomParallelInfo::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information that we need stored in each DOM node.
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct DomParallelInfo {
|
||||
/// The number of children that still need work done.
|
||||
pub children_to_process: AtomicIsize,
|
||||
}
|
||||
|
||||
impl DomParallelInfo {
|
||||
pub fn new() -> DomParallelInfo {
|
||||
DomParallelInfo {
|
||||
children_to_process: AtomicIsize::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -139,6 +139,14 @@ pub trait TNode : Sized + Copy + Clone + NodeInfo {
|
|||
|
||||
unsafe fn set_can_be_fragmented(&self, value: bool);
|
||||
|
||||
/// Atomically stores the number of children of this node that we will
|
||||
/// need to process during bottom-up traversal.
|
||||
fn store_children_to_process(&self, n: isize);
|
||||
|
||||
/// Atomically notes that a child has been processed during bottom-up
|
||||
/// traversal. Returns the number of children left to process.
|
||||
fn did_process_child(&self) -> isize;
|
||||
|
||||
/// Borrows the style data immutably. Fails on a conflicting borrow.
|
||||
#[inline(always)]
|
||||
fn borrow_data(&self) -> Option<AtomicRef<PersistentStyleData>>;
|
||||
|
|
|
@ -94,7 +94,6 @@ pub struct GeckoNode<'ln>(pub &'ln RawGeckoNode);
|
|||
|
||||
impl<'ln> GeckoNode<'ln> {
|
||||
fn from_content(content: &'ln nsIContent) -> Self {
|
||||
use std::mem;
|
||||
GeckoNode(&content._base)
|
||||
}
|
||||
|
||||
|
@ -302,6 +301,14 @@ impl<'ln> TNode for GeckoNode<'ln> {
|
|||
// Maybe this isn’t useful for Gecko?
|
||||
}
|
||||
|
||||
fn store_children_to_process(&self, _: isize) {
|
||||
// This is only used for bottom-up traversal, and is thus a no-op for Gecko.
|
||||
}
|
||||
|
||||
fn did_process_child(&self) -> isize {
|
||||
panic!("Atomic child count not implemented in Gecko");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn borrow_data(&self) -> Option<AtomicRef<PersistentStyleData>> {
|
||||
self.get_node_data().as_ref().map(|d| d.0.borrow())
|
||||
|
|
|
@ -107,10 +107,7 @@ fn top_down_dom<N, C>(unsafe_nodes: UnsafeNodeList,
|
|||
// Reset the count of children if we need to do a bottom-up traversal
|
||||
// after the top up.
|
||||
if context.needs_postorder_traversal() {
|
||||
node.mutate_data().unwrap()
|
||||
.parallel.children_to_process
|
||||
.store(children_to_process,
|
||||
Ordering::Relaxed);
|
||||
node.store_children_to_process(children_to_process);
|
||||
|
||||
// If there were no more children, start walking back up.
|
||||
if children_to_process == 0 {
|
||||
|
@ -161,12 +158,8 @@ fn bottom_up_dom<N, C>(root: OpaqueNode,
|
|||
Some(parent) => parent,
|
||||
};
|
||||
|
||||
let parent_data = parent.borrow_data().unwrap();
|
||||
|
||||
if parent_data
|
||||
.parallel
|
||||
.children_to_process
|
||||
.fetch_sub(1, Ordering::Relaxed) != 1 {
|
||||
let remaining = parent.did_process_child();
|
||||
if remaining != 0 {
|
||||
// Get out of here and find another node to work on.
|
||||
break
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче