aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/rule_tree/mod.rs27
1 files changed, 16 insertions, 11 deletions
diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs
index 5534d76323a..f1574ea5856 100644
--- a/components/style/rule_tree/mod.rs
+++ b/components/style/rule_tree/mod.rs
@@ -200,21 +200,26 @@ 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 prev_sibling = self.prev_sibling.swap(ptr::null_mut(), Ordering::SeqCst);
- let next_sibling = self.next_sibling.swap(ptr::null_mut(), Ordering::SeqCst);
-
- if prev_sibling != ptr::null_mut() {
- let really_previous = WeakRuleNode { ptr: prev_sibling };
- really_previous.upgrade()
- .get().next_sibling.store(next_sibling, Ordering::SeqCst);
+ // 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 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 == ptr::null_mut() {
+ let parent = self.parent.as_ref().unwrap();
+ parent.get().first_child.store(next_sibling, Ordering::Relaxed);
} else {
- self.parent.as_ref().unwrap()
- .get().first_child.store(ptr::null_mut(), Ordering::SeqCst);
+ let previous = &*prev_sibling;
+ previous.next_sibling.store(next_sibling, Ordering::Relaxed);
}
+ // Store the previous sibling pointer in the next sibling if present,
+ // otherwise we're done.
if next_sibling != ptr::null_mut() {
- let really_next = WeakRuleNode { ptr: next_sibling };
- really_next.upgrade().get().prev_sibling.store(prev_sibling, Ordering::SeqCst);
+ let next = &*next_sibling;
+ next.prev_sibling.store(prev_sibling, Ordering::Relaxed);
}
}