servo: Merge #12826 - Add safer bindings for dealing with owned Arcs over FFI (from Manishearth:addref); r=emilio,bholley
authorManish Goregaokar <manishsmail@gmail.com>
Wed, 17 Aug 2016 07:35:43 -0500
changeset 339511 0c19f00167c2bbee9696e75137985709dead7872
parent 339510 27e7e5cc53f38a4b9724f422f7db4ac64e52f1ec
child 339512 266e6fc7de565f413ba9207be829ca26121ae616
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio, bholley
servo: Merge #12826 - Add safer bindings for dealing with owned Arcs over FFI (from Manishearth:addref); r=emilio,bholley Not yet ready to land, since I need to implement the logic for borrowed refs too. Ready for review for the first part. The corresponding gecko changes are at https://github.com/servo/gecko-dev/compare/crashfix...Manishearth:addref-borrow (I'll upload them to the bug once the borrow stuff is done) r? @bholley Source-Repo: https://github.com/servo/servo Source-Revision: fc7053e030999ed118c9cf2cac0835286d6dde06
servo/components/style/gecko_conversions.rs
servo/components/style/gecko_glue.rs
servo/components/style/lib.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/properties/longhand/inherited_svg.mako.rs
servo/ports/geckolib/binding_tools/regen.py
servo/ports/geckolib/gecko_bindings/bindings.rs
servo/ports/geckolib/gecko_bindings/structs_debug.rs
servo/ports/geckolib/gecko_bindings/structs_release.rs
servo/ports/geckolib/gecko_bindings/sugar/mod.rs
servo/ports/geckolib/gecko_bindings/sugar/refptr.rs
servo/ports/geckolib/glue.rs
servo/ports/geckolib/wrapper.rs
--- a/servo/components/style/gecko_conversions.rs
+++ b/servo/components/style/gecko_conversions.rs
@@ -1,20 +1,33 @@
 /* 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/. */
 
 //! 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::structs::nsStyleCoord_CalcValue;
+use gecko_bindings::sugar::refptr::HasArcFFI;
+use properties::ComputedValues;
+use stylesheets::Stylesheet;
 use values::computed::{CalcLengthOrPercentage, LengthOrPercentage};
 
+unsafe impl HasArcFFI for Stylesheet {
+    type FFIType = RawServoStyleSheet;
+}
+unsafe impl HasArcFFI for ComputedValues {
+    type FFIType = ServoComputedValues;
+}
+
 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,
         }
deleted file mode 100644
--- a/servo/components/style/gecko_glue.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-/* 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/. */
-
-#![allow(unsafe_code)]
-
-use std::marker::PhantomData;
-use std::mem::{forget, transmute};
-use std::sync::Arc;
-
-pub struct ArcHelpers<GeckoType, ServoType> {
-    phantom1: PhantomData<GeckoType>,
-    phantom2: PhantomData<ServoType>,
-}
-
-impl<GeckoType, ServoType> ArcHelpers<GeckoType, ServoType> {
-    pub fn with<F, Output>(raw: *mut GeckoType, cb: F) -> Output
-                           where F: FnOnce(&Arc<ServoType>) -> Output {
-        debug_assert!(!raw.is_null());
-
-        let owned = unsafe { Self::into(raw) };
-        let result = cb(&owned);
-        forget(owned);
-        result
-    }
-
-    pub fn maybe_with<F, Output>(maybe_raw: *mut GeckoType, cb: F) -> Output
-                                 where F: FnOnce(Option<&Arc<ServoType>>) -> Output {
-        let owned = if maybe_raw.is_null() {
-            None
-        } else {
-            Some(unsafe { Self::into(maybe_raw) })
-        };
-
-        let result = cb(owned.as_ref());
-        forget(owned);
-
-        result
-    }
-
-    pub unsafe fn into(ptr: *mut GeckoType) -> Arc<ServoType> {
-        transmute(ptr)
-    }
-
-    pub fn from(owned: Arc<ServoType>) -> *mut GeckoType {
-        unsafe { transmute(owned) }
-    }
-
-    pub fn borrow<F, Output>(borrowed: &Arc<ServoType>, cb: F) -> Output
-        where F: FnOnce(&mut GeckoType) -> Output
-    {
-        let borrowed_gecko_type: *const &mut GeckoType =
-            unsafe { transmute(borrowed) };
-
-        unsafe { cb(*borrowed_gecko_type) }
-    }
-
-    pub unsafe fn addref(ptr: *mut GeckoType) {
-        Self::with(ptr, |arc| forget(arc.clone()));
-    }
-
-    pub unsafe fn release(ptr: *mut GeckoType) {
-        let _ = Self::into(ptr);
-    }
-}
--- a/servo/components/style/lib.rs
+++ b/servo/components/style/lib.rs
@@ -78,17 +78,16 @@ pub mod cascade_info;
 pub mod context;
 pub mod custom_properties;
 pub mod data;
 pub mod dom;
 pub mod element_state;
 pub mod error_reporting;
 pub mod font_face;
 #[cfg(feature = "gecko")] pub mod gecko_conversions;
-#[cfg(feature = "gecko")] pub mod gecko_glue;
 #[cfg(feature = "gecko")] pub mod gecko_selector_impl;
 #[cfg(feature = "gecko")] pub mod gecko_values;
 pub mod keyframes;
 pub mod logical_geometry;
 pub mod matching;
 pub mod media_queries;
 pub mod parallel;
 pub mod parser;
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -19,20 +19,20 @@ use gecko_bindings::bindings::Gecko_Dest
 % endfor
 use gecko_bindings::bindings::{Gecko_CopyMozBindingFrom, Gecko_CopyListStyleTypeFrom};
 use gecko_bindings::bindings::{Gecko_SetMozBinding, Gecko_SetListStyleType};
 use gecko_bindings::bindings::{Gecko_SetNullImageValue, Gecko_SetGradientImageValue};
 use gecko_bindings::bindings::{Gecko_EnsureImageLayersLength, Gecko_CreateGradient};
 use gecko_bindings::bindings::{Gecko_CopyImageValueFrom, Gecko_CopyFontFamilyFrom};
 use gecko_bindings::bindings::{Gecko_FontFamilyList_AppendGeneric, Gecko_FontFamilyList_AppendNamed};
 use gecko_bindings::bindings::{Gecko_FontFamilyList_Clear, Gecko_InitializeImageLayer};
-use gecko_bindings::bindings;
+use gecko_bindings::bindings::ServoComputedValuesBorrowed;
 use gecko_bindings::structs;
 use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordDataMut};
-use gecko_glue::ArcHelpers;
+use gecko_bindings::sugar::refptr::HasArcFFI;
 use gecko_values::{StyleCoordHelpers, GeckoStyleCoordConvertible, convert_nscolor_to_rgba};
 use gecko_values::convert_rgba_to_nscolor;
 use gecko_values::round_border_to_device_pixels;
 use logical_geometry::WritingMode;
 use properties::CascadePropertyFn;
 use properties::longhands;
 use std::fmt::{self, Debug};
 use std::mem::{transmute, uninitialized, zeroed};
@@ -1353,20 +1353,19 @@ fn static_assert() {
     }
 
     ${impl_coord_copy('column_width', 'mColumnWidth')}
 </%self:impl_trait>
 
 <%def name="define_ffi_struct_accessor(style_struct)">
 #[no_mangle]
 #[allow(non_snake_case, unused_variables)]
-pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values: *mut bindings::ServoComputedValues)
+pub extern "C" fn Servo_GetStyle${style_struct.gecko_name}(computed_values: ServoComputedValuesBorrowed)
   -> *const ${style_struct.gecko_ffi_name} {
-    type Helpers = ArcHelpers<bindings::ServoComputedValues, ComputedValues>;
-    Helpers::with(computed_values, |values| values.get_${style_struct.name_lower}().get_gecko()
+    ComputedValues::with(computed_values, |values| values.get_${style_struct.name_lower}().get_gecko()
                                                 as *const ${style_struct.gecko_ffi_name})
 }
 </%def>
 
 % for style_struct in data.style_structs:
 ${declare_style_struct(style_struct)}
 ${impl_style_struct(style_struct)}
 % if not style_struct.name in data.manual_style_structs:
--- a/servo/components/style/properties/longhand/inherited_svg.mako.rs
+++ b/servo/components/style/properties/longhand/inherited_svg.mako.rs
@@ -29,16 +29,17 @@
                          products="gecko",
                          gecko_constant_prefix="NS_STYLE_COLOR_INTERPOLATION",
                          animatable=False)}
 
 ${helpers.predefined_type("fill-opacity", "Opacity", "1.0",
                           products="gecko", animatable=False)}
 
 ${helpers.single_keyword("fill-rule", "nonzero evenodd",
+                         gecko_enum_prefix="StyleFillRule",
                          products="gecko", animatable=False)}
 
 ${helpers.single_keyword("shape-rendering",
                          "auto optimizeSpeed crispEdges geometricPrecision",
                          products="gecko",
                          animatable=False)}
 
 ${helpers.single_keyword("stroke-linecap", "butt round square",
@@ -52,10 +53,10 @@
                           animatable=False)}
 
 ${helpers.predefined_type("stroke-opacity", "Opacity", "1.0",
                           products="gecko", animatable=False)}
 
 // Section 14 - Clipping, Masking and Compositing
 ${helpers.single_keyword("clip-rule", "nonzero evenodd",
                          products="gecko",
-                         gecko_constant_prefix="NS_STYLE_FILL_RULE",
+                         gecko_enum_prefix="StyleFillRule",
                          animatable=False)}
