Bug 1309109 part 7 - Remove the extra level of GeckoDeclarationBlock. r=manishearth,mystor draft
authorXidorn Quan <me@upsuper.org>
Fri, 14 Oct 2016 00:30:51 +1100
changeset 426170 b476cdcc3ae63935a4ecf46b8fb73efb3483ef49
parent 426169 5f8c706d7361f0be2c27f90ad960237845efd238
child 534115 ad6179390dab6715cb9c3411761977cb30021ff3
push id32640
push userxquan@mozilla.com
push dateTue, 18 Oct 2016 00:25:47 +0000
reviewersmanishearth, mystor
bugs1309109
milestone52.0a1
Bug 1309109 part 7 - Remove the extra level of GeckoDeclarationBlock. r=manishearth,mystor MozReview-Commit-ID: 2TzqrAWbaeD
layout/style/ServoBindingList.h
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoDeclarationBlock.cpp
servo/components/style/gecko/conversions.rs
servo/components/style/gecko/wrapper.rs
servo/components/style/gecko_bindings/bindings.rs
servo/ports/geckolib/glue.rs
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -61,31 +61,24 @@ SERVO_BINDING_FUNC(Servo_ParseProperty,
                    ThreadSafePrincipalHolder* principal)
 SERVO_BINDING_FUNC(Servo_RestyleWithAddedDeclaration,
                    ServoComputedValuesStrong,
                    RawServoDeclarationBlockBorrowed declarations,
                    ServoComputedValuesBorrowed previous_style)
 
 // Style attribute
 SERVO_BINDING_FUNC(Servo_ParseStyleAttribute, RawServoDeclarationBlockStrong,
-                   const uint8_t* bytes, uint32_t length,
-                   nsHTMLCSSStyleSheet* cache)
+                   const uint8_t* bytes, uint32_t length)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_AddRef, void,
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_Release, void,
                    RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_Equals, bool,
                    RawServoDeclarationBlockBorrowed a,
                    RawServoDeclarationBlockBorrowed b)
-SERVO_BINDING_FUNC(Servo_DeclarationBlock_GetCache, nsHTMLCSSStyleSheet*,
-                   RawServoDeclarationBlockBorrowed declarations)
-SERVO_BINDING_FUNC(Servo_DeclarationBlock_SetImmutable, void,
-                   RawServoDeclarationBlockBorrowed declarations)
-SERVO_BINDING_FUNC(Servo_DeclarationBlock_ClearCachePointer, void,
-                   RawServoDeclarationBlockBorrowed declarations)
 SERVO_BINDING_FUNC(Servo_DeclarationBlock_SerializeOneValue, void,
                    RawServoDeclarationBlockBorrowed declarations,
                    nsString* buffer)
 
 // CSS supports()
 SERVO_BINDING_FUNC(Servo_CSSSupports, bool,
                    const uint8_t* name, uint32_t name_length,
                    const uint8_t* value, uint32_t value_length)
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -308,28 +308,29 @@ Gecko_StoreStyleDifference(RawGeckoNodeB
 
   primaryFrame->StyleContext()->StoreChangeHint(aChangeHintToStore);
 #else
   MOZ_CRASH("stylo: Shouldn't call Gecko_StoreStyleDifference in "
             "non-stylo build");
 #endif
 }
 
-RawServoDeclarationBlock*
+RawServoDeclarationBlockStrongBorrowedOrNull
 Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed aElement)
 {
   const nsAttrValue* attr = aElement->GetParsedAttr(nsGkAtoms::style);
   if (!attr || attr->Type() != nsAttrValue::eCSSDeclaration) {
     return nullptr;
   }
   DeclarationBlock* decl = attr->GetCSSDeclarationValue();
   if (!decl || decl->IsGecko()) {
     return nullptr;
   }
-  return decl->AsServo()->Raw();
+  return reinterpret_cast<const RawServoDeclarationBlockStrong*>
+    (&decl->AsServo()->Raw());
 }
 
 void
 Gecko_FillAllBackgroundLists(nsStyleImageLayers* aLayers, uint32_t aMaxLen)
 {
   nsRuleNode::FillAllBackgroundLists(*aLayers, aMaxLen);
 }
 
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -212,17 +212,17 @@ nsIAtom* Gecko_GetElementId(RawGeckoElem
 
 SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_, RawGeckoElementBorrowed)
 SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS(Gecko_Snapshot,
                                               ServoElementSnapshot*)
 
 #undef SERVO_DECLARE_ELEMENT_ATTR_MATCHING_FUNCTIONS
 
 // Style attributes.
-RawServoDeclarationBlockBorrowedOrNull
+RawServoDeclarationBlockStrongBorrowedOrNull
 Gecko_GetServoDeclarationBlock(RawGeckoElementBorrowed element);
 
 // Atoms.
 nsIAtom* Gecko_Atomize(const char* aString, uint32_t aLength);
 void Gecko_AddRefAtom(nsIAtom* aAtom);
 void Gecko_ReleaseAtom(nsIAtom* aAtom);
 const uint16_t* Gecko_GetAtomAsUTF16(nsIAtom* aAtom, uint32_t* aLength);
 bool Gecko_AtomEqualsUTF8(nsIAtom* aAtom, const char* aString, uint32_t aLength);
--- a/layout/style/ServoDeclarationBlock.cpp
+++ b/layout/style/ServoDeclarationBlock.cpp
@@ -9,15 +9,14 @@
 
 namespace mozilla {
 
 /* static */ already_AddRefed<ServoDeclarationBlock>
 ServoDeclarationBlock::FromStyleAttribute(const nsAString& aString)
 {
   NS_ConvertUTF16toUTF8 value(aString);
   RefPtr<RawServoDeclarationBlock> raw = Servo_ParseStyleAttribute(
-      reinterpret_cast<const uint8_t*>(value.get()),
-      value.Length(), nullptr).Consume();
+      reinterpret_cast<const uint8_t*>(value.get()), value.Length()).Consume();
   RefPtr<ServoDeclarationBlock> decl = new ServoDeclarationBlock(raw.forget());
   return decl.forget();
 }
 
 } // namespace mozilla
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -4,32 +4,38 @@
 
 //! This module contains conversion helpers between Servo and Gecko types
 //! Ideally, it would be in geckolib itself, but coherence
 //! forces us to keep the traits and implementations here
 
 #![allow(unsafe_code)]
 
 use app_units::Au;
-use gecko_bindings::bindings::{RawServoStyleSheet, ServoComputedValues};
+use gecko_bindings::bindings::{RawServoStyleSheet, ServoComputedValues, RawServoDeclarationBlock};
 use gecko_bindings::structs::nsStyleCoord_CalcValue;
 use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI};
-use properties::ComputedValues;
+use parking_lot::RwLock;
+use properties::{ComputedValues, PropertyDeclarationBlock};
 use stylesheets::Stylesheet;
 use values::computed::{CalcLengthOrPercentage, LengthOrPercentage, LengthOrPercentageOrAuto};
 
 unsafe impl HasFFI for Stylesheet {
     type FFIType = RawServoStyleSheet;
 }
 unsafe impl HasArcFFI for Stylesheet {}
 unsafe impl HasFFI for ComputedValues {
     type FFIType = ServoComputedValues;
 }
 unsafe impl HasArcFFI for ComputedValues {}
 
+unsafe impl HasFFI for RwLock<PropertyDeclarationBlock> {
+    type FFIType = RawServoDeclarationBlock;
+}
+unsafe impl HasArcFFI for RwLock<PropertyDeclarationBlock> {}
+
 impl From<CalcLengthOrPercentage> for nsStyleCoord_CalcValue {
     fn from(other: CalcLengthOrPercentage) -> nsStyleCoord_CalcValue {
         let has_percentage = other.percentage.is_some();
         nsStyleCoord_CalcValue {
             mLength: other.length.map_or(0, |l| l.0),
             mPercent: other.percentage.unwrap_or(0.0),
             mHasPercent: has_percentage,
         }
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -25,72 +25,42 @@ use gecko_bindings::bindings::{Gecko_IsU
 use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
 use gecko_bindings::bindings::Gecko_ClassOrClassList;
 use gecko_bindings::bindings::Gecko_GetStyleContext;
 use gecko_bindings::structs;
 use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
 use gecko_bindings::structs::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
 use gecko_bindings::structs::{nsChangeHint, nsIAtom, nsIContent, nsStyleContext};
 use gecko_bindings::structs::OpaqueStyleData;
-use gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasFFI};
+use gecko_bindings::sugar::ownership::FFIArcHelpers;
 use libc::uintptr_t;
 use parking_lot::RwLock;
 use parser::ParserContextExtraData;
 use properties::{ComputedValues, parse_style_attribute};
 use properties::PropertyDeclarationBlock;
 use selector_impl::ElementExt;
 use selector_matching::ApplicableDeclarationBlock;
 use selectors::Element;
 use selectors::parser::{AttrSelector, NamespaceConstraint};
 use sink::Push;
 use std::fmt;
 use std::ops::BitOr;
 use std::ptr;
 use std::sync::Arc;
-use std::sync::atomic::{AtomicBool, AtomicPtr};
 use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
 use url::Url;
 
 pub struct NonOpaqueStyleData(AtomicRefCell<PersistentStyleData>);
 
 impl NonOpaqueStyleData {
     pub fn new() -> Self {
         NonOpaqueStyleData(AtomicRefCell::new(PersistentStyleData::new()))
     }
 }
 
-
-pub struct GeckoDeclarationBlock {
-    pub declarations: Option<Arc<RwLock<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,
-    // but it is fine as far as we only access them in a single thread.
-    // If we need to access them in different threads, we would need
-    // to redesign how it works with MiscContainer in Gecko side.
-    pub cache: AtomicPtr<bindings::nsHTMLCSSStyleSheet>,
-    pub immutable: AtomicBool,
-}
-
-impl PartialEq for GeckoDeclarationBlock {
-    fn eq(&self, other: &GeckoDeclarationBlock) -> bool {
-        match (&self.declarations, &other.declarations) {
-            (&None, &None) => true,
-            (&Some(ref s), &Some(ref other)) => *s.read() == *other.read(),
-            _ => false,
-        }
-    }
-}
-
-unsafe impl HasFFI for GeckoDeclarationBlock {
-    type FFIType = bindings::RawServoDeclarationBlock;
-}
-unsafe impl HasArcFFI for GeckoDeclarationBlock {}
-
-
 // We can eliminate OpaqueStyleData when the bindings move into the style crate.
 fn to_opaque_style_data(d: *mut NonOpaqueStyleData) -> *mut OpaqueStyleData {
     d as *mut OpaqueStyleData
 }
 fn from_opaque_style_data(d: *mut OpaqueStyleData) -> *mut NonOpaqueStyleData {
     d as *mut NonOpaqueStyleData
 }
 
@@ -481,23 +451,23 @@ impl<'le> fmt::Debug for GeckoElement<'l
         if let Some(id) = self.get_id() {
             try!(write!(f, " id={}", id));
         }
         write!(f, ">")
     }
 }
 
 impl<'le> GeckoElement<'le> {
-    pub fn parse_style_attribute(value: &str) -> Option<PropertyDeclarationBlock> {
+    pub fn parse_style_attribute(value: &str) -> PropertyDeclarationBlock {
         // FIXME(bholley): Real base URL and error reporter.
         let base_url = &*DUMMY_BASE_URL;
         // FIXME(heycam): Needs real ParserContextExtraData so that URLs parse
         // properly.
         let extra_data = ParserContextExtraData::default();
-        Some(parse_style_attribute(value, &base_url, Box::new(StdoutErrorReporter), extra_data))
+        parse_style_attribute(value, &base_url, Box::new(StdoutErrorReporter), extra_data)
     }
 }
 
 lazy_static! {
     pub static ref DUMMY_BASE_URL: Url = {
         Url::parse("http://www.example.org").unwrap()
     };
 }
@@ -507,22 +477,17 @@ impl<'le> TElement for GeckoElement<'le>
     type ConcreteDocument = GeckoDocument<'le>;
 
     fn as_node(&self) -> Self::ConcreteNode {
         unsafe { GeckoNode(&*(self.0 as *const _ as *const RawGeckoNode)) }
     }
 
     fn style_attribute(&self) -> Option<&Arc<RwLock<PropertyDeclarationBlock>>> {
         let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.0) };
-        if declarations.is_none() {
-            None
-        } else {
-            let declarations = GeckoDeclarationBlock::arc_from_borrowed(&declarations).unwrap();
-            declarations.declarations.as_ref().map(|r| r as *const Arc<_>).map(|ptr| unsafe { &*ptr })
-        }
+        declarations.map(|s| s.into_arc_opt_borrow()).unwrap_or(None)
     }
 
     fn get_state(&self) -> ElementState {
         unsafe {
             ElementState::from_bits_truncate(Gecko_ElementState(self.0) as u16)
         }
     }
 
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -170,24 +170,16 @@ use gecko_bindings::structs::nsString;
 extern "C" {
     pub fn Gecko_EnsureTArrayCapacity(aArray: *mut ::std::os::raw::c_void,
                                       aCapacity: usize, aElementSize: usize);
 }
 extern "C" {
     pub fn Gecko_ClearPODTArray(aArray: *mut ::std::os::raw::c_void,
                                 aElementSize: usize, aElementAlign: usize);
 }
-#[repr(C)]
-#[derive(Debug, Copy)]
-pub struct nsHTMLCSSStyleSheet {
-    pub _address: u8,
-}
-impl Clone for nsHTMLCSSStyleSheet {
-    fn clone(&self) -> Self { *self }
-}
 extern "C" {
     pub fn Gecko_ChildrenCount(node: RawGeckoNodeBorrowed) -> u32;
 }
 extern "C" {
     pub fn Gecko_NodeIsElement(node: RawGeckoNodeBorrowed) -> bool;
 }
 extern "C" {
     pub fn Gecko_GetParentNode(node: RawGeckoNodeBorrowed)
@@ -364,17 +356,17 @@ extern "C" {
 extern "C" {
     pub fn Gecko_SnapshotClassOrClassList(element: *mut ServoElementSnapshot,
                                           class_: *mut *mut nsIAtom,
                                           classList: *mut *mut *mut nsIAtom)
      -> u32;
 }
 extern "C" {
     pub fn Gecko_GetServoDeclarationBlock(element: RawGeckoElementBorrowed)
-     -> RawServoDeclarationBlockBorrowedOrNull;
+     -> RawServoDeclarationBlockStrongBorrowedOrNull;
 }
 extern "C" {
     pub fn Gecko_Atomize(aString: *const ::std::os::raw::c_char, aLength: u32)
      -> *mut nsIAtom;
 }
 extern "C" {
     pub fn Gecko_AddRefAtom(aAtom: *mut nsIAtom);
 }
@@ -858,47 +850,33 @@ extern "C" {
 extern "C" {
     pub fn Servo_RestyleWithAddedDeclaration(declarations:
                                                  RawServoDeclarationBlockBorrowed,
                                              previous_style:
                                                  ServoComputedValuesBorrowed)
      -> ServoComputedValuesStrong;
 }
 extern "C" {
-    pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
-                                     cache: *mut nsHTMLCSSStyleSheet)
+    pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32)
      -> RawServoDeclarationBlockStrong;
 }
 extern "C" {
     pub fn Servo_DeclarationBlock_AddRef(declarations:
                                              RawServoDeclarationBlockBorrowed);
 }
 extern "C" {
     pub fn Servo_DeclarationBlock_Release(declarations:
                                               RawServoDeclarationBlockBorrowed);
 }
 extern "C" {
     pub fn Servo_DeclarationBlock_Equals(a: RawServoDeclarationBlockBorrowed,
                                          b: RawServoDeclarationBlockBorrowed)
      -> bool;
 }
 extern "C" {
-    pub fn Servo_DeclarationBlock_GetCache(declarations:
-                                               RawServoDeclarationBlockBorrowed)
-     -> *mut nsHTMLCSSStyleSheet;
-}
-extern "C" {
-    pub fn Servo_DeclarationBlock_SetImmutable(declarations:
-                                                   RawServoDeclarationBlockBorrowed);
-}
-extern "C" {
-    pub fn Servo_DeclarationBlock_ClearCachePointer(declarations:
-                                                        RawServoDeclarationBlockBorrowed);
-}
-extern "C" {
     pub fn Servo_DeclarationBlock_SerializeOneValue(declarations:
                                                         RawServoDeclarationBlockBorrowed,
                                                     buffer: *mut nsString);
 }
 extern "C" {
     pub fn Servo_CSSSupports(name: *const u8, name_length: u32,
                              value: *const u8, value_length: u32) -> bool;
 }
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3,38 +3,36 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use app_units::Au;
 use cssparser::{Parser, ToCss};
 use env_logger;
 use euclid::Size2D;
 use parking_lot::RwLock;
 use std::mem::transmute;
-use std::ptr;
 use std::slice;
 use std::str::from_utf8_unchecked;
 use std::sync::{Arc, Mutex};
-use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
 use style::arc_ptr_eq;
 use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
 use style::dom::{NodeInfo, TElement, TNode};
 use style::error_reporting::StdoutErrorReporter;
 use style::gecko::data::{NUM_THREADS, PerDocumentStyleData};
 use style::gecko::selector_impl::{GeckoSelectorImpl, PseudoElement};
 use style::gecko::snapshot::GeckoElementSnapshot;
 use style::gecko::traversal::RecalcStyleOnly;
-use style::gecko::wrapper::{DUMMY_BASE_URL, GeckoDeclarationBlock};
+use style::gecko::wrapper::DUMMY_BASE_URL;
 use style::gecko::wrapper::{GeckoElement, GeckoNode};
 use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoNodeBorrowed};
 use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
 use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
 use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
 use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
 use style::gecko_bindings::bindings::{ThreadSafePrincipalHolder, ThreadSafeURIHolder};
