aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Sapin <simon.sapin@exyr.org>2016-11-05 14:17:48 +0100
committerSimon Sapin <simon.sapin@exyr.org>2016-11-05 17:29:56 +0100
commit1a18161006c67424750943e1b29d3f3aead92d5e (patch)
treec056cc7600a828cf00340befce3157d470ae819f
parent2dd2c9cedde733f30042163c20e763b243567780 (diff)
downloadservo-1a18161006c67424750943e1b29d3f3aead92d5e.tar.gz
servo-1a18161006c67424750943e1b29d3f3aead92d5e.zip
rule tree: more descriptive field names
-rw-r--r--components/style/rule_tree/mod.rs178
1 files changed, 84 insertions, 94 deletions
diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs
index 1b32ab287e8..5534d76323a 100644
--- a/components/style/rule_tree/mod.rs
+++ b/components/style/rule_tree/mod.rs
@@ -120,6 +120,7 @@ impl RuleTree {
current
}
+ /// This can only be called when no other threads is accessing this tree.
pub unsafe fn gc(&self) {
self.root.gc();
}
@@ -140,10 +141,10 @@ struct RuleNode {
/// meaningless in the root node.
importance: Importance,
- children: RuleChildrenList,
refcount: AtomicUsize,
- next: AtomicPtr<RuleNode>,
- prev: AtomicPtr<RuleNode>,
+ first_child: AtomicPtr<RuleNode>,
+ next_sibling: AtomicPtr<RuleNode>,
+ prev_sibling: AtomicPtr<RuleNode>,
/// The next item in the rule tree free list, that starts on the root node.
next_free: AtomicPtr<RuleNode>,
@@ -163,10 +164,10 @@ impl RuleNode {
parent: Some(parent),
source: Some(source),
importance: importance,
- children: RuleChildrenList::new(),
refcount: AtomicUsize::new(1),
- next: AtomicPtr::new(ptr::null_mut()),
- prev: AtomicPtr::new(ptr::null_mut()),
+ first_child: AtomicPtr::new(ptr::null_mut()),
+ next_sibling: AtomicPtr::new(ptr::null_mut()),
+ prev_sibling: AtomicPtr::new(ptr::null_mut()),
next_free: AtomicPtr::new(ptr::null_mut()),
}
}
@@ -177,10 +178,10 @@ impl RuleNode {
parent: None,
source: None,
importance: Importance::Normal,
- children: RuleChildrenList::new(),
refcount: AtomicUsize::new(1),
- next: AtomicPtr::new(ptr::null_mut()),
- prev: AtomicPtr::new(ptr::null_mut()),
+ first_child: AtomicPtr::new(ptr::null_mut()),
+ next_sibling: AtomicPtr::new(ptr::null_mut()),
+ prev_sibling: AtomicPtr::new(ptr::null_mut()),
next_free: AtomicPtr::new(FREE_LIST_SENTINEL),
}
}
@@ -199,21 +200,21 @@ impl RuleNode {
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()));
- let previous = self.prev.swap(ptr::null_mut(), Ordering::SeqCst);
- let next = self.next.swap(ptr::null_mut(), Ordering::SeqCst);
+ let prev_sibling = self.prev_sibling.swap(ptr::null_mut(), Ordering::SeqCst);
+ let next_sibling = self.next_sibling.swap(ptr::null_mut(), Ordering::SeqCst);
- if previous != ptr::null_mut() {
- let really_previous = WeakRuleNode { ptr: previous };
+ if prev_sibling != ptr::null_mut() {
+ let really_previous = WeakRuleNode { ptr: prev_sibling };
really_previous.upgrade()
- .get().next.store(next, Ordering::SeqCst);
+ .get().next_sibling.store(next_sibling, Ordering::SeqCst);
} else {
self.parent.as_ref().unwrap()
- .get().children.head.store(ptr::null_mut(), Ordering::SeqCst);
+ .get().first_child.store(ptr::null_mut(), Ordering::SeqCst);
}
- if next != ptr::null_mut() {
- let really_next = WeakRuleNode { ptr: next };
- really_next.upgrade().get().prev.store(previous, Ordering::SeqCst);
+ if next_sibling != ptr::null_mut() {
+ let really_next = WeakRuleNode { ptr: next_sibling };
+ really_next.upgrade().get().prev_sibling.store(prev_sibling, Ordering::SeqCst);
}
}
@@ -245,10 +246,22 @@ impl RuleNode {
}
let _ = write!(writer, "\n");
- for child in self.children.iter() {
+ for child in self.iter_children() {
child.get().dump(writer, indent + INDENT_INCREMENT);
}
}
+
+ fn iter_children(&self) -> RuleChildrenListIter {
+ // FIXME(emilio): Fiddle with memory orderings.
+ let first_child = self.first_child.load(Ordering::SeqCst);
+ RuleChildrenListIter {
+ current: if first_child.is_null() {
+ None
+ } else {
+ Some(WeakRuleNode { ptr: first_child })
+ }
+ }
+ }
}
#[derive(Clone)]
@@ -286,10 +299,10 @@ impl StrongRuleNode {
}
}
- fn next(&self) -> Option<WeakRuleNode> {
+ fn next_sibling(&self) -> Option<WeakRuleNode> {
// FIXME(emilio): Investigate what ordering can we achieve without
// messing things up.
- let ptr = self.get().next.load(Ordering::SeqCst);
+ let ptr = self.get().next_sibling.load(Ordering::SeqCst);
if ptr.is_null() {
None
} else {
@@ -308,7 +321,7 @@ impl StrongRuleNode {
source: StyleSource,
importance: Importance) -> StrongRuleNode {
let mut last = None;
- for child in self.get().children.iter() {
+ for child in self.get().iter_children() {
if child .get().importance == importance &&
child.get().source.as_ref().unwrap().ptr_equals(&source) {
return child;
@@ -316,25 +329,25 @@ impl StrongRuleNode {
last = Some(child);
}
- let node = Box::new(RuleNode::new(root,
- self.clone(),
- source.clone(),
- importance));
- let new_ptr = &*node as *const _ as *mut RuleNode;
+ let mut node = Box::new(RuleNode::new(root,
+ self.clone(),
+ source.clone(),
+ importance));
+ let new_ptr: *mut RuleNode = &mut *node;
loop {
let strong;
{
- let next_ptr = match last {
- Some(ref l) => &l.get().next,
- None => &self.get().children.head,
+ let next_sibling_ptr = match last {
+ Some(ref l) => &l.get().next_sibling,
+ None => &self.get().first_child,
};
let existing =
- next_ptr.compare_and_swap(ptr::null_mut(),
- new_ptr,
- Ordering::SeqCst);
+ next_sibling_ptr.compare_and_swap(ptr::null_mut(),
+ new_ptr,
+ Ordering::SeqCst);
if existing == ptr::null_mut() {
// Now we know we're in the correct position in the child list,
@@ -342,21 +355,22 @@ impl StrongRuleNode {
// accessed again in a single-threaded manner when we're
// sweeping possibly dead nodes.
if let Some(ref l) = last {
- node.prev.store(l.ptr(), Ordering::Relaxed);
+ node.prev_sibling.store(l.ptr(), Ordering::Relaxed);
}
return StrongRuleNode::new(node);
}
+ // Existing is not null: some thread insert a child node since we accessed `last`.
strong = WeakRuleNode { ptr: existing }.upgrade();
if strong.get().source.as_ref().unwrap().ptr_equals(&source) {
- // Some thread that was racing with as inserted the same rule
- // node than us, so give up and just use that.
+ // That node happens to be for the same style source, use that.
return strong;
}
}
+ // Try again inserting after the new last child.
last = Some(strong);
}
}
@@ -479,40 +493,42 @@ impl Drop for StrongRuleNode {
node.refcount.fetch_sub(1, Ordering::SeqCst) == 1
};
- if should_drop {
- debug_assert_eq!(node.children.head.load(Ordering::SeqCst),
- ptr::null_mut());
- if node.parent.is_none() {
- debug!("Dropping root node!");
- // NOTE: Calling this is fine, because the rule tree root
- // destructor needs to happen from the layout thread, where the
- // stylist, and hence, the rule tree, is held.
- unsafe { self.gc() };
- let _ = unsafe { Box::from_raw(self.ptr()) };
- return;
- }
-
- // The node is already in the free list, so do nothing.
- if node.next_free.load(Ordering::SeqCst) != ptr::null_mut() {
- return;
- }
+ if !should_drop {
+ return
+ }
- let free_list =
- &unsafe { &*node.root.as_ref().unwrap().ptr() }.next_free;
- loop {
- let next_free = free_list.load(Ordering::SeqCst);
- debug_assert!(!next_free.is_null());
+ debug_assert_eq!(node.first_child.load(Ordering::SeqCst),
+ ptr::null_mut());
+ if node.parent.is_none() {
+ debug!("Dropping root node!");
+ // NOTE: Calling this is fine, because the rule tree root
+ // destructor needs to happen from the layout thread, where the
+ // stylist, and hence, the rule tree, is held.
+ unsafe { self.gc() };
+ let _ = unsafe { Box::from_raw(self.ptr()) };
+ return;
+ }
- node.next_free.store(next_free, Ordering::SeqCst);
+ // The node is already in the free list, so do nothing.
+ if node.next_free.load(Ordering::SeqCst) != ptr::null_mut() {
+ return;
+ }
- let existing =
- free_list.compare_and_swap(next_free,
- self.ptr(),
- Ordering::SeqCst);
- if existing == next_free {
- // Successfully inserted, yay! Otherwise try again.
- break;
- }
+ let free_list =
+ &unsafe { &*node.root.as_ref().unwrap().ptr() }.next_free;
+ loop {
+ let next_free = free_list.load(Ordering::SeqCst);
+ debug_assert!(!next_free.is_null());
+
+ node.next_free.store(next_free, Ordering::SeqCst);
+
+ let existing =
+ free_list.compare_and_swap(next_free,
+ self.ptr(),
+ Ordering::SeqCst);
+ if existing == next_free {
+ // Successfully inserted, yay! Otherwise try again.
+ break;
}
}
}
@@ -542,32 +558,6 @@ impl WeakRuleNode {
}
}
-struct RuleChildrenList {
- head: AtomicPtr<RuleNode>,
-}
-
-impl RuleChildrenList {
- fn new() -> Self {
- RuleChildrenList {
- head: AtomicPtr::new(ptr::null_mut())
- }
- }
-
- fn iter(&self) -> RuleChildrenListIter {
- // FIXME(emilio): Fiddle with memory orderings.
- let head = self.head.load(Ordering::SeqCst);
- RuleChildrenListIter {
- current: if head.is_null() {
- None
- } else {
- Some(WeakRuleNode {
- ptr: head,
- })
- },
- }
- }
-}
-
struct RuleChildrenListIter {
current: Option<WeakRuleNode>,
}
@@ -578,7 +568,7 @@ impl Iterator for RuleChildrenListIter {
fn next(&mut self) -> Option<Self::Item> {
self.current.take().map(|current| {
let current = current.upgrade();
- self.current = current.next();
+ self.current = current.next_sibling();
current
})
}