Bug 1480649 - Use union to wrap different shape-like types. r=xidorn
authorBoris Chiou <boris.chiou@gmail.com>
Tue, 07 Aug 2018 07:56:01 +0000
changeset 430429 924956d87045a070e38a312cb88966313e75d015
parent 430376 7d78ffbf4c4a31bfc808e80ea09c6c131328c4ad
child 430430 d0e9a6ae0f655fd6fd1292834398530de58c9637
push id34405
push userncsoregi@mozilla.com
push dateWed, 08 Aug 2018 09:57:26 +0000
treeherdermozilla-central@c65991f3fa10 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersxidorn
bugs1480649
milestone63.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 1480649 - Use union to wrap different shape-like types. r=xidorn 1. We will add more shape-like types in the future, so it's better to use union to reduce the memory usage. 2. Those shape-like types are mutual exclusive, so we could use union to wrap them. Differential Revision: https://phabricator.services.mozilla.com/D2746
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
servo/components/style/gecko/conversions.rs
servo/components/style/properties/gecko.mako.rs
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -988,22 +988,31 @@ StyleBasicShape::GetShapeTypeName() cons
       return eCSSKeyword_inset;
   }
   MOZ_ASSERT_UNREACHABLE("unexpected type");
   return eCSSKeyword_UNKNOWN;
 }
 
 // --------------------
 // StyleShapeSource
+StyleShapeSource::StyleShapeSource()
+  : mBasicShape()
+{
+}
 
 StyleShapeSource::StyleShapeSource(const StyleShapeSource& aSource)
 {
   DoCopy(aSource);
 }
 