--- a/servo/ports/geckolib/binding_tools/regen.py
+++ b/servo/ports/geckolib/binding_tools/regen.py
@@ -64,17 +64,17 @@ COMPILATION_TARGETS = {
             "release": {
             }
         },
         "match_headers": [
             "RefCountType.h", "nscore.h", "nsError.h", "nsID.h", "nsString",
             "nsAString", "nsSubstring", "nsTSubstring", "nsTString",
             "nsISupportsBase.h", "nsCOMPtr.h", "nsIAtom.h", "nsIURI.h",
             "nsAutoPtr.h", "nsColor.h", "nsCoord.h", "nsPoint.h", "nsRect.h",
-            "nsMargin.h", "nsThemeConstants.h", "nsCSSProperty.h",
+            "nsMargin.h", "nsThemeConstants.h", "nsCSSProperty.h", "nsCSSPropertyID.h",
             "CSSVariableValues.h", "nsFont.h", "nsTHashtable.h",
             "PLDHashTable.h", "nsColor.h", "nsStyleStruct.h", "nsStyleCoord.h",
             "RefPtr.h", "nsISupportsImpl.h", "gfxFontConstants.h",
             "gfxFontFamilyList.h", "gfxFontFeatures.h", "imgRequestProxy.h",
             "nsIRequest.h", "imgIRequest.h", "CounterStyleManager.h",
             "nsStyleConsts.h", "nsCSSValue.h", "SheetType.h", "nsIPrincipal.h",
             "nsDataHashtable.h", "nsCSSScanner.h", "nsTArray",
             "pair", "SheetParsingMode.h", "StaticPtr.h", "nsProxyRelease.h",
@@ -111,16 +111,19 @@ COMPILATION_TARGETS = {
         ],
     },
     # Generation of the ffi bindings.
     "bindings": {
         "target_dir": "../gecko_bindings",
         "raw_lines": [
             "use heapsize::HeapSizeOf;",
         ],
+        "flags": [
+            "-ignore-methods",
+        ],
         "match_headers": [
             "ServoBindings.h",
             "nsStyleStructList.h",
         ],
         "files": [
             "{}/dist/include/mozilla/ServoBindings.h",
         ],
 
@@ -140,16 +143,17 @@ COMPILATION_TARGETS = {
             "nsStyleCoord::Calc", "nsRestyleHint", "ServoElementSnapshot",
             "nsChangeHint", "SheetParsingMode", "nsMainThreadPtrHandle",
             "nsMainThreadPtrHolder", "nscolor", "nsFont", "FontFamilyList",
             "FontFamilyType", "nsIAtom", "nsStyleContext"
         ],
         "void_types": [
             "nsINode", "nsIDocument", "nsIPrincipal", "nsIURI",
         ],
+        "servo_arc_types": ["ServoComputedValues", "RawServoStyleSheet"]
     },
 
     "atoms": {
         "custom_build": regen_atoms.build,
     }
 }
 
 
