mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
style: Don't assume siblings are alive in the rule tree when removing ourselves from the child list.
We can't assume all our siblings are alive because they may very well be in the free list too. This tempts to happen when the rule nodes are destroyed as part of the last GC, the one that runs in the root destructor. Also, properly put the next sibling back into the list when the rules are GCd.
This commit is contained in:
parent
164e956944
commit
65f239c9e1
1 changed files with 15 additions and 10 deletions
|
@ -200,21 +200,26 @@ impl RuleNode {
|
||||||
unsafe fn remove_from_child_list(&self) {
|
unsafe fn remove_from_child_list(&self) {
|
||||||
debug!("Remove from child list: {:?}, parent: {:?}",
|
debug!("Remove from child list: {:?}, parent: {:?}",
|
||||||
self as *const RuleNode, self.parent.as_ref().map(|p| p.ptr()));
|
self as *const RuleNode, self.parent.as_ref().map(|p| p.ptr()));
|
||||||
let prev_sibling = self.prev_sibling.swap(ptr::null_mut(), Ordering::SeqCst);
|
// NB: The other siblings we use in this function can also be dead, so
|
||||||
let next_sibling = self.next_sibling.swap(ptr::null_mut(), Ordering::SeqCst);
|
// 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);
|
||||||
|
|
||||||
if prev_sibling != ptr::null_mut() {
|
// Store the `next` pointer as appropriate, either in the previous
|
||||||
let really_previous = WeakRuleNode { ptr: prev_sibling };
|
// sibling, or in the parent otherwise.
|
||||||
really_previous.upgrade()
|
if prev_sibling == ptr::null_mut() {
|
||||||
.get().next_sibling.store(next_sibling, Ordering::SeqCst);
|
let parent = self.parent.as_ref().unwrap();
|
||||||
|
parent.get().first_child.store(next_sibling, Ordering::Relaxed);
|
||||||
} else {
|
} else {
|
||||||
self.parent.as_ref().unwrap()
|
let previous = &*prev_sibling;
|
||||||
.get().first_child.store(ptr::null_mut(), Ordering::SeqCst);
|
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() {
|
if next_sibling != ptr::null_mut() {
|
||||||
let really_next = WeakRuleNode { ptr: next_sibling };
|
let next = &*next_sibling;
|
||||||
really_next.upgrade().get().prev_sibling.store(prev_sibling, Ordering::SeqCst);
|
next.prev_sibling.store(prev_sibling, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue