mirror of
https://github.com/servo/servo.git
synced 2025-08-04 13:10:20 +01:00
Use NonZeroPtrMut for {Strong,Weak}RuleNode.
MozReview-Commit-ID: Da4Ds7SIcCD
This commit is contained in:
parent
eee07be227
commit
b3a61b7a1c
2 changed files with 37 additions and 39 deletions
|
@ -14,7 +14,7 @@ use smallvec::SmallVec;
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
|
||||||
use stylearc::Arc;
|
use stylearc::{Arc, NonZeroPtrMut};
|
||||||
use stylesheets::StyleRule;
|
use stylesheets::StyleRule;
|
||||||
use stylist::ApplicableDeclarationList;
|
use stylist::ApplicableDeclarationList;
|
||||||
use thread_state;
|
use thread_state;
|
||||||
|
@ -637,7 +637,7 @@ impl RuleNode {
|
||||||
current: if first_child.is_null() {
|
current: if first_child.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(WeakRuleNode { ptr: first_child })
|
Some(WeakRuleNode::from_ptr(first_child))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -645,15 +645,13 @@ impl RuleNode {
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct WeakRuleNode {
|
struct WeakRuleNode {
|
||||||
ptr: *mut RuleNode,
|
p: NonZeroPtrMut<RuleNode>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A strong reference to a rule node.
|
/// A strong reference to a rule node.
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub struct StrongRuleNode {
|
pub struct StrongRuleNode {
|
||||||
// TODO: Mark this as NonZero once stable to save space inside Option.
|
p: NonZeroPtrMut<RuleNode>,
|
||||||
// https://github.com/rust-lang/rust/issues/27730
|
|
||||||
ptr: *mut RuleNode,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "servo")]
|
#[cfg(feature = "servo")]
|
||||||
|
@ -670,15 +668,17 @@ impl StrongRuleNode {
|
||||||
|
|
||||||
debug!("Creating rule node: {:p}", ptr);
|
debug!("Creating rule node: {:p}", ptr);
|
||||||
|
|
||||||
|
StrongRuleNode::from_ptr(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_ptr(ptr: *mut RuleNode) -> Self {
|
||||||
StrongRuleNode {
|
StrongRuleNode {
|
||||||
ptr: ptr,
|
p: NonZeroPtrMut::new(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn downgrade(&self) -> WeakRuleNode {
|
fn downgrade(&self) -> WeakRuleNode {
|
||||||
WeakRuleNode {
|
WeakRuleNode::from_ptr(self.ptr())
|
||||||
ptr: self.ptr,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_sibling(&self) -> Option<WeakRuleNode> {
|
fn next_sibling(&self) -> Option<WeakRuleNode> {
|
||||||
|
@ -688,9 +688,7 @@ impl StrongRuleNode {
|
||||||
if ptr.is_null() {
|
if ptr.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(WeakRuleNode {
|
Some(WeakRuleNode::from_ptr(ptr))
|
||||||
ptr: ptr
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -748,7 +746,7 @@ impl StrongRuleNode {
|
||||||
|
|
||||||
// Existing is not null: some thread inserted a child node since
|
// Existing is not null: some thread inserted a child node since
|
||||||
// we accessed `last`.
|
// we accessed `last`.
|
||||||
strong = WeakRuleNode { ptr: existing }.upgrade();
|
strong = WeakRuleNode::from_ptr(existing).upgrade();
|
||||||
|
|
||||||
if strong.get().source.as_ref().unwrap().ptr_equals(&source) {
|
if strong.get().source.as_ref().unwrap().ptr_equals(&source) {
|
||||||
// That node happens to be for the same style source, use
|
// That node happens to be for the same style source, use
|
||||||
|
@ -764,15 +762,15 @@ impl StrongRuleNode {
|
||||||
|
|
||||||
/// Raw pointer to the RuleNode
|
/// Raw pointer to the RuleNode
|
||||||
pub fn ptr(&self) -> *mut RuleNode {
|
pub fn ptr(&self) -> *mut RuleNode {
|
||||||
self.ptr
|
self.p.ptr()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get(&self) -> &RuleNode {
|
fn get(&self) -> &RuleNode {
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
let node = unsafe { &*self.ptr };
|
let node = unsafe { &*self.ptr() };
|
||||||
assert!(node.refcount.load(Ordering::Relaxed) > 0);
|
assert!(node.refcount.load(Ordering::Relaxed) > 0);
|
||||||
}
|
}
|
||||||
unsafe { &*self.ptr }
|
unsafe { &*self.ptr() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the style source corresponding to this rule node. May return `None`
|
/// Get the style source corresponding to this rule node. May return `None`
|
||||||
|
@ -808,7 +806,7 @@ impl StrongRuleNode {
|
||||||
unsafe fn pop_from_free_list(&self) -> Option<WeakRuleNode> {
|
unsafe fn pop_from_free_list(&self) -> Option<WeakRuleNode> {
|
||||||
// NB: This can run from the root node destructor, so we can't use
|
// NB: This can run from the root node destructor, so we can't use
|
||||||
// `get()`, since it asserts the refcount is bigger than zero.
|
// `get()`, since it asserts the refcount is bigger than zero.
|
||||||
let me = &*self.ptr;
|
let me = &*self.ptr();
|
||||||
|
|
||||||
debug_assert!(me.is_root());
|
debug_assert!(me.is_root());
|
||||||
|
|
||||||
|
@ -831,7 +829,7 @@ impl StrongRuleNode {
|
||||||
debug_assert!(!current.is_null(),
|
debug_assert!(!current.is_null(),
|
||||||
"Multiple threads are operating on the free list at the \
|
"Multiple threads are operating on the free list at the \
|
||||||
same time?");
|
same time?");
|
||||||
debug_assert!(current != self.ptr,
|
debug_assert!(current != self.ptr(),
|
||||||
"How did the root end up in the free list?");
|
"How did the root end up in the free list?");
|
||||||
|
|
||||||
let next = (*current).next_free.swap(ptr::null_mut(), Ordering::Relaxed);
|
let next = (*current).next_free.swap(ptr::null_mut(), Ordering::Relaxed);
|
||||||
|
@ -843,17 +841,17 @@ impl StrongRuleNode {
|
||||||
|
|
||||||
debug!("Popping from free list: cur: {:?}, next: {:?}", current, next);
|
debug!("Popping from free list: cur: {:?}, next: {:?}", current, next);
|
||||||
|
|
||||||
Some(WeakRuleNode { ptr: current })
|
Some(WeakRuleNode::from_ptr(current))
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn assert_free_list_has_no_duplicates_or_null(&self) {
|
unsafe fn assert_free_list_has_no_duplicates_or_null(&self) {
|
||||||
assert!(cfg!(debug_assertions), "This is an expensive check!");
|
assert!(cfg!(debug_assertions), "This is an expensive check!");
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
let me = &*self.ptr;
|
let me = &*self.ptr();
|
||||||
assert!(me.is_root());
|
assert!(me.is_root());
|
||||||
|
|
||||||
let mut current = self.ptr;
|
let mut current = self.ptr();
|
||||||
let mut seen = HashSet::new();
|
let mut seen = HashSet::new();
|
||||||
while current != FREE_LIST_SENTINEL {
|
while current != FREE_LIST_SENTINEL {
|
||||||
let next = (*current).next_free.load(Ordering::Relaxed);
|
let next = (*current).next_free.load(Ordering::Relaxed);
|
||||||
|
@ -872,7 +870,7 @@ impl StrongRuleNode {
|
||||||
|
|
||||||
// NB: This can run from the root node destructor, so we can't use
|
// NB: This can run from the root node destructor, so we can't use
|
||||||
// `get()`, since it asserts the refcount is bigger than zero.
|
// `get()`, since it asserts the refcount is bigger than zero.
|
||||||
let me = &*self.ptr;
|
let me = &*self.ptr();
|
||||||
|
|
||||||
debug_assert!(me.is_root(), "Can't call GC on a non-root node!");
|
debug_assert!(me.is_root(), "Can't call GC on a non-root node!");
|
||||||
|
|
||||||
|
@ -1237,19 +1235,17 @@ impl Clone for StrongRuleNode {
|
||||||
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);
|
debug_assert!(self.get().refcount.load(Ordering::Relaxed) > 0);
|
||||||
self.get().refcount.fetch_add(1, Ordering::Relaxed);
|
self.get().refcount.fetch_add(1, Ordering::Relaxed);
|
||||||
StrongRuleNode {
|
StrongRuleNode::from_ptr(self.ptr())
|
||||||
ptr: self.ptr,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for StrongRuleNode {
|
impl Drop for StrongRuleNode {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let node = unsafe { &*self.ptr };
|
let node = unsafe { &*self.ptr() };
|
||||||
|
|
||||||
debug!("{:?}: {:?}-", self.ptr(), node.refcount.load(Ordering::Relaxed));
|
debug!("{:?}: {:?}-", self.ptr(), node.refcount.load(Ordering::Relaxed));
|
||||||
debug!("Dropping node: {:?}, root: {:?}, parent: {:?}",
|
debug!("Dropping node: {:?}, root: {:?}, parent: {:?}",
|
||||||
self.ptr,
|
self.ptr(),
|
||||||
node.root.as_ref().map(|r| r.ptr()),
|
node.root.as_ref().map(|r| r.ptr()),
|
||||||
node.parent.as_ref().map(|p| p.ptr()));
|
node.parent.as_ref().map(|p| p.ptr()));
|
||||||
let should_drop = {
|
let should_drop = {
|
||||||
|
@ -1330,9 +1326,7 @@ impl Drop for StrongRuleNode {
|
||||||
|
|
||||||
impl<'a> From<&'a StrongRuleNode> for WeakRuleNode {
|
impl<'a> From<&'a StrongRuleNode> for WeakRuleNode {
|
||||||
fn from(node: &'a StrongRuleNode) -> Self {
|
fn from(node: &'a StrongRuleNode) -> Self {
|
||||||
WeakRuleNode {
|
WeakRuleNode::from_ptr(node.ptr())
|
||||||
ptr: node.ptr(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1340,15 +1334,19 @@ impl WeakRuleNode {
|
||||||
fn upgrade(&self) -> StrongRuleNode {
|
fn upgrade(&self) -> StrongRuleNode {
|
||||||
debug!("Upgrading weak node: {:p}", self.ptr());
|
debug!("Upgrading weak node: {:p}", self.ptr());
|
||||||
|
|
||||||
let node = unsafe { &*self.ptr };
|
let node = unsafe { &*self.ptr() };
|
||||||
node.refcount.fetch_add(1, Ordering::Relaxed);
|
node.refcount.fetch_add(1, Ordering::Relaxed);
|
||||||
StrongRuleNode {
|
StrongRuleNode::from_ptr(self.ptr())
|
||||||
ptr: self.ptr,
|
}
|
||||||
|
|
||||||
|
fn from_ptr(ptr: *mut RuleNode) -> Self {
|
||||||
|
WeakRuleNode {
|
||||||
|
p: NonZeroPtrMut::new(ptr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ptr(&self) -> *mut RuleNode {
|
fn ptr(&self) -> *mut RuleNode {
|
||||||
self.ptr
|
self.p.ptr()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,10 +29,10 @@ fn size_of_selectors_dummy_types() {
|
||||||
size_of_test!(test_size_of_rule, style::stylist::Rule, 40);
|
size_of_test!(test_size_of_rule, style::stylist::Rule, 40);
|
||||||
|
|
||||||
size_of_test!(test_size_of_option_arc_cv, Option<Arc<ComputedValues>>, 8);
|
size_of_test!(test_size_of_option_arc_cv, Option<Arc<ComputedValues>>, 8);
|
||||||
size_of_test!(test_size_of_option_rule_node, Option<StrongRuleNode>, 16);
|
size_of_test!(test_size_of_option_rule_node, Option<StrongRuleNode>, 8);
|
||||||
size_of_test!(test_size_of_computed_style, ComputedStyle, 40);
|
size_of_test!(test_size_of_computed_style, ComputedStyle, 32);
|
||||||
size_of_test!(test_size_of_element_styles, ElementStyles, 56);
|
size_of_test!(test_size_of_element_styles, ElementStyles, 48);
|
||||||
size_of_test!(test_size_of_element_data, ElementData, 72);
|
size_of_test!(test_size_of_element_data, ElementData, 56);
|
||||||
|
|
||||||
size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32);
|
size_of_test!(test_size_of_property_declaration, style::properties::PropertyDeclaration, 32);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue