Bug 1309090 - Use AtomicRefCell for RawServoStyleSet. draft
authorBobby Holley <bobbyholley@gmail.com>
Mon, 10 Oct 2016 18:51:46 -0700
changeset 423384 e66a22d2cdfb36b8d9e322c98d39fbef42e8e1ec
parent 423383 913504bef37118f7ff4cff50a6bea8e69de8bfec
child 533441 b95c2edd366789dd417ff9c2c16945a08dcacfbf
push id31892
push userbmo:bobbyholley@gmail.com
push dateTue, 11 Oct 2016 03:53:36 +0000
bugs1309090
milestone52.0a1
Bug 1309090 - Use AtomicRefCell for RawServoStyleSet. MozReview-Commit-ID: 27JeRluDAo3
layout/style/ServoBindingList.h
servo/components/style/gecko/data.rs
servo/components/style/gecko_bindings/bindings.rs
servo/ports/geckolib/glue.rs
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -33,23 +33,23 @@ SERVO_BINDING_FUNC(Servo_StyleSheet_AddR
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSheet_Release, void,
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSheet_HasRules, bool,
                    RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_Init, RawServoStyleSetOwned)
 SERVO_BINDING_FUNC(Servo_StyleSet_Drop, void, RawServoStyleSetOwned set)
 SERVO_BINDING_FUNC(Servo_StyleSet_AppendStyleSheet, void,
-                   RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet)
+                   RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_PrependStyleSheet, void,
-                   RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet)
+                   RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_RemoveStyleSheet, void,
-                   RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet)
+                   RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet)
 SERVO_BINDING_FUNC(Servo_StyleSet_InsertStyleSheetBefore, void,
-                   RawServoStyleSetBorrowedMut set, RawServoStyleSheetBorrowed sheet,
+                   RawServoStyleSetBorrowed set, RawServoStyleSheetBorrowed sheet,
                    RawServoStyleSheetBorrowed reference)
 
 // Animations API
 SERVO_BINDING_FUNC(Servo_ParseProperty,
                    ServoDeclarationBlockStrong,
                    const uint8_t* property_bytes,
                    uint32_t property_length,
                    const uint8_t* value_bytes,
@@ -91,22 +91,22 @@ SERVO_BINDING_FUNC(Servo_CSSSupports, bo
                    const uint8_t* value, uint32_t value_length)
 
 // Computed style data
 SERVO_BINDING_FUNC(Servo_ComputedValues_Get, ServoComputedValuesStrong,
                    RawGeckoNodeBorrowed node)
 SERVO_BINDING_FUNC(Servo_ComputedValues_GetForAnonymousBox,
                    ServoComputedValuesStrong,
                    ServoComputedValuesBorrowedOrNull parent_style_or_null,
-                   nsIAtom* pseudoTag, RawServoStyleSetBorrowedMut set)
+                   nsIAtom* pseudoTag, RawServoStyleSetBorrowed set)
 SERVO_BINDING_FUNC(Servo_ComputedValues_GetForPseudoElement,
                    ServoComputedValuesStrong,
                    ServoComputedValuesBorrowed parent_style,
                    RawGeckoElementBorrowed match_element, nsIAtom* pseudo_tag,
-                   RawServoStyleSetBorrowedMut set, bool is_probe)
+                   RawServoStyleSetBorrowed set, bool is_probe)
 SERVO_BINDING_FUNC(Servo_ComputedValues_Inherit, ServoComputedValuesStrong,
                    ServoComputedValuesBorrowedOrNull parent_style)
 SERVO_BINDING_FUNC(Servo_ComputedValues_AddRef, void,
                    ServoComputedValuesBorrowed computed_values)
 SERVO_BINDING_FUNC(Servo_ComputedValues_Release, void,
                    ServoComputedValuesBorrowed computed_values)
 
 // Initialize Servo components. Should be called exactly once at startup.
@@ -116,17 +116,17 @@ SERVO_BINDING_FUNC(Servo_Shutdown, void)
 
 // Restyle hints
 SERVO_BINDING_FUNC(Servo_ComputeRestyleHint, nsRestyleHint,
                    RawGeckoElementBorrowed element, ServoElementSnapshot* snapshot,
                    RawServoStyleSetBorrowed set)
 
 // Restyle the given subtree.
 SERVO_BINDING_FUNC(Servo_RestyleSubtree, void,
-                   RawGeckoNodeBorrowed node, RawServoStyleSetBorrowedMut set)
+                   RawGeckoNodeBorrowed node, RawServoStyleSetBorrowed set)
 
 // Style-struct management.
 #define STYLE_STRUCT(name, checkdata_cb)                            \
   struct nsStyle##name;                                             \
   SERVO_BINDING_FUNC(Servo_GetStyle##name, const nsStyle##name*,  \
                      ServoComputedValuesBorrowedOrNull computed_values)
 #include "nsStyleStructList.h"
 #undef STYLE_STRUCT
--- a/servo/components/style/gecko/data.rs
+++ b/servo/components/style/gecko/data.rs
@@ -1,12 +1,13 @@
 /* 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/. */
 
+use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut};
 use animation::Animation;
 use context::SharedStyleContext;
 use dom::OpaqueNode;
 use euclid::size::TypedSize2D;
 use gecko_bindings::bindings::RawServoStyleSet;
 use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
 use media_queries::{Device, MediaType};
 use num_cpus;
@@ -17,17 +18,17 @@ use std::collections::HashMap;
 use std::env;
 use std::sync::{Arc, RwLock};
 use std::sync::mpsc::{Receiver, Sender, channel};
 use style_traits::ViewportPx;
 use stylesheets::Stylesheet;
 use thread_state;
 use workqueue::WorkQueue;
 
-pub struct PerDocumentStyleData {
+pub struct PerDocumentStyleDataImpl {
     /// Rule processor.
     pub stylist: Arc<Stylist>,
 
     /// List of stylesheets, mirrored from Gecko.
     pub stylesheets: Vec<Arc<Stylesheet>>,
 
     /// Whether the stylesheets list above has changed since the last restyle.
     pub stylesheets_changed: bool,
@@ -39,50 +40,62 @@ pub struct PerDocumentStyleData {
     pub expired_animations: Arc<RwLock<HashMap<OpaqueNode, Vec<Animation>>>>,
 
     // FIXME(bholley): This shouldn't be per-document.
     pub work_queue: Option<WorkQueue<SharedStyleContext, WorkQueueData>>,
 
     pub num_threads: usize,
 }
 
+pub struct PerDocumentStyleData(AtomicRefCell<PerDocumentStyleDataImpl>);
+
 lazy_static! {
     pub static ref NUM_THREADS: usize = {
         match env::var("STYLO_THREADS").map(|s| s.parse::<usize>().expect("invalid STYLO_THREADS")) {
             Ok(num) => num,
             _ => cmp::max(num_cpus::get() * 3 / 4, 1),
         }
     };
 }
 
 impl PerDocumentStyleData {
-    pub fn new() -> PerDocumentStyleData {
+    pub fn new() -> Self {
         // FIXME(bholley): Real window size.
         let window_size: TypedSize2D<f32, ViewportPx> = TypedSize2D::new(800.0, 600.0);
         let device = Device::new(MediaType::Screen, window_size);
 
         let (new_anims_sender, new_anims_receiver) = channel();
 
-        PerDocumentStyleData {
+        PerDocumentStyleData(AtomicRefCell::new(PerDocumentStyleDataImpl {
             stylist: Arc::new(Stylist::new(device)),
             stylesheets: vec![],
             stylesheets_changed: true,
             new_animations_sender: new_anims_sender,
             new_animations_receiver: new_anims_receiver,
             running_animations: Arc::new(RwLock::new(HashMap::new())),
             expired_animations: Arc::new(RwLock::new(HashMap::new())),
             work_queue: if *NUM_THREADS <= 1 {
                 None
             } else {
                 WorkQueue::new("StyleWorker", thread_state::LAYOUT, *NUM_THREADS).ok()
             },
             num_threads: *NUM_THREADS,
-        }
+        }))
+    }
+
+    pub fn borrow(&self) -> AtomicRef<PerDocumentStyleDataImpl> {
+        self.0.borrow()
     }
 
+    pub fn borrow_mut(&self) -> AtomicRefMut<PerDocumentStyleDataImpl> {
+        self.0.borrow_mut()
+    }
+}
+
+impl PerDocumentStyleDataImpl {
     pub fn flush_stylesheets(&mut self) {
         // The stylist wants to be flushed if either the stylesheets change or the
         // device dimensions change. When we add support for media queries, we'll
         // need to detect the latter case and trigger a flush as well.
         if self.stylesheets_changed {
             let _ = Arc::get_mut(&mut self.stylist).unwrap()
                                                    .update(&self.stylesheets, None, true);
             self.stylesheets_changed = false;
@@ -91,15 +104,15 @@ impl PerDocumentStyleData {
 }
 
 unsafe impl HasFFI for PerDocumentStyleData {
     type FFIType = RawServoStyleSet;
 }
 unsafe impl HasSimpleFFI for PerDocumentStyleData {}
 unsafe impl HasBoxFFI for PerDocumentStyleData {}
 
-impl Drop for PerDocumentStyleData {
+impl Drop for PerDocumentStyleDataImpl {
     fn drop(&mut self) {
         if let Some(ref mut queue) = self.work_queue {
             queue.shutdown();
         }
     }
 }
--- a/servo/components/style/gecko_bindings/bindings.rs
+++ b/servo/components/style/gecko_bindings/bindings.rs
@@ -827,31 +827,31 @@ extern "C" {
 }
 extern "C" {
     pub fn Servo_StyleSet_Init() -> RawServoStyleSetOwned;
 }
 extern "C" {
     pub fn Servo_StyleSet_Drop(set: RawServoStyleSetOwned);
 }
 extern "C" {
-    pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowedMut,
+    pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowed,
                                            sheet: RawServoStyleSheetBorrowed);
 }
 extern "C" {
-    pub fn Servo_StyleSet_PrependStyleSheet(set: RawServoStyleSetBorrowedMut,
+    pub fn Servo_StyleSet_PrependStyleSheet(set: RawServoStyleSetBorrowed,
                                             sheet:
                                                 RawServoStyleSheetBorrowed);
 }
 extern "C" {
-    pub fn Servo_StyleSet_RemoveStyleSheet(set: RawServoStyleSetBorrowedMut,
+    pub fn Servo_StyleSet_RemoveStyleSheet(set: RawServoStyleSetBorrowed,
                                            sheet: RawServoStyleSheetBorrowed);
 }
 extern "C" {
     pub fn Servo_StyleSet_InsertStyleSheetBefore(set:
-                                                     RawServoStyleSetBorrowedMut,
+                                                     RawServoStyleSetBorrowed,
                                                  sheet:
                                                      RawServoStyleSheetBorrowed,
                                                  reference:
                                                      RawServoStyleSheetBorrowed);
 }
 extern "C" {
     pub fn Servo_ParseProperty(property_bytes: *const u8,
                                property_length: u32, value_bytes: *const u8,
@@ -913,27 +913,27 @@ extern "C" {
     pub fn Servo_ComputedValues_Get(node: RawGeckoNodeBorrowed)
      -> ServoComputedValuesStrong;
 }
 extern "C" {
     pub fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
                                                        ServoComputedValuesBorrowedOrNull,
                                                    pseudoTag: *mut nsIAtom,
                                                    set:
-                                                       RawServoStyleSetBorrowedMut)
+                                                       RawServoStyleSetBorrowed)
      -> ServoComputedValuesStrong;
 }
 extern "C" {
     pub fn Servo_ComputedValues_GetForPseudoElement(parent_style:
                                                         ServoComputedValuesBorrowed,
                                                     match_element:
                                                         RawGeckoElementBorrowed,
                                                     pseudo_tag: *mut nsIAtom,
                                                     set:
-                                                        RawServoStyleSetBorrowedMut,
+                                                        RawServoStyleSetBorrowed,
                                                     is_probe: bool)
      -> ServoComputedValuesStrong;
 }
 extern "C" {
     pub fn Servo_ComputedValues_Inherit(parent_style:
                                             ServoComputedValuesBorrowedOrNull)
      -> ServoComputedValuesStrong;
 }
@@ -954,17 +954,17 @@ extern "C" {
 extern "C" {
     pub fn Servo_ComputeRestyleHint(element: RawGeckoElementBorrowed,
                                     snapshot: *mut ServoElementSnapshot,
                                     set: RawServoStyleSetBorrowed)
      -> nsRestyleHint;
 }
 extern "C" {
     pub fn Servo_RestyleSubtree(node: RawGeckoNodeBorrowed,
-                                set: RawServoStyleSetBorrowedMut);
+                                set: RawServoStyleSetBorrowed);
 }
 extern "C" {
     pub fn Servo_GetStyleFont(computed_values:
                                   ServoComputedValuesBorrowedOrNull)
      -> *const nsStyleFont;
 }
 extern "C" {
     pub fn Servo_GetStyleColor(computed_values:
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -10,17 +10,17 @@ 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, TDocument, TElement, TNode};
+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::{GeckoElement, GeckoNode};
 use style::gecko_bindings::bindings::{RawGeckoElementBorrowed, RawGeckoNodeBorrowed};
@@ -85,17 +85,17 @@ fn restyle_subtree(node: GeckoNode, raw_
     //
     // FIXME(bholley): this should move into Servo_Initialize as soon as we get
     // rid of the HackilyFindSomeDeviceContext stuff that happens during
     // initial_values computation, since that stuff needs to be called further
     // along in startup than the sensible place to call Servo_Initialize.
     ComputedValues::initial_values();
 
     // The stylist consumes stylesheets lazily.
-    let per_doc_data = PerDocumentStyleData::from_ffi_mut(raw_data);
+    let mut per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     per_doc_data.flush_stylesheets();
 
     let local_context_data =
         LocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
 
     let shared_style_context = SharedStyleContext {
         // FIXME (bug 1303229): Use the actual viewport size here
         viewport_size: Size2D::new(Au(0), Au(0)),
@@ -197,50 +197,50 @@ pub extern "C" fn Servo_StyleSheet_FromU
     unsafe {
         transmute(sheet)
     }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorrowedMut,
                                                   raw_sheet: RawServoStyleSheetBorrowed) {
-    let data = PerDocumentStyleData::from_ffi_mut(raw_data);
+    let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     let sheet = HasArcFFI::as_arc(&raw_sheet);
     data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
     data.stylesheets.push(sheet.clone());
     data.stylesheets_changed = true;
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBorrowedMut,
                                                    raw_sheet: RawServoStyleSheetBorrowed) {
-    let data = PerDocumentStyleData::from_ffi_mut(raw_data);
+    let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     let sheet = HasArcFFI::as_arc(&raw_sheet);
     data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
     data.stylesheets.insert(0, sheet.clone());
     data.stylesheets_changed = true;
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleSetBorrowedMut,
                                                         raw_sheet: RawServoStyleSheetBorrowed,
                                                         raw_reference: RawServoStyleSheetBorrowed) {
-    let data = PerDocumentStyleData::from_ffi_mut(raw_data);
+    let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     let sheet = HasArcFFI::as_arc(&raw_sheet);
     let reference = HasArcFFI::as_arc(&raw_reference);
     data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
     let index = data.stylesheets.iter().position(|x| arc_ptr_eq(x, reference)).unwrap();
     data.stylesheets.insert(index, sheet.clone());
     data.stylesheets_changed = true;
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: RawServoStyleSetBorrowedMut,
                                                   raw_sheet: RawServoStyleSheetBorrowed) {
-    let data = PerDocumentStyleData::from_ffi_mut(raw_data);
+    let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     let sheet = HasArcFFI::as_arc(&raw_sheet);
     data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
     data.stylesheets_changed = true;
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSheet_HasRules(raw_sheet: RawServoStyleSheetBorrowed) -> bool {
     !Stylesheet::as_arc(&raw_sheet).rules.is_empty()
@@ -275,17 +275,17 @@ pub extern "C" fn Servo_ComputedValues_G
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowedOrNull,
                                                          pseudo_tag: *mut nsIAtom,
                                                          raw_data: RawServoStyleSetBorrowedMut)
      -> ServoComputedValuesStrong {
     // The stylist consumes stylesheets lazily.
-    let data = PerDocumentStyleData::from_ffi_mut(raw_data);
+    let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     data.flush_stylesheets();
 
     let atom = Atom::from(pseudo_tag);
     let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
 
 
     let maybe_parent = ComputedValues::arc_from_borrowed(&parent_style_or_null);
     let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent);
@@ -308,17 +308,17 @@ pub extern "C" fn Servo_ComputedValues_G
             ComputedValues::as_arc(&parent_style).clone().into_strong()
         }
     };
 
     let atom = Atom::from(pseudo_tag);
     let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ false);
 
     // The stylist consumes stylesheets lazily.
-    let data = PerDocumentStyleData::from_ffi_mut(raw_data);
+    let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     data.flush_stylesheets();
 
     let element = GeckoElement(match_element);
 
 
     match GeckoSelectorImpl::pseudo_element_cascade_type(&pseudo) {
         PseudoElementCascadeType::Eager => {
             let node = element.as_node();
@@ -516,17 +516,17 @@ pub extern "C" fn Servo_CSSSupports(prop
         Err(()) => false,
     }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_ComputeRestyleHint(element: RawGeckoElementBorrowed,
                                            snapshot: *mut ServoElementSnapshot,
                                            raw_data: RawServoStyleSetBorrowed) -> nsRestyleHint {
-    let per_doc_data = PerDocumentStyleData::from_ffi(raw_data);
+    let per_doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
     let snapshot = unsafe { GeckoElementSnapshot::from_raw(snapshot) };
     let element = GeckoElement(element);
 
     // NB: This involves an FFI call, we can get rid of it easily if needed.
     let current_state = element.get_state();
 
     let hint = per_doc_data.stylist
                            .compute_restyle_hint(&element, &snapshot,