servo: Merge #17504 - Make EagerPseudoStyles use an Arc, not a Box (from bholley:arc_pseudos); r=bholley

Reviewed in https://bugzilla.mozilla.org/show_bug.cgi?id=1371049

Fixes #17300

Source-Repo: https://github.com/servo/servo
Source-Revision: a29261dec196ab5c887655e479e503ca6cbb9229

--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 5afe2398f112e628ae4f4ddc0452c9700ea90b3b
This commit is contained in:
Bobby Holley 2017-06-23 20:07:45 -07:00
Родитель 513195535b
Коммит f47e6c9832
2 изменённых файлов: 48 добавлений и 18 удалений

Просмотреть файл

@ -332,7 +332,7 @@ impl Clone for EagerPseudoCascadeInputs {
impl EagerPseudoCascadeInputs {
/// Construct inputs from previous cascade results, if any.
fn new_from_style(styles: &EagerPseudoStyles) -> Self {
EagerPseudoCascadeInputs(styles.0.as_ref().map(|styles| {
EagerPseudoCascadeInputs(styles.as_array().map(|styles| {
let mut inputs: [Option<CascadeInputs>; EAGER_PSEUDO_COUNT] = Default::default();
for i in 0..EAGER_PSEUDO_COUNT {
inputs[i] = styles[i].as_ref().map(|s| CascadeInputs::new_from_style(s));

Просмотреть файл

@ -13,6 +13,7 @@ use properties::longhands::display::computed_value as display;
use rule_tree::StrongRuleNode;
use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage};
use shared_lock::{Locked, StylesheetGuards};
use std::ops::{Deref, DerefMut};
use stylearc::Arc;
bitflags! {
@ -98,24 +99,41 @@ impl RestyleData {
}
}
/// A list of styles for eagerly-cascaded pseudo-elements.
/// Lazily-allocated.
#[derive(Debug)]
pub struct EagerPseudoStyles(pub Option<Box<[Option<Arc<ComputedValues>>; EAGER_PSEUDO_COUNT]>>);
/// A lazily-allocated list of styles for eagerly-cascaded pseudo-elements.
///
/// We use an Arc so that sharing these styles via the style sharing cache does
/// not require duplicate allocations. We leverage the copy-on-write semantics of
/// Arc::make_mut(), which is free (i.e. does not require atomic RMU operations)
/// in servo_arc.
#[derive(Clone, Debug)]
pub struct EagerPseudoStyles(Option<Arc<EagerPseudoArray>>);
#[derive(Debug, Default)]
struct EagerPseudoArray(EagerPseudoArrayInner);
type EagerPseudoArrayInner = [Option<Arc<ComputedValues>>; EAGER_PSEUDO_COUNT];
impl Deref for EagerPseudoArray {
type Target = EagerPseudoArrayInner;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for EagerPseudoArray {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
// Manually implement `Clone` here because the derived impl of `Clone` for
// array types assumes the value inside is `Copy`.
impl Clone for EagerPseudoStyles {
impl Clone for EagerPseudoArray {
fn clone(&self) -> Self {
if self.0.is_none() {
return EagerPseudoStyles(None)
}
let self_values = self.0.as_ref().unwrap();
let mut values: [Option<Arc<ComputedValues>>; EAGER_PSEUDO_COUNT] = Default::default();
let mut clone = Self::default();
for i in 0..EAGER_PSEUDO_COUNT {
values[i] = self_values[i].clone();
clone[i] = self.0[i].clone();
}
EagerPseudoStyles(Some(Box::new(values)))
clone
}
}
@ -125,6 +143,14 @@ impl EagerPseudoStyles {
self.0.is_none()
}
/// Grabs a reference to the list of styles, if they exist.
pub fn as_array(&self) -> Option<&EagerPseudoArrayInner> {
match self.0 {
None => None,
Some(ref x) => Some(&x.0),
}
}
/// Returns a reference to the style for a given eager pseudo, if it exists.
pub fn get(&self, pseudo: &PseudoElement) -> Option<&Arc<ComputedValues>> {
debug_assert!(pseudo.is_eager());
@ -134,7 +160,10 @@ impl EagerPseudoStyles {
/// Returns a mutable reference to the style for a given eager pseudo, if it exists.
pub fn get_mut(&mut self, pseudo: &PseudoElement) -> Option<&mut Arc<ComputedValues>> {
debug_assert!(pseudo.is_eager());
self.0.as_mut().and_then(|p| p[pseudo.eager_index()].as_mut())
match self.0 {
None => return None,
Some(ref mut arc) => Arc::make_mut(arc)[pseudo.eager_index()].as_mut(),
}
}
/// Returns true if the EagerPseudoStyles has the style for |pseudo|.
@ -145,9 +174,10 @@ impl EagerPseudoStyles {
/// Sets the style for the eager pseudo.
pub fn set(&mut self, pseudo: &PseudoElement, value: Arc<ComputedValues>) {
if self.0.is_none() {
self.0 = Some(Box::new(Default::default()));
self.0 = Some(Arc::new(Default::default()));
}
self.0.as_mut().unwrap()[pseudo.eager_index()] = Some(value);
let arr = Arc::make_mut(self.0.as_mut().unwrap());
arr[pseudo.eager_index()] = Some(value);
}
/// Inserts a pseudo-element. The pseudo-element must not already exist.
@ -158,9 +188,9 @@ impl EagerPseudoStyles {
/// Removes a pseudo-element style if it exists, and returns it.
pub fn take(&mut self, pseudo: &PseudoElement) -> Option<Arc<ComputedValues>> {
let result = match self.0.as_mut() {
let result = match self.0 {
None => return None,
Some(arr) => arr[pseudo.eager_index()].take(),
Some(ref mut arc) => Arc::make_mut(arc)[pseudo.eager_index()].take(),
};
let empty = self.0.as_ref().unwrap().iter().all(|x| x.is_none());
if empty {