Bug 1538661 - Simplify Owned FFI types. r=boris
authorEmilio Cobos Álvarez <emilio@crisal.io>
Tue, 26 Mar 2019 18:15:59 +0000
changeset 466139 75d859821fcf2006ba6070bddf80627fbf6aa065
parent 466138 0969fd6383cea58141d70fbb2d0895ccb476af6c
child 466140 76a3365dabc828137b58059681654ec3d417abce
push id35762
push usercsabou@mozilla.com
push dateWed, 27 Mar 2019 04:44:00 +0000
treeherdermozilla-central@bc572aee49b6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersboris
bugs1538661
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1538661 - Simplify Owned FFI types. r=boris And make them actually sound. We're defining functions on Rust-land that get structs as arguments, but declaring them in C++ as getting pointers. This is another step in order to be able to autogenerate ServoBindings.h and remove bindings.rs altogether. We remove FooOwned in favor of Owned<Foo>, which is generated via cbindgen. It'd be good to actually mark Owned and such as MOZ_MUST_USE_TYPE, so I sent https://github.com/eqrion/cbindgen/pull/307 for that. Differential Revision: https://phabricator.services.mozilla.com/D24681
dom/base/Document.cpp
dom/base/ResponsiveImageSelector.cpp
dom/base/ShadowRoot.cpp
dom/base/nsINode.cpp
dom/xbl/nsXBLPrototypeResources.cpp
layout/style/GeckoBindings.cpp
layout/style/GeckoBindings.h
layout/style/ServoBindingTypes.h
layout/style/ServoBindings.h
layout/style/ServoBindings.toml
layout/style/ServoBoxedTypeList.h
layout/style/moz.build
layout/style/test/gtest/StyloParsingBench.cpp
servo/components/style/build_gecko.rs
servo/components/style/cbindgen.toml
servo/components/style/gecko_bindings/sugar/ownership.rs
servo/ports/geckolib/glue.rs
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -1343,17 +1343,17 @@ Document::Document(const char* aContentT
       mCachedTabSizeGeneration(0),
       mInRDMPane(false) {
   MOZ_LOG(gDocumentLeakPRLog, LogLevel::Debug, ("DOCUMENT %p created", this));
 
   SetIsInDocument();
   SetIsConnected(true);
 
   if (StaticPrefs::layout_css_use_counters_enabled()) {
-    mStyleUseCounters.reset(Servo_UseCounters_Create());
+    mStyleUseCounters = Servo_UseCounters_Create().Consume();
   }
 
   SetContentTypeInternal(nsDependentCString(aContentType));
 
   // Start out mLastStyleSheetSet as null, per spec
   SetDOMStringToNull(mLastStyleSheetSet);
 
   // void state used to differentiate an empty source from an unselected source
--- a/dom/base/ResponsiveImageSelector.cpp
+++ b/dom/base/ResponsiveImageSelector.cpp
@@ -218,17 +218,17 @@ void ResponsiveImageSelector::ClearSelec
   mSelectedCandidateIndex = -1;
   mSelectedCandidateURL = nullptr;
 }
 
 bool ResponsiveImageSelector::SetSizesFromDescriptor(const nsAString& aSizes) {
   ClearSelectedCandidate();
 
   NS_ConvertUTF16toUTF8 sizes(aSizes);
-  mServoSourceSizeList.reset(Servo_SourceSizeList_Parse(&sizes));
+  mServoSourceSizeList = Servo_SourceSizeList_Parse(&sizes).Consume();
   return !!mServoSourceSizeList;
 }
 
 void ResponsiveImageSelector::AppendCandidateIfUnique(
     const ResponsiveImageCandidate& aCandidate) {
   int numCandidates = mCandidates.Length();
 
   // With the exception of Default, which should not be added until we are done
--- a/dom/base/ShadowRoot.cpp
+++ b/dom/base/ShadowRoot.cpp
@@ -361,17 +361,17 @@ void ShadowRoot::InsertSheetAt(size_t aI
   }
 }
 
 void ShadowRoot::InsertSheetIntoAuthorData(size_t aIndex, StyleSheet& aSheet) {
   MOZ_ASSERT(SheetAt(aIndex) == &aSheet);
   MOZ_ASSERT(aSheet.IsApplicable());
 
   if (!mServoStyles) {
-    mServoStyles.reset(Servo_AuthorStyles_Create());
+    mServoStyles = Servo_AuthorStyles_Create().Consume();
   }
 
   if (mStyleRuleMap) {
     mStyleRuleMap->SheetAdded(aSheet);
   }
 
   for (size_t i = aIndex + 1; i < SheetCount(); ++i) {
     StyleSheet* beforeSheet = SheetAt(i);
--- a/dom/base/nsINode.cpp
+++ b/dom/base/nsINode.cpp
@@ -2494,18 +2494,18 @@ const RawServoSelectorList* nsINode::Par
       return nullptr;
     }
 
     return list->get();
   }
 
   NS_ConvertUTF16toUTF8 selectorString(aSelectorString);
 
-  auto selectorList = UniquePtr<RawServoSelectorList>(
-      Servo_SelectorList_Parse(&selectorString));
+  UniquePtr<RawServoSelectorList> selectorList =
+      Servo_SelectorList_Parse(&selectorString).Consume();
   if (!selectorList) {
     aRv.ThrowDOMException(NS_ERROR_DOM_SYNTAX_ERR,
                           NS_LITERAL_CSTRING("'") + selectorString +
                               NS_LITERAL_CSTRING("' is not a valid selector"));
   }
 
   auto* ret = selectorList.get();
   cache.CacheList(aSelectorString, std::move(selectorList));
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -115,17 +115,17 @@ void nsXBLPrototypeResources::Traverse(n
 }
 
 void nsXBLPrototypeResources::Unlink() { mStyleSheetList.Clear(); }
 
 void nsXBLPrototypeResources::ClearLoader() { mLoader = nullptr; }
 
 void nsXBLPrototypeResources::SyncServoStyles() {
   mStyleRuleMap.reset(nullptr);
-  mServoStyles.reset(Servo_AuthorStyles_Create());
+  mServoStyles = Servo_AuthorStyles_Create().Consume();
   for (auto& sheet : mStyleSheetList) {
     Servo_AuthorStyles_AppendStyleSheet(mServoStyles.get(), sheet);
   }
 }
 
 void nsXBLPrototypeResources::ComputeServoStyles(
     const ServoStyleSet& aMasterStyleSet) {
   SyncServoStyles();
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -2056,18 +2056,18 @@ GeckoFontMetrics Gecko_GetFontMetrics(co
                     : -1.0;
   return ret;
 }
 
 NS_IMPL_THREADSAFE_FFI_REFCOUNTING(SheetLoadDataHolder, SheetLoadDataHolder);
 
 void Gecko_StyleSheet_FinishAsyncParse(
     SheetLoadDataHolder* aData, RawServoStyleSheetContentsStrong aSheetContents,
-    StyleUseCountersOwned aUseCounters) {
-  UniquePtr<StyleUseCounters> useCounters(aUseCounters);
+    StyleOwnedOrNull<StyleUseCounters> aUseCounters) {
+  UniquePtr<StyleUseCounters> useCounters = aUseCounters.Consume();
   RefPtr<SheetLoadDataHolder> loadData = aData;
   RefPtr<RawServoStyleSheetContents> sheetContents = aSheetContents.Consume();
   NS_DispatchToMainThread(NS_NewRunnableFunction(
       __func__, [d = std::move(loadData), contents = std::move(sheetContents),
                  counters = std::move(useCounters)]() mutable {
         MOZ_ASSERT(NS_IsMainThread());
         SheetLoadData* data = d->get();
         if (Document* doc = data->mLoader->GetDocument()) {
--- a/layout/style/GeckoBindings.h
+++ b/layout/style/GeckoBindings.h
@@ -105,17 +105,17 @@ void Gecko_DestroyStyleChildrenIterator(
 const nsINode* Gecko_GetNextStyleChild(mozilla::dom::StyleChildrenIterator*);
 
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(mozilla::css::SheetLoadDataHolder,
                                    SheetLoadDataHolder);
 
 void Gecko_StyleSheet_FinishAsyncParse(
     mozilla::css::SheetLoadDataHolder* data,
     RawServoStyleSheetContentsStrong sheet_contents,
-    StyleUseCountersOwnedOrNull use_counters);
+    mozilla::StyleOwnedOrNull<StyleUseCounters> use_counters);
 
 mozilla::StyleSheet* Gecko_LoadStyleSheet(
     mozilla::css::Loader* loader, mozilla::StyleSheet* parent,
     mozilla::css::SheetLoadData* parent_load_data,
     mozilla::css::LoaderReusableStyleSheets* reusable_sheets,
     RawServoCssUrlDataStrong url, RawServoMediaListStrong media_list);
 
 void Gecko_LoadStyleSheetAsync(mozilla::css::SheetLoadDataHolder* parent_data,
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -24,28 +24,22 @@
 //
 // Each of these types can have a number of different typedefs generated for
 // them, representing different notions of ownership when passing or receiving
 // these values across bindings and FFI:
 //
 //   RawServo{Type}Strong
 //     strong reference to an Arc-managed value
 //
-//   RawServo{Type}Owned
-//   RawServo{Type}OwnedOrNull
-//     owned reference to a Box-managed value (or null)
-//
 // All of these strong, and owned types are generated by adding
 // entries to one of these files:
 //
 //   ServoArcTypeList.h
 //     generates the Strong type
 //
-//   ServoBoxedTypeList.h
-//     generates the Owned & OwnedOrNull types
 //
 // The strong, and owned reference types should be used in FFI function
 // signatures where possible, to help indicate the ownership properties that
 // both sides of the function call must adhere to.
 //
 // There are some special cases defined at the bottom of this file that don't
 // fit neatly into these three categories.
 //
@@ -57,23 +51,16 @@
 // convert it into an already_AddRefed<RawServo{Type}>, otherwise it will leak.
 //
 // We don't currently have any cases where we pass a Strong value to Servo; this
 // could be done by creating a RawServo{Type}Strong struct value whose mPtr is
 // initialized to the result of calling `.forget().take()` on a
 // RefPtr<RawServo{Type}>, but it's probably easier just to pass a raw pointer
 // and let the Rust code turn it into an Arc.
 //
-// The Owned types are C++ typedefs for raw pointers.  When receiving an Owned
-// value from a Servo_* FFI function, it should be assigned to a UniquePtr<>,
-// otherwise it will leak.
-//
-// To pass an Owned value to Servo, call `release()` on the UniquePtr<> it's
-// living in (to take ownership of it), and pass that pointer in directly.
-//
 // TODO(heycam): We should perhaps have a similar struct for Owned types with a
 // Consume() method to convert them into a UniquePtr.  The struct for Strong
 // types at least have MOZ_MUST_USE_TYPE on them.
 //
 //
 // Using these types in Rust =========================
 //
 // The FFI type names are available in Rust in the gecko_bindings::bindings mod,
@@ -96,43 +83,38 @@
 // `Arc<Foo>`.
 //
 // The Owned types are defined as gecko_bindings::sugar::ownership::Owned<T>
 // (or OwnedOrNull<T>).
 //
 // This is another FFI safe type that represents the owning reference to the
 // value.  Dropping an Owned<T> will leak the value.
 //
-// A RawServoFooOwned received from FFI can be converted into a `Box<Foo>`
-// by calling `into_box()` or `into_box_opt()` on it.  To pass a
-// RawServoFooOwned back to Gecko, call `HasBoxFFI::into_ffi()` passing in
-// the `Box<Foo>` value.
-//
+// An Owned<RawServoFoo> received from FFI can be converted into a `Box<Foo>`
+// by calling `into_box()`.  To pass an Owned<RawServoFoo> back to Gecko, call
+// `HasBoxFFI::into_ffi()` passing in the `Box<Foo>` value.
 //
 // Reading through servo/components/style/gecko_bindings/sugar/ownership.rs
 // is also instructive in understanding all this.
 
 #ifndef mozilla_ServoBindingTypes_h
 #define mozilla_ServoBindingTypes_h
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/ServoComputedData.h"
 #include "mozilla/ServoTypes.h"
 #include "mozilla/UniquePtr.h"
 #include "mozilla/gfx/Types.h"
 #include "nsCSSPropertyID.h"
 #include "nsStyleAutoArray.h"
+#include "nsStyleConsts.h"
 #include "nsTArray.h"
 
 // Forward declarations.
 
-#define SERVO_BOXED_TYPE(name_, type_) struct type_;
-#include "mozilla/ServoBoxedTypeList.h"
-#undef SERVO_BOXED_TYPE
-
 #define SERVO_ARC_TYPE(name_, type_) struct type_;
 #include "mozilla/ServoArcTypeList.h"
 #undef SERVO_ARC_TYPE
 
 class nsCSSPropertyIDSet;
 class nsCSSValue;
 class nsINode;
 class nsPresContext;
@@ -153,23 +135,19 @@ struct URLExtraData;
 using ComputedKeyframeValues = nsTArray<PropertyStyleAnimationValuePair>;
 using GfxMatrix4x4 = mozilla::gfx::Float[16];
 
 namespace dom {
 class StyleChildrenIterator;
 class Document;
 class Element;
 }  // namespace dom
+
 }  // namespace mozilla
 
-#define DECL_OWNED_REF_TYPE_FOR(type_) typedef type_* type_##Owned;
-
-#define DECL_NULLABLE_OWNED_REF_TYPE_FOR(type_) \
-  typedef type_* type_##OwnedOrNull;
-
 #define SERVO_ARC_TYPE(name_, type_)                                    \
   struct MOZ_MUST_USE_TYPE type_##Strong {                              \
     type_* mPtr;                                                        \
     already_AddRefed<type_> Consume();                                  \
   };                                                                    \
   extern "C" {                                                          \
   void Servo_##name_##_AddRef(const type_*);                            \
   void Servo_##name_##_Release(const type_*);                           \
@@ -179,38 +157,49 @@ class Element;
   struct RefPtrTraits<type_> {                                          \
     static void AddRef(type_* aPtr) { Servo_##name_##_AddRef(aPtr); }   \
     static void Release(type_* aPtr) { Servo_##name_##_Release(aPtr); } \
   };                                                                    \
   }
 #include "mozilla/ServoArcTypeList.h"
 #undef SERVO_ARC_TYPE
 
-#define SERVO_BOXED_TYPE(name_, type_)                                 \
-  DECL_OWNED_REF_TYPE_FOR(type_)                                       \
-  DECL_NULLABLE_OWNED_REF_TYPE_FOR(type_)                              \
-  extern "C" void Servo_##name_##_Drop(type_##Owned ptr);              \
-  namespace mozilla {                                                  \
-  template <>                                                          \
-  class DefaultDelete<type_> {                                         \
-   public:                                                             \
-    void operator()(type_* aPtr) const { Servo_##name_##_Drop(aPtr); } \
-  };                                                                   \
+// See the comment in ServoBindings.h about the same.
+#pragma GCC diagnostic push
+#ifdef __clang__
+#  pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
+#endif
+
+#define SERVO_BOXED_TYPE(name_, type_)                              \
+  struct type_;                                                     \
+  extern "C" void Servo_##name_##_Drop(mozilla::StyleOwned<type_>); \
+  namespace mozilla {                                               \
+  template <>                                                       \
+  class DefaultDelete<type_> {                                      \
+   public:                                                          \
+    void operator()(type_* aPtr) const {                            \
+      Servo_##name_##_Drop(mozilla::StyleOwned<type_>{aPtr});       \
+    }                                                               \
+  };                                                                \
   }
-#include "mozilla/ServoBoxedTypeList.h"
+SERVO_BOXED_TYPE(StyleSet, RawServoStyleSet)
+SERVO_BOXED_TYPE(AuthorStyles, RawServoAuthorStyles)
+SERVO_BOXED_TYPE(SelectorList, RawServoSelectorList)
+SERVO_BOXED_TYPE(SourceSizeList, RawServoSourceSizeList)
+SERVO_BOXED_TYPE(UseCounters, StyleUseCounters)
 #undef SERVO_BOXED_TYPE
 
+#pragma GCC diagnostic pop
+
 // Other special cases.
 
 // TODO(heycam): Handle these elsewhere.
 struct RawServoAnimationValueTable;
 struct RawServoAnimationValueMap;
 
 struct MOZ_MUST_USE_TYPE ComputedStyleStrong {
   mozilla::ComputedStyle* mPtr;
   already_AddRefed<mozilla::ComputedStyle> Consume();
 };
 
 #undef DECL_ARC_REF_TYPE_FOR
-#undef DECL_OWNED_REF_TYPE_FOR
-#undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
 
 #endif  // mozilla_ServoBindingTypes_h
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -45,16 +45,26 @@ namespace dom {
 enum class IterationCompositeOperation : uint8_t;
 }
 }  // namespace mozilla
 
 namespace nsStyleTransformMatrix {
 enum class MatrixTransformOperator : uint8_t;
 }
 
+// The clang we use on windows complains about returning StyleStrong<> and
+// StyleOwned<>, since the template parameters are incomplete.
+//
+// But they only contain pointers so it is ok. Also, this warning hilariously
+// doesn't exist in GCC.
+#pragma GCC diagnostic push
+#ifdef __clang__
+#  pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"
+#endif
+
 extern "C" {
 
 // Element data
 void Servo_Element_ClearData(const mozilla::dom::Element* node);
 
 size_t Servo_Element_SizeOfExcludingThisAndCVs(
     mozilla::MallocSizeOf malloc_size_of,
     mozilla::MallocSizeOf malloc_enclosing_size_of,
@@ -133,17 +143,16 @@ void Servo_StyleSet_RebuildCachedData(co
 // We'd like to return `OriginFlags` here, but bindgen bitfield enums don't
 // work as return values with the Linux 32-bit ABI at the moment because
 // they wrap the value in a struct.
 mozilla::MediumFeaturesChangedResult Servo_StyleSet_MediumFeaturesChanged(
     const RawServoStyleSet* document_set,
     nsTArray<RawServoAuthorStyles*>* non_document_sets,
     bool may_affect_default_style);
 
-void Servo_StyleSet_Drop(RawServoStyleSetOwned set);
 void Servo_StyleSet_CompatModeChanged(const RawServoStyleSet* raw_data);
 
 void Servo_StyleSet_AppendStyleSheet(const RawServoStyleSet* set,
                                      const mozilla::StyleSheet* gecko_sheet);
 
 void Servo_StyleSet_RemoveStyleSheet(const RawServoStyleSet* set,
                                      const mozilla::StyleSheet* gecko_sheet);
 
@@ -177,25 +186,24 @@ const RawServoCounterStyleRule* Servo_St
 // references.
 gfxFontFeatureValueSet* Servo_StyleSet_BuildFontFeatureValueSet(
     const RawServoStyleSet* set);
 
 ComputedStyleStrong Servo_StyleSet_ResolveForDeclarations(
     const RawServoStyleSet* set, const mozilla::ComputedStyle* parent_style,
     const RawServoDeclarationBlock* declarations);
 
-void Servo_SelectorList_Drop(RawServoSelectorList*);
-RawServoSelectorList* Servo_SelectorList_Parse(const nsACString* selector_list);
-RawServoSourceSizeList* Servo_SourceSizeList_Parse(const nsACString* value);
+mozilla::StyleOwnedOrNull<RawServoSelectorList> Servo_SelectorList_Parse(
+    const nsACString* selector_list);
+mozilla::StyleOwned<RawServoSourceSizeList> Servo_SourceSizeList_Parse(
+    const nsACString* value);
 
 int32_t Servo_SourceSizeList_Evaluate(const RawServoStyleSet* set,
                                       const RawServoSourceSizeList*);
 
-void Servo_SourceSizeList_Drop(RawServoSourceSizeList*);
-
 bool Servo_SelectorList_Matches(const mozilla::dom::Element*,
                                 const RawServoSelectorList*);
 
 const mozilla::dom::Element* Servo_SelectorList_Closest(
     const mozilla::dom::Element*, const RawServoSelectorList*);
 
 const mozilla::dom::Element* Servo_SelectorList_QueryFirst(
     const nsINode*, const RawServoSelectorList*, bool may_use_invalidation);
@@ -210,18 +218,17 @@ void Servo_StyleSet_AddSizeOfExcludingTh
     mozilla::ServoStyleSetSizes* sizes, const RawServoStyleSet* set);
 
 void Servo_UACache_AddSizeOf(mozilla::MallocSizeOf malloc_size_of,
                              mozilla::MallocSizeOf malloc_enclosing_size_of,
                              mozilla::ServoStyleSetSizes* sizes);
 
 // AuthorStyles
 
-RawServoAuthorStyles* Servo_AuthorStyles_Create();
-void Servo_AuthorStyles_Drop(RawServoAuthorStyles*);
+mozilla::StyleOwned<RawServoAuthorStyles> Servo_AuthorStyles_Create();
 
 void Servo_AuthorStyles_AppendStyleSheet(RawServoAuthorStyles*,
                                          const mozilla::StyleSheet*);
 
 void Servo_AuthorStyles_RemoveStyleSheet(RawServoAuthorStyles*,
                                          const mozilla::StyleSheet*);
 
 void Servo_AuthorStyles_InsertStyleSheetBefore(
@@ -967,18 +974,17 @@ bool Servo_Property_IsInherited(const ns
 bool Servo_Property_SupportsType(const nsACString* name, uint8_t ty,
                                  bool* found);
 
 void Servo_Property_GetCSSValuesForProperty(const nsACString* name, bool* found,
                                             nsTArray<nsString>* result);
 
 uint64_t Servo_PseudoClass_GetStates(const nsACString* name);
 
-StyleUseCounters* Servo_UseCounters_Create();
-void Servo_UseCounters_Drop(StyleUseCountersOwned);
+mozilla::StyleOwned<StyleUseCounters> Servo_UseCounters_Create();
 
 void Servo_UseCounters_Merge(const StyleUseCounters* doc_counters,
                              const StyleUseCounters* sheet_counters);
 
 bool Servo_IsCssPropertyRecordedInUseCounter(const StyleUseCounters*,
                                              const nsACString* property,
                                              bool* out_known_prop);
 
@@ -993,9 +999,11 @@ void Servo_Quotes_GetQuote(const RawServ
 #define SERVO_ARC_TYPE(name_, type_)         \
   void Servo_##name_##_AddRef(const type_*); \
   void Servo_##name_##_Release(const type_*);
 #include "mozilla/ServoArcTypeList.h"
 #undef SERVO_ARC_TYPE
 
 }  // extern "C"
 
+#pragma GCC diagnostic pop
+
 #endif  // mozilla_ServoBindings_h
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -449,16 +449,18 @@ cbindgen-types = [
     { gecko = "StyleLetterSpacing", servo = "values::computed::text::LetterSpacing" },
     { gecko = "StyleGenericLineHeight", servo = "values::generics::text::LineHeight" },
     { gecko = "StyleContain", servo = "values::computed::Contain" },
     { gecko = "StyleRestyleHint", servo = "invalidation::element::restyle_hints::RestyleHint" },
     { gecko = "StyleTouchAction", servo = "values::computed::TouchAction" },
     { gecko = "StyleWillChangeBits", servo = "values::specified::box_::WillChangeBits" },
     { gecko = "StyleTextDecorationLine", servo = "values::computed::TextDecorationLine" },
     { gecko = "StyleMozListReversed", servo = "values::computed::MozListReversed" },
+    { gecko = "StyleOwned", servo = "gecko_bindings::sugar::ownership::Owned" },
+    { gecko = "StyleOwnedOrNull", servo = "gecko_bindings::sugar::ownership::OwnedOrNull" },
 ]
 
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::RustCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
deleted file mode 100644
--- a/layout/style/ServoBoxedTypeList.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* 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/. */
-
-/* a list of all Servo Box<T> types used across bindings, for preprocessing */
-
-// The first argument is the name of the Servo type used inside the Box.
-// This doesn't need to be accurate; it's only used to generate nice looking
-// FFI function names.
-//
-// The second argument is the name of an opaque Gecko type that will
-// correspond to the Servo type used inside the Box.  The convention for the
-// the name of the opaque Gecko type is "RawServo{Type}", where {Type} is
-// the name of the Servo type or something close to it.
-//
-// See the comment at the top of ServoBindingTypes.h for how to use these.
-//
-// If you add an entry to this file, you should also add impls of HasFFI
-// (with FFIType equal to ::gecko_bindings::structs::RawServo{Type}),
-// HasSimpleFFI, and HasBoxFFI to the Servo type. You will also need to
-// add a Servo_{FriendlyServoName}_Drop function to servo/ports/gecko/glue.rs.
-//
-// TODO(heycam): Do some of this automatically.
-
-// clang-format off
-// Needs to be a on single line
-SERVO_BOXED_TYPE(StyleSet, RawServoStyleSet)
-SERVO_BOXED_TYPE(AuthorStyles, RawServoAuthorStyles)
-SERVO_BOXED_TYPE(SelectorList, RawServoSelectorList)
-SERVO_BOXED_TYPE(SourceSizeList, RawServoSourceSizeList)
-SERVO_BOXED_TYPE(UseCounters, StyleUseCounters)
-// clang-format on
--- a/layout/style/moz.build
+++ b/layout/style/moz.build
@@ -88,17 +88,16 @@ EXPORTS.mozilla += [
     'PostTraversalTask.h',
     'PreferenceSheet.h',
     'PreloadedStyleSheet.h',
     'PseudoStyleType.h',
     'RustCell.h',
     'ServoArcTypeList.h',
     'ServoBindings.h',
     'ServoBindingTypes.h',
-    'ServoBoxedTypeList.h',
     'ServoComputedData.h',
     'ServoComputedDataInlines.h',
     'ServoCSSParser.h',
     'ServoCSSRuleList.h',
     'ServoElementSnapshot.h',
     'ServoElementSnapshotTable.h',
     'ServoStyleSet.h',
     'ServoStyleSetInlines.h',
--- a/layout/style/test/gtest/StyloParsingBench.cpp
+++ b/layout/style/test/gtest/StyloParsingBench.cpp
@@ -80,17 +80,17 @@ static void ServoGetPropertyValueById() 
     ASSERT_TRUE(value.EqualsLiteral("10px"));
   }
 }
 
 MOZ_GTEST_BENCH(Stylo, Servo_StyleSheet_FromUTF8Bytes_Bench,
                 [] { ServoParsingBench(nullptr); });
 
 MOZ_GTEST_BENCH(Stylo, Servo_StyleSheet_FromUTF8Bytes_Bench_UseCounters, [] {
-  UniquePtr<StyleUseCounters> counters(Servo_UseCounters_Create());
+  UniquePtr<StyleUseCounters> counters = Servo_UseCounters_Create().Consume();
   ServoParsingBench(counters.get());
 });
 
 MOZ_GTEST_BENCH(Stylo, Servo_DeclarationBlock_SetPropertyById_Bench,
                 [] { ServoSetPropertyByIdBench(NS_LITERAL_CSTRING("10px")); });
 
 MOZ_GTEST_BENCH(Stylo,
                 Servo_DeclarationBlock_SetPropertyById_WithInitialSpace_Bench,
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -253,23 +253,16 @@ mod bindings {
 
     fn get_arc_types() -> Vec<String> {
         get_types("ServoArcTypeList.h", "SERVO_ARC_TYPE")
             .into_iter()
             .map(|(_, type_name)| type_name)
             .collect()
     }
 
-    fn get_boxed_types() -> Vec<String> {
-        get_types("ServoBoxedTypeList.h", "SERVO_BOXED_TYPE")
-            .into_iter()
-            .map(|(_, type_name)| type_name)
-            .collect()
-    }
-
     struct BuilderWithConfig<'a> {
         builder: Builder,
         config: &'a Table,
         used_keys: HashSet<&'static str>,
     }
     impl<'a> BuilderWithConfig<'a> {
         fn new(builder: Builder, config: &'a Table) -> Self {
             BuilderWithConfig {
@@ -448,32 +441,16 @@ mod bindings {
         for ty in get_arc_types().iter() {
             builder = builder
                 .blacklist_type(format!("{}Strong", ty))
                 .raw_line(format!(
                     "pub type {0}Strong = ::gecko_bindings::sugar::ownership::Strong<{0}>;",
                     ty
                 ));
         }
-        for ty in get_boxed_types().iter() {
-            builder = builder
-                .blacklist_type(format!("{}Owned", ty))
-                .raw_line(format!(
-                    "pub type {0}Owned = ::gecko_bindings::sugar::ownership::Owned<{0}>;",
-                    ty
-                ))
-                .blacklist_type(format!("{}OwnedOrNull", ty))
-                .raw_line(format!(
-                    concat!(
-                        "pub type {0}OwnedOrNull = ",
-                        "::gecko_bindings::sugar::ownership::OwnedOrNull<{0}>;"
-                    ),
-                    ty
-                ));
-        }
         write_binding_file(builder, BINDINGS_FILE, &fixups);
     }
 
     fn generate_atoms() {
         let script = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap())
             .join("gecko")
             .join("regen_atoms.py");
         println!("cargo:rerun-if-changed={}", script.display());
--- a/servo/components/style/cbindgen.toml
+++ b/servo/components/style/cbindgen.toml
@@ -104,16 +104,18 @@ include = [
   "TransformOrigin",
   "WordBreak",
   "Contain",
   "RestyleHint",
   "TouchAction",
   "WillChangeBits",
   "TextDecorationLine",
   "MozListReversed",
+  "Owned",
+  "OwnedOrNull",
 ]
 item_types = ["enums", "structs", "typedefs"]
 
 [export.body]
 "CSSPixelLength" = """
   inline nscoord ToAppUnits() const;
   inline bool IsZero() const;
 """
@@ -203,8 +205,26 @@ item_types = ["enums", "structs", "typed
   inline const StyleLengthPercentage& Get(mozilla::HalfCorner) const;
 """
 
 "RestyleHint" = """
   static inline StyleRestyleHint RestyleSubtree();
   static inline StyleRestyleHint RecascadeSubtree();
   static inline StyleRestyleHint ForAnimations();
 """
+
+# TODO(emilio): Add hooks to cbindgen to be able to generate MOZ_MUST_USE_TYPE
+# or MOZ_MUST_USE on the functions.
+"Owned" = """
+  UniquePtr<GeckoType> Consume() {
+    UniquePtr<GeckoType> ret(ptr);
+    ptr = nullptr;
+    return ret;
+  }
+"""
+
+"OwnedOrNull" = """
+  UniquePtr<GeckoType> Consume() {
+    UniquePtr<GeckoType> ret(ptr);
+    ptr = nullptr;
+    return ret;
+  }
+"""
--- a/servo/components/style/gecko_bindings/sugar/ownership.rs
+++ b/servo/components/style/gecko_bindings/sugar/ownership.rs
@@ -315,37 +315,16 @@ impl<GeckoType> OwnedOrNull<GeckoType> {
     }
 
     /// Returns whether this pointer is null.
     #[inline]
     pub fn is_null(&self) -> bool {
         self.ptr.is_null()
     }
 
-    /// Returns an owned pointer if this is non-null, and `None` otherwise.
-    pub fn into_box_opt<ServoType>(self) -> Option<Box<ServoType>>
-    where
-        ServoType: HasBoxFFI<FFIType = GeckoType>,
-    {
-        if self.is_null() {
-            None
-        } else {
-            Some(unsafe { transmute(self) })
-        }
-    }
-
-    /// Returns an `Owned<GeckoType>` if non-null, `None` otherwise.
-    pub fn into_owned_opt(self) -> Option<Owned<GeckoType>> {
-        if self.is_null() {
-            None
-        } else {
-            Some(unsafe { transmute(self) })
-        }
-    }
-
     /// Gets a immutable reference to the underlying Gecko type, or `None` if
     /// null.
     pub fn borrow(&self) -> Option<&GeckoType> {
         unsafe { transmute(self) }
     }
 
     /// Gets a mutable reference to the underlying Gecko type, or `None` if
     /// null.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -91,17 +91,17 @@ use style::gecko_bindings::structs::Serv
 use style::gecko_bindings::structs::SheetLoadData;
 use style::gecko_bindings::structs::SheetLoadDataHolder;
 use style::gecko_bindings::structs::SheetParsingMode;
 use style::gecko_bindings::structs::StyleContentType;
 use style::gecko_bindings::structs::StyleRuleInclusion;
 use style::gecko_bindings::structs::StyleSheet as DomStyleSheet;
 use style::gecko_bindings::structs::URLExtraData;
 use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasArcFFI, HasFFI};
-use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, Strong};
+use style::gecko_bindings::sugar::ownership::{HasSimpleFFI, HasBoxFFI, Strong, Owned, OwnedOrNull};
 use style::gecko_bindings::sugar::refptr::RefPtr;
 use style::gecko_properties;
 use style::global_style_data::{GlobalStyleData, GLOBAL_STYLE_DATA, STYLE_THREAD_POOL};
 use style::invalidation::element::restyle_hints::RestyleHint;
 use style::media_queries::MediaList;
 use style::parser::{self, Parse, ParserContext};
 use style::properties::animated_properties::AnimationValue;
 use style::properties::{parse_one_declaration_into, parse_style_attribute};
@@ -1422,22 +1422,22 @@ pub extern "C" fn Servo_StyleSet_AppendS
     let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     let data = &mut *data;
     let guard = global_style_data.shared_lock.read();
     let sheet = unsafe { GeckoStyleSheet::new(sheet) };
     data.stylist.append_stylesheet(sheet, &guard);
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_AuthorStyles_Create() -> *mut RawServoAuthorStyles {
-    Box::into_raw(Box::new(AuthorStyles::<GeckoStyleSheet>::new())) as *mut _
-}
-
-#[no_mangle]
-pub extern "C" fn Servo_AuthorStyles_Drop(styles: bindings::RawServoAuthorStylesOwned) {
+pub extern "C" fn Servo_AuthorStyles_Create() -> Owned<RawServoAuthorStyles> {
+    Box::new(AuthorStyles::<GeckoStyleSheet>::new()).into_ffi()
+}
+
+#[no_mangle]
+pub extern "C" fn Servo_AuthorStyles_Drop(styles: Owned<RawServoAuthorStyles>) {
     let _ = styles.into_box::<AuthorStyles<_>>();
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_AuthorStyles_AppendStyleSheet(
     styles: &mut RawServoAuthorStyles,
     sheet: *const DomStyleSheet,
 ) {
@@ -3509,17 +3509,17 @@ pub extern "C" fn Servo_StyleSet_Init(
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_RebuildCachedData(raw_data: &RawServoStyleSet) {
     let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     data.stylist.device_mut().rebuild_cached_data();
 }
 
 #[no_mangle]
-pub extern "C" fn Servo_StyleSet_Drop(data: bindings::RawServoStyleSetOwned) {
+pub extern "C" fn Servo_StyleSet_Drop(data: Owned<RawServoStyleSet>) {
     let _ = data.into_box::<PerDocumentStyleData>();
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_StyleSet_CompatModeChanged(raw_data: &RawServoStyleSet) {
     let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
     let quirks_mode = data.stylist.device().document().mCompatMode;
     data.stylist.set_quirks_mode(quirks_mode.into());
@@ -5883,32 +5883,32 @@ pub extern "C" fn Servo_HasPendingRestyl
         element = e.traversal_parent();
     }
     false
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_SelectorList_Parse(
     selector_list: *const nsACString,
-) -> *mut RawServoSelectorList {
+) -> OwnedOrNull<RawServoSelectorList> {
     use style::selector_parser::SelectorParser;
 
     debug_assert!(!selector_list.is_null());
 
     let input = (*selector_list).as_str_unchecked();
     let selector_list = match SelectorParser::parse_author_origin_no_namespace(&input) {
         Ok(selector_list) => selector_list,
-        Err(..) => return ptr::null_mut(),
+        Err(..) => return OwnedOrNull::null(),
     };
 
-    Box::into_raw(Box::new(selector_list)) as *mut RawServoSelectorList
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn Servo_SelectorList_Drop(list: bindings::RawServoSelectorListOwned) {
+    Box::new(selector_list).into_ffi().maybe()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_SelectorList_Drop(list: Owned<RawServoSelectorList>) {
     let _ = list.into_box::<::selectors::SelectorList<SelectorImpl>>();
 }
 
 fn parse_color(
     value: &str,
     error_reporter: Option<&ParseErrorReporter>,
 ) -> Result<specified::Color, ()> {
     let mut input = ParserInput::new(value);
@@ -6156,34 +6156,34 @@ pub unsafe extern "C" fn Servo_ParseFont
     };
 
     true
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_SourceSizeList_Parse(
     value: *const nsACString,
-) -> *mut RawServoSourceSizeList {
+) -> Owned<RawServoSourceSizeList> {
     let value = (*value).as_str_unchecked();
     let mut input = ParserInput::new(value);
     let mut parser = Parser::new(&mut input);
 
     let context = ParserContext::new(
         Origin::Author,
         dummy_url_data(),
         Some(CssRuleType::Style),
         ParsingMode::DEFAULT,
         QuirksMode::NoQuirks,
         None,
         None,
     );
 
     // NB: Intentionally not calling parse_entirely.
     let list = SourceSizeList::parse(&context, &mut parser);
-    Box::into_raw(Box::new(list)) as *mut _
+    Box::new(list).into_ffi()
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_SourceSizeList_Evaluate(
     raw_data: &RawServoStyleSet,
     list: Option<&RawServoSourceSizeList>,
 ) -> i32 {
     let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
@@ -6194,17 +6194,17 @@ pub unsafe extern "C" fn Servo_SourceSiz
         Some(list) => SourceSizeList::from_ffi(list).evaluate(device, quirks_mode),
         None => SourceSizeList::empty().evaluate(device, quirks_mode),
     };
 
     result.0
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Servo_SourceSizeList_Drop(list: bindings::RawServoSourceSizeListOwned) {
+pub unsafe extern "C" fn Servo_SourceSizeList_Drop(list: Owned<RawServoSourceSizeList>) {
     let _ = list.into_box::<SourceSizeList>();
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_InvalidateStyleForDocStateChanges(
     root: &RawGeckoElement,
     document_style: &RawServoStyleSet,
     non_document_styles: *const nsTArray<&RawServoAuthorStyles>,
@@ -6250,22 +6250,22 @@ pub unsafe extern "C" fn Servo_PseudoCla
         None => 0,
         // Ignore :any-link since it contains both visited and unvisited state.
         Some(NonTSPseudoClass::AnyLink) => 0,
         Some(pseudo_class) => pseudo_class.state_flag().bits(),
     }
 }
 
 #[no_mangle]
-pub unsafe extern "C" fn Servo_UseCounters_Create() -> *mut structs::StyleUseCounters {
-    Box::into_raw(Box::<UseCounters>::default()) as *mut _
-}
-
-#[no_mangle]
-pub unsafe extern "C" fn Servo_UseCounters_Drop(c: bindings::StyleUseCountersOwned) {
+pub unsafe extern "C" fn Servo_UseCounters_Create() -> Owned<structs::StyleUseCounters> {
+    Box::<UseCounters>::default().into_ffi()
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_UseCounters_Drop(c: Owned<structs::StyleUseCounters>) {
     let _ = c.into_box::<UseCounters>();
 }
 
 #[no_mangle]
 pub unsafe extern "C" fn Servo_UseCounters_Merge(
     doc_counters: &UseCounters,
     sheet_counters: &UseCounters,
 ) {