aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/rule_tree/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/rule_tree/mod.rs')
-rw-r--r--components/style/rule_tree/mod.rs389
1 files changed, 224 insertions, 165 deletions
diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs
index 040a93d9a45..25d7a8e896d 100644
--- a/components/style/rule_tree/mod.rs
+++ b/components/style/rule_tree/mod.rs
@@ -13,7 +13,7 @@ use gecko::selector_parser::PseudoElement;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
use properties::{Importance, LonghandIdSet, PropertyDeclarationBlock};
use servo_arc::{Arc, ArcBorrow, NonZeroPtrMut};
-use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard};
+use shared_lock::{Locked, SharedRwLockReadGuard, StylesheetGuards};
use smallvec::SmallVec;
use std::io::{self, Write};
use std::mem;
@@ -52,15 +52,23 @@ pub struct RuleTree {
impl Drop for RuleTree {
fn drop(&mut self) {
// GC the rule tree.
- unsafe { self.gc(); }
+ unsafe {
+ self.gc();
+ }
// After the GC, the free list should be empty.
- debug_assert_eq!(self.root.get().next_free.load(Ordering::Relaxed), FREE_LIST_SENTINEL);
+ debug_assert_eq!(
+ self.root.get().next_free.load(Ordering::Relaxed),
+ FREE_LIST_SENTINEL
+ );
// Remove the sentinel. This indicates that GCs will no longer occur.
// Any further drops of StrongRuleNodes must occur on the main thread,
// and will trigger synchronous dropping of the Rule nodes.
- self.root.get().next_free.store(ptr::null_mut(), Ordering::Relaxed);
+ self.root
+ .get()
+ .next_free
+ .store(ptr::null_mut(), Ordering::Relaxed);
}
}
@@ -104,7 +112,9 @@ impl StyleSource {
match (self, other) {
(&Style(ref one), &Style(ref other)) => Arc::ptr_eq(one, other),
(&Declarations(ref one), &Declarations(ref other)) => Arc::ptr_eq(one, other),
- (&None, _) | (_, &None) => panic!("Should not check for equality between null StyleSource objects"),
+ (&None, _) | (_, &None) => {
+ panic!("Should not check for equality between null StyleSource objects")
+ },
_ => false,
}
}
@@ -185,10 +195,10 @@ impl RuleTree {
pub fn insert_ordered_rules_with_important<'a, I>(
&self,
iter: I,
- guards: &StylesheetGuards
+ guards: &StylesheetGuards,
) -> StrongRuleNode
where
- I: Iterator<Item=(StyleSource, CascadeLevel)>,
+ I: Iterator<Item = (StyleSource, CascadeLevel)>,
{
use self::CascadeLevel::*;
let mut current = self.root.clone();
@@ -283,7 +293,7 @@ impl RuleTree {
pub fn compute_rule_node(
&self,
applicable_declarations: &mut ApplicableDeclarationList,
- guards: &StylesheetGuards
+ guards: &StylesheetGuards,
) -> StrongRuleNode {
let rules = applicable_declarations.drain().map(|d| d.order_and_level());
let rule_node = self.insert_ordered_rules_with_important(rules, guards);
@@ -293,15 +303,15 @@ impl RuleTree {
/// Insert the given rules, that must be in proper order by specifity, and
/// return the corresponding rule node representing the last inserted one.
pub fn insert_ordered_rules<'a, I>(&self, iter: I) -> StrongRuleNode
- where I: Iterator<Item=(StyleSource, CascadeLevel)>,
+ where
+ I: Iterator<Item = (StyleSource, CascadeLevel)>,
{
self.insert_ordered_rules_from(self.root.clone(), iter)
}
- fn insert_ordered_rules_from<'a, I>(&self,
- from: StrongRuleNode,
- iter: I) -> StrongRuleNode
- where I: Iterator<Item=(StyleSource, CascadeLevel)>,
+ fn insert_ordered_rules_from<'a, I>(&self, from: StrongRuleNode, iter: I) -> StrongRuleNode
+ where
+ I: Iterator<Item = (StyleSource, CascadeLevel)>,
{
let mut current = from;
let mut last_level = current.get().level;
@@ -327,13 +337,14 @@ impl RuleTree {
///
/// Returns the resulting node that represents the new path, or None if
/// the old path is still valid.
- pub fn update_rule_at_level(&self,
- level: CascadeLevel,
- pdb: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
- path: &StrongRuleNode,
- guards: &StylesheetGuards,
- important_rules_changed: &mut bool)
- -> Option<StrongRuleNode> {
+ pub fn update_rule_at_level(
+ &self,
+ level: CascadeLevel,
+ pdb: Option<ArcBorrow<Locked<PropertyDeclarationBlock>>>,
+ path: &StrongRuleNode,
+ guards: &StylesheetGuards,
+ important_rules_changed: &mut bool,
+ ) -> Option<StrongRuleNode> {
debug_assert!(level.is_unique_per_element());
// TODO(emilio): Being smarter with lifetimes we could avoid a bit of
// the refcount churn.
@@ -384,8 +395,10 @@ impl RuleTree {
}
current = current.parent().unwrap().clone();
}
- debug_assert!(current.get().level != level,
- "Multiple rules should've been replaced?");
+ debug_assert!(
+ current.get().level != level,
+ "Multiple rules should've been replaced?"
+ );
// Insert the rule if it's relevant at this level in the cascade.
//
@@ -395,23 +408,26 @@ impl RuleTree {
if let Some(pdb) = pdb {
if level.is_important() {
if pdb.read_with(level.guard(guards)).any_important() {
- current = current.ensure_child(self.root.downgrade(),
- StyleSource::Declarations(pdb.clone_arc()),
- level);
+ current = current.ensure_child(
+ self.root.downgrade(),
+ StyleSource::Declarations(pdb.clone_arc()),
+ level,
+ );
}
} else {
if pdb.read_with(level.guard(guards)).any_normal() {
- current = current.ensure_child(self.root.downgrade(),
- StyleSource::Declarations(pdb.clone_arc()),
- level);
+ current = current.ensure_child(
+ self.root.downgrade(),
+ StyleSource::Declarations(pdb.clone_arc()),
+ level,
+ );
}
}
}
// Now the rule is in the relevant place, push the children as
// necessary.
- let rule =
- self.insert_ordered_rules_from(current, children.drain().rev());
+ let rule = self.insert_ordered_rules_from(current, children.drain().rev());
Some(rule)
}
@@ -432,8 +448,8 @@ impl RuleTree {
return path.clone();
}
- let iter = path.self_and_ancestors().take_while(
- |node| node.cascade_level() >= CascadeLevel::SMILOverride);
+ let iter = path.self_and_ancestors()
+ .take_while(|node| node.cascade_level() >= CascadeLevel::SMILOverride);
let mut last = path;
let mut children = SmallVec::<[_; 10]>::new();
for node in iter {
@@ -443,7 +459,8 @@ impl RuleTree {
last = node;
}
- let rule = self.insert_ordered_rules_from(last.parent().unwrap().clone(), children.drain().rev());
+ let rule =
+ self.insert_ordered_rules_from(last.parent().unwrap().clone(), children.drain().rev());
rule
}
@@ -459,11 +476,13 @@ impl RuleTree {
guards: &StylesheetGuards,
) -> StrongRuleNode {
let mut dummy = false;
- self.update_rule_at_level(CascadeLevel::Transitions,
- Some(pdb.borrow_arc()),
- path,
- guards,
- &mut dummy).expect("Should return a valid rule node")
+ self.update_rule_at_level(
+ CascadeLevel::Transitions,
+ Some(pdb.borrow_arc()),
+ path,
+ guards,
+ &mut dummy,
+ ).expect("Should return a valid rule node")
}
}
@@ -575,9 +594,9 @@ impl CascadeLevel {
#[inline]
pub fn is_animation(&self) -> bool {
match *self {
- CascadeLevel::SMILOverride |
- CascadeLevel::Animations |
- CascadeLevel::Transitions => true,
+ CascadeLevel::SMILOverride | CascadeLevel::Animations | CascadeLevel::Transitions => {
+ true
+ },
_ => false,
}
}
@@ -642,32 +661,32 @@ unsafe impl Send for RuleTree {}
#[cfg(feature = "gecko")]
#[cfg(debug_assertions)]
mod gecko_leak_checking {
-use std::mem::size_of;
-use std::os::raw::{c_char, c_void};
-use super::RuleNode;
+ use std::mem::size_of;
+ use std::os::raw::{c_char, c_void};
+ use super::RuleNode;
-extern "C" {
- pub fn NS_LogCtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32);
- pub fn NS_LogDtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32);
-}
+ extern "C" {
+ pub fn NS_LogCtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32);
+ pub fn NS_LogDtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32);
+ }
-static NAME: &'static [u8] = b"RuleNode\0";
+ static NAME: &'static [u8] = b"RuleNode\0";
-/// Logs the creation of a heap-allocated object to Gecko's leak-checking machinery.
-pub fn log_ctor(ptr: *const RuleNode) {
- let s = NAME as *const [u8] as *const u8 as *const c_char;
- unsafe {
- NS_LogCtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32);
+ /// Logs the creation of a heap-allocated object to Gecko's leak-checking machinery.
+ pub fn log_ctor(ptr: *const RuleNode) {
+ let s = NAME as *const [u8] as *const u8 as *const c_char;
+ unsafe {
+ NS_LogCtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32);
+ }
}
-}
-/// Logs the destruction of a heap-allocated object to Gecko's leak-checking machinery.
-pub fn log_dtor(ptr: *const RuleNode) {
- let s = NAME as *const [u8] as *const u8 as *const c_char;
- unsafe {
- NS_LogDtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32);
+ /// Logs the destruction of a heap-allocated object to Gecko's leak-checking machinery.
+ pub fn log_dtor(ptr: *const RuleNode) {
+ let s = NAME as *const [u8] as *const u8 as *const c_char;
+ unsafe {
+ NS_LogDtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32);
+ }
}
-}
}
@@ -686,10 +705,12 @@ fn log_drop(_ptr: *const RuleNode) {
}
impl RuleNode {
- fn new(root: WeakRuleNode,
- parent: StrongRuleNode,
- source: StyleSource,
- level: CascadeLevel) -> Self {
+ fn new(
+ root: WeakRuleNode,
+ parent: StrongRuleNode,
+ source: StyleSource,
+ level: CascadeLevel,
+ ) -> Self {
debug_assert!(root.upgrade().parent().is_none());
RuleNode {
root: Some(root),
@@ -751,21 +772,25 @@ impl RuleNode {
/// This is expected to be called before freeing the node from the free
/// list.
unsafe fn remove_from_child_list(&self) {
- debug!("Remove from child list: {:?}, parent: {:?}",
- self as *const RuleNode, self.parent.as_ref().map(|p| p.ptr()));
+ debug!(
+ "Remove from child list: {:?}, parent: {:?}",
+ self as *const RuleNode,
+ self.parent.as_ref().map(|p| p.ptr())
+ );
// NB: The other siblings we use in this function can also be dead, so
// we can't use `get` here, since it asserts.
- let prev_sibling =
- self.prev_sibling().swap(ptr::null_mut(), Ordering::Relaxed);
+ let prev_sibling = self.prev_sibling().swap(ptr::null_mut(), Ordering::Relaxed);
- let next_sibling =
- self.next_sibling.swap(ptr::null_mut(), Ordering::Relaxed);
+ let next_sibling = self.next_sibling.swap(ptr::null_mut(), Ordering::Relaxed);
// Store the `next` pointer as appropriate, either in the previous
// sibling, or in the parent otherwise.
if prev_sibling.is_null() {
let parent = self.parent.as_ref().unwrap();
- parent.get().first_child.store(next_sibling, Ordering::Relaxed);
+ parent
+ .get()
+ .first_child
+ .store(next_sibling, Ordering::Relaxed);
} else {
let previous = &*prev_sibling;
previous.next_sibling.store(next_sibling, Ordering::Relaxed);
@@ -786,9 +811,13 @@ impl RuleNode {
let _ = write!(writer, " ");
}
- let _ = writeln!(writer, " - {:?} (ref: {:?}, parent: {:?})",
- self as *const _, self.refcount.load(Ordering::Relaxed),
- self.parent.as_ref().map(|p| p.ptr()));
+ let _ = writeln!(
+ writer,
+ " - {:?} (ref: {:?}, parent: {:?})",
+ self as *const _,
+ self.refcount.load(Ordering::Relaxed),
+ self.parent.as_ref().map(|p| p.ptr())
+ );
for _ in 0..indent {
let _ = write!(writer, " ");
@@ -805,7 +834,10 @@ impl RuleNode {
let _ = write!(writer, "\n");
for child in self.iter_children() {
- child.upgrade().get().dump(guards, writer, indent + INDENT_INCREMENT);
+ child
+ .upgrade()
+ .get()
+ .dump(guards, writer, indent + INDENT_INCREMENT);
}
}
@@ -817,7 +849,7 @@ impl RuleNode {
None
} else {
Some(WeakRuleNode::from_ptr(first_child))
- }
+ },
}
}
}
@@ -864,7 +896,7 @@ impl StrongRuleNode {
fn from_ptr(ptr: *mut RuleNode) -> Self {
StrongRuleNode {
- p: NonZeroPtrMut::new(ptr)
+ p: NonZeroPtrMut::new(ptr),
}
}
@@ -881,7 +913,7 @@ impl StrongRuleNode {
&self,
root: WeakRuleNode,
source: StyleSource,
- level: CascadeLevel
+ level: CascadeLevel,
) -> StrongRuleNode {
let mut last = None;
@@ -894,17 +926,13 @@ impl StrongRuleNode {
// WeakRuleNode, and implementing this on WeakRuleNode itself...
for child in self.get().iter_children() {
let child_node = unsafe { &*child.ptr() };
- if child_node.level == level &&
- child_node.source.ptr_equals(&source) {
+ if child_node.level == level && child_node.source.ptr_equals(&source) {
return child.upgrade();
}
last = Some(child);
}
- let mut node = Box::new(RuleNode::new(root,
- self.clone(),
- source.clone(),
- level));
+ let mut node = Box::new(RuleNode::new(root, self.clone(), source.clone(), level));
let new_ptr: *mut RuleNode = &mut *node;
loop {
@@ -920,9 +948,7 @@ impl StrongRuleNode {
// We use `AqcRel` semantics to ensure the initializing writes
// in `node` are visible after the swap succeeds.
let existing =
- next_sibling_ptr.compare_and_swap(ptr::null_mut(),
- new_ptr,
- Ordering::AcqRel);
+ next_sibling_ptr.compare_and_swap(ptr::null_mut(), new_ptr, Ordering::AcqRel);
if existing.is_null() {
// Now we know we're in the correct position in the child
@@ -985,7 +1011,7 @@ impl StrongRuleNode {
/// Get an iterator for this rule node and its ancestors.
pub fn self_and_ancestors(&self) -> SelfAndAncestors {
SelfAndAncestors {
- current: Some(self)
+ current: Some(self),
}
}
@@ -1008,29 +1034,41 @@ impl StrongRuleNode {
// case, so just don't crash in the case we're doing the final GC in
// script.
- debug_assert!(!thread_state::get().is_worker() &&
- (thread_state::get().is_layout() ||
- thread_state::get().is_script()));
+ debug_assert!(
+ !thread_state::get().is_worker() &&
+ (thread_state::get().is_layout() || thread_state::get().is_script())
+ );
let current = me.next_free.load(Ordering::Relaxed);
if current == FREE_LIST_SENTINEL {
return None;
}
- debug_assert!(!current.is_null(),
- "Multiple threads are operating on the free list at the \
- same time?");
- debug_assert!(current != self.ptr(),
- "How did the root end up in the free list?");
-
- let next = (*current).next_free.swap(ptr::null_mut(), Ordering::Relaxed);
-
- debug_assert!(!next.is_null(),
- "How did a null pointer end up in the free list?");
+ debug_assert!(
+ !current.is_null(),
+ "Multiple threads are operating on the free list at the \
+ same time?"
+ );
+ debug_assert!(
+ current != self.ptr(),
+ "How did the root end up in the free list?"
+ );
+
+ let next = (*current)
+ .next_free
+ .swap(ptr::null_mut(), Ordering::Relaxed);
+
+ debug_assert!(
+ !next.is_null(),
+ "How did a null pointer end up in the free list?"
+ );
me.next_free.store(next, Ordering::Relaxed);
- debug!("Popping from free list: cur: {:?}, next: {:?}", current, next);
+ debug!(
+ "Popping from free list: cur: {:?}, next: {:?}",
+ current, next
+ );
Some(WeakRuleNode::from_ptr(current))
}
@@ -1105,7 +1143,7 @@ impl StrongRuleNode {
author_colors_allowed: bool,
) -> bool
where
- E: ::dom::TElement
+ E: ::dom::TElement,
{
use gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BACKGROUND;
use gecko_bindings::structs::NS_AUTHOR_SPECIFIED_BORDER;
@@ -1116,10 +1154,8 @@ impl StrongRuleNode {
use values::specified::Color;
// Reset properties:
- const BACKGROUND_PROPS: &'static [LonghandId] = &[
- LonghandId::BackgroundColor,
- LonghandId::BackgroundImage,
- ];
+ const BACKGROUND_PROPS: &'static [LonghandId] =
+ &[LonghandId::BackgroundColor, LonghandId::BackgroundImage];
const BORDER_PROPS: &'static [LonghandId] = &[
LonghandId::BorderTopColor,
@@ -1138,7 +1174,6 @@ impl StrongRuleNode {
LonghandId::BorderTopRightRadius,
LonghandId::BorderBottomRightRadius,
LonghandId::BorderBottomLeftRadius,
-
LonghandId::BorderInlineStartColor,
LonghandId::BorderInlineStartStyle,
LonghandId::BorderInlineStartWidth,
@@ -1158,7 +1193,6 @@ impl StrongRuleNode {
LonghandId::PaddingRight,
LonghandId::PaddingBottom,
LonghandId::PaddingLeft,
-
LonghandId::PaddingInlineStart,
LonghandId::PaddingInlineEnd,
LonghandId::PaddingBlockStart,
@@ -1187,7 +1221,7 @@ impl StrongRuleNode {
// If author colors are not allowed, only claim to have author-specified
// rules if we're looking at a non-color property or if we're looking at
// the background color and it's set to transparent.
- const IGNORED_WHEN_COLORS_DISABLED: &'static [LonghandId] = &[
+ const IGNORED_WHEN_COLORS_DISABLED: &'static [LonghandId] = &[
LonghandId::BackgroundImage,
LonghandId::BorderTopColor,
LonghandId::BorderRightColor,
@@ -1222,30 +1256,31 @@ impl StrongRuleNode {
for node in element_rule_node.self_and_ancestors() {
let source = node.style_source();
let declarations = if source.is_some() {
- source.read(node.cascade_level().guard(guards)).declaration_importance_iter()
+ source
+ .read(node.cascade_level().guard(guards))
+ .declaration_importance_iter()
} else {
- continue
+ continue;
};
// Iterate over declarations of the longhands we care about.
let node_importance = node.importance();
- let longhands = declarations.rev()
- .filter_map(|(declaration, importance)| {
- if importance != node_importance { return None }
- match declaration.id() {
- PropertyDeclarationId::Longhand(id) => {
- Some((id, declaration))
- }
- _ => None
- }
- });
+ let longhands = declarations.rev().filter_map(|(declaration, importance)| {
+ if importance != node_importance {
+ return None;
+ }
+ match declaration.id() {
+ PropertyDeclarationId::Longhand(id) => Some((id, declaration)),
+ _ => None,
+ }
+ });
match node.cascade_level() {
// Non-author rules:
CascadeLevel::UANormal |
CascadeLevel::UAImportant |
CascadeLevel::UserNormal |
- CascadeLevel::UserImportant => {
+ CascadeLevel::UserImportant => {
for (id, declaration) in longhands {
if properties.contains(id) {
// This property was set by a non-author rule.
@@ -1256,13 +1291,15 @@ impl StrongRuleNode {
// However, if it is inherited, then it might be
// inherited from an author rule from an
// ancestor element's rule nodes.
- if declaration.get_css_wide_keyword() == Some(CSSWideKeyword::Inherit) {
+ if declaration.get_css_wide_keyword() ==
+ Some(CSSWideKeyword::Inherit)
+ {
have_explicit_ua_inherit = true;
inherited_properties.insert(id);
}
}
}
- }
+ },
// Author rules:
CascadeLevel::PresHints |
CascadeLevel::AuthorNormal |
@@ -1275,18 +1312,22 @@ impl StrongRuleNode {
for (id, declaration) in longhands {
if properties.contains(id) {
if !author_colors_allowed {
- if let PropertyDeclaration::BackgroundColor(ref color) = *declaration {
- return *color == Color::transparent()
+ if let PropertyDeclaration::BackgroundColor(ref color) =
+ *declaration
+ {
+ return *color == Color::transparent();
}
}
- return true
+ return true;
}
}
- }
+ },
}
}
- if !have_explicit_ua_inherit { break }
+ if !have_explicit_ua_inherit {
+ break;
+ }
// Continue to the parent element and search for the inherited properties.
if let Some(pseudo) = pseudo.take() {
@@ -1296,7 +1337,7 @@ impl StrongRuleNode {
} else {
element = match element.inheritance_parent() {
Some(parent) => parent,
- None => break
+ None => break,
};
let parent_data = element.mutate_data().unwrap();
@@ -1322,9 +1363,10 @@ impl StrongRuleNode {
///
/// If there are any custom properties, we set the boolean value of the
/// returned tuple to true.
- pub fn get_properties_overriding_animations(&self,
- guards: &StylesheetGuards)
- -> (LonghandIdSet, bool) {
+ pub fn get_properties_overriding_animations(
+ &self,
+ guards: &StylesheetGuards,
+ ) -> (LonghandIdSet, bool) {
use properties::PropertyDeclarationId;
// We want to iterate over cascade levels that override the animations
@@ -1335,15 +1377,16 @@ impl StrongRuleNode {
// transitions and animations are present for a given element and
// property, transitions are suppressed so that they don't actually
// override animations.
- let iter =
- self.self_and_ancestors()
- .skip_while(|node| node.cascade_level() == CascadeLevel::Transitions)
- .take_while(|node| node.cascade_level() > CascadeLevel::Animations);
+ let iter = self.self_and_ancestors()
+ .skip_while(|node| node.cascade_level() == CascadeLevel::Transitions)
+ .take_while(|node| node.cascade_level() > CascadeLevel::Animations);
let mut result = (LonghandIdSet::new(), false);
for node in iter {
let style = node.style_source();
- for (decl, important) in style.read(node.cascade_level().guard(guards))
- .declaration_importance_iter() {
+ for (decl, important) in style
+ .read(node.cascade_level().guard(guards))
+ .declaration_importance_iter()
+ {
// Although we are only iterating over cascade levels that
// override animations, in a given property declaration block we
// can have a mixture of !important and non-!important
@@ -1352,7 +1395,7 @@ impl StrongRuleNode {
if important.important() {
match decl.id() {
PropertyDeclarationId::Longhand(id) => result.0.insert(id),
- PropertyDeclarationId::Custom(_) => result.1 = true
+ PropertyDeclarationId::Custom(_) => result.1 = true,
}
}
}
@@ -1363,8 +1406,10 @@ impl StrongRuleNode {
/// Returns PropertyDeclarationBlock for this node.
/// This function must be called only for animation level node.
fn get_animation_style(&self) -> &Arc<Locked<PropertyDeclarationBlock>> {
- debug_assert!(self.cascade_level().is_animation(),
- "The cascade level should be an animation level");
+ debug_assert!(
+ self.cascade_level().is_animation(),
+ "The cascade level should be an animation level"
+ );
match *self.style_source() {
StyleSource::Declarations(ref block) => block,
StyleSource::Style(_) => unreachable!("animating style should not be a style rule"),
@@ -1405,7 +1450,11 @@ impl<'a> Iterator for SelfAndAncestors<'a> {
impl Clone for StrongRuleNode {
fn clone(&self) -> Self {
- debug!("{:?}: {:?}+", self.ptr(), self.get().refcount.load(Ordering::Relaxed));
+ debug!(
+ "{:?}: {:?}+",
+ self.ptr(),
+ self.get().refcount.load(Ordering::Relaxed)
+ );
debug_assert!(self.get().refcount.load(Ordering::Relaxed) > 0);
self.get().refcount.fetch_add(1, Ordering::Relaxed);
StrongRuleNode::from_ptr(self.ptr())
@@ -1416,22 +1465,27 @@ impl Drop for StrongRuleNode {
fn drop(&mut self) {
let node = unsafe { &*self.ptr() };
- debug!("{:?}: {:?}-", self.ptr(), node.refcount.load(Ordering::Relaxed));
- debug!("Dropping node: {:?}, root: {:?}, parent: {:?}",
- self.ptr(),
- node.root.as_ref().map(|r| r.ptr()),
- node.parent.as_ref().map(|p| p.ptr()));
+ debug!(
+ "{:?}: {:?}-",
+ self.ptr(),
+ node.refcount.load(Ordering::Relaxed)
+ );
+ debug!(
+ "Dropping node: {:?}, root: {:?}, parent: {:?}",
+ self.ptr(),
+ node.root.as_ref().map(|r| r.ptr()),
+ node.parent.as_ref().map(|p| p.ptr())
+ );
let should_drop = {
debug_assert!(node.refcount.load(Ordering::Relaxed) > 0);
node.refcount.fetch_sub(1, Ordering::Relaxed) == 1
};
if !should_drop {
- return
+ return;
}
- debug_assert_eq!(node.first_child.load(Ordering::Acquire),
- ptr::null_mut());
+ debug_assert_eq!(node.first_child.load(Ordering::Acquire), ptr::null_mut());
if node.parent.is_none() {
debug!("Dropping root node!");
// The free list should be null by this point
@@ -1456,9 +1510,10 @@ impl Drop for StrongRuleNode {
//
// [1] https://bugzilla.mozilla.org/show_bug.cgi?id=439184
if old_head.is_null() {
- debug_assert!(!thread_state::get().is_worker() &&
- (thread_state::get().is_layout() ||
- thread_state::get().is_script()));
+ debug_assert!(
+ !thread_state::get().is_worker() &&
+ (thread_state::get().is_layout() || thread_state::get().is_script())
+ );
// Add the node as the sole entry in the free list.
debug_assert!(node.next_free.load(Ordering::Relaxed).is_null());
node.next_free.store(FREE_LIST_SENTINEL, Ordering::Relaxed);
@@ -1472,12 +1527,13 @@ impl Drop for StrongRuleNode {
// enforced by having the gc() method live on StrongRuleNode rather than
// RuleNode.
let strong_root: StrongRuleNode = node.root.as_ref().unwrap().upgrade();
- unsafe { strong_root.gc(); }
+ unsafe {
+ strong_root.gc();
+ }
// Leave the free list null, like we found it, such that additional
// drops for straggling rule nodes will take this same codepath.
- debug_assert_eq!(root.next_free.load(Ordering::Relaxed),
- FREE_LIST_SENTINEL);
+ debug_assert_eq!(root.next_free.load(Ordering::Relaxed), FREE_LIST_SENTINEL);
root.next_free.store(ptr::null_mut(), Ordering::Relaxed);
// Return. If strong_root is the last strong reference to the root,
@@ -1500,10 +1556,12 @@ impl Drop for StrongRuleNode {
// reads/writes we do below are properly visible from multiple threads
// racing.
loop {
- match free_list.compare_exchange_weak(old_head,
- FREE_LIST_LOCKED,
- Ordering::Acquire,
- Ordering::Relaxed) {
+ match free_list.compare_exchange_weak(
+ old_head,
+ FREE_LIST_LOCKED,
+ Ordering::Acquire,
+ Ordering::Relaxed,
+ ) {
Ok(..) => {
if old_head != FREE_LIST_LOCKED {
break;
@@ -1533,7 +1591,8 @@ impl Drop for StrongRuleNode {
// Increment the free count. This doesn't need to be an RMU atomic
// operation, because the free list is "locked".
let old_free_count = root.free_count().load(Ordering::Relaxed);
- root.free_count().store(old_free_count + 1, Ordering::Relaxed);
+ root.free_count()
+ .store(old_free_count + 1, Ordering::Relaxed);
// This can be release because of the locking of the free list, that
// ensures that all the other nodes racing with this one are using
@@ -1559,7 +1618,7 @@ impl WeakRuleNode {
fn from_ptr(ptr: *mut RuleNode) -> Self {
WeakRuleNode {
- p: NonZeroPtrMut::new(ptr)
+ p: NonZeroPtrMut::new(ptr),
}
}