+StyleShapeSource::~StyleShapeSource()
+{
+  DoDestroy();
+}
+
 StyleShapeSource&
 StyleShapeSource::operator=(const StyleShapeSource& aOther)
 {
   if (this != &aOther) {
     DoCopy(aOther);
   }
 
   return *this;
@@ -1035,28 +1044,31 @@ StyleShapeSource::operator==(const Style
   MOZ_ASSERT_UNREACHABLE("Unexpected shape source type!");
   return true;
 }
 
 void
 StyleShapeSource::SetURL(css::URLValue* aValue)
 {
   MOZ_ASSERT(aValue);
-  if (!mShapeImage) {
-    mShapeImage = MakeUnique<nsStyleImage>();
+  if (mType != StyleShapeSourceType::Image &&
+      mType != StyleShapeSourceType::URL) {
+    DoDestroy();
+    new (&mShapeImage) UniquePtr<nsStyleImage>(new nsStyleImage());
   }
   mShapeImage->SetURLValue(do_AddRef(aValue));
   mType = StyleShapeSourceType::URL;
 }
 
 void
 StyleShapeSource::SetShapeImage(UniquePtr<nsStyleImage> aShapeImage)
 {
   MOZ_ASSERT(aShapeImage);
-  mShapeImage = std::move(aShapeImage);
+  DoDestroy();
+  new (&mShapeImage) UniquePtr<nsStyleImage>(std::move(aShapeImage));
   mType = StyleShapeSourceType::Image;
 }
 
 imgIRequest*
 StyleShapeSource::GetShapeImageData() const
 {
   if (mType != StyleShapeSourceType::Image) {
     return nullptr;
@@ -1067,24 +1079,26 @@ StyleShapeSource::GetShapeImageData() co
   return mShapeImage->GetImageData();
 }
 
 void
 StyleShapeSource::SetBasicShape(UniquePtr<StyleBasicShape> aBasicShape,
                                 StyleGeometryBox aReferenceBox)
 {
   MOZ_ASSERT(aBasicShape);
-  mBasicShape = std::move(aBasicShape);
+  DoDestroy();
+  new (&mBasicShape) UniquePtr<StyleBasicShape>(std::move(aBasicShape));
   mReferenceBox = aReferenceBox;
   mType = StyleShapeSourceType::Shape;
 }
 
 void
 StyleShapeSource::SetReferenceBox(StyleGeometryBox aReferenceBox)
 {
+  DoDestroy();
   mReferenceBox = aReferenceBox;
   mType = StyleShapeSourceType::Box;
 }
 
 void
 StyleShapeSource::DoCopy(const StyleShapeSource& aOther)
 {
   switch (aOther.mType) {
@@ -1107,16 +1121,35 @@ StyleShapeSource::DoCopy(const StyleShap
       break;
 
     case StyleShapeSourceType::Box:
       SetReferenceBox(aOther.GetReferenceBox());
       break;
   }
 }
 
+void
+StyleShapeSource::DoDestroy()
+{
+  switch (mType) {
+    case StyleShapeSourceType::Shape:
+      mBasicShape.~UniquePtr<StyleBasicShape>();
+      break;
+    case StyleShapeSourceType::Image:
+    case StyleShapeSourceType::URL:
+      mShapeImage.~UniquePtr<nsStyleImage>();
+      break;
+    case StyleShapeSourceType::None:
+    case StyleShapeSourceType::Box:
+      // Not a union type, so do nothing.
+      break;
+  }
+  mType = StyleShapeSourceType::None;
+}
+
 // --------------------
 // nsStyleFilter
 //
 nsStyleFilter::nsStyleFilter()
   : mType(NS_STYLE_FILTER_NONE)
   , mDropShadow(nullptr)
 {
   MOZ_COUNT_CTOR(nsStyleFilter);
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1968,23 +1968,21 @@ private:
   // position of center for ellipse or circle
   mozilla::Position mPosition;
   // corner radii for inset (0 if not set)
   nsStyleCorners mRadius;
 };
 
 struct StyleShapeSource final
 {
-  StyleShapeSource() = default;
+  StyleShapeSource();
 
   StyleShapeSource(const StyleShapeSource& aSource);
 
-  ~StyleShapeSource()
-  {
-  }
+  ~StyleShapeSource();
 
   StyleShapeSource& operator=(const StyleShapeSource& aOther);
 
   bool operator==(const StyleShapeSource& aOther) const;
 
   bool operator!=(const StyleShapeSource& aOther) const
   {
     return !(*this == aOther);
@@ -2036,19 +2034,24 @@ struct StyleShapeSource final
   }
 
   void SetReferenceBox(StyleGeometryBox aReferenceBox);
 
 private:
   void* operator new(size_t) = delete;
 
   void DoCopy(const StyleShapeSource& aOther);
-
-  mozilla::UniquePtr<StyleBasicShape> mBasicShape;
-  mozilla::UniquePtr<nsStyleImage> mShapeImage;
+  void DoDestroy();
+
+  union {
+    mozilla::UniquePtr<StyleBasicShape> mBasicShape;
+    mozilla::UniquePtr<nsStyleImage> mShapeImage;
+    // TODO: Bug 1429298, implement SVG Path function.
+    // TODO: Bug 1480665, implement ray() function.
+  };
   StyleShapeSourceType mType = StyleShapeSourceType::None;
   StyleGeometryBox mReferenceBox = StyleGeometryBox::NoBox;
 };
 
 } // namespace mozilla
 
 struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay
 {
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -654,17 +654,17 @@ pub mod basic_shape {
         ) -> Option<ShapeSource<BasicShape, ReferenceBox, ImageOrUrl>>
         where
             ReferenceBox: From<StyleGeometryBox>,
         {
             match self.mType {
                 StyleShapeSourceType::None => Some(ShapeSource::None),
                 StyleShapeSourceType::Box => Some(ShapeSource::Box(self.mReferenceBox.into())),
                 StyleShapeSourceType::Shape => {
-                    let other_shape = unsafe { &*self.mBasicShape.mPtr };
+                    let other_shape = unsafe { &*self.__bindgen_anon_1.mBasicShape.as_ref().mPtr };
                     let shape = other_shape.into();
                     let reference_box = if self.mReferenceBox == StyleGeometryBox::NoBox {
                         None
                     } else {
                         Some(self.mReferenceBox.into())
                     };
                     Some(ShapeSource::Shape(shape, reference_box))
                 },
@@ -672,17 +672,17 @@ pub mod basic_shape {
             }
         }
     }
 
     impl<'a> From<&'a StyleShapeSource> for ClippingShape {
         fn from(other: &'a StyleShapeSource) -> Self {
             match other.mType {
                 StyleShapeSourceType::URL => unsafe {
-                    let shape_image = &*other.mShapeImage.mPtr;
+                    let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
                     let other_url = RefPtr::new(*shape_image.__bindgen_anon_1.mURLValue.as_ref());
                     let url = ComputedUrl::from_url_value(other_url);
                     ShapeSource::ImageOrUrl(url)
                 },
                 StyleShapeSourceType::Image => {
                     unreachable!("ClippingShape doesn't support Image!");
                 },
                 _ => other
@@ -694,17 +694,17 @@ pub mod basic_shape {
 
     impl<'a> From<&'a StyleShapeSource> for FloatAreaShape {
         fn from(other: &'a StyleShapeSource) -> Self {
             match other.mType {
                 StyleShapeSourceType::URL => {
                     unreachable!("FloatAreaShape doesn't support URL!");
                 },
                 StyleShapeSourceType::Image => unsafe {
-                    let shape_image = &*other.mShapeImage.mPtr;
+                    let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
                     let image = shape_image.into_image().expect("Cannot convert to Image");
                     ShapeSource::ImageOrUrl(image)
                 },
                 _ => other
                     .into_shape_source()
                     .expect("Couldn't convert to StyleSource!"),
             }
         }
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -4955,17 +4955,17 @@ fn static_assert() {
                 unsafe {
                     bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.0.url_value.get())
                 }
             }
             % elif ident == "shape_outside":
             ShapeSource::ImageOrUrl(image) => {
                 unsafe {
                     bindings::Gecko_NewShapeImage(${ident});
-                    let style_image = &mut *${ident}.mShapeImage.mPtr;
+                    let style_image = &mut *${ident}.__bindgen_anon_1.mShapeImage.as_mut().mPtr;
                     style_image.set(image);
                 }
             }
             % else:
                <% raise Exception("Unknown property: %s" % ident) %>
             }
             % endif
             ShapeSource::None => {} // don't change the type
@@ -4975,17 +4975,17 @@ fn static_assert() {
             }
             ShapeSource::Shape(servo_shape, maybe_box) => {
                 fn init_shape(${ident}: &mut StyleShapeSource, basic_shape_type: StyleBasicShapeType)
                               -> &mut StyleBasicShape {
                     unsafe {
                         // Create StyleBasicShape in StyleShapeSource. mReferenceBox and mType
                         // will be set manually later.
                         Gecko_NewBasicShape(${ident}, basic_shape_type);
-                        &mut *${ident}.mBasicShape.mPtr
+                        &mut *${ident}.__bindgen_anon_1.mBasicShape.as_mut().mPtr
                     }
                 }
                 match servo_shape {
                     BasicShape::Inset(inset) => {
                         let shape = init_shape(${ident}, StyleBasicShapeType::Inset);
                         unsafe { shape.mCoordinates.set_len(4) };
 
                         // set_len() can't call constructors, so the coordinates