Bug 1404243 Part 3 - Remove refcount for StyleBasicShape, and use UniquePtr to hold it. draft
authorTing-Yu Lin <tlin@mozilla.com>
Mon, 25 Sep 2017 18:50:24 +0800
changeset 673201 070e993fd42511de5a3ca7b72bc3b07177382a66
parent 673200 ef39ecaf85dbc849f8c338b335f3cd43b2e842e2
child 673202 1d9f89de86dded0a53791e7dea7e4d1ffdff1c6f
push id82495
push userbmo:tlin@mozilla.com
push dateMon, 02 Oct 2017 03:57:39 +0000
bugs1404243
milestone58.0a1
Bug 1404243 Part 3 - Remove refcount for StyleBasicShape, and use UniquePtr to hold it. After StyleBasicShape is set to StyleShapeSource, it's life cycle never go beyond StyleShapeSource, so I make StyleBasicShape hold by a UniquePtr in StyleShapeSource. Also, replace all raw pointers to StyleBasicShape by UniquePtr in all APIs. MozReview-Commit-ID: 1MfIFjP8TsQ
layout/base/ShapeUtils.cpp
layout/base/ShapeUtils.h
layout/generic/nsFloatManager.cpp
layout/generic/nsFloatManager.h
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoBindings.toml
layout/style/StyleAnimationValue.cpp
layout/style/nsComputedDOMStyle.cpp
layout/style/nsComputedDOMStyle.h
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/nsCSSClipPathInstance.cpp
--- a/layout/base/ShapeUtils.cpp
+++ b/layout/base/ShapeUtils.cpp
@@ -33,33 +33,33 @@ ShapeUtils::ComputeShapeRadius(const Sty
     case StyleShapeRadius::ClosestSide:
       length = dist1 > dist2 ? dist2 : dist1;
       break;
   }
   return length;
 }
 
 nsPoint
-ShapeUtils::ComputeCircleOrEllipseCenter(const StyleBasicShape* aBasicShape,
+ShapeUtils::ComputeCircleOrEllipseCenter(const UniquePtr<StyleBasicShape>& aBasicShape,
                                          const nsRect& aRefBox)
 {
   MOZ_ASSERT(aBasicShape->GetShapeType() == StyleBasicShapeType::Circle ||
              aBasicShape->GetShapeType() == StyleBasicShapeType::Ellipse,
              "The basic shape must be circle() or ellipse!");
 
   nsPoint topLeft, anchor;
   nsSize size(aRefBox.Size());
   nsImageRenderer::ComputeObjectAnchorPoint(aBasicShape->GetPosition(),
                                             size, size,
                                             &topLeft, &anchor);
   return anchor + aRefBox.TopLeft();
 }
 
 nscoord
-ShapeUtils::ComputeCircleRadius(const StyleBasicShape* aBasicShape,
+ShapeUtils::ComputeCircleRadius(const UniquePtr<StyleBasicShape>& aBasicShape,
                                 const nsPoint& aCenter,
                                 const nsRect& aRefBox)
 {
   MOZ_ASSERT(aBasicShape->GetShapeType() == StyleBasicShapeType::Circle,
              "The basic shape must be circle()!");
 
   const nsTArray<nsStyleCoord>& coords = aBasicShape->Coordinates();
   MOZ_ASSERT(coords.Length() == 1, "wrong number of arguments");
@@ -81,17 +81,17 @@ ShapeUtils::ComputeCircleRadius(const St
                                                    aRefBox.height);
     r = nsRuleNode::ComputeCoordPercentCalc(coords[0],
                                             NSToCoordRound(referenceLength));
   }
   return r;
 }
 
 nsSize
-ShapeUtils::ComputeEllipseRadii(const StyleBasicShape* aBasicShape,
+ShapeUtils::ComputeEllipseRadii(const UniquePtr<StyleBasicShape>& aBasicShape,
                                 const nsPoint& aCenter,
                                 const nsRect& aRefBox)
 {
   MOZ_ASSERT(aBasicShape->GetShapeType() == StyleBasicShapeType::Ellipse,
              "The basic shape must be ellipse()!");
 
   const nsTArray<nsStyleCoord>& coords = aBasicShape->Coordinates();
   MOZ_ASSERT(coords.Length() == 2, "wrong number of arguments");
@@ -112,17 +112,17 @@ ShapeUtils::ComputeEllipseRadii(const St
   } else {
     radii.height = nsRuleNode::ComputeCoordPercentCalc(coords[1], aRefBox.height);
   }
 
   return radii;
 }
 
 /* static */ nsRect
-ShapeUtils::ComputeInsetRect(const StyleBasicShape* aBasicShape,
+ShapeUtils::ComputeInsetRect(const UniquePtr<StyleBasicShape>& aBasicShape,
                              const nsRect& aRefBox)
 {
   MOZ_ASSERT(aBasicShape->GetShapeType() == StyleBasicShapeType::Inset,
              "The basic shape must be inset()!");
 
   const nsTArray<nsStyleCoord>& coords = aBasicShape->Coordinates();
   MOZ_ASSERT(coords.Length() == 4, "wrong number of arguments");
 
@@ -133,29 +133,29 @@ ShapeUtils::ComputeInsetRect(const Style
 
   nsRect insetRect(aRefBox);
   insetRect.Deflate(inset);
 
   return insetRect;
 }
 
 /* static */ bool
-ShapeUtils::ComputeInsetRadii(const StyleBasicShape* aBasicShape,
+ShapeUtils::ComputeInsetRadii(const UniquePtr<StyleBasicShape>& aBasicShape,
                               const nsRect& aInsetRect,
                               const nsRect& aRefBox,
                               nscoord aRadii[8])
 {
   const nsStyleCorners& radius = aBasicShape->GetRadius();
   return nsIFrame::ComputeBorderRadii(radius, aInsetRect.Size(), aRefBox.Size(),
                                       Sides(), aRadii);
 
 }
 
 /* static */ nsTArray<nsPoint>
-ShapeUtils::ComputePolygonVertices(const StyleBasicShape* aBasicShape,
+ShapeUtils::ComputePolygonVertices(const UniquePtr<StyleBasicShape>& aBasicShape,
                                    const nsRect& aRefBox)
 {
   MOZ_ASSERT(aBasicShape->GetShapeType() == StyleBasicShapeType::Polygon,
              "The basic shape must be polygon()!");
 
   const nsTArray<nsStyleCoord>& coords = aBasicShape->Coordinates();
   MOZ_ASSERT(coords.Length() % 2 == 0 &&
              coords.Length() >= 2, "Wrong number of arguments!");
--- a/layout/base/ShapeUtils.h
+++ b/layout/base/ShapeUtils.h
@@ -31,58 +31,58 @@ struct ShapeUtils final
                                     const nscoord aCenter,
                                     const nscoord aPosMin,
                                     const nscoord aPosMax);
 
   // Compute the center of a circle or an ellipse.
   // @param aRefBox The reference box of the basic shape.
   // @return The point of the center.
   static nsPoint ComputeCircleOrEllipseCenter(
-    const StyleBasicShape* aBasicShape,
+    const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsRect& aRefBox);
 
   // Compute the radius for a circle.
   // @param aCenter the center of the circle.
   // @param aRefBox the reference box of the circle.
   // @return The length of the radius in app units.
   static nscoord ComputeCircleRadius(
-    const StyleBasicShape* aBasicShape,
+    const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsPoint& aCenter, const nsRect& aRefBox);
 
   // Compute the radii for an ellipse.
   // @param aCenter the center of the ellipse.
   // @param aRefBox the reference box of the ellipse.
   // @return The radii of the ellipse in app units. The width and height
   // represent the x-axis and y-axis radii of the ellipse.
   static nsSize ComputeEllipseRadii(
-    const StyleBasicShape* aBasicShape,
+    const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsPoint& aCenter, const nsRect& aRefBox);
 
   // Compute the rect for an inset.
   // @param aRefBox the reference box of the inset.
   // @return The inset rect in app units.
   static nsRect ComputeInsetRect(
-    const StyleBasicShape* aBasicShape,
+    const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsRect& aRefBox);
 
   // Compute the radii for an inset.
   // @param aRefBox the reference box of the inset.
   // @param aInsetRect the inset rect computed by ComputeInsetRect().
   // @param aRadii the returned radii in app units.
   // @return true if any of the radii is nonzero; false otherwise.
   static bool ComputeInsetRadii(
-    const StyleBasicShape* aBasicShape,
+    const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsRect& aInsetRect,
     const nsRect& aRefBox,
     nscoord aRadii[8]);
 
   // Compute the vertices for a polygon.
   // @param aRefBox the reference box of the polygon.
   // @return The vertices in app units; the coordinate space is the same
   //         as aRefBox.
   static nsTArray<nsPoint> ComputePolygonVertices(
-    const StyleBasicShape* aBasicShape,
+    const UniquePtr<StyleBasicShape>& aBasicShape,
     const nsRect& aRefBox);
 };
 
 } // namespace mozilla
 
 #endif // mozilla_ShapeUtils_h
--- a/layout/generic/nsFloatManager.cpp
+++ b/layout/generic/nsFloatManager.cpp
@@ -769,17 +769,17 @@ nsFloatManager::FloatInfo::FloatInfo(nsI
   // Initialize <shape-box>'s reference rect.
   LogicalRect shapeBoxRect =
     ShapeInfo::ComputeShapeBoxRect(shapeOutside, mFrame, aMarginRect, aWM);
 
   if (shapeOutside.GetType() == StyleShapeSourceType::Box) {
     mShapeInfo = ShapeInfo::CreateShapeBox(mFrame, shapeBoxRect, aWM,
                                            aContainerSize);
   } else if (shapeOutside.GetType() == StyleShapeSourceType::Shape) {
-    StyleBasicShape* const basicShape = shapeOutside.GetBasicShape();
+    const UniquePtr<StyleBasicShape>& basicShape = shapeOutside.GetBasicShape();
 
     switch (basicShape->GetShapeType()) {
       case StyleBasicShapeType::Polygon:
         mShapeInfo =
           ShapeInfo::CreatePolygon(basicShape, shapeBoxRect, aWM,
                                    aContainerSize);
         break;
       case StyleBasicShapeType::Circle:
@@ -956,17 +956,17 @@ nsFloatManager::ShapeInfo::CreateShapeBo
 
   return MakeUnique<RoundedBoxShapeInfo>(logicalShapeBoxRect,
                                          ConvertToFloatLogical(physicalRadii,
                                                                aWM));
 }
 
 /* static */ UniquePtr<nsFloatManager::ShapeInfo>
 nsFloatManager::ShapeInfo::CreateInset(
-  const StyleBasicShape* aBasicShape,
+  const UniquePtr<StyleBasicShape>& aBasicShape,
   const LogicalRect& aShapeBoxRect,
   WritingMode aWM,
   const nsSize& aContainerSize)
 {
   // Use physical coordinates to compute inset() because the top, right,
   // bottom and left offsets are physical.
   // https://drafts.csswg.org/css-shapes-1/#funcdef-inset
   nsRect physicalShapeBoxRect =
@@ -988,17 +988,17 @@ nsFloatManager::ShapeInfo::CreateInset(
 
   return MakeUnique<RoundedBoxShapeInfo>(logicalInsetRect,
                                          ConvertToFloatLogical(physicalRadii,
                                                                aWM));
 }
 
 /* static */ UniquePtr<nsFloatManager::ShapeInfo>
 nsFloatManager::ShapeInfo::CreateCircleOrEllipse(
-  const StyleBasicShape* aBasicShape,
+  const UniquePtr<StyleBasicShape>& aBasicShape,
   const LogicalRect& aShapeBoxRect,
   WritingMode aWM,
   const nsSize& aContainerSize)
 {
   // Use physical coordinates to compute the center of circle() or ellipse()
   // since the <position> keywords such as 'left', 'top', etc. are physical.
   // https://drafts.csswg.org/css-shapes-1/#funcdef-ellipse
   nsRect physicalShapeBoxRect =
@@ -1024,17 +1024,17 @@ nsFloatManager::ShapeInfo::CreateCircleO
     radii = nsSize(logicalRadii.ISize(aWM), logicalRadii.BSize(aWM));
   }
 
   return MakeUnique<EllipseShapeInfo>(logicalCenter, radii);
 }
 
 /* static */ UniquePtr<nsFloatManager::ShapeInfo>
 nsFloatManager::ShapeInfo::CreatePolygon(
-  const StyleBasicShape* aBasicShape,
+  const UniquePtr<StyleBasicShape>& aBasicShape,
   const LogicalRect& aShapeBoxRect,
   WritingMode aWM,
   const nsSize& aContainerSize)
 {
   // Use physical coordinates to compute each (xi, yi) vertex because CSS
   // represents them using physical coordinates.
   // https://drafts.csswg.org/css-shapes-1/#funcdef-polygon
   nsRect physicalShapeBoxRect =
--- a/layout/generic/nsFloatManager.h
+++ b/layout/generic/nsFloatManager.h
@@ -377,29 +377,29 @@ private:
 
     static mozilla::UniquePtr<ShapeInfo> CreateShapeBox(
       nsIFrame* const aFrame,
       const mozilla::LogicalRect& aShapeBoxRect,
       mozilla::WritingMode aWM,
       const nsSize& aContainerSize);
 
     static mozilla::UniquePtr<ShapeInfo> CreateInset(
-      const mozilla::StyleBasicShape* aBasicShape,
+      const mozilla::UniquePtr<mozilla::StyleBasicShape>& aBasicShape,
       const mozilla::LogicalRect& aShapeBoxRect,
       mozilla::WritingMode aWM,
       const nsSize& aContainerSize);
 
     static mozilla::UniquePtr<ShapeInfo> CreateCircleOrEllipse(
-      const mozilla::StyleBasicShape* aBasicShape,
+      const mozilla::UniquePtr<mozilla::StyleBasicShape>& aBasicShape,
       const mozilla::LogicalRect& aShapeBoxRect,
       mozilla::WritingMode aWM,
       const nsSize& aContainerSize);
 
     static mozilla::UniquePtr<ShapeInfo> CreatePolygon(
-      const mozilla::StyleBasicShape* aBasicShape,
+      const mozilla::UniquePtr<mozilla::StyleBasicShape>& aBasicShape,
       const mozilla::LogicalRect& aShapeBoxRect,
       mozilla::WritingMode aWM,
       const nsSize& aContainerSize);
 
   protected:
     // Compute the minimum line-axis difference between the bounding shape
     // box and its rounded corner within the given band (block-axis region).
     // This is used as a helper function to compute the LineRight() and
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1988,21 +1988,22 @@ Gecko_DestroyShapeSource(mozilla::StyleS
 
 void
 Gecko_StyleShapeSource_SetURLValue(mozilla::StyleShapeSource* aShape, ServoBundledURI aURI)
 {
   RefPtr<css::URLValue> url = aURI.IntoCssUrl();
   aShape->SetURL(url.get());
 }
 
-mozilla::StyleBasicShape*
-Gecko_NewBasicShape(mozilla::StyleBasicShapeType aType)
+void
+Gecko_NewBasicShape(mozilla::StyleShapeSource* aShape,
+                    mozilla::StyleBasicShapeType aType)
 {
-  RefPtr<StyleBasicShape> ptr = new mozilla::StyleBasicShape(aType);
-  return ptr.forget().take();
+  aShape->SetBasicShape(MakeUnique<mozilla::StyleBasicShape>(aType),
+                        StyleGeometryBox::NoBox);
 }
 
 void
 Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len)
 {
   effects->mFilters.Clear();
   effects->mFilters.SetLength(new_len);
 }
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -499,17 +499,18 @@ mozilla::PropertyValuePair* Gecko_Append
 void Gecko_ResetStyleCoord(nsStyleUnit* unit, nsStyleUnion* value);
 
 // Set an nsStyleCoord to a computed `calc()` value
 void Gecko_SetStyleCoordCalcValue(nsStyleUnit* unit, nsStyleUnion* value, nsStyleCoord::CalcValue calc);
 
 void Gecko_CopyShapeSourceFrom(mozilla::StyleShapeSource* dst, const mozilla::StyleShapeSource* src);
 
 void Gecko_DestroyShapeSource(mozilla::StyleShapeSource* shape);
-mozilla::StyleBasicShape* Gecko_NewBasicShape(mozilla::StyleBasicShapeType type);
+void Gecko_NewBasicShape(mozilla::StyleShapeSource* shape,
+                         mozilla::StyleBasicShapeType type);
 void Gecko_StyleShapeSource_SetURLValue(mozilla::StyleShapeSource* shape, ServoBundledURI uri);
 
 void Gecko_ResetFilters(nsStyleEffects* effects, size_t new_len);
 void Gecko_CopyFiltersFrom(nsStyleEffects* aSrc, nsStyleEffects* aDest);
 void Gecko_nsStyleFilter_SetURLValue(nsStyleFilter* effects, ServoBundledURI uri);
 
 void Gecko_nsStyleSVGPaint_CopyFrom(nsStyleSVGPaint* dest, const nsStyleSVGPaint* src);
 void Gecko_nsStyleSVGPaint_SetURLValue(nsStyleSVGPaint* paint, ServoBundledURI uri);
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -282,17 +282,16 @@ whitelist-types = [
     "ServoComputedDataBorrowed",
     "ServoElementSnapshot",
     "ServoStyleContextStrong",
     "ServoStyleContextBorrowed",
     "ServoStyleContextBorrowedOrNull",
     "SheetParsingMode",
     "StaticRefPtr",
     "StyleAnimation",
-    "StyleBasicShape",
     "StyleBasicShapeType",
     "StyleGeometryBox",
     "StyleShapeSource",
     "StyleTransition",
     "ThemeWidgetType",
     "mozilla::UniquePtr",
     "mozilla::DefaultDelete",
     "mozilla::Side",
@@ -437,17 +436,16 @@ structs-types = [
     "Keyframe",
     "PropertyValuePair",
     "SeenPtrs",
     "ServoBundledURI",
     "ServoElementSnapshot",
     "ServoElementSnapshotTable",
     "ServoStyleSetSizes",
     "SheetParsingMode",
-    "StyleBasicShape",
     "StyleBasicShapeType",
     "StyleShapeSource",
     "StyleTransition",
     "gfxFontFeatureValueSet",
     "nsCSSCounterStyleRule",
     "nsCSSFontFaceRule",
     "nsCSSKeyword",
     "nsCSSPropertyID",
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -4153,17 +4153,17 @@ ExtractImageLayerSizePairList(const nsSt
 
 static bool
 StyleShapeSourceToCSSArray(const StyleShapeSource& aShapeSource,
                            nsCSSValue::Array* aResult)
 {
   MOZ_ASSERT(aResult->Count() == 2,
              "Expected array to be presized for a function and the sizing-box");
 
-  const StyleBasicShape* shape = aShapeSource.GetBasicShape();
+  const UniquePtr<StyleBasicShape>& shape = aShapeSource.GetBasicShape();
   nsCSSKeyword functionName = shape->GetShapeTypeName();
   RefPtr<nsCSSValue::Array> functionArray;
   switch (shape->GetShapeType()) {
     case StyleBasicShapeType::Circle:
     case StyleBasicShapeType::Ellipse: {
       const nsTArray<nsStyleCoord>& coords = shape->Coordinates();
       MOZ_ASSERT(coords.Length() == ShapeArgumentCount(functionName) - 1,
                  "Unexpected radii count");
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -6351,17 +6351,17 @@ nsComputedDOMStyle::BasicShapeRadiiToStr
     return;
   }
   aCssText.AppendLiteral(" / ");
   aCssText.Append(verticalString);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::CreatePrimitiveValueForBasicShape(
-  const StyleBasicShape* aStyleBasicShape)
+  const UniquePtr<StyleBasicShape>& aStyleBasicShape)
 {
   MOZ_ASSERT(aStyleBasicShape, "Expect a valid basic shape pointer!");
 
   StyleBasicShapeType type = aStyleBasicShape->GetShapeType();
   // Shape function name and opening parenthesis.
   nsAutoString shapeFunctionString;
   AppendASCIItoUTF16(nsCSSKeywords::GetStringValue(
                        aStyleBasicShape->GetShapeTypeName()),
@@ -6432,17 +6432,17 @@ nsComputedDOMStyle::CreatePrimitiveValue
   RefPtr<nsROCSSPrimitiveValue> functionValue = new nsROCSSPrimitiveValue;
   functionValue->SetString(shapeFunctionString);
   return functionValue.forget();
 }
 
 template<typename ReferenceBox>
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::CreatePrimitiveValueForShapeSource(
-  const StyleBasicShape* aStyleBasicShape,
+  const UniquePtr<StyleBasicShape>& aStyleBasicShape,
   ReferenceBox aReferenceBox,
   const KTableEntry aBoxKeywordTable[])
 {
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
   if (aStyleBasicShape) {
     valueList->AppendCSSValue(
       CreatePrimitiveValueForBasicShape(aStyleBasicShape));
   }
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -7,16 +7,17 @@
 
 #ifndef nsComputedDOMStyle_h__
 #define nsComputedDOMStyle_h__
 
 #include "mozilla/ArenaRefPtr.h"
 #include "mozilla/ArenaRefPtrInlines.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/StyleComplexColor.h"
+#include "mozilla/UniquePtr.h"
 #include "nsCOMPtr.h"
 #include "nscore.h"
 #include "nsCSSProps.h"
 #include "nsDOMCSSDeclaration.h"
 #include "nsStyleContext.h"
 #include "nsIWeakReferenceUtils.h"
 #include "mozilla/gfx/Types.h"
 #include "nsCoord.h"
@@ -698,23 +699,23 @@ private:
 
   already_AddRefed<CSSValue>
   GetShapeSource(const mozilla::StyleShapeSource& aShapeSource,
                  const KTableEntry aBoxKeywordTable[]);
 
   template<typename ReferenceBox>
   already_AddRefed<CSSValue>
   CreatePrimitiveValueForShapeSource(
-    const mozilla::StyleBasicShape* aStyleBasicShape,
+    const mozilla::UniquePtr<mozilla::StyleBasicShape>& aStyleBasicShape,
     ReferenceBox aReferenceBox,
     const KTableEntry aBoxKeywordTable[]);
 
   // Helper function for computing basic shape styles.
   already_AddRefed<CSSValue> CreatePrimitiveValueForBasicShape(
-    const mozilla::StyleBasicShape* aStyleBasicShape);
+    const mozilla::UniquePtr<mozilla::StyleBasicShape>& aStyleBasicShape);
   void BoxValuesToString(nsAString& aString,
                          const nsTArray<nsStyleCoord>& aBoxValues);
   void BasicShapeRadiiToString(nsAString& aCssText,
                                const nsStyleCorners& aCorners);
 
   // Find out if we can safely skip flushing for aDocument (i.e. pending
   // restyles does not affect mContent).
   mozilla::FlushTarget GetFlushTarget(nsIDocument* aDocument) const;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -9790,31 +9790,31 @@ nsRuleNode::ComputeSVGData(void* aStartS
 
   default:
     MOZ_ASSERT(false, "unrecognized -moz-context-properties value");
   }
 
   COMPUTE_END_INHERITED(SVG, svg)
 }
 
-static already_AddRefed<StyleBasicShape>
+static UniquePtr<StyleBasicShape>
 GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
                                GeckoStyleContext* aStyleContext,
                                nsPresContext* aPresContext,
                                RuleNodeCacheConditions& aConditions)
 {
-  RefPtr<StyleBasicShape> basicShape;
+  UniquePtr<StyleBasicShape> basicShape;
 
   nsCSSValue::Array* shapeFunction = aValue.GetArrayValue();
   nsCSSKeyword functionName =
     (nsCSSKeyword)shapeFunction->Item(0).GetIntValue();
 
   if (functionName == eCSSKeyword_polygon) {
     MOZ_ASSERT(!basicShape, "did not expect value");
-    basicShape = new StyleBasicShape(StyleBasicShapeType::Polygon);
+    basicShape = MakeUnique<StyleBasicShape>(StyleBasicShapeType::Polygon);
     MOZ_ASSERT(shapeFunction->Count() > 1,
                "polygon has wrong number of arguments");
     size_t j = 1;
     if (shapeFunction->Item(j).GetUnit() == eCSSUnit_Enumerated) {
       StyleFillRule rule;
       SetEnumValueHelper::SetEnumeratedValue(rule, shapeFunction->Item(j));
       basicShape->SetFillRule(rule);
       ++j;
@@ -9841,17 +9841,17 @@ GetStyleBasicShapeFromCSSValue(const nsC
       curPair = curPair->mNext;
     }
   } else if (functionName == eCSSKeyword_circle ||
              functionName == eCSSKeyword_ellipse) {
     StyleBasicShapeType type = functionName == eCSSKeyword_circle ?
       StyleBasicShapeType::Circle :
       StyleBasicShapeType::Ellipse;
     MOZ_ASSERT(!basicShape, "did not expect value");
-    basicShape = new StyleBasicShape(type);
+    basicShape = MakeUnique<StyleBasicShape>(type);
     const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
       SETCOORD_STORE_CALC | SETCOORD_ENUMERATED;
     size_t count = type == StyleBasicShapeType::Circle ? 2 : 3;
     MOZ_ASSERT(shapeFunction->Count() == count + 1,
                "unexpected arguments count");
     MOZ_ASSERT(type == StyleBasicShapeType::Circle ||
                (shapeFunction->Item(1).GetUnit() == eCSSUnit_Null) ==
                (shapeFunction->Item(2).GetUnit() == eCSSUnit_Null),
@@ -9877,17 +9877,17 @@ GetStyleBasicShapeFromCSSValue(const nsC
                            basicShape->GetPosition(),
                            aConditions);
     } else {
       MOZ_ASSERT(positionVal.GetUnit() == eCSSUnit_Null,
                  "expected no value");
     }
   } else if (functionName == eCSSKeyword_inset) {
     MOZ_ASSERT(!basicShape, "did not expect value");
-    basicShape = new StyleBasicShape(StyleBasicShapeType::Inset);
+    basicShape = MakeUnique<StyleBasicShape>(StyleBasicShapeType::Inset);
     MOZ_ASSERT(shapeFunction->Count() == 6,
                "inset function has wrong number of arguments");
     MOZ_ASSERT(shapeFunction->Item(1).GetUnit() != eCSSUnit_Null,
                "no shape arguments defined");
     const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
       SETCOORD_STORE_CALC;
     nsTArray<nsStyleCoord>& coords = basicShape->Coordinates();
     for (size_t j = 1; j <= 4; ++j) {
@@ -9938,17 +9938,17 @@ GetStyleBasicShapeFromCSSValue(const nsC
       NS_FOR_CSS_HALF_CORNERS(j) {
         insetRadius.Set(j, zero);
       }
     }
   } else {
     NS_NOTREACHED("unexpected basic shape function");
   }
 
-  return basicShape.forget();
+  return basicShape;
 }
 
 static void
 SetStyleShapeSourceToCSSValue(
   StyleShapeSource* aShapeSource,
   const nsCSSValue* aValue,
   GeckoStyleContext* aStyleContext,
   nsPresContext* aPresContext,
@@ -9957,33 +9957,33 @@ SetStyleShapeSourceToCSSValue(
   MOZ_ASSERT(aValue->GetUnit() == eCSSUnit_Array,
              "expected a basic shape or reference box");
 
   const nsCSSValue::Array* array = aValue->GetArrayValue();
   MOZ_ASSERT(array->Count() == 1 || array->Count() == 2,
              "Expect one or both of a shape function and a reference box");
 
   StyleGeometryBox referenceBox = StyleGeometryBox::NoBox;
-  RefPtr<StyleBasicShape> basicShape;
+  UniquePtr<StyleBasicShape> basicShape;
 
   for (size_t i = 0; i < array->Count(); ++i) {
     const nsCSSValue& item = array->Item(i);
     if (item.GetUnit() == eCSSUnit_Enumerated) {
       referenceBox = static_cast<StyleGeometryBox>(item.GetIntValue());
     } else if (item.GetUnit() == eCSSUnit_Function) {
       basicShape = GetStyleBasicShapeFromCSSValue(item, aStyleContext,
                                                   aPresContext, aConditions);
     } else {
       MOZ_ASSERT_UNREACHABLE("Unexpected unit!");
       return;
     }
   }
 
   if (basicShape) {
-    aShapeSource->SetBasicShape(basicShape, referenceBox);
+    aShapeSource->SetBasicShape(Move(basicShape), referenceBox);
   } else {
     aShapeSource->SetReferenceBox(referenceBox);
   }
 }
 
 // Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
 static bool
 SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1042,33 +1042,35 @@ StyleBasicShape::GetShapeTypeName() cons
 // StyleShapeSource
 
 StyleShapeSource::StyleShapeSource(const StyleShapeSource& aSource)
   : StyleShapeSource()
 {
   if (aSource.mType == StyleShapeSourceType::URL) {
     SetURL(aSource.mURL);
   } else if (aSource.mType == StyleShapeSourceType::Shape) {
-    SetBasicShape(aSource.mBasicShape, aSource.mReferenceBox);
+    SetBasicShape(MakeUnique<StyleBasicShape>(*aSource.mBasicShape),
+                  aSource.mReferenceBox);
   } else if (aSource.mType == StyleShapeSourceType::Box) {
     SetReferenceBox(aSource.mReferenceBox);
   }
 }
 
 StyleShapeSource&
 StyleShapeSource::operator=(const StyleShapeSource& aOther)
 {
   if (this == &aOther) {
     return *this;
   }
 
   if (aOther.mType == StyleShapeSourceType::URL) {
     SetURL(aOther.mURL);
   } else if (aOther.mType == StyleShapeSourceType::Shape) {
-    SetBasicShape(aOther.mBasicShape, aOther.mReferenceBox);
+    SetBasicShape(MakeUnique<StyleBasicShape>(*aOther.mBasicShape),
+                  aOther.mReferenceBox);
   } else if (aOther.mType == StyleShapeSourceType::Box) {
     SetReferenceBox(aOther.mReferenceBox);
   } else {
     ReleaseRef();
     mReferenceBox = StyleGeometryBox::NoBox;
     mType = StyleShapeSourceType::None;
   }
   return *this;
@@ -1100,47 +1102,42 @@ StyleShapeSource::SetURL(css::URLValue* 
   ReleaseRef();
   mURL = aValue;
   mURL->AddRef();
   mType = StyleShapeSourceType::URL;
   return true;
 }
 
 void
-StyleShapeSource::SetBasicShape(StyleBasicShape* aBasicShape,
+StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
                                 StyleGeometryBox aReferenceBox)
 {
   NS_ASSERTION(aBasicShape, "expected pointer");
   ReleaseRef();
-  mBasicShape = aBasicShape;
-  mBasicShape->AddRef();
+  mBasicShape = Move(aBasicShape);
   mReferenceBox = aReferenceBox;
   mType = StyleShapeSourceType::Shape;
 }
 
 void
 StyleShapeSource::SetReferenceBox(StyleGeometryBox aReferenceBox)
 {
   ReleaseRef();
   mReferenceBox = aReferenceBox;
   mType = StyleShapeSourceType::Box;
 }
 
 void
 StyleShapeSource::ReleaseRef()
 {
-  if (mType == StyleShapeSourceType::Shape) {
-    NS_ASSERTION(mBasicShape, "expected pointer");
-    mBasicShape->Release();
-  } else if (mType == StyleShapeSourceType::URL) {
+  if (mType == StyleShapeSourceType::URL) {
     NS_ASSERTION(mURL, "expected pointer");
     mURL->Release();
   }
-  // Both mBasicShape and mURL are pointers in a union. Nulling one of them
-  // nulls both of them.
+
   mURL = nullptr;
 }
 
 // --------------------
 // nsStyleFilter
 //
 nsStyleFilter::nsStyleFilter()
   : mType(NS_STYLE_FILTER_NONE)
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -2416,35 +2416,31 @@ public:
            mCoordinates == aOther.mCoordinates &&
            mPosition == aOther.mPosition &&
            mRadius == aOther.mRadius;
   }
   bool operator!=(const StyleBasicShape& aOther) const {
     return !(*this == aOther);
   }
 
-  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(StyleBasicShape);
-
 private:
-  ~StyleBasicShape() {}
-
   StyleBasicShapeType mType;
   StyleFillRule mFillRule;
 
   // mCoordinates has coordinates for polygon or radii for
   // ellipse and circle.
   // (top, right, bottom, left) for inset
   nsTArray<nsStyleCoord> mCoordinates;
   // position of center for ellipse or circle
   Position mPosition;
   // corner radii for inset (0 if not set)
   nsStyleCorners mRadius;
 };
 
-struct StyleShapeSource
+struct StyleShapeSource final
 {
   StyleShapeSource()
     : mURL(nullptr)
   {}
 
   StyleShapeSource(const StyleShapeSource& aSource);
 
   ~StyleShapeSource()
@@ -2469,23 +2465,23 @@ struct StyleShapeSource
   css::URLValue* GetURL() const
   {
     MOZ_ASSERT(mType == StyleShapeSourceType::URL, "Wrong shape source type!");
     return mURL;
   }
 
   bool SetURL(css::URLValue* aValue);
 
-  StyleBasicShape* GetBasicShape() const
+  const UniquePtr<StyleBasicShape>& GetBasicShape() const
   {
     MOZ_ASSERT(mType == StyleShapeSourceType::Shape, "Wrong shape source type!");
     return mBasicShape;
   }
 
-  void SetBasicShape(StyleBasicShape* aBasicShape,
+  void SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
                      StyleGeometryBox aReferenceBox);
 
   StyleGeometryBox GetReferenceBox() const
   {
     MOZ_ASSERT(mType == StyleShapeSourceType::Box ||
                mType == StyleShapeSourceType::Shape,
                "Wrong shape source type!");
     return mReferenceBox;
@@ -2493,18 +2489,18 @@ struct StyleShapeSource
 
   void SetReferenceBox(StyleGeometryBox aReferenceBox);
 
 private:
   void ReleaseRef();
 
   void* operator new(size_t) = delete;
 
+  mozilla::UniquePtr<StyleBasicShape> mBasicShape;
   union {
-    StyleBasicShape* mBasicShape;
     css::URLValue* mURL;
   };
   StyleShapeSourceType mType = StyleShapeSourceType::None;
   StyleGeometryBox mReferenceBox = StyleGeometryBox::NoBox;
 };
 
 } // namespace mozilla
 
--- a/layout/svg/nsCSSClipPathInstance.cpp
+++ b/layout/svg/nsCSSClipPathInstance.cpp
@@ -82,17 +82,17 @@ nsCSSClipPathInstance::CreateClipPath(Dr
     RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
     return builder->Finish();
   }
 
   nscoord appUnitsPerDevPixel =
     mTargetFrame->PresContext()->AppUnitsPerDevPixel();
   r = ToAppUnits(r.ToNearestPixels(appUnitsPerDevPixel), appUnitsPerDevPixel);
 
-  StyleBasicShape* basicShape = mClipPathStyle.GetBasicShape();
+  const UniquePtr<StyleBasicShape>& basicShape = mClipPathStyle.GetBasicShape();
   switch (basicShape->GetShapeType()) {
     case StyleBasicShapeType::Circle:
       return CreateClipPathCircle(aDrawTarget, r);
     case StyleBasicShapeType::Ellipse:
       return CreateClipPathEllipse(aDrawTarget, r);
     case StyleBasicShapeType::Polygon:
       return CreateClipPathPolygon(aDrawTarget, r);
     case StyleBasicShapeType::Inset:
@@ -105,17 +105,17 @@ nsCSSClipPathInstance::CreateClipPath(Dr
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
   return builder->Finish();
 }
 
 already_AddRefed<Path>
 nsCSSClipPathInstance::CreateClipPathCircle(DrawTarget* aDrawTarget,
                                             const nsRect& aRefBox)
 {
-  StyleBasicShape* basicShape = mClipPathStyle.GetBasicShape();
+  const UniquePtr<StyleBasicShape>& basicShape = mClipPathStyle.GetBasicShape();
 
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
 
   nsPoint center =
     ShapeUtils::ComputeCircleOrEllipseCenter(basicShape, aRefBox);
   nscoord r = ShapeUtils::ComputeCircleRadius(basicShape, center, aRefBox);
   nscoord appUnitsPerDevPixel =
     mTargetFrame->PresContext()->AppUnitsPerDevPixel();
@@ -125,17 +125,17 @@ nsCSSClipPathInstance::CreateClipPathCir
   builder->Close();
   return builder->Finish();
 }
 
 already_AddRefed<Path>
 nsCSSClipPathInstance::CreateClipPathEllipse(DrawTarget* aDrawTarget,
                                              const nsRect& aRefBox)
 {
-  StyleBasicShape* basicShape = mClipPathStyle.GetBasicShape();
+  const UniquePtr<StyleBasicShape>& basicShape = mClipPathStyle.GetBasicShape();
 
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
 
   nsPoint center =
     ShapeUtils::ComputeCircleOrEllipseCenter(basicShape, aRefBox);
   nsSize radii = ShapeUtils::ComputeEllipseRadii(basicShape, center, aRefBox);
   nscoord appUnitsPerDevPixel =
     mTargetFrame->PresContext()->AppUnitsPerDevPixel();
@@ -145,17 +145,17 @@ nsCSSClipPathInstance::CreateClipPathEll
   builder->Close();
   return builder->Finish();
 }
 
 already_AddRefed<Path>
 nsCSSClipPathInstance::CreateClipPathPolygon(DrawTarget* aDrawTarget,
                                              const nsRect& aRefBox)
 {
-  StyleBasicShape* basicShape = mClipPathStyle.GetBasicShape();
+  const UniquePtr<StyleBasicShape>& basicShape = mClipPathStyle.GetBasicShape();
   FillRule fillRule = basicShape->GetFillRule() == StyleFillRule::Nonzero ?
                         FillRule::FILL_WINDING : FillRule::FILL_EVEN_ODD;
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder(fillRule);
 
   nsTArray<nsPoint> vertices =
     ShapeUtils::ComputePolygonVertices(basicShape, aRefBox);
   if (vertices.IsEmpty()) {
     MOZ_ASSERT_UNREACHABLE(
@@ -171,17 +171,17 @@ nsCSSClipPathInstance::CreateClipPathPol
   builder->Close();
   return builder->Finish();
 }
 
 already_AddRefed<Path>
 nsCSSClipPathInstance::CreateClipPathInset(DrawTarget* aDrawTarget,
                                            const nsRect& aRefBox)
 {
-  StyleBasicShape* basicShape = mClipPathStyle.GetBasicShape();
+  const UniquePtr<StyleBasicShape>& basicShape = mClipPathStyle.GetBasicShape();
 
   RefPtr<PathBuilder> builder = aDrawTarget->CreatePathBuilder();
 
   nscoord appUnitsPerDevPixel =
     mTargetFrame->PresContext()->AppUnitsPerDevPixel();
 
   nsRect insetRect = ShapeUtils::ComputeInsetRect(basicShape, aRefBox);
   const Rect insetRectPixels = NSRectToRect(insetRect, appUnitsPerDevPixel);