@@ -295,17 +299,26 @@ def build(objdir, target_name, kind_name
     if "opaque_types" in current_target:
         for ty in current_target["opaque_types"]:
             flags.append("-opaque-type")
             flags.append(ty)
     if "void_types" in current_target:
         for ty in current_target["void_types"]:
             flags.append("-raw-line")
             flags.append("pub enum {} {{}}".format(ty))
-
+    if "servo_arc_types" in current_target:
+        for ty in current_target["servo_arc_types"]:
+            flags.append("-blacklist-type")
+            flags.append("{}Strong".format(ty))
+            flags.append("-raw-line")
+            flags.append("pub type {0}Strong = ::sugar::refptr::Strong<{0}>;".format(ty))
+            flags.append("-blacklist-type")
+            flags.append("{}Borrowed".format(ty))
+            flags.append("-raw-line")
+            flags.append("pub type {0}Borrowed<'a> = ::sugar::refptr::Borrowed<'a, {0}>;".format(ty))
     if "structs_types" in current_target:
         for ty in current_target["structs_types"]:
             ty_fragments = ty.split("::")
             mangled_name = ty.replace("::", "_")
             flags.append("-blacklist-type")
             flags.append(ty_fragments[-1])
             flags.append("-raw-line")
             if len(ty_fragments) > 1:
--- a/servo/ports/geckolib/gecko_bindings/bindings.rs
+++ b/servo/ports/geckolib/gecko_bindings/bindings.rs
@@ -1,15 +1,19 @@
 /* automatically generated by rust-bindgen */
 
 use heapsize::HeapSizeOf;
 pub enum nsINode {}
 pub enum nsIDocument {}
 pub enum nsIPrincipal {}
 pub enum nsIURI {}
+pub type ServoComputedValuesStrong = ::sugar::refptr::Strong<ServoComputedValues>;
+pub type ServoComputedValuesBorrowed<'a> = ::sugar::refptr::Borrowed<'a, ServoComputedValues>;
+pub type RawServoStyleSheetStrong = ::sugar::refptr::Strong<RawServoStyleSheet>;
+pub type RawServoStyleSheetBorrowed<'a> = ::sugar::refptr::Borrowed<'a, RawServoStyleSheet>;
 use structs::nsStyleFont;
 unsafe impl Send for nsStyleFont {}
 unsafe impl Sync for nsStyleFont {}
 impl HeapSizeOf for nsStyleFont { fn heap_size_of_children(&self) -> usize { 0 } }
 use structs::nsStyleColor;
 unsafe impl Send for nsStyleColor {}
 unsafe impl Sync for nsStyleColor {}
 impl HeapSizeOf for nsStyleColor { fn heap_size_of_children(&self) -> usize { 0 } }
@@ -296,17 +300,17 @@ extern "C" {
     pub fn Gecko_CopyMozBindingFrom(des: *mut nsStyleDisplay,
                                     src: *const nsStyleDisplay);
     pub fn Gecko_GetNodeFlags(node: *mut RawGeckoNode) -> u32;
     pub fn Gecko_SetNodeFlags(node: *mut RawGeckoNode, flags: u32);
     pub fn Gecko_UnsetNodeFlags(node: *mut RawGeckoNode, flags: u32);
     pub fn Gecko_GetStyleContext(node: *mut RawGeckoNode)
      -> *mut nsStyleContext;
     pub fn Gecko_CalcStyleDifference(oldstyle: *mut nsStyleContext,
-                                     newstyle: *mut ServoComputedValues)
+                                     newstyle: ServoComputedValuesBorrowed)
      -> nsChangeHint;
     pub fn Gecko_StoreStyleDifference(node: *mut RawGeckoNode,
                                       change: nsChangeHint);
     pub fn Gecko_EnsureTArrayCapacity(array: *mut ::std::os::raw::c_void,
                                       capacity: usize, elem_size: usize);
     pub fn Gecko_EnsureImageLayersLength(layers: *mut nsStyleImageLayers,
                                          len: usize);
     pub fn Gecko_InitializeImageLayer(layer: *mut Layer,
@@ -321,29 +325,30 @@ extern "C" {
     pub fn Servo_StylesheetFromUTF8Bytes(bytes: *const u8, length: u32,
                                          parsing_mode: SheetParsingMode,
                                          base_bytes: *const u8,
                                          base_length: u32,
                                          base: *mut ThreadSafeURIHolder,
                                          referrer: *mut ThreadSafeURIHolder,
                                          principal:
                                              *mut ThreadSafePrincipalHolder)
-     -> *mut RawServoStyleSheet;
-    pub fn Servo_AddRefStyleSheet(sheet: *mut RawServoStyleSheet);
-    pub fn Servo_ReleaseStyleSheet(sheet: *mut RawServoStyleSheet);
-    pub fn Servo_AppendStyleSheet(sheet: *mut RawServoStyleSheet,
+     -> RawServoStyleSheetStrong;
+    pub fn Servo_AddRefStyleSheet(sheet: RawServoStyleSheetBorrowed);
+    pub fn Servo_ReleaseStyleSheet(sheet: RawServoStyleSheetBorrowed);
+    pub fn Servo_AppendStyleSheet(sheet: RawServoStyleSheetBorrowed,
                                   set: *mut RawServoStyleSet);
-    pub fn Servo_PrependStyleSheet(sheet: *mut RawServoStyleSheet,
+    pub fn Servo_PrependStyleSheet(sheet: RawServoStyleSheetBorrowed,
                                    set: *mut RawServoStyleSet);
-    pub fn Servo_RemoveStyleSheet(sheet: *mut RawServoStyleSheet,
+    pub fn Servo_RemoveStyleSheet(sheet: RawServoStyleSheetBorrowed,
                                   set: *mut RawServoStyleSet);
-    pub fn Servo_InsertStyleSheetBefore(sheet: *mut RawServoStyleSheet,
-                                        reference: *mut RawServoStyleSheet,
+    pub fn Servo_InsertStyleSheetBefore(sheet: RawServoStyleSheetBorrowed,
+                                        reference: RawServoStyleSheetBorrowed,
                                         set: *mut RawServoStyleSet);
-    pub fn Servo_StyleSheetHasRules(sheet: *mut RawServoStyleSheet) -> bool;
+    pub fn Servo_StyleSheetHasRules(sheet: RawServoStyleSheetBorrowed)
+     -> bool;
     pub fn Servo_InitStyleSet() -> *mut RawServoStyleSet;
     pub fn Servo_DropStyleSet(set: *mut RawServoStyleSet);
     pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
                                      cache: *mut nsHTMLCSSStyleSheet)
      -> *mut ServoDeclarationBlock;
     pub fn Servo_DropDeclarationBlock(declarations:
                                           *mut ServoDeclarationBlock);
     pub fn Servo_GetDeclarationBlockCache(declarations:
@@ -351,191 +356,197 @@ extern "C" {
      -> *mut nsHTMLCSSStyleSheet;
     pub fn Servo_SetDeclarationBlockImmutable(declarations:
                                                   *mut ServoDeclarationBlock);
     pub fn Servo_ClearDeclarationBlockCachePointer(declarations:
                                                        *mut ServoDeclarationBlock);
     pub fn Servo_CSSSupports(name: *const u8, name_length: u32,
                              value: *const u8, value_length: u32) -> bool;
     pub fn Servo_GetComputedValues(node: *mut RawGeckoNode)
-     -> *mut ServoComputedValues;
+     -> ServoComputedValuesStrong;
     pub fn Servo_GetComputedValuesForAnonymousBox(parentStyleOrNull:
-                                                      *mut ServoComputedValues,
+                                                      ServoComputedValuesBorrowed,
                                                   pseudoTag: *mut nsIAtom,
                                                   set: *mut RawServoStyleSet)
-     -> *mut ServoComputedValues;
+     -> ServoComputedValuesStrong;
     pub fn Servo_GetComputedValuesForPseudoElement(parent_style:
-                                                       *mut ServoComputedValues,
+                                                       ServoComputedValuesBorrowed,
                                                    match_element:
                                                        *mut RawGeckoElement,
                                                    pseudo_tag: *mut nsIAtom,
                                                    set: *mut RawServoStyleSet,
                                                    is_probe: bool)
-     -> *mut ServoComputedValues;
-    pub fn Servo_InheritComputedValues(parent_style: *mut ServoComputedValues)
-     -> *mut ServoComputedValues;
-    pub fn Servo_AddRefComputedValues(arg1: *mut ServoComputedValues);
-    pub fn Servo_ReleaseComputedValues(arg1: *mut ServoComputedValues);
+     -> ServoComputedValuesStrong;
+    pub fn Servo_InheritComputedValues(parent_style:
+                                           ServoComputedValuesBorrowed)
+     -> ServoComputedValuesStrong;
+    pub fn Servo_AddRefComputedValues(arg1: ServoComputedValuesBorrowed);
+    pub fn Servo_ReleaseComputedValues(arg1: ServoComputedValuesBorrowed);
     pub fn Servo_Initialize();
     pub fn Servo_Shutdown();
     pub fn Servo_RestyleDocument(doc: *mut RawGeckoDocument,
                                  set: *mut RawServoStyleSet);
     pub fn Servo_RestyleSubtree(node: *mut RawGeckoNode,
                                 set: *mut RawServoStyleSet);
     pub fn Servo_ComputeRestyleHint(element: *mut RawGeckoElement,
                                     snapshot: *mut ServoElementSnapshot,
                                     set: *mut RawServoStyleSet)
      -> nsRestyleHint;
     pub fn Gecko_Construct_nsStyleFont(ptr: *mut nsStyleFont);
     pub fn Gecko_CopyConstruct_nsStyleFont(ptr: *mut nsStyleFont,
                                            other: *const nsStyleFont);
     pub fn Gecko_Destroy_nsStyleFont(ptr: *mut nsStyleFont);
-    pub fn Servo_GetStyleFont(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleFont(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleFont;
     pub fn Gecko_Construct_nsStyleColor(ptr: *mut nsStyleColor);
     pub fn Gecko_CopyConstruct_nsStyleColor(ptr: *mut nsStyleColor,
                                             other: *const nsStyleColor);
     pub fn Gecko_Destroy_nsStyleColor(ptr: *mut nsStyleColor);
-    pub fn Servo_GetStyleColor(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleColor(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleColor;
     pub fn Gecko_Construct_nsStyleList(ptr: *mut nsStyleList);
     pub fn Gecko_CopyConstruct_nsStyleList(ptr: *mut nsStyleList,
                                            other: *const nsStyleList);
     pub fn Gecko_Destroy_nsStyleList(ptr: *mut nsStyleList);
-    pub fn Servo_GetStyleList(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleList(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleList;
     pub fn Gecko_Construct_nsStyleText(ptr: *mut nsStyleText);
     pub fn Gecko_CopyConstruct_nsStyleText(ptr: *mut nsStyleText,
                                            other: *const nsStyleText);
     pub fn Gecko_Destroy_nsStyleText(ptr: *mut nsStyleText);
-    pub fn Servo_GetStyleText(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleText(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleText;
     pub fn Gecko_Construct_nsStyleVisibility(ptr: *mut nsStyleVisibility);
     pub fn Gecko_CopyConstruct_nsStyleVisibility(ptr: *mut nsStyleVisibility,
                                                  other:
                                                      *const nsStyleVisibility);
     pub fn Gecko_Destroy_nsStyleVisibility(ptr: *mut nsStyleVisibility);
-    pub fn Servo_GetStyleVisibility(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleVisibility(computedValues:
+                                        ServoComputedValuesBorrowed)
      -> *const nsStyleVisibility;
     pub fn Gecko_Construct_nsStyleUserInterface(ptr:
                                                     *mut nsStyleUserInterface);
     pub fn Gecko_CopyConstruct_nsStyleUserInterface(ptr:
                                                         *mut nsStyleUserInterface,
                                                     other:
                                                         *const nsStyleUserInterface);
     pub fn Gecko_Destroy_nsStyleUserInterface(ptr: *mut nsStyleUserInterface);
     pub fn Servo_GetStyleUserInterface(computedValues:
-                                           *mut ServoComputedValues)
+                                           ServoComputedValuesBorrowed)
      -> *const nsStyleUserInterface;
     pub fn Gecko_Construct_nsStyleTableBorder(ptr: *mut nsStyleTableBorder);
     pub fn Gecko_CopyConstruct_nsStyleTableBorder(ptr:
                                                       *mut nsStyleTableBorder,
                                                   other:
                                                       *const nsStyleTableBorder);
     pub fn Gecko_Destroy_nsStyleTableBorder(ptr: *mut nsStyleTableBorder);
-    pub fn Servo_GetStyleTableBorder(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleTableBorder(computedValues:
+                                         ServoComputedValuesBorrowed)
      -> *const nsStyleTableBorder;
     pub fn Gecko_Construct_nsStyleSVG(ptr: *mut nsStyleSVG);
     pub fn Gecko_CopyConstruct_nsStyleSVG(ptr: *mut nsStyleSVG,
                                           other: *const nsStyleSVG);
     pub fn Gecko_Destroy_nsStyleSVG(ptr: *mut nsStyleSVG);
-    pub fn Servo_GetStyleSVG(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleSVG(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleSVG;
     pub fn Gecko_Construct_nsStyleVariables(ptr: *mut nsStyleVariables);
     pub fn Gecko_CopyConstruct_nsStyleVariables(ptr: *mut nsStyleVariables,
                                                 other:
                                                     *const nsStyleVariables);
     pub fn Gecko_Destroy_nsStyleVariables(ptr: *mut nsStyleVariables);
-    pub fn Servo_GetStyleVariables(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleVariables(computedValues:
+                                       ServoComputedValuesBorrowed)
      -> *const nsStyleVariables;
     pub fn Gecko_Construct_nsStyleBackground(ptr: *mut nsStyleBackground);
     pub fn Gecko_CopyConstruct_nsStyleBackground(ptr: *mut nsStyleBackground,
                                                  other:
                                                      *const nsStyleBackground);
     pub fn Gecko_Destroy_nsStyleBackground(ptr: *mut nsStyleBackground);
-    pub fn Servo_GetStyleBackground(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleBackground(computedValues:
+                                        ServoComputedValuesBorrowed)
      -> *const nsStyleBackground;
     pub fn Gecko_Construct_nsStylePosition(ptr: *mut nsStylePosition);
     pub fn Gecko_CopyConstruct_nsStylePosition(ptr: *mut nsStylePosition,
                                                other: *const nsStylePosition);
     pub fn Gecko_Destroy_nsStylePosition(ptr: *mut nsStylePosition);
-    pub fn Servo_GetStylePosition(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStylePosition(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStylePosition;
     pub fn Gecko_Construct_nsStyleTextReset(ptr: *mut nsStyleTextReset);
     pub fn Gecko_CopyConstruct_nsStyleTextReset(ptr: *mut nsStyleTextReset,
                                                 other:
                                                     *const nsStyleTextReset);
     pub fn Gecko_Destroy_nsStyleTextReset(ptr: *mut nsStyleTextReset);
-    pub fn Servo_GetStyleTextReset(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleTextReset(computedValues:
+                                       ServoComputedValuesBorrowed)
      -> *const nsStyleTextReset;
     pub fn Gecko_Construct_nsStyleDisplay(ptr: *mut nsStyleDisplay);
     pub fn Gecko_CopyConstruct_nsStyleDisplay(ptr: *mut nsStyleDisplay,
                                               other: *const nsStyleDisplay);
     pub fn Gecko_Destroy_nsStyleDisplay(ptr: *mut nsStyleDisplay);
-    pub fn Servo_GetStyleDisplay(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleDisplay(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleDisplay;
     pub fn Gecko_Construct_nsStyleContent(ptr: *mut nsStyleContent);
     pub fn Gecko_CopyConstruct_nsStyleContent(ptr: *mut nsStyleContent,
                                               other: *const nsStyleContent);
     pub fn Gecko_Destroy_nsStyleContent(ptr: *mut nsStyleContent);
-    pub fn Servo_GetStyleContent(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleContent(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleContent;
     pub fn Gecko_Construct_nsStyleUIReset(ptr: *mut nsStyleUIReset);
     pub fn Gecko_CopyConstruct_nsStyleUIReset(ptr: *mut nsStyleUIReset,
                                               other: *const nsStyleUIReset);
     pub fn Gecko_Destroy_nsStyleUIReset(ptr: *mut nsStyleUIReset);
-    pub fn Servo_GetStyleUIReset(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleUIReset(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleUIReset;
     pub fn Gecko_Construct_nsStyleTable(ptr: *mut nsStyleTable);
     pub fn Gecko_CopyConstruct_nsStyleTable(ptr: *mut nsStyleTable,
                                             other: *const nsStyleTable);
     pub fn Gecko_Destroy_nsStyleTable(ptr: *mut nsStyleTable);
-    pub fn Servo_GetStyleTable(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleTable(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleTable;
     pub fn Gecko_Construct_nsStyleMargin(ptr: *mut nsStyleMargin);
     pub fn Gecko_CopyConstruct_nsStyleMargin(ptr: *mut nsStyleMargin,
                                              other: *const nsStyleMargin);
     pub fn Gecko_Destroy_nsStyleMargin(ptr: *mut nsStyleMargin);
-    pub fn Servo_GetStyleMargin(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleMargin(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleMargin;
     pub fn Gecko_Construct_nsStylePadding(ptr: *mut nsStylePadding);
     pub fn Gecko_CopyConstruct_nsStylePadding(ptr: *mut nsStylePadding,
                                               other: *const nsStylePadding);
     pub fn Gecko_Destroy_nsStylePadding(ptr: *mut nsStylePadding);
-    pub fn Servo_GetStylePadding(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStylePadding(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStylePadding;
     pub fn Gecko_Construct_nsStyleBorder(ptr: *mut nsStyleBorder);
     pub fn Gecko_CopyConstruct_nsStyleBorder(ptr: *mut nsStyleBorder,
                                              other: *const nsStyleBorder);
     pub fn Gecko_Destroy_nsStyleBorder(ptr: *mut nsStyleBorder);
-    pub fn Servo_GetStyleBorder(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleBorder(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleBorder;
     pub fn Gecko_Construct_nsStyleOutline(ptr: *mut nsStyleOutline);
     pub fn Gecko_CopyConstruct_nsStyleOutline(ptr: *mut nsStyleOutline,
                                               other: *const nsStyleOutline);
     pub fn Gecko_Destroy_nsStyleOutline(ptr: *mut nsStyleOutline);
-    pub fn Servo_GetStyleOutline(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleOutline(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleOutline;
     pub fn Gecko_Construct_nsStyleXUL(ptr: *mut nsStyleXUL);
     pub fn Gecko_CopyConstruct_nsStyleXUL(ptr: *mut nsStyleXUL,
                                           other: *const nsStyleXUL);
     pub fn Gecko_Destroy_nsStyleXUL(ptr: *mut nsStyleXUL);
-    pub fn Servo_GetStyleXUL(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleXUL(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleXUL;
     pub fn Gecko_Construct_nsStyleSVGReset(ptr: *mut nsStyleSVGReset);
     pub fn Gecko_CopyConstruct_nsStyleSVGReset(ptr: *mut nsStyleSVGReset,
                                                other: *const nsStyleSVGReset);
     pub fn Gecko_Destroy_nsStyleSVGReset(ptr: *mut nsStyleSVGReset);
-    pub fn Servo_GetStyleSVGReset(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleSVGReset(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleSVGReset;
     pub fn Gecko_Construct_nsStyleColumn(ptr: *mut nsStyleColumn);
     pub fn Gecko_CopyConstruct_nsStyleColumn(ptr: *mut nsStyleColumn,
                                              other: *const nsStyleColumn);
     pub fn Gecko_Destroy_nsStyleColumn(ptr: *mut nsStyleColumn);
-    pub fn Servo_GetStyleColumn(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleColumn(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleColumn;
     pub fn Gecko_Construct_nsStyleEffects(ptr: *mut nsStyleEffects);
     pub fn Gecko_CopyConstruct_nsStyleEffects(ptr: *mut nsStyleEffects,
                                               other: *const nsStyleEffects);
     pub fn Gecko_Destroy_nsStyleEffects(ptr: *mut nsStyleEffects);
-    pub fn Servo_GetStyleEffects(computedValues: *mut ServoComputedValues)
+    pub fn Servo_GetStyleEffects(computedValues: ServoComputedValuesBorrowed)
      -> *const nsStyleEffects;
 }
--- a/servo/ports/geckolib/gecko_bindings/structs_debug.rs
+++ b/servo/ports/geckolib/gecko_bindings/structs_debug.rs
@@ -184,22 +184,16 @@ pub const NS_ERROR_MODULE_DOM_PUSH: ::st
 pub const NS_ERROR_MODULE_DOM_MEDIA: ::std::os::raw::c_uint = 41;
 pub const NS_ERROR_MODULE_GENERAL: ::std::os::raw::c_uint = 51;
 pub const NS_ERROR_SEVERITY_SUCCESS: ::std::os::raw::c_uint = 0;
 pub const NS_ERROR_SEVERITY_ERROR: ::std::os::raw::c_uint = 1;
 pub const NS_ERROR_MODULE_BASE_OFFSET: ::std::os::raw::c_uint = 69;
 pub const MOZ_STRING_WITH_OBSOLETE_API: ::std::os::raw::c_uint = 1;
 pub const NSID_LENGTH: ::std::os::raw::c_uint = 39;
 pub const NS_NUMBER_OF_FLAGS_IN_REFCNT: ::std::os::raw::c_uint = 2;
-pub const _STL_PAIR_H: ::std::os::raw::c_uint = 1;
-pub const _GLIBCXX_UTILITY: ::std::os::raw::c_uint = 1;
-pub const __cpp_lib_tuple_element_t: ::std::os::raw::c_uint = 201402;
-pub const __cpp_lib_tuples_by_type: ::std::os::raw::c_uint = 201304;
-pub const __cpp_lib_exchange_function: ::std::os::raw::c_uint = 201304;
-pub const __cpp_lib_integer_sequence: ::std::os::raw::c_uint = 201304;
 pub const NS_EVENT_STATE_HIGHEST_SERVO_BIT: ::std::os::raw::c_uint = 6;
 pub const DOM_USER_DATA: ::std::os::raw::c_uint = 1;
 pub const SMIL_MAPPED_ATTR_ANIMVAL: ::std::os::raw::c_uint = 2;
 pub const TWIPS_PER_POINT_INT: ::std::os::raw::c_uint = 20;
 pub const POINTS_PER_INCH_INT: ::std::os::raw::c_uint = 72;
 pub const NS_ATTRNAME_NODEINFO_BIT: ::std::os::raw::c_uint = 1;
 pub const NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM: ::std::os::raw::c_uint = 12;
 pub const NS_ATTRVALUE_INTEGERTYPE_BITS: ::std::os::raw::c_uint = 4;
@@ -799,18 +793,16 @@ pub const NS_STYLE_DOMINANT_BASELINE_HAN
 pub const NS_STYLE_DOMINANT_BASELINE_MATHEMATICAL: ::std::os::raw::c_uint = 7;
 pub const NS_STYLE_DOMINANT_BASELINE_CENTRAL: ::std::os::raw::c_uint = 8;
 pub const NS_STYLE_DOMINANT_BASELINE_MIDDLE: ::std::os::raw::c_uint = 9;
 pub const NS_STYLE_DOMINANT_BASELINE_TEXT_AFTER_EDGE: ::std::os::raw::c_uint =
     10;
 pub const NS_STYLE_DOMINANT_BASELINE_TEXT_BEFORE_EDGE: ::std::os::raw::c_uint
           =
     11;
-pub const NS_STYLE_FILL_RULE_NONZERO: ::std::os::raw::c_uint = 0;
-pub const NS_STYLE_FILL_RULE_EVENODD: ::std::os::raw::c_uint = 1;
 pub const NS_STYLE_IMAGE_RENDERING_AUTO: ::std::os::raw::c_uint = 0;
 pub const NS_STYLE_IMAGE_RENDERING_OPTIMIZESPEED: ::std::os::raw::c_uint = 1;
 pub const NS_STYLE_IMAGE_RENDERING_OPTIMIZEQUALITY: ::std::os::raw::c_uint =
     2;
 pub const NS_STYLE_IMAGE_RENDERING_CRISPEDGES: ::std::os::raw::c_uint = 3;
 pub const NS_STYLE_MASK_TYPE_LUMINANCE: ::std::os::raw::c_uint = 0;
 pub const NS_STYLE_MASK_TYPE_ALPHA: ::std::os::raw::c_uint = 1;
 pub const NS_STYLE_PAINT_ORDER_NORMAL: ::std::os::raw::c_uint = 0;
@@ -2792,22 +2784,16 @@ pub struct nsIExpandedPrincipal {
 #[repr(C)]
 pub struct _vftable_nsIExpandedPrincipal {
     pub _base: _vftable_nsISupports,
 }
 impl ::std::clone::Clone for nsIExpandedPrincipal {
     fn clone(&self) -> Self { *self }
 }
 #[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct _Make_integer_sequence<_Tp, _ISeq> {
-    pub _phantom0: ::std::marker::PhantomData<_Tp>,
-    pub _phantom1: ::std::marker::PhantomData<_ISeq>,
-}
-#[repr(C)]
 #[derive(Debug, Copy)]
 pub struct nsIURI {
     pub _base: nsISupports,
 }
 #[repr(C)]
 pub struct _vftable_nsIURI {
     pub _base: _vftable_nsISupports,
 }
@@ -2849,17 +2835,17 @@ impl ::std::clone::Clone for nsIRequest 
  * instances. These states are calculated by IntrinsicState() and
  * ContentStatesChanged() has to be called when one of them changes thus
  * informing the layout/style engine of the change.
  * Event states are associated with pseudo-classes.
  */
 #[repr(C)]
 #[derive(Debug, Copy)]
 pub struct EventStates {
-    pub mStates: ::std::os::raw::c_ulong,
+    pub mStates: ::std::os::raw::c_ulonglong,
 }
 impl ::std::clone::Clone for EventStates {
     fn clone(&self) -> Self { *self }
 }
 #[test]
 fn bindgen_test_layout_EventStates() {
     assert_eq!(::std::mem::size_of::<EventStates>() , 8usize);
     assert_eq!(::std::mem::align_of::<EventStates>() , 8usize);
@@ -2979,17 +2965,17 @@ impl ::std::clone::Clone for nsMutationG
 #[test]
 fn bindgen_test_layout_nsMutationGuard() {
     assert_eq!(::std::mem::size_of::<nsMutationGuard>() , 8usize);
     assert_eq!(::std::mem::align_of::<nsMutationGuard>() , 8usize);
 }
 extern "C" {
     #[link_name = "_ZN15nsMutationGuard11sGenerationE"]
     pub static mut nsMutationGuard_consts_sGeneration:
-               ::std::os::raw::c_ulong;
+               ::std::os::raw::c_ulonglong;
 }
 pub type Float = f32;
 #[repr(i8)]
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
 pub enum SurfaceType {
     DATA = 0,
     D2D1_BITMAP = 1,
     D2D1_DRAWTARGET = 2,
@@ -3509,16 +3495,17 @@ pub enum nsChangeHint {
     nsChangeHint_UpdateTextPath = 524288,
     nsChangeHint_SchedulePaint = 1048576,
     nsChangeHint_NeutralChange = 2097152,
     nsChangeHint_InvalidateRenderingObservers = 4194304,
     nsChangeHint_ReflowChangesSizeOrPosition = 8388608,
     nsChangeHint_UpdateComputedBSize = 16777216,
     nsChangeHint_UpdateUsesOpacity = 33554432,
     nsChangeHint_UpdateBackgroundPosition = 67108864,
+    nsChangeHint_AllHints = 134217727,
 }
 pub type nsChangeHint_size_t = ::std::os::raw::c_int;
 /**
  * |nsRestyleHint| is a bitfield for the result of
  * |HasStateDependentStyle| and |HasAttributeDependentStyle|.  When no
  * restyling is necessary, use |nsRestyleHint(0)|.
  *
  * Without eRestyle_Force or eRestyle_ForceDescendants, the restyling process
@@ -3999,16 +3986,19 @@ pub enum StyleClipPathGeometryBox {
     Border = 3,
     Margin = 4,
     Fill = 5,
     Stroke = 6,
     View = 7,
 }
 #[repr(i8)]
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum StyleFillRule { Nonzero = 0, Evenodd = 1, }
+#[repr(i8)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
 pub enum StyleFloat {
     None_ = 0,
     Left = 1,
     Right = 2,
     InlineStart = 3,
     InlineEnd = 4,
 }
 #[repr(i8)]
@@ -4047,31 +4037,31 @@ pub enum StyleUserSelect {
     Elements = 3,
     All = 4,
     Toggle = 5,
     TriState = 6,
     Auto = 7,
     MozAll = 8,
     MozText = 9,
 }
-pub const eCSSProperty_COUNT_DUMMY: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_z_index;
-pub const eCSSProperty_all: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_COUNT_no_shorthands;
-pub const eCSSProperty_COUNT_DUMMY2: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_transition;
-pub const eCSSPropertyAlias_WordWrap: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_COUNT;
-pub const eCSSProperty_COUNT_DUMMY3: nsCSSProperty =
-    nsCSSProperty::eCSSPropertyAlias_WebkitUserSelect;
-pub const eCSSPropertyExtra_no_properties: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_COUNT_with_aliases;
+pub const eCSSProperty_COUNT_DUMMY: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_z_index;
+pub const eCSSProperty_all: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_COUNT_no_shorthands;
+pub const eCSSProperty_COUNT_DUMMY2: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_transition;
+pub const eCSSPropertyAlias_WordWrap: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_COUNT;
+pub const eCSSProperty_COUNT_DUMMY3: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSPropertyAlias_WebkitUserSelect;
+pub const eCSSPropertyExtra_no_properties: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_COUNT_with_aliases;
 #[repr(i32)]
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum nsCSSProperty {
+pub enum nsCSSPropertyID {
     eCSSProperty_UNKNOWN = -1,
     eCSSProperty_align_content = 0,
     eCSSProperty_align_items = 1,
     eCSSProperty_align_self = 2,
     eCSSProperty_animation_delay = 3,
     eCSSProperty_animation_direction = 4,
     eCSSProperty_animation_duration = 5,
     eCSSProperty_animation_fill_mode = 6,
@@ -5077,18 +5067,18 @@ pub struct nsCSSValueGradient {
 fn bindgen_test_layout_nsCSSValueGradient() {
     assert_eq!(::std::mem::size_of::<nsCSSValueGradient>() , 112usize);
     assert_eq!(::std::mem::align_of::<nsCSSValueGradient>() , 8usize);
 }
 #[repr(C)]
 pub struct nsCSSValueTokenStream {
     pub mRefCnt: nsAutoRefCnt,
     pub _mOwningThread: nsAutoOwningThread,
-    pub mPropertyID: nsCSSProperty,
-    pub mShorthandPropertyID: nsCSSProperty,
+    pub mPropertyID: nsCSSPropertyID,
+    pub mShorthandPropertyID: nsCSSPropertyID,
     pub mTokenStream: nsString,
     pub mBaseURI: nsCOMPtr<nsIURI>,
     pub mSheetURI: nsCOMPtr<nsIURI>,
     pub mSheetPrincipal: nsCOMPtr<nsIPrincipal>,
     pub mLineNumber: u32,
     pub mLineOffset: u32,
     pub mLevel: SheetType,
 }
@@ -5818,20 +5808,20 @@ fn bindgen_test_layout_nsStyleImageLayer
 #[test]
 fn bindgen_test_layout_nsStyleImageLayers() {
     assert_eq!(::std::mem::size_of::<nsStyleImageLayers>() , 176usize);
     assert_eq!(::std::mem::align_of::<nsStyleImageLayers>() , 8usize);
 }
 extern "C" {
     #[link_name = "_ZN18nsStyleImageLayers21kBackgroundLayerTableE"]
     pub static mut nsStyleImageLayers_consts_kBackgroundLayerTable:
-               *const nsCSSProperty;
+               *const nsCSSPropertyID;
     #[link_name = "_ZN18nsStyleImageLayers15kMaskLayerTableE"]
     pub static mut nsStyleImageLayers_consts_kMaskLayerTable:
-               *const nsCSSProperty;
+               *const nsCSSPropertyID;
 }
 #[repr(C)]
 pub struct nsStyleBackground {
     pub mImage: nsStyleImageLayers,
     pub mBackgroundColor: nscolor,
 }
 #[test]
 fn bindgen_test_layout_nsStyleBackground() {
@@ -6352,17 +6342,17 @@ fn bindgen_test_layout_nsTimingFunction(
     assert_eq!(::std::mem::align_of::<nsTimingFunction>() , 4usize);
 }
 #[repr(C)]
 #[derive(Debug)]
 pub struct StyleTransition {
     pub mTimingFunction: nsTimingFunction,
     pub mDuration: f32,
     pub mDelay: f32,
-    pub mProperty: nsCSSProperty,
+    pub mProperty: nsCSSPropertyID,
     pub mUnknownProperty: nsCOMPtr<nsIAtom>,
 }
 #[test]
 fn bindgen_test_layout_StyleTransition() {
     assert_eq!(::std::mem::size_of::<StyleTransition>() , 40usize);
     assert_eq!(::std::mem::align_of::<StyleTransition>() , 8usize);
 }
 #[repr(C)]
@@ -6383,17 +6373,17 @@ fn bindgen_test_layout_StyleAnimation() 
     assert_eq!(::std::mem::align_of::<StyleAnimation>() , 8usize);
 }
 #[repr(C)]
 #[derive(Debug)]
 pub struct StyleBasicShape {
     pub mRefCnt: nsAutoRefCnt,
     pub _mOwningThread: nsAutoOwningThread,
     pub mType: StyleBasicShapeType,
-    pub mFillRule: i32,
+    pub mFillRule: StyleFillRule,
     pub mCoordinates: nsTArray<nsStyleCoord>,
     pub mPosition: nsStyleImageLayers_Position,
     pub mRadius: nsStyleCorners,
 }
 #[test]
 fn bindgen_test_layout_StyleBasicShape() {
     assert_eq!(::std::mem::size_of::<StyleBasicShape>() , 128usize);
     assert_eq!(::std::mem::align_of::<StyleBasicShape>() , 8usize);
@@ -6733,20 +6723,20 @@ pub struct nsStyleSVG {
     pub mMarkerMid: FragmentOrURL,
     pub mMarkerStart: FragmentOrURL,
     pub mStrokeDasharray: nsTArray<nsStyleCoord>,
     pub mStrokeDashoffset: nsStyleCoord,
     pub mStrokeWidth: nsStyleCoord,
     pub mFillOpacity: f32,
     pub mStrokeMiterlimit: f32,
     pub mStrokeOpacity: f32,
-    pub mClipRule: u8,
+    pub mClipRule: StyleFillRule,
     pub mColorInterpolation: u8,
     pub mColorInterpolationFilters: u8,
-    pub mFillRule: u8,
+    pub mFillRule: StyleFillRule,
     pub mPaintOrder: u8,
     pub mShapeRendering: u8,
     pub mStrokeLinecap: u8,
     pub mStrokeLinejoin: u8,
     pub mTextAnchor: u8,
     pub mContextFlags: u8,
 }
 #[repr(u32)]
--- a/servo/ports/geckolib/gecko_bindings/structs_release.rs
+++ b/servo/ports/geckolib/gecko_bindings/structs_release.rs
@@ -184,22 +184,16 @@ pub const NS_ERROR_MODULE_DOM_PUSH: ::st
 pub const NS_ERROR_MODULE_DOM_MEDIA: ::std::os::raw::c_uint = 41;
 pub const NS_ERROR_MODULE_GENERAL: ::std::os::raw::c_uint = 51;
 pub const NS_ERROR_SEVERITY_SUCCESS: ::std::os::raw::c_uint = 0;
 pub const NS_ERROR_SEVERITY_ERROR: ::std::os::raw::c_uint = 1;
 pub const NS_ERROR_MODULE_BASE_OFFSET: ::std::os::raw::c_uint = 69;
 pub const MOZ_STRING_WITH_OBSOLETE_API: ::std::os::raw::c_uint = 1;
 pub const NSID_LENGTH: ::std::os::raw::c_uint = 39;
 pub const NS_NUMBER_OF_FLAGS_IN_REFCNT: ::std::os::raw::c_uint = 2;
-pub const _STL_PAIR_H: ::std::os::raw::c_uint = 1;
-pub const _GLIBCXX_UTILITY: ::std::os::raw::c_uint = 1;
-pub const __cpp_lib_tuple_element_t: ::std::os::raw::c_uint = 201402;
-pub const __cpp_lib_tuples_by_type: ::std::os::raw::c_uint = 201304;
-pub const __cpp_lib_exchange_function: ::std::os::raw::c_uint = 201304;
-pub const __cpp_lib_integer_sequence: ::std::os::raw::c_uint = 201304;
 pub const NS_EVENT_STATE_HIGHEST_SERVO_BIT: ::std::os::raw::c_uint = 6;
 pub const DOM_USER_DATA: ::std::os::raw::c_uint = 1;
 pub const SMIL_MAPPED_ATTR_ANIMVAL: ::std::os::raw::c_uint = 2;
 pub const TWIPS_PER_POINT_INT: ::std::os::raw::c_uint = 20;
 pub const POINTS_PER_INCH_INT: ::std::os::raw::c_uint = 72;
 pub const NS_ATTRNAME_NODEINFO_BIT: ::std::os::raw::c_uint = 1;
 pub const NS_ATTRVALUE_MAX_STRINGLENGTH_ATOM: ::std::os::raw::c_uint = 12;
 pub const NS_ATTRVALUE_INTEGERTYPE_BITS: ::std::os::raw::c_uint = 4;
@@ -799,18 +793,16 @@ pub const NS_STYLE_DOMINANT_BASELINE_HAN
 pub const NS_STYLE_DOMINANT_BASELINE_MATHEMATICAL: ::std::os::raw::c_uint = 7;
 pub const NS_STYLE_DOMINANT_BASELINE_CENTRAL: ::std::os::raw::c_uint = 8;
 pub const NS_STYLE_DOMINANT_BASELINE_MIDDLE: ::std::os::raw::c_uint = 9;
 pub const NS_STYLE_DOMINANT_BASELINE_TEXT_AFTER_EDGE: ::std::os::raw::c_uint =
     10;
 pub const NS_STYLE_DOMINANT_BASELINE_TEXT_BEFORE_EDGE: ::std::os::raw::c_uint
           =
     11;
-pub const NS_STYLE_FILL_RULE_NONZERO: ::std::os::raw::c_uint = 0;
-pub const NS_STYLE_FILL_RULE_EVENODD: ::std::os::raw::c_uint = 1;
 pub const NS_STYLE_IMAGE_RENDERING_AUTO: ::std::os::raw::c_uint = 0;
 pub const NS_STYLE_IMAGE_RENDERING_OPTIMIZESPEED: ::std::os::raw::c_uint = 1;
 pub const NS_STYLE_IMAGE_RENDERING_OPTIMIZEQUALITY: ::std::os::raw::c_uint =
     2;
 pub const NS_STYLE_IMAGE_RENDERING_CRISPEDGES: ::std::os::raw::c_uint = 3;
 pub const NS_STYLE_MASK_TYPE_LUMINANCE: ::std::os::raw::c_uint = 0;
 pub const NS_STYLE_MASK_TYPE_ALPHA: ::std::os::raw::c_uint = 1;
 pub const NS_STYLE_PAINT_ORDER_NORMAL: ::std::os::raw::c_uint = 0;
@@ -2771,22 +2763,16 @@ pub struct nsIExpandedPrincipal {
 #[repr(C)]
 pub struct _vftable_nsIExpandedPrincipal {
     pub _base: _vftable_nsISupports,
 }
 impl ::std::clone::Clone for nsIExpandedPrincipal {
     fn clone(&self) -> Self { *self }
 }
 #[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct _Make_integer_sequence<_Tp, _ISeq> {
-    pub _phantom0: ::std::marker::PhantomData<_Tp>,
-    pub _phantom1: ::std::marker::PhantomData<_ISeq>,
-}
-#[repr(C)]
 #[derive(Debug, Copy)]
 pub struct nsIURI {
     pub _base: nsISupports,
 }
 #[repr(C)]
 pub struct _vftable_nsIURI {
     pub _base: _vftable_nsISupports,
 }
@@ -2828,17 +2814,17 @@ impl ::std::clone::Clone for nsIRequest 
  * instances. These states are calculated by IntrinsicState() and
  * ContentStatesChanged() has to be called when one of them changes thus
  * informing the layout/style engine of the change.
  * Event states are associated with pseudo-classes.
  */
 #[repr(C)]
 #[derive(Debug, Copy)]
 pub struct EventStates {
-    pub mStates: ::std::os::raw::c_ulong,
+    pub mStates: ::std::os::raw::c_ulonglong,
 }
 impl ::std::clone::Clone for EventStates {
     fn clone(&self) -> Self { *self }
 }
 #[test]
 fn bindgen_test_layout_EventStates() {
     assert_eq!(::std::mem::size_of::<EventStates>() , 8usize);
     assert_eq!(::std::mem::align_of::<EventStates>() , 8usize);
@@ -2958,17 +2944,17 @@ impl ::std::clone::Clone for nsMutationG
 #[test]
 fn bindgen_test_layout_nsMutationGuard() {
     assert_eq!(::std::mem::size_of::<nsMutationGuard>() , 8usize);
     assert_eq!(::std::mem::align_of::<nsMutationGuard>() , 8usize);
 }
 extern "C" {
     #[link_name = "_ZN15nsMutationGuard11sGenerationE"]
     pub static mut nsMutationGuard_consts_sGeneration:
-               ::std::os::raw::c_ulong;
+               ::std::os::raw::c_ulonglong;
 }
 pub type Float = f32;
 #[repr(i8)]
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
 pub enum SurfaceType {
     DATA = 0,
     D2D1_BITMAP = 1,
     D2D1_DRAWTARGET = 2,
@@ -3488,16 +3474,17 @@ pub enum nsChangeHint {
     nsChangeHint_UpdateTextPath = 524288,
     nsChangeHint_SchedulePaint = 1048576,
     nsChangeHint_NeutralChange = 2097152,
     nsChangeHint_InvalidateRenderingObservers = 4194304,
     nsChangeHint_ReflowChangesSizeOrPosition = 8388608,
     nsChangeHint_UpdateComputedBSize = 16777216,
     nsChangeHint_UpdateUsesOpacity = 33554432,
     nsChangeHint_UpdateBackgroundPosition = 67108864,
+    nsChangeHint_AllHints = 134217727,
 }
 pub type nsChangeHint_size_t = ::std::os::raw::c_int;
 /**
  * |nsRestyleHint| is a bitfield for the result of
  * |HasStateDependentStyle| and |HasAttributeDependentStyle|.  When no
  * restyling is necessary, use |nsRestyleHint(0)|.
  *
  * Without eRestyle_Force or eRestyle_ForceDescendants, the restyling process
@@ -3978,16 +3965,19 @@ pub enum StyleClipPathGeometryBox {
     Border = 3,
     Margin = 4,
     Fill = 5,
     Stroke = 6,
     View = 7,
 }
 #[repr(i8)]
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
+pub enum StyleFillRule { Nonzero = 0, Evenodd = 1, }
+#[repr(i8)]
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
 pub enum StyleFloat {
     None_ = 0,
     Left = 1,
     Right = 2,
     InlineStart = 3,
     InlineEnd = 4,
 }
 #[repr(i8)]
@@ -4026,31 +4016,31 @@ pub enum StyleUserSelect {
     Elements = 3,
     All = 4,
     Toggle = 5,
     TriState = 6,
     Auto = 7,
     MozAll = 8,
     MozText = 9,
 }
-pub const eCSSProperty_COUNT_DUMMY: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_z_index;
-pub const eCSSProperty_all: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_COUNT_no_shorthands;
-pub const eCSSProperty_COUNT_DUMMY2: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_transition;
-pub const eCSSPropertyAlias_WordWrap: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_COUNT;
-pub const eCSSProperty_COUNT_DUMMY3: nsCSSProperty =
-    nsCSSProperty::eCSSPropertyAlias_WebkitUserSelect;
-pub const eCSSPropertyExtra_no_properties: nsCSSProperty =
-    nsCSSProperty::eCSSProperty_COUNT_with_aliases;
+pub const eCSSProperty_COUNT_DUMMY: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_z_index;
+pub const eCSSProperty_all: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_COUNT_no_shorthands;
+pub const eCSSProperty_COUNT_DUMMY2: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_transition;
+pub const eCSSPropertyAlias_WordWrap: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_COUNT;
+pub const eCSSProperty_COUNT_DUMMY3: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSPropertyAlias_WebkitUserSelect;
+pub const eCSSPropertyExtra_no_properties: nsCSSPropertyID =
+    nsCSSPropertyID::eCSSProperty_COUNT_with_aliases;
 #[repr(i32)]
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
-pub enum nsCSSProperty {
+pub enum nsCSSPropertyID {
     eCSSProperty_UNKNOWN = -1,
     eCSSProperty_align_content = 0,
     eCSSProperty_align_items = 1,
     eCSSProperty_align_self = 2,
     eCSSProperty_animation_delay = 3,
     eCSSProperty_animation_direction = 4,
     eCSSProperty_animation_duration = 5,
     eCSSProperty_animation_fill_mode = 6,
@@ -5056,18 +5046,18 @@ pub struct nsCSSValueGradient {
 fn bindgen_test_layout_nsCSSValueGradient() {
     assert_eq!(::std::mem::size_of::<nsCSSValueGradient>() , 112usize);
     assert_eq!(::std::mem::align_of::<nsCSSValueGradient>() , 8usize);
 }
 #[repr(C)]
 pub struct nsCSSValueTokenStream {
     pub mRefCnt: nsAutoRefCnt,
     pub _mOwningThread: nsAutoOwningThread,
-    pub mPropertyID: nsCSSProperty,
-    pub mShorthandPropertyID: nsCSSProperty,
+    pub mPropertyID: nsCSSPropertyID,
+    pub mShorthandPropertyID: nsCSSPropertyID,
     pub mTokenStream: nsString,
     pub mBaseURI: nsCOMPtr<nsIURI>,
     pub mSheetURI: nsCOMPtr<nsIURI>,
     pub mSheetPrincipal: nsCOMPtr<nsIPrincipal>,
     pub mLineNumber: u32,
     pub mLineOffset: u32,
     pub mLevel: SheetType,
 }
@@ -5796,20 +5786,20 @@ fn bindgen_test_layout_nsStyleImageLayer
 #[test]
 fn bindgen_test_layout_nsStyleImageLayers() {
     assert_eq!(::std::mem::size_of::<nsStyleImageLayers>() , 168usize);
     assert_eq!(::std::mem::align_of::<nsStyleImageLayers>() , 8usize);
 }
 extern "C" {
     #[link_name = "_ZN18nsStyleImageLayers21kBackgroundLayerTableE"]
     pub static mut nsStyleImageLayers_consts_kBackgroundLayerTable:
-               *const nsCSSProperty;
+               *const nsCSSPropertyID;
     #[link_name = "_ZN18nsStyleImageLayers15kMaskLayerTableE"]
     pub static mut nsStyleImageLayers_consts_kMaskLayerTable:
-               *const nsCSSProperty;
+               *const nsCSSPropertyID;
 }
 #[repr(C)]
 pub struct nsStyleBackground {
     pub mImage: nsStyleImageLayers,
     pub mBackgroundColor: nscolor,
 }
 #[test]
 fn bindgen_test_layout_nsStyleBackground() {
@@ -6330,17 +6320,17 @@ fn bindgen_test_layout_nsTimingFunction(
     assert_eq!(::std::mem::align_of::<nsTimingFunction>() , 4usize);
 }
 #[repr(C)]
 #[derive(Debug)]
 pub struct StyleTransition {
     pub mTimingFunction: nsTimingFunction,
     pub mDuration: f32,
     pub mDelay: f32,
-    pub mProperty: nsCSSProperty,
+    pub mProperty: nsCSSPropertyID,
     pub mUnknownProperty: nsCOMPtr<nsIAtom>,
 }
 #[test]
 fn bindgen_test_layout_StyleTransition() {
     assert_eq!(::std::mem::size_of::<StyleTransition>() , 40usize);
     assert_eq!(::std::mem::align_of::<StyleTransition>() , 8usize);
 }
 #[repr(C)]
@@ -6361,17 +6351,17 @@ fn bindgen_test_layout_StyleAnimation() 
     assert_eq!(::std::mem::align_of::<StyleAnimation>() , 8usize);
 }
 #[repr(C)]
 #[derive(Debug)]
 pub struct StyleBasicShape {
     pub mRefCnt: nsAutoRefCnt,
     pub _mOwningThread: nsAutoOwningThread,
     pub mType: StyleBasicShapeType,
-    pub mFillRule: i32,
+    pub mFillRule: StyleFillRule,
     pub mCoordinates: nsTArray<nsStyleCoord>,
     pub mPosition: nsStyleImageLayers_Position,
     pub mRadius: nsStyleCorners,
 }
 #[test]
 fn bindgen_test_layout_StyleBasicShape() {
     assert_eq!(::std::mem::size_of::<StyleBasicShape>() , 128usize);
     assert_eq!(::std::mem::align_of::<StyleBasicShape>() , 8usize);
@@ -6710,20 +6700,20 @@ pub struct nsStyleSVG {
     pub mMarkerMid: FragmentOrURL,
     pub mMarkerStart: FragmentOrURL,
     pub mStrokeDasharray: nsTArray<nsStyleCoord>,
     pub mStrokeDashoffset: nsStyleCoord,
     pub mStrokeWidth: nsStyleCoord,
     pub mFillOpacity: f32,
     pub mStrokeMiterlimit: f32,
     pub mStrokeOpacity: f32,
-    pub mClipRule: u8,
+    pub mClipRule: StyleFillRule,
     pub mColorInterpolation: u8,
     pub mColorInterpolationFilters: u8,
-    pub mFillRule: u8,
+    pub mFillRule: StyleFillRule,
     pub mPaintOrder: u8,
     pub mShapeRendering: u8,
     pub mStrokeLinecap: u8,
     pub mStrokeLinejoin: u8,
     pub mTextAnchor: u8,
     pub mContextFlags: u8,
 }
 #[repr(u32)]
--- a/servo/ports/geckolib/gecko_bindings/sugar/mod.rs
+++ b/servo/ports/geckolib/gecko_bindings/sugar/mod.rs
@@ -1,7 +1,8 @@
 /* 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/. */
 
 mod ns_style_auto_array;
 pub mod ns_style_coord;
 mod ns_t_array;
+pub mod refptr;
new file mode 100644
--- /dev/null
+++ b/servo/ports/geckolib/gecko_bindings/sugar/refptr.rs
@@ -0,0 +1,117 @@
+/* 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 std::marker::PhantomData;
+use std::mem::{forget, transmute};
+use std::ptr;
+use std::sync::Arc;
+
+/// Helper trait for conversions between FFI Strong/Borrowed types and Arcs
+///
+/// Should be implemented by types which are passed over FFI as Arcs
+/// via Strong and Borrowed
+pub unsafe trait HasArcFFI where Self: Sized {
+    /// Gecko's name for the type
+    /// This is equivalent to ArcInner<Self>
+    type FFIType: Sized;
+
+    /// Given a non-null borrowed FFI reference, this produces a temporary
+    /// Arc which is borrowed by the given closure and used.
+    /// Panics on null.
+    fn with<F, Output>(raw: Borrowed<Self::FFIType>, cb: F) -> Output
+               where F: FnOnce(&Arc<Self>) -> Output {
+        Self::maybe_with(raw, |opt| cb(opt.unwrap()))
+    }
+
+    /// Given a maybe-null borrowed FFI reference, this produces a temporary
+    /// Option<Arc> (None if null) which is borrowed by the given closure and used
+    fn maybe_with<F, Output>(maybe_raw: Borrowed<Self::FFIType>, cb: F) -> Output
+                         where F: FnOnce(Option<&Arc<Self>>) -> Output {
+        cb(Self::borrowed_as(&maybe_raw))
+    }
+
+    /// Given a non-null strong FFI reference, converts it into an Arc.
+    /// Panics on null.
+    fn into(ptr: Strong<Self::FFIType>) -> Arc<Self> {
+        assert!(!ptr.is_null());
+        unsafe { transmute(ptr) }
+    }
+
+    fn borrowed_as<'a>(ptr: &'a Borrowed<'a, Self::FFIType>) -> Option<&'a Arc<Self>> {
+        unsafe {
+            if ptr.is_null() {
+                None
+            } else {
+                Some(transmute::<&Borrowed<_>, &Arc<_>>(ptr))
+            }
+        }
+    }
+
+    /// Converts an Arc into a strong FFI reference.
+    fn from_arc(owned: Arc<Self>) -> Strong<Self::FFIType> {
+        unsafe { transmute(owned) }
+    }
+
+    /// Artificially increments the refcount of a borrowed Arc over FFI.
+    unsafe fn addref(ptr: Borrowed<Self::FFIType>) {
+        Self::with(ptr, |arc| forget(arc.clone()));
+    }
+
+    /// Given a (possibly null) borrowed FFI reference, decrements the refcount.
+    /// Unsafe since it doesn't consume the backing Arc. Run it only when you
+    /// know that a strong reference to the backing Arc is disappearing
+    /// (usually on the C++ side) without running the Arc destructor.
+    unsafe fn release(ptr: Borrowed<Self::FFIType>) {
+        if let Some(arc) = Self::borrowed_as(&ptr) {
+            let _: Arc<_> = ptr::read(arc as *const Arc<_>);
+        }
+    }
+
+    /// Produces a borrowed FFI reference by borrowing an Arc.
+    fn to_borrowed<'a>(arc: &'a Arc<Self>)
+        -> Borrowed<'a, Self::FFIType> {
+        let borrowedptr = arc as *const Arc<Self> as *const Borrowed<'a, Self::FFIType>;
+        unsafe { ptr::read(borrowedptr) }
+    }
+
+    /// Produces a null strong FFI reference
+    fn null_strong() -> Strong<Self::FFIType> {
+        unsafe { transmute(ptr::null::<Self::FFIType>()) }
+    }
+}
+
+#[repr(C)]
+/// Gecko-FFI-safe borrowed Arc (&T where T is an ArcInner).
+/// This can be null.
+pub struct Borrowed<'a, T: 'a> {
+    ptr: *const T,
+    _marker: PhantomData<&'a T>,
+}
+
+// manual impls because derive doesn't realize that `T: Clone` isn't necessary
+impl<'a, T> Copy for Borrowed<'a, T> {}
+
+impl<'a, T> Clone for Borrowed<'a, T> {
+    fn clone(&self) -> Self { *self }
+}
+
+impl<'a, T> Borrowed<'a, T> {
+    pub fn is_null(&self) -> bool {
+        self.ptr == ptr::null()
+    }
+}
+
+#[repr(C)]
+/// Gecko-FFI-safe Arc (T is an ArcInner).
+/// This can be null.
+pub struct Strong<T> {
+    ptr: *const T,
+    _marker: PhantomData<T>,
+}
+
+impl<T> Strong<T> {
+    pub fn is_null(&self) -> bool {
+        self.ptr == ptr::null()
+    }
+}
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3,36 +3,38 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #![allow(unsafe_code)]
 
 use app_units::Au;
 use data::{NUM_THREADS, PerDocumentStyleData};
 use env_logger;
 use euclid::Size2D;
+use gecko_bindings::bindings::RawServoStyleSet;
 use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
-use gecko_bindings::bindings::{RawServoStyleSet, RawServoStyleSheet, ServoComputedValues};
+use gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
+use gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
 use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder};
 use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet};
 use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
 use gecko_bindings::structs::ServoElementSnapshot;
 use gecko_bindings::structs::nsRestyleHint;
 use gecko_bindings::structs::{SheetParsingMode, nsIAtom};
+use gecko_bindings::sugar::refptr::HasArcFFI;
 use gecko_string_cache::Atom;
 use snapshot::GeckoElementSnapshot;
 use std::mem::transmute;
 use std::ptr;
 use std::slice;
 use std::str::from_utf8_unchecked;
 use std::sync::{Arc, Mutex};
 use style::arc_ptr_eq;
 use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
 use style::dom::{TDocument, TElement, TNode};
 use style::error_reporting::StdoutErrorReporter;
-use style::gecko_glue::ArcHelpers;
 use style::gecko_selector_impl::{GeckoSelectorImpl, PseudoElement};
 use style::parallel;
 use style::parser::ParserContextExtraData;
 use style::properties::{ComputedValues, PropertyDeclarationBlock, parse_one_declaration};
 use style::selector_impl::PseudoElementCascadeType;
 use style::sequential;
 use style::stylesheets::{Stylesheet, Origin};
 use style::timer::Timer;
@@ -140,17 +142,17 @@ pub extern "C" fn Servo_DropNodeData(dat
 pub extern "C" fn Servo_StylesheetFromUTF8Bytes(bytes: *const u8,
                                                 length: u32,
                                                 mode: SheetParsingMode,
                                                 base_bytes: *const u8,
                                                 base_length: u32,
                                                 base: *mut ThreadSafeURIHolder,
                                                 referrer: *mut ThreadSafeURIHolder,
                                                 principal: *mut ThreadSafePrincipalHolder)
-                                                -> *mut RawServoStyleSheet {
+                                                -> RawServoStyleSheetStrong {
     let input = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
 
     let origin = match mode {
         SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
         SheetParsingMode::eUserSheetFeatures => Origin::User,
         SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
     };
 
@@ -164,196 +166,183 @@ pub extern "C" fn Servo_StylesheetFromUT
     let sheet = Arc::new(Stylesheet::from_str(input, url, origin, Box::new(StdoutErrorReporter),
                                               extra_data));
     unsafe {
         transmute(sheet)
     }
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_AppendStyleSheet(raw_sheet: *mut RawServoStyleSheet,
+pub extern "C" fn Servo_AppendStyleSheet(raw_sheet: RawServoStyleSheetBorrowed,
                                          raw_data: *mut RawServoStyleSet) {
-    type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
-    Helpers::with(raw_sheet, |sheet| {
+    Stylesheet::with(raw_sheet, |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_PrependStyleSheet(raw_sheet: *mut RawServoStyleSheet,
+pub extern "C" fn Servo_PrependStyleSheet(raw_sheet: RawServoStyleSheetBorrowed,
                                           raw_data: *mut RawServoStyleSet) {
-    type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
-    Helpers::with(raw_sheet, |sheet| {
+    Stylesheet::with(raw_sheet, |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_InsertStyleSheetBefore(raw_sheet: *mut RawServoStyleSheet,
-                                               raw_reference: *mut RawServoStyleSheet,
+pub extern "C" fn Servo_InsertStyleSheetBefore(raw_sheet: RawServoStyleSheetBorrowed,
+                                               raw_reference: RawServoStyleSheetBorrowed,
                                                raw_data: *mut RawServoStyleSet) {
-    type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
-    Helpers::with(raw_sheet, |sheet| {
-        Helpers::with(raw_reference, |reference| {
+    Stylesheet::with(raw_sheet, |sheet| {
+        Stylesheet::with(raw_reference, |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_RemoveStyleSheet(raw_sheet: *mut RawServoStyleSheet,
+pub extern "C" fn Servo_RemoveStyleSheet(raw_sheet: RawServoStyleSheetBorrowed,
                                          raw_data: *mut RawServoStyleSet) {
-    type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
-    Helpers::with(raw_sheet, |sheet| {
+    Stylesheet::with(raw_sheet, |sheet| {
         data.stylesheets.retain(|x| !arc_ptr_eq(x, sheet));
         data.stylesheets_changed = true;
     });
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_StyleSheetHasRules(raw_sheet: *mut RawServoStyleSheet) -> bool {
-    type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
-    Helpers::with(raw_sheet, |sheet| !sheet.rules.is_empty())
+pub extern "C" fn Servo_StyleSheetHasRules(raw_sheet: RawServoStyleSheetBorrowed) -> bool {
+    Stylesheet::with(raw_sheet, |sheet| !sheet.rules.is_empty())
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_AddRefStyleSheet(sheet: *mut RawServoStyleSheet) -> () {
-    type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
-    unsafe { Helpers::addref(sheet) };
+pub extern "C" fn Servo_AddRefStyleSheet(sheet: RawServoStyleSheetBorrowed) -> () {
+    unsafe { Stylesheet::addref(sheet) };
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_ReleaseStyleSheet(sheet: *mut RawServoStyleSheet) -> () {
-    type Helpers = ArcHelpers<RawServoStyleSheet, Stylesheet>;
-    unsafe { Helpers::release(sheet) };
+pub extern "C" fn Servo_ReleaseStyleSheet(sheet: RawServoStyleSheetBorrowed) -> () {
+    unsafe { Stylesheet::release(sheet) };
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_GetComputedValues(node: *mut RawGeckoNode)
-     -> *mut ServoComputedValues {
+     -> ServoComputedValuesStrong {
     let node = unsafe { GeckoNode::from_raw(node) };
     let arc_cv = match node.borrow_data().map_or(None, |data| data.style.clone()) {
         Some(style) => style,
         None => {
             // FIXME(bholley): This case subverts the intended semantics of this
             // function, and exists only to make stylo builds more robust corner-
             // cases where Gecko wants the style for a node that Servo never
             // traversed. We should remove this as soon as possible.
             error!("stylo: encountered unstyled node, substituting default values.");
             Arc::new(ComputedValues::initial_values().clone())
         },
     };
-    unsafe { transmute(arc_cv) }
+    ComputedValues::from_arc(arc_cv)
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_GetComputedValuesForAnonymousBox(parent_style_or_null: *mut ServoComputedValues,
+pub extern "C" fn Servo_GetComputedValuesForAnonymousBox(parent_style_or_null: ServoComputedValuesBorrowed,
                                                          pseudo_tag: *mut nsIAtom,
                                                          raw_data: *mut RawServoStyleSet)
-     -> *mut ServoComputedValues {
+     -> ServoComputedValuesStrong {
     // The stylist consumes stylesheets lazily.
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
     data.flush_stylesheets();
 
     let atom = Atom::from(pseudo_tag);
     let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ true);
 
-    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
 
-    Helpers::maybe_with(parent_style_or_null, |maybe_parent| {
+    ComputedValues::maybe_with(parent_style_or_null, |maybe_parent| {
         let new_computed = data.stylist.precomputed_values_for_pseudo(&pseudo, maybe_parent);
-        new_computed.map_or(ptr::null_mut(), |c| Helpers::from(c))
+        new_computed.map_or(ComputedValues::null_strong(), |c| ComputedValues::from_arc(c))
     })
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_GetComputedValuesForPseudoElement(parent_style: *mut ServoComputedValues,
+pub extern "C" fn Servo_GetComputedValuesForPseudoElement(parent_style: ServoComputedValuesBorrowed,
                                                           match_element: *mut RawGeckoElement,
                                                           pseudo_tag: *mut nsIAtom,
                                                           raw_data: *mut RawServoStyleSet,
                                                           is_probe: bool)
-     -> *mut ServoComputedValues {
+     -> ServoComputedValuesStrong {
     debug_assert!(!match_element.is_null());
 
     let parent_or_null = || {
         if is_probe {
-            ptr::null_mut()
+            ComputedValues::null_strong()
         } else {
-            Servo_AddRefComputedValues(parent_style);
-            parent_style
+            ComputedValues::from_arc(ComputedValues::with(parent_style, |parent| parent.clone()))
         }
     };
 
     let atom = Atom::from(pseudo_tag);
     let pseudo = PseudoElement::from_atom_unchecked(atom, /* anon_box = */ false);
 
     // The stylist consumes stylesheets lazily.
     let data = PerDocumentStyleData::borrow_mut_from_raw(raw_data);
     data.flush_stylesheets();
 
     let element = unsafe { GeckoElement::from_raw(match_element) };
 
-    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
 
     match GeckoSelectorImpl::pseudo_element_cascade_type(&pseudo) {
         PseudoElementCascadeType::Eager => {
             let node = element.as_node();
             let maybe_computed = node.borrow_data()
                                      .and_then(|data| {
                                          data.per_pseudo.get(&pseudo).map(|c| c.clone())
                                      });
-            maybe_computed.map_or_else(parent_or_null, Helpers::from)
+            maybe_computed.map_or_else(parent_or_null, ComputedValues::from_arc)
         }
         PseudoElementCascadeType::Lazy => {
-            Helpers::with(parent_style, |parent| {
+            ComputedValues::with(parent_style, |parent| {
                 data.stylist
                     .lazily_compute_pseudo_element_style(&element, &pseudo, parent)
-                    .map_or_else(parent_or_null, Helpers::from)
+                    .map_or_else(parent_or_null, ComputedValues::from_arc)
             })
         }
         PseudoElementCascadeType::Precomputed => {
             unreachable!("Anonymous pseudo found in \
                          Servo_GetComputedValuesForPseudoElement");
         }
     }
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_InheritComputedValues(parent_style: *mut ServoComputedValues)
-     -> *mut ServoComputedValues {
-    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
+pub extern "C" fn Servo_InheritComputedValues(parent_style: ServoComputedValuesBorrowed)
+     -> ServoComputedValuesStrong {
     let style = if parent_style.is_null() {
         Arc::new(ComputedValues::initial_values().clone())
     } else {
-        Helpers::with(parent_style, ComputedValues::inherit_from)
+        ComputedValues::with(parent_style, ComputedValues::inherit_from)
     };
-    Helpers::from(style)
+    ComputedValues::from_arc(style)
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_AddRefComputedValues(ptr: *mut ServoComputedValues) -> () {
-    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
-    unsafe { Helpers::addref(ptr) };
+pub extern "C" fn Servo_AddRefComputedValues(ptr: ServoComputedValuesBorrowed) -> () {
+    unsafe { ComputedValues::addref(ptr) };
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_ReleaseComputedValues(ptr: *mut ServoComputedValues) -> () {
-    type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
-    unsafe { Helpers::release(ptr) };
+pub extern "C" fn Servo_ReleaseComputedValues(ptr: ServoComputedValuesBorrowed) -> () {
+    unsafe { ComputedValues::release(ptr) };
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_InitStyleSet() -> *mut RawServoStyleSet {
     let data = Box::new(PerDocumentStyleData::new());
     Box::into_raw(data) as *mut RawServoStyleSet
 }
 
--- a/servo/ports/geckolib/wrapper.rs
+++ b/servo/ports/geckolib/wrapper.rs
@@ -4,33 +4,33 @@
 
 #![allow(unsafe_code)]
 
 use gecko_bindings::bindings;
 use gecko_bindings::bindings::Gecko_ChildrenCount;
 use gecko_bindings::bindings::Gecko_ClassOrClassList;
 use gecko_bindings::bindings::Gecko_GetNodeData;
 use gecko_bindings::bindings::Gecko_GetStyleContext;
-use gecko_bindings::bindings::ServoComputedValues;
 use gecko_bindings::bindings::ServoNodeData;
 use gecko_bindings::bindings::{Gecko_CalcStyleDifference, Gecko_StoreStyleDifference};
 use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentElement};
 use gecko_bindings::bindings::{Gecko_GetFirstChild, Gecko_GetFirstChildElement};
 use gecko_bindings::bindings::{Gecko_GetLastChild, Gecko_GetLastChildElement};
 use gecko_bindings::bindings::{Gecko_GetNextSibling, Gecko_GetNextSiblingElement};
 use gecko_bindings::bindings::{Gecko_GetNodeFlags, Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
 use gecko_bindings::bindings::{Gecko_GetParentElement, Gecko_GetParentNode};
 use gecko_bindings::bindings::{Gecko_GetPrevSibling, Gecko_GetPrevSiblingElement};
 use gecko_bindings::bindings::{Gecko_GetServoDeclarationBlock, Gecko_IsHTMLElementInHTMLDocument};
 use gecko_bindings::bindings::{Gecko_IsLink, Gecko_IsRootElement, Gecko_IsTextNode};
 use gecko_bindings::bindings::{Gecko_IsUnvisitedLink, Gecko_IsVisitedLink};
 use gecko_bindings::bindings::{Gecko_LocalName, Gecko_Namespace, Gecko_NodeIsElement, Gecko_SetNodeData};
 use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
 use gecko_bindings::structs::{NODE_HAS_DIRTY_DESCENDANTS_FOR_SERVO, NODE_IS_DIRTY_FOR_SERVO};
 use gecko_bindings::structs::{nsIAtom, nsChangeHint, nsStyleContext};
+use gecko_bindings::sugar::refptr::HasArcFFI;
 use gecko_string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
 use glue::GeckoDeclarationBlock;
 use libc::uintptr_t;
 use selectors::Element;
 use selectors::matching::DeclarationBlock;
 use selectors::parser::{AttrSelector, NamespaceConstraint};
 use snapshot::GeckoElementSnapshot;
 use snapshot_helpers;
@@ -38,17 +38,16 @@ use std::marker::PhantomData;
 use std::ops::BitOr;
 use std::ptr;
 use std::sync::Arc;
 use style::data::PrivateStyleData;
 use style::dom::{OpaqueNode, PresentationalHintsSynthetizer};
 use style::dom::{TDocument, TElement, TNode, TRestyleDamage, UnsafeNode};
 use style::element_state::ElementState;
 use style::error_reporting::StdoutErrorReporter;
-use style::gecko_glue::ArcHelpers;
 use style::gecko_selector_impl::{GeckoSelectorImpl, NonTSPseudoClass, PseudoElement};
 use style::parser::ParserContextExtraData;
 use style::properties::{ComputedValues, parse_style_attribute};
 use style::properties::{PropertyDeclaration, PropertyDeclarationBlock};
 use style::refcell::{Ref, RefCell, RefMut};
 use style::selector_impl::ElementExt;
 use style::sink::Push;
 use url::Url;
@@ -103,23 +102,19 @@ impl TRestyleDamage for GeckoRestyleDama
 
     fn empty() -> Self {
         use std::mem;
         GeckoRestyleDamage(unsafe { mem::transmute(0u32) })
     }
 
     fn compute(source: &nsStyleContext,
                new_style: &Arc<ComputedValues>) -> Self {
-        type Helpers = ArcHelpers<ServoComputedValues, ComputedValues>;
         let context = source as *const nsStyleContext as *mut nsStyleContext;
-
-        Helpers::borrow(new_style, |new_style| {
-            let hint = unsafe { Gecko_CalcStyleDifference(context, new_style) };
-            GeckoRestyleDamage(hint)
-        })
+        let hint = unsafe { Gecko_CalcStyleDifference(context, ComputedValues::to_borrowed(new_style)) };
+        GeckoRestyleDamage(hint)
     }
 
     fn rebuild_and_reflow() -> Self {
         GeckoRestyleDamage(nsChangeHint::nsChangeHint_ReconstructFrame)
     }
 }
 
 impl BitOr for GeckoRestyleDamage {