Bug 1535165 - Make the will-change bitfield use cbindgen. r=dholbert
authorEmilio Cobos Álvarez <emilio@crisal.io>
Mon, 18 Mar 2019 18:08:08 +0000
changeset 464895 590e76eeb3e820b97663c710e48d195bc5d8cbae
parent 464894 8a5a706e25c81aec96eb4f6553c5d95ea25c0383
child 464896 8d1828122cf28320b41d00baea5d3b8992c2f643
push id35727
push userdvarga@mozilla.com
push dateTue, 19 Mar 2019 09:48:59 +0000
treeherdermozilla-central@70baa37ae1eb [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1535165
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 1535165 - Make the will-change bitfield use cbindgen. r=dholbert Differential Revision: https://phabricator.services.mozilla.com/D23414
layout/generic/nsFrame.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/painting/ActiveLayerTracker.cpp
layout/style/GeckoBindings.cpp
layout/style/GeckoBindings.h
layout/style/ServoBindings.toml
layout/style/nsStyleConsts.h
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/style/nsStyleStructInlines.h
servo/components/style/cbindgen.toml
servo/components/style/macros.rs
servo/components/style/properties/gecko.mako.rs
servo/components/style/values/specified/box.rs
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1631,17 +1631,17 @@ bool nsIFrame::ChildrenHavePerspective(
 }
 
 bool nsIFrame::HasOpacityInternal(float aThreshold,
                                   const nsStyleDisplay* aStyleDisplay,
                                   const nsStyleEffects* aStyleEffects,
                                   EffectSet* aEffectSet) const {
   MOZ_ASSERT(0.0 <= aThreshold && aThreshold <= 1.0, "Invalid argument");
   if (aStyleEffects->mOpacity < aThreshold ||
-      (aStyleDisplay->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY)) {
+      (aStyleDisplay->mWillChangeBitField & StyleWillChangeBits_OPACITY)) {
     return true;
   }
 
   if (!mMayHaveOpacityAnimation) {
     return false;
   }
 
   return ((nsLayoutUtils::IsPrimaryStyleFrame(this) ||
@@ -2838,27 +2838,27 @@ void nsIFrame::BuildDisplayListForStacki
   // we're painting, and we're not animating opacity. Don't do this
   // if we're going to compute plugin geometry, since opacity-0 plugins
   // need to have display items built for them.
   bool needHitTestInfo = aBuilder->BuildCompositorHitTestInfo() &&
                          StyleUI()->GetEffectivePointerEvents(this) !=
                              NS_STYLE_POINTER_EVENTS_NONE;
   bool opacityItemForEventsAndPluginsOnly = false;
   if (effects->mOpacity == 0.0 && aBuilder->IsForPainting() &&
-      !(disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_OPACITY) &&
+      !(disp->mWillChangeBitField & StyleWillChangeBits_OPACITY) &&
       !nsLayoutUtils::HasAnimationOfPropertySet(
           this, nsCSSPropertyIDSet::OpacityProperties(), effectSetForOpacity)) {
     if (needHitTestInfo || aBuilder->WillComputePluginGeometry()) {
       opacityItemForEventsAndPluginsOnly = true;
     } else {
       return;
     }
   }
 
-  if (disp->mWillChangeBitField != 0) {
+  if (disp->mWillChangeBitField) {
     aBuilder->AddToWillChangeBudget(this, GetSize());
   }
 
   // For preserves3d, use the dirty rect already installed on the
   // builder, since aDirtyRect maybe distorted for transforms along
   // the chain.
   nsRect visibleRect = aBuilder->GetVisibleRect();
   nsRect dirtyRect = aBuilder->GetDirtyRect();
@@ -10570,17 +10570,17 @@ bool nsIFrame::IsStackingContext(const n
          // strictly speaking, 'perspective' doesn't require visual atomicity,
          // but the spec says it acts like the rest of these
          ChildrenHavePerspective(aStyleDisplay) ||
          aStyleEffects->mMixBlendMode != NS_STYLE_BLEND_NORMAL ||
          nsSVGIntegrationUtils::UsingEffectsForFrame(this) ||
          (aIsPositioned && (aStyleDisplay->IsPositionForcingStackingContext() ||
                             aStylePosition->mZIndex.IsInteger())) ||
          (aStyleDisplay->mWillChangeBitField &
-          NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) ||
+          StyleWillChangeBits_STACKING_CONTEXT) ||
          aStyleDisplay->mIsolation != NS_STYLE_ISOLATION_AUTO;
 }
 
 bool nsIFrame::IsStackingContext() {
   const nsStyleDisplay* disp = StyleDisplay();
   const bool isPositioned = disp->IsAbsPosContainingBlock(this);
   return IsStackingContext(disp, StylePosition(), StyleEffects(), isPositioned);
 }
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -3432,17 +3432,17 @@ void ScrollFrameHelper::BuildDisplayList
   // borders and underneath borders and backgrounds of later elements
   // in the tree.
   // Note that this does not apply for overlay scrollbars; those are drawn
   // in the positioned-elements layer on top of everything else by the call
   // to AppendScrollPartsTo(..., true) further down.
   AppendScrollPartsTo(aBuilder, aLists, createLayersForScrollbars, false);
 
   const nsStyleDisplay* disp = mOuter->StyleDisplay();
-  if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL)) {
+  if (disp->mWillChangeBitField & StyleWillChangeBits_SCROLL) {
     aBuilder->AddToWillChangeBudget(mOuter, GetVisualViewportSize());
   }
 
   mScrollParentID = aBuilder->GetCurrentScrollParentId();
 
   Maybe<nsRect> contentBoxClip;
   Maybe<const DisplayItemClipChain*> extraContentBoxClipForNonCaretContent;
   if (MOZ_UNLIKELY(
@@ -5326,30 +5326,30 @@ bool ScrollFrameHelper::IsScrollbarOnRig
       return true;
     case 3:  // Always left
       return false;
   }
 }
 
 bool ScrollFrameHelper::IsMaybeScrollingActive() const {
   const nsStyleDisplay* disp = mOuter->StyleDisplay();
-  if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL)) {
+  if (disp->mWillChangeBitField & StyleWillChangeBits_SCROLL) {
     return true;
   }
 
   nsIContent* content = mOuter->GetContent();
   return mHasBeenScrolledRecently || IsAlwaysActive() ||
          nsLayoutUtils::HasDisplayPort(content) ||
          nsContentUtils::HasScrollgrab(content);
 }
 
 bool ScrollFrameHelper::IsScrollingActive(
     nsDisplayListBuilder* aBuilder) const {
   const nsStyleDisplay* disp = mOuter->StyleDisplay();
-  if (disp && (disp->mWillChangeBitField & NS_STYLE_WILL_CHANGE_SCROLL) &&
+  if (disp->mWillChangeBitField & StyleWillChangeBits_SCROLL &&
       aBuilder->IsInWillChangeBudget(mOuter, GetVisualViewportSize())) {
     return true;
   }
 
   nsIContent* content = mOuter->GetContent();
   return mHasBeenScrolledRecently || IsAlwaysActive() ||
          nsLayoutUtils::HasDisplayPort(content) ||
          nsContentUtils::HasScrollgrab(content);
--- a/layout/painting/ActiveLayerTracker.cpp
+++ b/layout/painting/ActiveLayerTracker.cpp
@@ -479,24 +479,24 @@ bool ActiveLayerTracker::IsStyleAnimated
   // (primary frame) but their will-change style will be specified on the style
   // frame and, unlike other transform properties, not inherited.
   // As a result, for transform properties only we need to be careful to look up
   // the will-change style on the _style_ frame.
   const nsIFrame* styleFrame = nsLayoutUtils::GetStyleFrame(aFrame);
   const nsCSSPropertyIDSet transformSet =
       nsCSSPropertyIDSet::TransformLikeProperties();
   if ((styleFrame && (styleFrame->StyleDisplay()->mWillChangeBitField &
-                      NS_STYLE_WILL_CHANGE_TRANSFORM)) &&
+                      StyleWillChangeBits_TRANSFORM)) &&
       aPropertySet.Intersects(transformSet) &&
       (!aBuilder ||
        aBuilder->IsInWillChangeBudget(aFrame, aFrame->GetSize()))) {
     return true;
   }
   if ((aFrame->StyleDisplay()->mWillChangeBitField &
-       NS_STYLE_WILL_CHANGE_OPACITY) &&
+       StyleWillChangeBits_OPACITY) &&
       aPropertySet.Intersects(nsCSSPropertyIDSet::OpacityProperties()) &&
       (!aBuilder ||
        aBuilder->IsInWillChangeBudget(aFrame, aFrame->GetSize()))) {
     return true;
   }
 
   LayerActivity* layerActivity = GetLayerActivity(aFrame);
   if (layerActivity) {
--- a/layout/style/GeckoBindings.cpp
+++ b/layout/style/GeckoBindings.cpp
@@ -1425,17 +1425,18 @@ void Gecko_ClearWillChange(nsStyleDispla
   aDisplay->mWillChange.Clear();
   aDisplay->mWillChange.SetCapacity(aLength);
 }
 
 void Gecko_AppendWillChange(nsStyleDisplay* aDisplay, nsAtom* aAtom) {
   aDisplay->mWillChange.AppendElement(aAtom);
 }
 
-void Gecko_CopyWillChangeFrom(nsStyleDisplay* aDest, nsStyleDisplay* aSrc) {
+void Gecko_CopyWillChangeFrom(nsStyleDisplay* aDest,
+                              const nsStyleDisplay* aSrc) {
   aDest->mWillChange.Clear();
   aDest->mWillChange.AppendElements(aSrc->mWillChange);
 }
 
 enum class KeyframeSearchDirection {
   Forwards,
   Backwards,
 };
--- a/layout/style/GeckoBindings.h
+++ b/layout/style/GeckoBindings.h
@@ -454,17 +454,17 @@ void Gecko_CopyCounterIncrementsFrom(nsS
 
 void Gecko_EnsureImageLayersLength(nsStyleImageLayers* layers, size_t len,
                                    nsStyleImageLayers::LayerType layer_type);
 
 void Gecko_EnsureStyleAnimationArrayLength(void* array, size_t len);
 void Gecko_EnsureStyleTransitionArrayLength(void* array, size_t len);
 void Gecko_ClearWillChange(nsStyleDisplay* display, size_t length);
 void Gecko_AppendWillChange(nsStyleDisplay* display, nsAtom* atom);
-void Gecko_CopyWillChangeFrom(nsStyleDisplay* dest, nsStyleDisplay* src);
+void Gecko_CopyWillChangeFrom(nsStyleDisplay* dest, const nsStyleDisplay* src);
 
 // Searches from the beginning of |keyframes| for a Keyframe object with the
 // specified offset and timing function. If none is found, a new Keyframe object
 // with the specified |offset| and |timingFunction| will be prepended to
 // |keyframes|.
 //
 // @param keyframes  An array of Keyframe objects, sorted by offset.
 //                   The first Keyframe in the array, if any, MUST have an
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -445,16 +445,17 @@ cbindgen-types = [
     { gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
     { gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
     { gecko = "StyleGenericBorderRadius", servo = "values::generics::border::BorderRadius" },
     { 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" },
 ]
 
 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>>" },
--- a/layout/style/nsStyleConsts.h
+++ b/layout/style/nsStyleConsts.h
@@ -235,26 +235,16 @@ enum class StyleWindowDragging : uint8_t
 // orient
 enum class StyleOrient : uint8_t {
   Inline,
   Block,
   Horizontal,
   Vertical,
 };
 
-// See nsStyleDisplay
-//
-// These need to be in sync with WillChangeBits in box.rs.
-#define NS_STYLE_WILL_CHANGE_STACKING_CONTEXT (1 << 0)
-#define NS_STYLE_WILL_CHANGE_TRANSFORM (1 << 1)
-#define NS_STYLE_WILL_CHANGE_SCROLL (1 << 2)
-#define NS_STYLE_WILL_CHANGE_OPACITY (1 << 3)
-#define NS_STYLE_WILL_CHANGE_FIXPOS_CB (1 << 4)
-#define NS_STYLE_WILL_CHANGE_ABSPOS_CB (1 << 5)
-
 // See AnimationEffect.webidl
 // and mozilla/dom/AnimationEffectBinding.h
 namespace dom {
 enum class PlaybackDirection : uint8_t;
 enum class FillMode : uint8_t;
 }  // namespace dom
 
 // Animation play state
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -2918,17 +2918,17 @@ nsStyleDisplay::nsStyleDisplay(const Doc
       mOverflowX(StyleOverflow::Visible),
       mOverflowY(StyleOverflow::Visible),
       mOverflowClipBoxBlock(StyleOverflowClipBox::PaddingBox),
       mOverflowClipBoxInline(StyleOverflowClipBox::PaddingBox),
       mResize(StyleResize::None),
       mOrient(StyleOrient::Inline),
       mIsolation(NS_STYLE_ISOLATION_AUTO),
       mTopLayer(NS_STYLE_TOP_LAYER_NONE),
-      mWillChangeBitField(0),
+      mWillChangeBitField({0}),
       mTouchAction(StyleTouchAction_AUTO),
       mScrollBehavior(NS_STYLE_SCROLL_BEHAVIOR_AUTO),
       mOverscrollBehaviorX(StyleOverscrollBehavior::Auto),
       mOverscrollBehaviorY(StyleOverscrollBehavior::Auto),
       mOverflowAnchor(StyleOverflowAnchor::Auto),
       mScrollSnapTypeX(StyleScrollSnapType::None),
       mScrollSnapTypeY(StyleScrollSnapType::None),
       mScrollSnapPointsX(eStyleUnit_None),
@@ -3275,30 +3275,33 @@ nsChangeHint nsStyleDisplay::CalcDiffere
     // A change from/to being a containing block for position:fixed.
     hint |= nsChangeHint_UpdateContainingBlock | nsChangeHint_UpdateOverflow |
             nsChangeHint_RepaintFrame;
   } else if (mChildPerspective != aNewData.mChildPerspective) {
     hint |= nsChangeHint_UpdateOverflow | nsChangeHint_RepaintFrame;
   }
 
   // Note that the HasTransformStyle() != aNewData.HasTransformStyle()
-  // test above handles relevant changes in the
-  // NS_STYLE_WILL_CHANGE_TRANSFORM bit, which in turn handles frame
-  // reconstruction for changes in the containing block of
-  // fixed-positioned elements.
-  uint8_t willChangeBitsChanged =
-      mWillChangeBitField ^ aNewData.mWillChangeBitField;
+  // test above handles relevant changes in the StyleWillChangeBit_TRANSFORM
+  // bit, which in turn handles frame reconstruction for changes in the
+  // containing block of fixed-positioned elements.
+  //
+  // TODO(emilio): Should add xor to the generated cbindgen type.
+  auto willChangeBitsChanged =
+      StyleWillChangeBits{static_cast<decltype(StyleWillChangeBits::bits)>(
+          mWillChangeBitField.bits ^ aNewData.mWillChangeBitField.bits)};
+
   if (willChangeBitsChanged &
-      (NS_STYLE_WILL_CHANGE_STACKING_CONTEXT | NS_STYLE_WILL_CHANGE_SCROLL |
-       NS_STYLE_WILL_CHANGE_OPACITY)) {
+      (StyleWillChangeBits_STACKING_CONTEXT | StyleWillChangeBits_SCROLL |
+       StyleWillChangeBits_OPACITY)) {
     hint |= nsChangeHint_RepaintFrame;
   }
 
   if (willChangeBitsChanged &
-      (NS_STYLE_WILL_CHANGE_FIXPOS_CB | NS_STYLE_WILL_CHANGE_ABSPOS_CB)) {
+      (StyleWillChangeBits_FIXPOS_CB | StyleWillChangeBits_ABSPOS_CB)) {
     hint |= nsChangeHint_UpdateContainingBlock;
   }
 
   // If touch-action is changed, we need to regenerate the event regions on
   // the layers and send it over to the compositor for APZ to handle.
   if (mTouchAction != aNewData.mTouchAction) {
     hint |= nsChangeHint_RepaintFrame;
   }
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1875,22 +1875,20 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   mozilla::StyleOverflow mOverflowX;
   mozilla::StyleOverflow mOverflowY;
   mozilla::StyleOverflowClipBox mOverflowClipBoxBlock;
   mozilla::StyleOverflowClipBox mOverflowClipBoxInline;
   mozilla::StyleResize mResize;
   mozilla::StyleOrient mOrient;
   uint8_t mIsolation;           // NS_STYLE_ISOLATION_*
   uint8_t mTopLayer;            // NS_STYLE_TOP_LAYER_*
-  uint8_t mWillChangeBitField;  // NS_STYLE_WILL_CHANGE_*
-                                // Stores a bitfield representation of the
-                                // properties that are frequently queried. This
-                                // should match mWillChange. Also tracks if any
-                                // of the properties in the will-change list
-                                // require a stacking context.
+  // Stores a bitfield representation of the properties that are frequently
+  // queried. This should match mWillChange. Also tracks if any of the
+  // properties in the will-change list require a stacking context.
+  mozilla::StyleWillChangeBits mWillChangeBitField;
   nsTArray<RefPtr<nsAtom>> mWillChange;
 
   mozilla::StyleTouchAction mTouchAction;
   uint8_t mScrollBehavior;  // NS_STYLE_SCROLL_BEHAVIOR_*
   mozilla::StyleOverscrollBehavior mOverscrollBehaviorX;
   mozilla::StyleOverscrollBehavior mOverscrollBehaviorY;
   mozilla::StyleOverflowAnchor mOverflowAnchor;
   mozilla::StyleScrollSnapAlign mScrollSnapAlign;
@@ -2147,17 +2145,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   }
 
   /* Returns whether the element has the -moz-transform property
    * or a related property. */
   bool HasTransformStyle() const {
     return mSpecifiedTransform || mSpecifiedRotate || mSpecifiedTranslate ||
            mSpecifiedScale ||
            mTransformStyle == NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D ||
-           (mWillChangeBitField & NS_STYLE_WILL_CHANGE_TRANSFORM) ||
+           (mWillChangeBitField & mozilla::StyleWillChangeBits_TRANSFORM) ||
            (mMotion && mMotion->HasPath());
   }
 
   bool HasIndividualTransform() const {
     return mSpecifiedRotate || mSpecifiedTranslate || mSpecifiedScale;
   }
 
   bool HasPerspectiveStyle() const { return !mChildPerspective.IsNone(); }
--- a/layout/style/nsStyleStructInlines.h
+++ b/layout/style/nsStyleStructInlines.h
@@ -130,17 +130,17 @@ bool nsStyleDisplay::HasPerspective(cons
 }
 
 bool nsStyleDisplay::IsFixedPosContainingBlockForNonSVGTextFrames(
     const mozilla::ComputedStyle& aStyle) const {
   // NOTE: Any CSS properties that influence the output of this function
   // should have the FIXPOS_CB flag set on them.
   NS_ASSERTION(aStyle.StyleDisplay() == this, "unexpected aStyle");
 
-  if (mWillChangeBitField & NS_STYLE_WILL_CHANGE_FIXPOS_CB) {
+  if (mWillChangeBitField & mozilla::StyleWillChangeBits_FIXPOS_CB) {
     return true;
   }
 
   return aStyle.StyleEffects()->HasFilters();
 }
 
 bool nsStyleDisplay::
     IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() const {
@@ -175,17 +175,17 @@ bool nsStyleDisplay::IsFixedPosContainin
              "Any fixed-pos CB should also be an abs-pos CB");
   return true;
 }
 
 bool nsStyleDisplay::IsAbsPosContainingBlockForNonSVGTextFrames() const {
   // NOTE: Any CSS properties that influence the output of this function
   // should have the ABSPOS_CB set on them.
   return IsAbsolutelyPositionedStyle() || IsRelativelyPositionedStyle() ||
-         (mWillChangeBitField & NS_STYLE_WILL_CHANGE_ABSPOS_CB);
+         (mWillChangeBitField & mozilla::StyleWillChangeBits_ABSPOS_CB);
 }
 
 bool nsStyleDisplay::IsAbsPosContainingBlock(
     const nsIFrame* aContextFrame) const {
   mozilla::ComputedStyle* style = aContextFrame->Style();
   NS_ASSERTION(style->StyleDisplay() == this, "unexpected aContextFrame");
   // NOTE: Any CSS properties that influence the output of this function
   // should have the ABSPOS_CB set on them.
--- a/servo/components/style/cbindgen.toml
+++ b/servo/components/style/cbindgen.toml
@@ -101,16 +101,17 @@ include = [
   "NonNegativeLengthOrNumberRect",
   "Perspective",
   "ZIndex",
   "TransformOrigin",
   "WordBreak",
   "Contain",
   "RestyleHint",
   "TouchAction",
+  "WillChangeBits",
   "TextDecorationLine",
 ]
 item_types = ["enums", "structs", "typedefs"]
 
 [export.body]
 "CSSPixelLength" = """
   inline nscoord ToAppUnits() const;
   inline bool IsZero() const;
--- a/servo/components/style/macros.rs
+++ b/servo/components/style/macros.rs
@@ -97,25 +97,8 @@ macro_rules! define_keyword_type {
                 input
                     .expect_ident_matching($css)
                     .map(|_| $name)
                     .map_err(|e| e.into())
             }
         }
     };
 }
-
-#[cfg(feature = "gecko")]
-macro_rules! impl_bitflags_conversions {
-    ($name:ident) => {
-        impl From<u8> for $name {
-            fn from(bits: u8) -> $name {
-                $name::from_bits(bits).expect("bits contain valid flag")
-            }
-        }
-
-        impl From<$name> for u8 {
-            fn from(v: $name) -> u8 {
-                v.bits()
-            }
-        }
-    };
-}
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -2935,73 +2935,71 @@ fn static_assert() {
     ${impl_animation_timing_function()}
 
     ${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')}
     ${impl_individual_transform('translate', 'Translate', 'mSpecifiedTranslate')}
     ${impl_individual_transform('scale', 'Scale', 'mSpecifiedScale')}
 
     pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
         use crate::gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange};
-        use crate::properties::longhands::will_change::computed_value::T;
+        use crate::values::specified::box_::{WillChangeBits, WillChange};
 
         match v {
-            T::AnimateableFeatures { features, bits } => {
+            WillChange::AnimateableFeatures { features, bits } => {
                 unsafe {
                     Gecko_ClearWillChange(&mut self.gecko, features.len());
                 }
 
                 for feature in features.iter() {
                     unsafe {
                         Gecko_AppendWillChange(&mut self.gecko, feature.0.as_ptr())
                     }
                 }
 
-                self.gecko.mWillChangeBitField = bits.bits();
+                self.gecko.mWillChangeBitField = bits;
             },
-            T::Auto => {
+            WillChange::Auto => {
                 unsafe {
                     Gecko_ClearWillChange(&mut self.gecko, 0);
                 }
-                self.gecko.mWillChangeBitField = 0;
+                self.gecko.mWillChangeBitField = WillChangeBits::empty();
             },
         };
     }
 
     pub fn copy_will_change_from(&mut self, other: &Self) {
         use crate::gecko_bindings::bindings::Gecko_CopyWillChangeFrom;
 
         self.gecko.mWillChangeBitField = other.gecko.mWillChangeBitField;
         unsafe {
-            Gecko_CopyWillChangeFrom(&mut self.gecko, &other.gecko as *const _ as *mut _);
+            Gecko_CopyWillChangeFrom(&mut self.gecko, &other.gecko);
         }
     }
 
     pub fn reset_will_change(&mut self, other: &Self) {
         self.copy_will_change_from(other)
     }
 
     pub fn clone_will_change(&self) -> longhands::will_change::computed_value::T {
-        use crate::properties::longhands::will_change::computed_value::T;
-        use crate::gecko_bindings::structs::nsAtom;
         use crate::values::CustomIdent;
-        use crate::values::specified::box_::WillChangeBits;
+        use crate::values::specified::box_::WillChange;
 
         if self.gecko.mWillChange.len() == 0 {
-            return T::Auto
+            return WillChange::Auto
         }
 
         let custom_idents: Vec<CustomIdent> = self.gecko.mWillChange.iter().map(|gecko_atom| {
             unsafe {
-                CustomIdent(Atom::from_raw(gecko_atom.mRawPtr as *mut nsAtom))
+                CustomIdent(Atom::from_raw(gecko_atom.mRawPtr))
             }
         }).collect();
 
-        T::AnimateableFeatures {
+        WillChange::AnimateableFeatures {
             features: custom_idents.into_boxed_slice(),
-            bits: WillChangeBits::from_bits_truncate(self.gecko.mWillChangeBitField),
+            bits: self.gecko.mWillChangeBitField,
         }
     }
 
     <% impl_shape_source("shape_outside", "mShapeOutside") %>
 
     pub fn set_offset_path(&mut self, v: longhands::offset_path::computed_value::T) {
         use crate::gecko_bindings::bindings::{Gecko_NewStyleMotion, Gecko_SetStyleMotion};
         use crate::gecko_bindings::structs::StyleShapeSourceType;
--- a/servo/components/style/values/specified/box.rs
+++ b/servo/components/style/values/specified/box.rs
@@ -550,19 +550,18 @@ impl WillChange {
     /// Get default value of `will-change` as `auto`
     pub fn auto() -> WillChange {
         WillChange::Auto
     }
 }
 
 bitflags! {
     /// The change bits that we care about.
-    ///
-    /// These need to be in sync with NS_STYLE_WILL_CHANGE_*.
     #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue)]
+    #[repr(C)]
     pub struct WillChangeBits: u8 {
         /// Whether the stacking context will change.
         const STACKING_CONTEXT = 1 << 0;
         /// Whether `transform` will change.
         const TRANSFORM = 1 << 1;
         /// Whether `scroll-position` will change.
         const SCROLL = 1 << 2;
         /// Whether `opacity` will change.
@@ -611,17 +610,17 @@ fn change_bits_for_maybe_property(ident:
     }
 }
 
 impl Parse for WillChange {
     /// auto | <animateable-feature>#
     fn parse<'i, 't>(
         context: &ParserContext,
         input: &mut Parser<'i, 't>,
-    ) -> Result<WillChange, ParseError<'i>> {
+    ) -> Result<Self, ParseError<'i>> {
         if input
             .try(|input| input.expect_ident_matching("auto"))
             .is_ok()
         {
             return Ok(WillChange::Auto);
         }
 
         let mut bits = WillChangeBits::empty();