Move all PropertyDeclarationBlock from RwLock<_> to Locked<_>

This commit is contained in:
Simon Sapin 2017-03-18 02:10:00 +01:00
parent aeffca2a59
commit 1bacd0eb15
28 changed files with 321 additions and 208 deletions

View file

@ -562,7 +562,7 @@ unsafe impl JSTraceable for StyleLocked<ViewportRule> {
}
}
unsafe impl JSTraceable for RwLock<PropertyDeclarationBlock> {
unsafe impl JSTraceable for StyleLocked<PropertyDeclarationBlock> {
unsafe fn trace(&self, _trc: *mut JSTracer) {
// Do nothing.
}

View file

@ -14,8 +14,7 @@ use dom::window::Window;
use dom_struct::dom_struct;
use std::sync::Arc;
use style::keyframes::Keyframe;
use style::shared_lock::Locked;
use style_traits::ToCss;
use style::shared_lock::{Locked, ToCssWithGuard};
#[dom_struct]
pub struct CSSKeyframeRule {
@ -70,6 +69,6 @@ impl SpecificCSSRule for CSSKeyframeRule {
fn get_css(&self) -> DOMString {
let guard = self.cssrule.shared_lock().read();
self.keyframerule.read_with(&guard).to_css_string().into()
self.keyframerule.read_with(&guard).to_css_string(&guard).into()
}
}

View file

@ -11,10 +11,9 @@ use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object};
use dom::bindings::str::DOMString;
use dom::cssrule::CSSRule;
use dom::element::Element;
use dom::node::{Node, window_from_node};
use dom::node::{Node, window_from_node, document_from_node};
use dom::window::Window;
use dom_struct::dom_struct;
use parking_lot::RwLock;
use servo_url::ServoUrl;
use std::ascii::AsciiExt;
use std::sync::Arc;
@ -23,6 +22,7 @@ use style::parser::ParserContextExtraData;
use style::properties::{Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId};
use style::properties::{parse_one_declaration, parse_style_attribute};
use style::selector_parser::PseudoElement;
use style::shared_lock::Locked;
use style_traits::ToCss;
// http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface
@ -40,7 +40,7 @@ pub enum CSSStyleOwner {
Element(JS<Element>),
CSSRule(JS<CSSRule>,
#[ignore_heap_size_of = "Arc"]
Arc<RwLock<PropertyDeclarationBlock>>),
Arc<Locked<PropertyDeclarationBlock>>),
}
impl CSSStyleOwner {
@ -55,10 +55,13 @@ impl CSSStyleOwner {
let mut changed = true;
match *self {
CSSStyleOwner::Element(ref el) => {
let document = document_from_node(&**el);
let shared_lock = document.style_shared_lock();
let mut attr = el.style_attribute().borrow_mut().take();
let result = if attr.is_some() {
let lock = attr.as_ref().unwrap();
let mut pdb = lock.write();
let mut guard = shared_lock.write();
let mut pdb = lock.write_with(&mut guard);
let result = f(&mut pdb, &mut changed);
result
} else {
@ -69,7 +72,7 @@ impl CSSStyleOwner {
// exact conditions under it changes.
changed = !pdb.declarations().is_empty();
if changed {
attr = Some(Arc::new(RwLock::new(pdb)));
attr = Some(Arc::new(shared_lock.wrap(pdb)));
}
result
@ -83,7 +86,8 @@ impl CSSStyleOwner {
//
// [1]: https://github.com/whatwg/html/issues/2306
if let Some(pdb) = attr {
let serialization = pdb.read().to_css_string();
let guard = shared_lock.read();
let serialization = pdb.read_with(&guard).to_css_string();
el.set_attribute(&local_name!("style"),
AttrValue::Declaration(serialization,
pdb));
@ -96,7 +100,10 @@ impl CSSStyleOwner {
result
}
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
let result = f(&mut *pdb.write(), &mut changed);
let result = {
let mut guard = rule.shared_lock().write();
f(&mut *pdb.write_with(&mut guard), &mut changed)
};
if changed {
rule.global().as_window().Document().invalidate_stylesheets();
}
@ -111,15 +118,20 @@ impl CSSStyleOwner {
match *self {
CSSStyleOwner::Element(ref el) => {
match *el.style_attribute().borrow() {
Some(ref pdb) => f(&pdb.read()),
Some(ref pdb) => {
let document = document_from_node(&**el);
let guard = document.style_shared_lock().read();
f(pdb.read_with(&guard))
}
None => {
let pdb = PropertyDeclarationBlock::new();
f(&pdb)
}
}
}
CSSStyleOwner::CSSRule(_, ref pdb) => {
f(&pdb.read())
CSSStyleOwner::CSSRule(ref rule, ref pdb) => {
let guard = rule.shared_lock().read();
f(pdb.read_with(&guard))
}
}
}

View file

@ -82,7 +82,6 @@ use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode};
use html5ever_atoms::{Prefix, LocalName, Namespace, QualName};
use js::jsapi::{HandleValue, JSAutoCompartment};
use net_traits::request::CorsSettings;
use parking_lot::RwLock;
use ref_filter_map::ref_filter_map;
use script_layout_interface::message::ReflowQueryType;
use script_thread::Runnable;
@ -108,6 +107,7 @@ use style::properties::longhands::{self, background_image, border_spacing, font_
use style::restyle_hints::RESTYLE_SELF;
use style::rule_tree::CascadeLevel;
use style::selector_parser::{NonTSPseudoClass, RestyleDamage, SelectorImpl, SelectorParser};
use style::shared_lock::{SharedRwLock, Locked};
use style::sink::Push;
use style::stylist::ApplicableDeclarationBlock;
use style::thread_state;
@ -129,7 +129,7 @@ pub struct Element {
attrs: DOMRefCell<Vec<JS<Attr>>>,
id_attribute: DOMRefCell<Option<Atom>>,
#[ignore_heap_size_of = "Arc"]
style_attribute: DOMRefCell<Option<Arc<RwLock<PropertyDeclarationBlock>>>>,
style_attribute: DOMRefCell<Option<Arc<Locked<PropertyDeclarationBlock>>>>,
attr_list: MutNullableJS<NamedNodeMap>,
class_list: MutNullableJS<DOMTokenList>,
state: Cell<ElementState>,
@ -352,7 +352,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<Arc<RwLock<PropertyDeclarationBlock>>>;
fn style_attribute(&self) -> *const Option<Arc<Locked<PropertyDeclarationBlock>>>;
fn local_name(&self) -> &LocalName;
fn namespace(&self) -> &Namespace;
fn get_lang_for_layout(&self) -> String;
@ -384,14 +384,18 @@ impl LayoutElementHelpers for LayoutJS<Element> {
where V: Push<ApplicableDeclarationBlock>
{
#[inline]
fn from_declaration(declaration: PropertyDeclaration) -> ApplicableDeclarationBlock {
fn from_declaration(shared_lock: &SharedRwLock, declaration: PropertyDeclaration)
-> ApplicableDeclarationBlock {
ApplicableDeclarationBlock::from_declarations(
Arc::new(RwLock::new(PropertyDeclarationBlock::with_one(
Arc::new(shared_lock.wrap(PropertyDeclarationBlock::with_one(
declaration, Importance::Normal
))),
CascadeLevel::PresHints)
}
let document = self.upcast::<Node>().owner_doc_for_layout();
let shared_lock = document.style_shared_lock();
let bgcolor = if let Some(this) = self.downcast::<HTMLBodyElement>() {
this.get_background_color()
} else if let Some(this) = self.downcast::<HTMLTableElement>() {
@ -408,6 +412,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(color) = bgcolor {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BackgroundColor(
CSSColor { parsed: Color::RGBA(color), authored: None })));
}
@ -420,6 +425,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(url) = background {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BackgroundImage(
background_image::SpecifiedValue(vec![
background_image::single_value::SpecifiedValue(Some(
@ -442,6 +448,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(color) = color {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Color(
longhands::color::SpecifiedValue(CSSColor {
parsed: Color::RGBA(color),
@ -459,6 +466,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(font_family) = font_family {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::FontFamily(
font_family::computed_value::T(vec![
font_family::computed_value::FontFamily::from_atom(
@ -469,6 +477,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(font_size) = font_size {
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::FontSize(font_size::SpecifiedValue(font_size.into()))))
}
@ -481,6 +490,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(cellspacing) = cellspacing {
let width_value = specified::Length::from_px(cellspacing as f32);
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderSpacing(
Box::new(border_spacing::SpecifiedValue {
horizontal: width_value.clone(),
@ -514,6 +524,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(size) = size {
let value = specified::NoCalcLength::ServoCharacterWidth(specified::CharacterWidth(size));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Width(
specified::LengthOrPercentageOrAuto::Length(value))));
}
@ -539,12 +550,14 @@ impl LayoutElementHelpers for LayoutJS<Element> {
let width_value =
specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Width(width_value)));
}
LengthOrPercentageOrAuto::Length(length) => {
let width_value = specified::LengthOrPercentageOrAuto::Length(
specified::NoCalcLength::Absolute(length));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Width(width_value)));
}
}
@ -564,12 +577,14 @@ impl LayoutElementHelpers for LayoutJS<Element> {
let height_value =
specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Height(height_value)));
}
LengthOrPercentageOrAuto::Length(length) => {
let height_value = specified::LengthOrPercentageOrAuto::Length(
specified::NoCalcLength::Absolute(length));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Height(height_value)));
}
}
@ -592,6 +607,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
// https://html.spec.whatwg.org/multipage/#textarea-effective-width
let value = specified::NoCalcLength::ServoCharacterWidth(specified::CharacterWidth(cols));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Width(specified::LengthOrPercentageOrAuto::Length(value))));
}
@ -610,6 +626,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
// https://html.spec.whatwg.org/multipage/#textarea-effective-height
let value = specified::NoCalcLength::FontRelative(specified::FontRelativeLength::Em(rows as CSSFloat));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::Height(specified::LengthOrPercentageOrAuto::Length(value))));
}
@ -623,12 +640,16 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(border) = border {
let width_value = specified::BorderWidth::from_length(specified::Length::from_px(border as f32));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderTopWidth(Box::new(width_value.clone()))));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderLeftWidth(Box::new(width_value.clone()))));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderBottomWidth(Box::new(width_value.clone()))));
hints.push(from_declaration(
shared_lock,
PropertyDeclaration::BorderRightWidth(Box::new(width_value))));
}
}
@ -672,7 +693,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
}
#[allow(unsafe_code)]
fn style_attribute(&self) -> *const Option<Arc<RwLock<PropertyDeclarationBlock>>> {
fn style_attribute(&self) -> *const Option<Arc<Locked<PropertyDeclarationBlock>>> {
unsafe {
(*self.unsafe_get()).style_attribute.borrow_for_layout()
}
@ -835,7 +856,7 @@ impl Element {
ns!()
}
pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<RwLock<PropertyDeclarationBlock>>>> {
pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<Locked<PropertyDeclarationBlock>>>> {
&self.style_attribute
}
@ -2170,7 +2191,7 @@ impl VirtualMethods for Element {
block
} else {
let win = window_from_node(self);
Arc::new(RwLock::new(parse_style_attribute(
Arc::new(doc.style_shared_lock().wrap(parse_style_attribute(
&attr.value(),
&doc.base_url(),
win.css_error_reporter(),

View file

@ -44,7 +44,6 @@ use dom::text::Text;
use gfx_traits::ByteIndex;
use html5ever_atoms::{LocalName, Namespace};
use msg::constellation_msg::PipelineId;
use parking_lot::RwLock;
use range::Range;
use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, TrustedNodeAddress};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
@ -69,7 +68,7 @@ use style::dom::UnsafeNode;
use style::element_state::*;
use style::properties::{ComputedValues, PropertyDeclarationBlock};
use style::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl};
use style::shared_lock::SharedRwLock as StyleSharedRwLock;
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked};
use style::sink::Push;
use style::str::is_whitespace;
use style::stylist::ApplicableDeclarationBlock;
@ -377,7 +376,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
ServoLayoutNode::from_layout_js(self.element.upcast())
}
fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>> {
fn style_attribute(&self) -> Option<&Arc<StyleLocked<PropertyDeclarationBlock>>> {
unsafe {
(*self.element.style_attribute()).as_ref()
}

View file

@ -13,7 +13,7 @@ path = "lib.rs"
doctest = false
[features]
gecko = ["nsstring_vendor", "rayon/unstable"]
gecko = ["nsstring_vendor", "rayon/unstable", "num_cpus"]
use_bindgen = ["bindgen", "regex"]
servo = ["serde/unstable", "serde", "serde_derive", "heapsize_derive",
"style_traits/servo", "servo_atoms", "html5ever-atoms",
@ -37,6 +37,7 @@ lazy_static = "0.2"
log = "0.3"
matches = "0.1"
nsstring_vendor = {path = "gecko_bindings/nsstring_vendor", optional = true}
num_cpus = {version = "1.1.0", optional = true}
num-integer = "0.1.32"
num-traits = "0.1.32"
ordered-float = "0.4"

View file

@ -415,7 +415,7 @@ fn compute_style_for_animation_step(context: &SharedStyleContext,
match step.value {
KeyframesStepValue::ComputedValues => style_from_cascade.clone(),
KeyframesStepValue::Declarations { block: ref declarations } => {
let guard = declarations.read();
let guard = declarations.read_with(context.guards.author);
// No !important in keyframes.
debug_assert!(guard.declarations().iter()

View file

@ -11,9 +11,9 @@ use app_units::Au;
use cssparser::{self, Color, RGBA};
use euclid::num::Zero;
use num_traits::ToPrimitive;
use parking_lot::RwLock;
use properties::PropertyDeclarationBlock;
use servo_url::ServoUrl;
use shared_lock::Locked;
use std::ascii::AsciiExt;
use std::str::FromStr;
use std::sync::Arc;
@ -61,7 +61,7 @@ pub enum AttrValue {
/// declarationblock for longer than needed.
Declaration(String,
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
Arc<RwLock<PropertyDeclarationBlock>>)
Arc<Locked<PropertyDeclarationBlock>>)
}
/// Shared implementation to parse an integer according to

View file

@ -11,10 +11,10 @@ use {Atom, Namespace, LocalName};
use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
use data::ElementData;
use element_state::ElementState;
use parking_lot::RwLock;
use properties::{ComputedValues, PropertyDeclarationBlock};
use selector_parser::{ElementExt, PreExistingComputedValues, PseudoElement};
use selectors::matching::ElementSelectorFlags;
use shared_lock::Locked;
use sink::Push;
use std::fmt;
use std::fmt::Debug;
@ -230,8 +230,8 @@ pub trait PresentationalHintsSynthetizer {
/// The animation rules. The first one is for Animation cascade level, and the second one is for
/// Transition cascade level.
pub struct AnimationRules(pub Option<Arc<RwLock<PropertyDeclarationBlock>>>,
pub Option<Arc<RwLock<PropertyDeclarationBlock>>>);
pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>,
pub Option<Arc<Locked<PropertyDeclarationBlock>>>);
/// The element trait, the main abstraction the style crate acts over.
pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + PresentationalHintsSynthetizer {
@ -252,7 +252,7 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
}
/// Get this element's style attribute.
fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>>;
fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>>;
/// Get this element's animation rules.
fn get_animation_rules(&self, _pseudo: Option<&PseudoElement>) -> AnimationRules {
@ -261,13 +261,13 @@ pub trait TElement : PartialEq + Debug + Sized + Copy + Clone + ElementExt + Pre
/// Get this element's animation rule.
fn get_animation_rule(&self, _pseudo: Option<&PseudoElement>)
-> Option<Arc<RwLock<PropertyDeclarationBlock>>> {
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
None
}
/// Get this element's transition rule.
fn get_transition_rule(&self, _pseudo: Option<&PseudoElement>)
-> Option<Arc<RwLock<PropertyDeclarationBlock>>> {
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
None
}

View file

@ -48,7 +48,7 @@ impl_arc_ffi!(Stylesheet => RawServoStyleSheet
impl_arc_ffi!(ComputedValues => ServoComputedValues
[Servo_ComputedValues_AddRef, Servo_ComputedValues_Release]);
impl_arc_ffi!(RwLock<PropertyDeclarationBlock> => RawServoDeclarationBlock
impl_arc_ffi!(Locked<PropertyDeclarationBlock> => RawServoDeclarationBlock
[Servo_DeclarationBlock_AddRef, Servo_DeclarationBlock_Release]);
impl_arc_ffi!(Locked<StyleRule> => RawServoStyleRule

View file

@ -0,0 +1,50 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
//! Global style data
use num_cpus;
use rayon;
use shared_lock::SharedRwLock;
use std::cmp;
use std::env;
/// Global style data
pub struct GlobalStyleData {
/// How many threads parallel styling can use.
pub num_threads: usize,
/// The parallel styling thread pool.
pub style_thread_pool: Option<rayon::ThreadPool>,
/// Shared RWLock for CSSOM objects
pub shared_lock: SharedRwLock,
}
lazy_static! {
/// Global style data
pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = {
let stylo_threads = env::var("STYLO_THREADS")
.map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS value"));
let num_threads = match stylo_threads {
Ok(num) => num,
_ => cmp::max(num_cpus::get() * 3 / 4, 1),
};
let pool = if num_threads <= 1 {
None
} else {
let configuration =
rayon::Configuration::new().set_num_threads(num_threads);
let pool = rayon::ThreadPool::new(configuration).ok();
pool
};
GlobalStyleData {
num_threads: num_threads,
style_thread_pool: pool,
shared_lock: SharedRwLock::new(),
}
};
}

View file

@ -10,6 +10,7 @@ mod non_ts_pseudo_class_list;
pub mod arc_types;
pub mod conversions;
pub mod data;
pub mod global_style_data;
pub mod media_queries;
pub mod restyle_damage;
pub mod selector_parser;

View file

@ -20,6 +20,7 @@ use dom::{AnimationRules, LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode}
use dom::{OpaqueNode, PresentationalHintsSynthetizer};
use element_state::ElementState;
use error_reporting::StdoutErrorReporter;
use gecko::global_style_data::GLOBAL_STYLE_DATA;
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
use gecko::snapshot_helpers;
use gecko_bindings::bindings;
@ -53,6 +54,7 @@ use selectors::Element;
use selectors::matching::{ElementSelectorFlags, StyleRelations, matches_complex_selector};
use selectors::parser::{AttrSelector, NamespaceConstraint};
use servo_url::ServoUrl;
use shared_lock::Locked;
use sink::Push;
use std::fmt;
use std::ptr;
@ -407,12 +409,14 @@ fn selector_flags_to_node_flags(flags: ElementSelectorFlags) -> u32 {
fn get_animation_rule(element: &GeckoElement,
pseudo: Option<&PseudoElement>,
cascade_level: CascadeLevel)
-> Option<Arc<RwLock<PropertyDeclarationBlock>>> {
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
let atom_ptr = PseudoElement::ns_atom_or_null_from_opt(pseudo);
let animation_values = Arc::new(RwLock::new(AnimationValueMap::new()));
if unsafe { Gecko_GetAnimationRule(element.0, atom_ptr, cascade_level,
HasArcFFI::arc_as_borrowed(&animation_values)) } {
Some(Arc::new(RwLock::new(PropertyDeclarationBlock::from_animation_value_map(&animation_values.read()))))
let shared_lock = &GLOBAL_STYLE_DATA.shared_lock;
Some(Arc::new(shared_lock.wrap(
PropertyDeclarationBlock::from_animation_value_map(&animation_values.read()))))
} else {
None
}
@ -425,7 +429,7 @@ impl<'le> TElement for GeckoElement<'le> {
unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
}
fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>> {
fn style_attribute(&self) -> Option<&Arc<Locked<PropertyDeclarationBlock>>> {
let declarations = unsafe { Gecko_GetStyleAttrDeclarationBlock(self.0) };
declarations.map(|s| s.as_arc_opt()).unwrap_or(None)
}
@ -436,12 +440,12 @@ impl<'le> TElement for GeckoElement<'le> {
}
fn get_animation_rule(&self, pseudo: Option<&PseudoElement>)
-> Option<Arc<RwLock<PropertyDeclarationBlock>>> {
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
get_animation_rule(self, pseudo, CascadeLevel::Animations)
}
fn get_transition_rule(&self, pseudo: Option<&PseudoElement>)
-> Option<Arc<RwLock<PropertyDeclarationBlock>>> {
-> Option<Arc<Locked<PropertyDeclarationBlock>>> {
get_animation_rule(self, pseudo, CascadeLevel::Transitions)
}

View file

@ -8,14 +8,13 @@
use cssparser::{AtRuleParser, Parser, QualifiedRuleParser, RuleListParser};
use cssparser::{DeclarationListParser, DeclarationParser, parse_one_rule};
use parking_lot::RwLock;
use parser::{ParserContext, ParserContextExtraData, log_css_error};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock, PropertyId};
use properties::{PropertyDeclarationId, LonghandId, ParsedDeclaration};
use properties::LonghandIdSet;
use properties::animated_properties::TransitionProperty;
use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction;
use shared_lock::{SharedRwLock, SharedRwLockReadGuard, Locked};
use shared_lock::{SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard};
use std::fmt;
use std::sync::Arc;
use style_traits::ToCss;
@ -102,11 +101,12 @@ pub struct Keyframe {
///
/// Note that `!important` rules in keyframes don't apply, but we keep this
/// `Arc` just for convenience.
pub block: Arc<RwLock<PropertyDeclarationBlock>>,
pub block: Arc<Locked<PropertyDeclarationBlock>>,
}
impl ToCss for Keyframe {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
impl ToCssWithGuard for Keyframe {
fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
let mut iter = self.selector.percentages().iter();
try!(iter.next().unwrap().to_css(dest));
for percentage in iter {
@ -114,7 +114,7 @@ impl ToCss for Keyframe {
try!(percentage.to_css(dest));
}
try!(dest.write_str(" { "));
try!(self.block.read().to_css(dest));
try!(self.block.read_with(guard).to_css(dest));
try!(dest.write_str(" }"));
Ok(())
}
@ -154,7 +154,7 @@ pub enum KeyframesStepValue {
Declarations {
/// The declaration block per se.
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
block: Arc<RwLock<PropertyDeclarationBlock>>
block: Arc<Locked<PropertyDeclarationBlock>>
},
/// A synthetic step computed from the current computed values at the time
/// of the animation.
@ -180,10 +180,11 @@ pub struct KeyframesStep {
impl KeyframesStep {
#[inline]
fn new(percentage: KeyframePercentage,
value: KeyframesStepValue) -> Self {
value: KeyframesStepValue,
guard: &SharedRwLockReadGuard) -> Self {
let declared_timing_function = match value {
KeyframesStepValue::Declarations { ref block } => {
block.read().declarations().iter().any(|&(ref prop_decl, _)| {
block.read_with(guard).declarations().iter().any(|&(ref prop_decl, _)| {
match *prop_decl {
PropertyDeclaration::AnimationTimingFunction(..) => true,
_ => false,
@ -201,13 +202,14 @@ impl KeyframesStep {
}
/// Return specified TransitionTimingFunction if this KeyframesSteps has 'animation-timing-function'.
pub fn get_animation_timing_function(&self) -> Option<SpecifiedTimingFunction> {
pub fn get_animation_timing_function(&self, guard: &SharedRwLockReadGuard)
-> Option<SpecifiedTimingFunction> {
if !self.declared_timing_function {
return None;
}
match self.value {
KeyframesStepValue::Declarations { ref block } => {
let guard = block.read();
let guard = block.read_with(guard);
let &(ref declaration, _) =
guard.get(PropertyDeclarationId::Longhand(LonghandId::AnimationTimingFunction)).unwrap();
match *declaration {
@ -249,7 +251,8 @@ fn get_animated_properties(keyframes: &[Arc<Locked<Keyframe>>], guard: &SharedRw
// it here.
for keyframe in keyframes {
let keyframe = keyframe.read_with(&guard);
for &(ref declaration, importance) in keyframe.block.read().declarations().iter() {
let block = keyframe.block.read_with(guard);
for &(ref declaration, importance) in block.declarations().iter() {
assert!(!importance.important());
if let Some(property) = TransitionProperty::from_declaration(declaration) {
@ -294,7 +297,7 @@ impl KeyframesAnimation {
for percentage in keyframe.selector.0.iter() {
result.steps.push(KeyframesStep::new(*percentage, KeyframesStepValue::Declarations {
block: keyframe.block.clone(),
}));
}, guard));
}
}
@ -304,12 +307,14 @@ impl KeyframesAnimation {
// Prepend autogenerated keyframes if appropriate.
if result.steps[0].start_percentage.0 != 0. {
result.steps.insert(0, KeyframesStep::new(KeyframePercentage::new(0.),
KeyframesStepValue::ComputedValues));
KeyframesStepValue::ComputedValues,
guard));
}
if result.steps.last().unwrap().start_percentage.0 != 1. {
result.steps.push(KeyframesStep::new(KeyframePercentage::new(1.),
KeyframesStepValue::ComputedValues));
KeyframesStepValue::ComputedValues,
guard));
}
result
@ -381,7 +386,7 @@ impl<'a> QualifiedRuleParser for KeyframeListParser<'a> {
}
Ok(Arc::new(self.shared_lock.wrap(Keyframe {
selector: prelude,
block: Arc::new(RwLock::new(block)),
block: Arc::new(self.shared_lock.wrap(block)),
})))
}
}

View file

@ -57,6 +57,7 @@ extern crate log;
#[macro_use]
extern crate matches;
#[cfg(feature = "gecko")] extern crate nsstring_vendor as nsstring;
#[cfg(feature = "gecko")] extern crate num_cpus;
extern crate num_integer;
extern crate num_traits;
extern crate ordered_float;

View file

@ -886,7 +886,8 @@ pub trait MatchMethods : TElement {
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(CascadeLevel::StyleAttributeNormal,
style_attribute,
primary_rules);
primary_rules,
&context.shared.guards);
if let Some(n) = new_node {
*primary_rules = n;
rule_node_changed = true;
@ -895,7 +896,8 @@ pub trait MatchMethods : TElement {
let new_node = context.shared.stylist.rule_tree
.update_rule_at_level(CascadeLevel::StyleAttributeImportant,
style_attribute,
primary_rules);
primary_rules,
&context.shared.guards);
if let Some(n) = new_node {
*primary_rules = n;
rule_node_changed = true;

View file

@ -10,7 +10,6 @@
use arc_ptr_eq;
#[cfg(feature = "servo")]
use heapsize::HeapSizeOf;
use parking_lot::{RwLock, RwLockReadGuard};
use properties::{Importance, PropertyDeclarationBlock};
use shared_lock::{Locked, ReadGuards, SharedRwLockReadGuard};
use std::io::{self, Write};
@ -54,7 +53,7 @@ pub enum StyleSource {
/// A style rule stable pointer.
Style(Arc<Locked<StyleRule>>),
/// A declaration block stable pointer.
Declarations(Arc<RwLock<PropertyDeclarationBlock>>),
Declarations(Arc<Locked<PropertyDeclarationBlock>>),
}
impl StyleSource {
@ -82,13 +81,12 @@ impl StyleSource {
/// Read the style source guard, and obtain thus read access to the
/// underlying property declaration block.
#[inline]
pub fn read<'a>(&'a self, guard: &'a SharedRwLockReadGuard)
-> RwLockReadGuard<'a, PropertyDeclarationBlock> {
pub fn read<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a PropertyDeclarationBlock {
let block = match *self {
StyleSource::Style(ref rule) => &rule.read_with(guard).block,
StyleSource::Declarations(ref block) => block,
};
block.read()
block.read_with(guard)
}
}
@ -162,8 +160,9 @@ impl RuleTree {
/// the old path is still valid.
pub fn update_rule_at_level(&self,
level: CascadeLevel,
pdb: Option<&Arc<RwLock<PropertyDeclarationBlock>>>,
path: &StrongRuleNode)
pdb: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
path: &StrongRuleNode,
guards: &ReadGuards)
-> Option<StrongRuleNode> {
debug_assert!(level.is_unique_per_element());
// TODO(emilio): Being smarter with lifetimes we could avoid a bit of
@ -222,13 +221,13 @@ impl RuleTree {
// pretty bad styling cases already.
if let Some(pdb) = pdb {
if level.is_important() {
if pdb.read().any_important() {
if pdb.read_with(level.guard(guards)).any_important() {
current = current.ensure_child(self.root.downgrade(),
StyleSource::Declarations(pdb.clone()),
level);
}
} else {
if pdb.read().any_normal() {
if pdb.read_with(level.guard(guards)).any_normal() {
current = current.ensure_child(self.root.downgrade(),
StyleSource::Declarations(pdb.clone()),
level);

View file

@ -469,7 +469,7 @@ impl ToCssWithGuard for KeyframesRule {
}
first = false;
let keyframe = lock.read_with(&guard);
try!(keyframe.to_css(dest));
try!(keyframe.to_css(guard, dest));
}
dest.write_str(" }")
}
@ -528,19 +528,19 @@ impl ToCssWithGuard for SupportsRule {
#[derive(Debug)]
pub struct StyleRule {
pub selectors: SelectorList<SelectorImpl>,
pub block: Arc<RwLock<PropertyDeclarationBlock>>,
pub block: Arc<Locked<PropertyDeclarationBlock>>,
}
impl ToCssWithGuard for StyleRule {
// https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSStyleRule
fn to_css<W>(&self, _guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
where W: fmt::Write {
// Step 1
try!(self.selectors.to_css(dest));
// Step 2
try!(dest.write_str(" { "));
// Step 3
let declaration_block = self.block.read();
let declaration_block = self.block.read_with(guard);
try!(declaration_block.to_css(dest));
// Step 4
if declaration_block.declarations().len() > 0 {
@ -1018,9 +1018,10 @@ impl<'a, 'b> QualifiedRuleParser for NestedRuleParser<'a, 'b> {
fn parse_block(&mut self, prelude: SelectorList<SelectorImpl>, input: &mut Parser)
-> Result<CssRule, ()> {
let declarations = parse_property_declaration_list(self.context, input);
Ok(CssRule::Style(Arc::new(self.shared_lock.wrap(StyleRule {
selectors: prelude,
block: Arc::new(RwLock::new(parse_property_declaration_list(self.context, input)))
block: Arc::new(self.shared_lock.wrap(declarations))
}))))
}
}

View file

@ -12,7 +12,6 @@ use dom::{AnimationRules, PresentationalHintsSynthetizer, TElement};
use error_reporting::StdoutErrorReporter;
use keyframes::KeyframesAnimation;
use media_queries::Device;
use parking_lot::RwLock;
use pdqsort::sort_by;
use properties::{self, CascadeFlags, ComputedValues};
#[cfg(feature = "servo")]
@ -542,7 +541,7 @@ impl Stylist {
&self,
element: &E,
parent_bf: Option<&BloomFilter>,
style_attribute: Option<&Arc<RwLock<PropertyDeclarationBlock>>>,
style_attribute: Option<&Arc<Locked<PropertyDeclarationBlock>>>,
animation_rules: AnimationRules,
pseudo_element: Option<&PseudoElement>,
guards: &ReadGuards,
@ -613,7 +612,7 @@ impl Stylist {
// Step 4: Normal style attributes.
if let Some(sa) = style_attribute {
if sa.read().any_normal() {
if sa.read_with(guards.author).any_normal() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
@ -649,7 +648,7 @@ impl Stylist {
// Step 7: `!important` style attributes.
if let Some(sa) = style_attribute {
if sa.read().any_important() {
if sa.read_with(guards.author).any_important() {
relations |= AFFECTED_BY_STYLE_ATTRIBUTE;
Push::push(
applicable_declarations,
@ -1005,7 +1004,7 @@ impl SelectorMap {
if rule.selector.compound_selector.is_empty() &&
rule.selector.next.is_none() {
let style_rule = rule.style_rule.read_with(guard);
let block = style_rule.block.read();
let block = style_rule.block.read_with(guard);
if block.any_normal() {
matching_rules_list.push(
rule.to_applicable_declaration_block(cascade_level));
@ -1069,7 +1068,7 @@ impl SelectorMap {
{
for rule in rules.iter() {
let style_rule = rule.style_rule.read_with(guard);
let block = style_rule.block.read();
let block = style_rule.block.read_with(guard);
let any_declaration_for_importance = if cascade_level.is_important() {
block.any_important()
} else {
@ -1208,7 +1207,7 @@ impl ApplicableDeclarationBlock {
/// Constructs an applicable declaration block from a given property
/// declaration block and importance.
#[inline]
pub fn from_declarations(declarations: Arc<RwLock<PropertyDeclarationBlock>>,
pub fn from_declarations(declarations: Arc<Locked<PropertyDeclarationBlock>>,
level: CascadeLevel)
-> Self {
ApplicableDeclarationBlock {