Skip to content

Commit

Permalink
Use Arc<PropertyDeclarationBlock> everwhere it’s appropriate.
Browse files Browse the repository at this point in the history
  • Loading branch information
SimonSapin committed Aug 31, 2016
1 parent c50e6ad commit acc38aa
Show file tree
Hide file tree
Showing 13 changed files with 85 additions and 68 deletions.
3 changes: 2 additions & 1 deletion components/script/dom/cssstyledeclaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use dom::node::{Node, NodeDamage, window_from_node};
use dom::window::Window;
use std::ascii::AsciiExt;
use std::slice;
use std::sync::Arc;
use string_cache::Atom;
use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand, Importance};
Expand Down Expand Up @@ -367,7 +368,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
*element.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() {
None // Step 2
} else {
Some(decl_block)
Some(Arc::new(decl_block))
};
element.sync_property_with_attrs_style();
let node = element.upcast::<Node>();
Expand Down
27 changes: 18 additions & 9 deletions components/script/dom/element.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub struct Element {
prefix: Option<DOMString>,
attrs: DOMRefCell<Vec<JS<Attr>>>,
id_attribute: DOMRefCell<Option<Atom>>,
style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>,
style_attribute: DOMRefCell<Option<Arc<PropertyDeclarationBlock>>>,
attr_list: MutNullableHeap<JS<NamedNodeMap>>,
class_list: MutNullableHeap<JS<DOMTokenList>>,
state: Cell<ElementState>,
Expand Down Expand Up @@ -297,7 +297,7 @@ pub trait LayoutElementHelpers {
#[allow(unsafe_code)]
unsafe fn html_element_in_html_document_for_layout(&self) -> bool;
fn id_attribute(&self) -> *const Option<Atom>;
fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock>;
fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>>;
fn local_name(&self) -> &Atom;
fn namespace(&self) -> &Namespace;
fn get_checked_state_for_layout(&self) -> bool;
Expand Down Expand Up @@ -329,7 +329,10 @@ impl LayoutElementHelpers for LayoutJS<Element> {
#[inline]
fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock {
DeclarationBlock::from_declarations(
Arc::new(vec![(rule, Importance::Normal)]),
Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(vec![(rule, Importance::Normal)]),
important_count: 0,
}),
Importance::Normal)
}

Expand Down Expand Up @@ -615,7 +618,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}