-use style::gecko_bindings::bindings::{nsHTMLCSSStyleSheet, ServoComputedValuesBorrowedOrNull};
+use style::gecko_bindings::bindings::ServoComputedValuesBorrowedOrNull;
 use style::gecko_bindings::bindings::Gecko_Utf8SliceToString;
 use style::gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
 use style::gecko_bindings::structs::{SheetParsingMode, nsIAtom};
 use style::gecko_bindings::structs::ServoElementSnapshot;
 use style::gecko_bindings::structs::nsRestyleHint;
 use style::gecko_bindings::structs::nsString;
 use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasBoxFFI};
 use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
@@ -126,38 +124,34 @@ pub extern "C" fn Servo_RestyleSubtree(n
     restyle_subtree(node, raw_data);
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_RestyleWithAddedDeclaration(declarations: RawServoDeclarationBlockBorrowed,
                                                     previous_style: ServoComputedValuesBorrowed)
   -> ServoComputedValuesStrong
 {
-    match GeckoDeclarationBlock::as_arc(&declarations).declarations {
-        Some(ref declarations) => {
-            let declaration_block = ApplicableDeclarationBlock {
-                mixed_declarations: declarations.clone(),
-                importance: Importance::Normal,
-                source_order: 0,
-                specificity: ::std::u32::MAX,
-            };
-            let previous_style = ComputedValues::as_arc(&previous_style);
+    let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+    let declaration_block = ApplicableDeclarationBlock {
+        mixed_declarations: declarations.clone(),
+        importance: Importance::Normal,
+        source_order: 0,
+        specificity: ::std::u32::MAX,
+    };
+    let previous_style = ComputedValues::as_arc(&previous_style);
 
-            // FIXME (bug 1303229): Use the actual viewport size here
-            let (computed, _) = cascade(Size2D::new(Au(0), Au(0)),
-                                        &[declaration_block],
-                                        false,
-                                        Some(previous_style),
-                                        None,
-                                        None,
-                                        Box::new(StdoutErrorReporter));
-            Arc::new(computed).into_strong()
-        },
-        None => ServoComputedValuesStrong::null(),
-    }
+    // FIXME (bug 1303229): Use the actual viewport size here
+    let (computed, _) = cascade(Size2D::new(Au(0), Au(0)),
+                                &[declaration_block],
+                                false,
+                                Some(previous_style),
+                                None,
+                                None,
+                                Box::new(StdoutErrorReporter));
+    Arc::new(computed).into_strong()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleWorkerThreadCount() -> u32 {
     *NUM_THREADS as u32
 }
 
 #[no_mangle]
@@ -404,102 +398,75 @@ pub extern "C" fn Servo_ParseProperty(pr
     match PropertyDeclaration::parse(name, &context, &mut Parser::new(value_str),
                                      &mut results, false) {
         PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {},
         _ => return RawServoDeclarationBlockStrong::null(),
     }
 
     let results = results.into_iter().map(|r| (r, Importance::Normal)).collect();
 
-    Arc::new(GeckoDeclarationBlock {
-        declarations: Some(Arc::new(RwLock::new(PropertyDeclarationBlock {
-            declarations: results,
-            important_count: 0,
-        }))),
-        cache: AtomicPtr::new(ptr::null_mut()),
-        immutable: AtomicBool::new(false),
-    }).into_strong()
+    Arc::new(RwLock::new(PropertyDeclarationBlock {
+        declarations: results,
+        important_count: 0,
+    })).into_strong()
 }
+
 #[no_mangle]
-pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
-                                            cache: *mut nsHTMLCSSStyleSheet)
+pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32)
                                             -> RawServoDeclarationBlockStrong {
     let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
-    Arc::new(GeckoDeclarationBlock {
-        declarations: GeckoElement::parse_style_attribute(value).map(|block| {
-            Arc::new(RwLock::new(block))
-        }),
-        cache: AtomicPtr::new(cache),
-        immutable: AtomicBool::new(false),
-    }).into_strong()
+    Arc::new(RwLock::new(GeckoElement::parse_style_attribute(value))).into_strong()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_AddRef(declarations: RawServoDeclarationBlockBorrowed) {
-    unsafe { GeckoDeclarationBlock::addref(declarations) };
+    unsafe { RwLock::<PropertyDeclarationBlock>::addref(declarations) };
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_Release(declarations: RawServoDeclarationBlockBorrowed) {
-    unsafe { GeckoDeclarationBlock::release(declarations) };
+    unsafe { RwLock::<PropertyDeclarationBlock>::release(declarations) };
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_Equals(a: RawServoDeclarationBlockBorrowed,
                                                 b: RawServoDeclarationBlockBorrowed)
                                                 -> bool {
-    GeckoDeclarationBlock::as_arc(&a) == GeckoDeclarationBlock::as_arc(&b)
-}
-
-#[no_mangle]
-pub extern "C" fn Servo_DeclarationBlock_GetCache(declarations: RawServoDeclarationBlockBorrowed)
-                                                 -> *mut nsHTMLCSSStyleSheet {
-    GeckoDeclarationBlock::as_arc(&declarations).cache.load(Ordering::Relaxed)
-}
-
-#[no_mangle]
-pub extern "C" fn Servo_DeclarationBlock_SetImmutable(declarations: RawServoDeclarationBlockBorrowed) {
-    GeckoDeclarationBlock::as_arc(&declarations).immutable.store(true, Ordering::Relaxed)
-}
-
-#[no_mangle]
-pub extern "C" fn Servo_DeclarationBlock_ClearCachePointer(declarations: RawServoDeclarationBlockBorrowed) {
-    GeckoDeclarationBlock::as_arc(&declarations).cache.store(ptr::null_mut(), Ordering::Relaxed)
+    *RwLock::<PropertyDeclarationBlock>::as_arc(&a).read() == *RwLock::<PropertyDeclarationBlock>::as_arc(&b).read()
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_DeclarationBlock_SerializeOneValue(
     declarations: RawServoDeclarationBlockBorrowed,
     buffer: *mut nsString)
 {
     let mut string = String::new();
 
-    if let Some(ref declarations) = GeckoDeclarationBlock::as_arc(&declarations).declarations {
-        declarations.read().to_css(&mut string).unwrap();
-        // FIXME: We are expecting |declarations| to be a declaration block with either a single
-        // longhand property-declaration or a series of longhand property-declarations that make
-        // up a single shorthand property. As a result, it should be possible to serialize
-        // |declarations| as a single declaration. However, we only want to return the *value* from
-        // that single declaration. For now, we just manually strip the property name, colon,
-        // leading spacing, and trailing space. In future we should find a more robust way to do
-        // this.
-        //
-        // See https://github.com/servo/servo/issues/13423
-        debug_assert!(string.find(':').is_some());
-        let position = string.find(':').unwrap();
-        // Get the value after the first colon and any following whitespace.
-        let value = &string[(position + 1)..].trim_left();
-        debug_assert!(value.ends_with(';'));
-        let length = value.len() - 1; // Strip last semicolon.
+    let declarations = RwLock::<PropertyDeclarationBlock>::as_arc(&declarations);
+    declarations.read().to_css(&mut string).unwrap();
+    // FIXME: We are expecting |declarations| to be a declaration block with either a single
+    // longhand property-declaration or a series of longhand property-declarations that make
+    // up a single shorthand property. As a result, it should be possible to serialize
+    // |declarations| as a single declaration. However, we only want to return the *value* from
+    // that single declaration. For now, we just manually strip the property name, colon,
+    // leading spacing, and trailing space. In future we should find a more robust way to do
+    // this.
+    //
+    // See https://github.com/servo/servo/issues/13423
+    debug_assert!(string.find(':').is_some());
+    let position = string.find(':').unwrap();
+    // Get the value after the first colon and any following whitespace.
+    let value = &string[(position + 1)..].trim_left();
+    debug_assert!(value.ends_with(';'));
+    let length = value.len() - 1; // Strip last semicolon.
 
-        // FIXME: Once we have nsString bindings for Servo (bug 1294742), we should be able to drop
-        // this and fill in |buffer| directly.
-        unsafe {
-            Gecko_Utf8SliceToString(buffer, value.as_ptr(), length);
-        }
+    // FIXME: Once we have nsString bindings for Servo (bug 1294742), we should be able to drop
+    // this and fill in |buffer| directly.
+    unsafe {
+        Gecko_Utf8SliceToString(buffer, value.as_ptr(), length);
     }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_CSSSupports(property: *const u8, property_length: u32,
                                     value: *const u8, value_length: u32) -> bool {
     let property = unsafe { from_utf8_unchecked(slice::from_raw_parts(property, property_length as usize)) };
     let value    = unsafe { from_utf8_unchecked(slice::from_raw_parts(value, value_length as usize)) };