#[allow(unsafe_code)]
fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock> {
fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>> {
unsafe {
(*self.unsafe_get()).style_attribute.borrow_for_layout()
}
Expand Down Expand Up @@ -704,7 +707,7 @@ impl Element {
self.attrs.borrow()
}

pub fn style_attribute(&self) -> &DOMRefCell<Option<PropertyDeclarationBlock>> {
pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<PropertyDeclarationBlock>>> {
&self.style_attribute
}

Expand Down Expand Up @@ -774,6 +777,7 @@ impl Element {
matching
});
if let Some(index) = index {
let declarations = Arc::make_mut(declarations);
Arc::make_mut(&mut declarations.declarations).remove(index);
if importance.unwrap().important() {
declarations.important_count -= 1;
Expand All @@ -796,6 +800,7 @@ impl Element {
{
// Usually, the reference count will be 1 here. But transitions could make it greater
// than that.
let declaration_block = Arc::make_mut(declaration_block);
let existing_declarations = Arc::make_mut(&mut declaration_block.declarations);

'outer: for incoming_declaration in declarations {
Expand Down Expand Up @@ -829,10 +834,10 @@ impl Element {
0
};

*inline_declarations = Some(PropertyDeclarationBlock {
*inline_declarations = Some(Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(declarations.into_iter().map(|d| (d, importance)).collect()),
important_count: important_count,
});
}));
}

update(self, declarations, importance);
Expand All @@ -847,6 +852,7 @@ impl Element {
if let &mut Some(ref mut block) = &mut *inline_declarations {
// Usually, the reference counts of `from` and `to` will be 1 here. But transitions
// could make them greater than that.
let block = Arc::make_mut(block);
let declarations = Arc::make_mut(&mut block.declarations);
for &mut (ref declaration, ref mut importance) in declarations {
if properties.iter().any(|p| declaration.name() == **p) {
Expand Down Expand Up @@ -2102,8 +2108,11 @@ impl VirtualMethods for Element {
*self.style_attribute.borrow_mut() =
mutation.new_value(attr).map(|value| {
let win = window_from_node(self);
parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter(),
ParserContextExtraData::default())
Arc::new(parse_style_attribute(
&value,
&doc.base_url(),
win.css_error_reporter(),
ParserContextExtraData::default()))
});
if node.is_in_doc() {
node.dirty(NodeDamage::NodeStyleDamaged);
Expand Down
4 changes: 2 additions & 2 deletions components/script/layout_wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,9 +451,9 @@ impl<'le> TElement for ServoLayoutElement<'le> {
ServoLayoutNode::from_layout_js(self.element.upcast())
}

fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> {
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
unsafe {
&*self.element.style_attribute()
(*self.element.style_attribute()).as_ref()
}
}

Expand Down
2 changes: 1 addition & 1 deletion components/style/dom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre

fn as_node(&self) -> Self::ConcreteNode;

fn style_attribute(&self) -> &Option<PropertyDeclarationBlock>;
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>>;

fn get_state(&self) -> ElementState;

Expand Down
19 changes: 11 additions & 8 deletions components/style/keyframes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use cssparser::{DeclarationListParser, DeclarationParser};
use parser::{ParserContext, log_css_error};
use properties::PropertyDeclarationParseResult;
use properties::animated_properties::TransitionProperty;
use properties::{PropertyDeclaration, Importance};
use properties::{PropertyDeclaration, PropertyDeclarationBlock, Importance};
use std::sync::Arc;

/// A number from 1 to 100, indicating the percentage of the animation where
Expand Down Expand Up @@ -77,7 +77,7 @@ pub struct Keyframe {
/// so the second value of these tuples is always `Importance::Normal`.
/// But including them enables `compute_style_for_animation_step` to create a `DeclarationBlock`
/// by cloning an `Arc<_>` (incrementing a reference count) rather than re-creating a `Vec<_>`.
pub declarations: Arc<Vec<(PropertyDeclaration, Importance)>>,
pub block: Arc<PropertyDeclarationBlock>,
}

/// A keyframes step value. This can be a synthetised keyframes animation, that
Expand All @@ -88,7 +88,7 @@ pub struct Keyframe {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum KeyframesStepValue {
/// See `Keyframe::declarations`’s docs about the presence of `Importance`.
Declarations(Arc<Vec<(PropertyDeclaration, Importance)>>),
Declarations(Arc<PropertyDeclarationBlock>),
ComputedValues,
}

Expand All @@ -113,8 +113,8 @@ impl KeyframesStep {
fn new(percentage: KeyframePercentage,
value: KeyframesStepValue) -> Self {
let declared_timing_function = match value {
KeyframesStepValue::Declarations(ref declarations) => {
declarations.iter().any(|&(ref prop_decl, _)| {
KeyframesStepValue::Declarations(ref block) => {
block.declarations.iter().any(|&(ref prop_decl, _)| {
match *prop_decl {
PropertyDeclaration::AnimationTimingFunction(..) => true,
_ => false,
Expand Down Expand Up @@ -154,7 +154,7 @@ fn get_animated_properties(keyframe: &Keyframe) -> Vec<TransitionProperty> {
let mut ret = vec![];
// NB: declarations are already deduplicated, so we don't have to check for
// it here.
for &(ref declaration, _) in keyframe.declarations.iter() {
for &(ref declaration, _) in keyframe.block.declarations.iter() {
if let Some(property) = TransitionProperty::from_declaration(declaration) {
ret.push(property);
}
Expand All @@ -179,7 +179,7 @@ impl KeyframesAnimation {
for keyframe in keyframes {
for percentage in keyframe.selector.0.iter() {
steps.push(KeyframesStep::new(*percentage,
KeyframesStepValue::Declarations(keyframe.declarations.clone())));
KeyframesStepValue::Declarations(keyframe.block.clone())));
}
}

Expand Down Expand Up @@ -265,7 +265,10 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
}
Ok(Arc::new(Keyframe {
selector: prelude,
declarations: Arc::new(declarations),
block: Arc::new(PropertyDeclarationBlock {
declarations: Arc::new(declarations),
important_count: 0,
}),
}))
}
}
Expand Down
6 changes: 3 additions & 3 deletions components/style/matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use context::{StyleContext, SharedStyleContext};
use data::PrivateStyleData;
use dom::{TElement, TNode, TRestyleDamage, UnsafeNode};
use properties::longhands::display::computed_value as display;
use properties::{ComputedValues, cascade};
use properties::{ComputedValues, cascade, PropertyDeclarationBlock};
use selector_impl::{TheSelectorImpl, PseudoElement};
use selector_matching::{DeclarationBlock, Stylist};
use selectors::bloom::BloomFilter;
Expand Down Expand Up @@ -139,7 +139,7 @@ impl<'a> Hash for ApplicableDeclarationsCacheQuery<'a> {
for declaration in self.declarations {
// Each declaration contians an Arc, which is a stable
// pointer; we use that for hashing and equality.
let ptr: *const Vec<_> = &*declaration.mixed_declarations;
let ptr: *const PropertyDeclarationBlock = &*declaration.mixed_declarations;
ptr.hash(state);
declaration.importance.hash(state);
}
Expand Down Expand Up @@ -651,7 +651,7 @@ pub trait ElementMatchMethods : TElement {
applicable_declarations: &mut ApplicableDeclarations)
-> StyleRelations {
use traversal::relations_are_shareable;
let style_attribute = self.style_attribute().as_ref();
let style_attribute = self.style_attribute();

let mut relations =
stylist.push_applicable_declarations(self,
Expand Down
2 changes: 1 addition & 1 deletion components/style/properties/properties.mako.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ impl Importance {

/// Overridden declarations are skipped.
// FIXME (https://github.com/servo/servo/issues/3426)
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, Clone)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct PropertyDeclarationBlock {
#[cfg_attr(feature = "servo", ignore_heap_size_of = "#7038")]
Expand Down
22 changes: 9 additions & 13 deletions components/style/selector_matching.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ impl Stylist {
selector: selector.complex_selector.clone(),
declarations: DeclarationBlock {
specificity: selector.specificity,
mixed_declarations: $style_rule.declarations.declarations.clone(),
mixed_declarations: $style_rule.declarations.clone(),
importance: $importance,
source_order: rules_source_order,
},
Expand Down Expand Up @@ -346,7 +346,7 @@ impl Stylist {
&self,
element: &E,
parent_bf: Option<&BloomFilter>,
style_attribute: Option<&PropertyDeclarationBlock>,
style_attribute: Option<&Arc<PropertyDeclarationBlock>>,
pseudo_element: Option<&PseudoElement>,
applicable_declarations: &mut V) -> StyleRelations
where E: Element<Impl=TheSelectorImpl> +
Expand Down Expand Up @@ -398,14 +398,12 @@ impl Stylist {
debug!("author normal: {:?}", relations);

// Step 4: Normal style attributes.
if let Some(ref sa) = style_attribute {
if let Some(sa) = style_attribute {
if sa.declarations.len() as u32 - sa.important_count > 0 {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
DeclarationBlock::from_declarations(
sa.declarations.clone(),
Importance::Normal));
DeclarationBlock::from_declarations(sa.clone(), Importance::Normal));
}
}

Expand All @@ -420,14 +418,12 @@ impl Stylist {
debug!("author important: {:?}", relations);

// Step 6: `!important` style attributes.
if let Some(ref sa) = style_attribute {
if let Some(sa) = style_attribute {
if sa.important_count > 0 {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
DeclarationBlock::from_declarations(
sa.declarations.clone(),
Importance::Important));
DeclarationBlock::from_declarations(sa.clone(), Importance::Important));
}
}

Expand Down Expand Up @@ -845,15 +841,15 @@ pub struct Rule {
pub struct DeclarationBlock {
/// Contains declarations of either importance, but only those of self.importance are relevant.
/// Use DeclarationBlock::iter
pub mixed_declarations: Arc<Vec<(PropertyDeclaration, Importance)>>,
pub mixed_declarations: Arc<PropertyDeclarationBlock>,
pub importance: Importance,
pub source_order: usize,
pub specificity: u32,
}

impl DeclarationBlock {
#[inline]
pub fn from_declarations(declarations: Arc<Vec<(PropertyDeclaration, Importance)>>,
pub fn from_declarations(declarations: Arc<PropertyDeclarationBlock>,
importance: Importance)
-> Self {
DeclarationBlock {
Expand All @@ -866,7 +862,7 @@ impl DeclarationBlock {

pub fn iter(&self) -> DeclarationBlockIter {
DeclarationBlockIter {
iter: self.mixed_declarations.iter(),
iter: self.mixed_declarations.declarations.iter(),
importance: self.importance,
}
}
Expand Down
4 changes: 2 additions & 2 deletions ports/geckolib/glue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ pub extern "C" fn Servo_StyleSet_Drop(data: *mut RawServoStyleSet) -> () {
}

pub struct GeckoDeclarationBlock {
pub declarations: Option<PropertyDeclarationBlock>,
pub declarations: Option<Arc<PropertyDeclarationBlock>>,
// XXX The following two fields are made atomic to work around the
// ownership system so that they can be changed inside a shared
// instance. It wouldn't provide safety as Rust usually promises,
Expand All @@ -377,7 +377,7 @@ pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
-> ServoDeclarationBlockStrong {
let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
GeckoDeclarationBlock::from_arc(Arc::new(GeckoDeclarationBlock {
declarations: GeckoElement::parse_style_attribute(value),
declarations: GeckoElement::parse_style_attribute(value).map(Arc::new),
cache: AtomicPtr::new(cache),
immutable: AtomicBool::new(false),
}))
Expand Down
15 changes: 7 additions & 8 deletions ports/geckolib/wrapper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ use snapshot::GeckoElementSnapshot;
use snapshot_helpers;
use std::fmt;
use std::marker::PhantomData;
use std::mem::transmute;
use std::ops::BitOr;
use std::ptr;
use std::sync::Arc;
Expand Down Expand Up @@ -460,8 +459,6 @@ lazy_static! {
};
}

static NO_STYLE_ATTRIBUTE: Option<PropertyDeclarationBlock> = None;

impl<'le> TElement for GeckoElement<'le> {
type ConcreteNode = GeckoNode<'le>;
type ConcreteDocument = GeckoDocument<'le>;
Expand All @@ -470,14 +467,16 @@ impl<'le> TElement for GeckoElement<'le> {
unsafe { GeckoNode::from_raw(self.element as *mut RawGeckoNode) }
}

fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> {
fn style_attribute(&self) -> Option<&Arc<PropertyDeclarationBlock>> {
let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.element) };
if declarations.is_null() {
&NO_STYLE_ATTRIBUTE
None
} else {
GeckoDeclarationBlock::with(declarations, |declarations| {
unsafe { transmute(&declarations.declarations) }
})
let opt_ptr = GeckoDeclarationBlock::with(declarations, |declarations| {
// Use a raw poointer to extend the lifetime
declarations.declarations.as_ref().map(|r| r as *const Arc<_>)
});
opt_ptr.map(|ptr| unsafe { &*ptr })
}
}

Expand Down
8 changes: 4 additions & 4 deletions tests/unit/script/size_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,10 @@ macro_rules! sizeof_checker (
// Update the sizes here
sizeof_checker!(size_event_target, EventTarget, 40);
sizeof_checker!(size_node, Node, 152);
sizeof_checker!(size_element, Element, 328);
sizeof_checker!(size_htmlelement, HTMLElement, 344);
sizeof_checker!(size_div, HTMLDivElement, 344);
sizeof_checker!(size_span, HTMLSpanElement, 344);
sizeof_checker!(size_element, Element, 320);
sizeof_checker!(size_htmlelement, HTMLElement, 336);
sizeof_checker!(size_div, HTMLDivElement, 336);
sizeof_checker!(size_span, HTMLSpanElement, 336);
sizeof_checker!(size_text, Text, 184);
sizeof_checker!(size_characterdata, CharacterData, 184);
sizeof_checker!(size_servothreadsafelayoutnode, ServoThreadSafeLayoutNode, 16);
Loading

0 comments on commit acc38aa

Please sign in to comment.