Bug 1388255 - Make nsStylePosition::mGridTemplate{Columns,Rows} a UniquePtr. r?dholbert,canaltinova draft
authorXidorn Quan <me@upsuper.org>
Wed, 09 Aug 2017 11:30:25 +1000
changeset 644851 b47810c5455601390acc07bdc336782d5844d82b
parent 644850 2ddf3d614872165a02fe0888571eff39bc7475cf
child 725722 d8c9dc0b93981d513162ad16300cbf7949034cab
push id73559
push userxquan@mozilla.com
push dateFri, 11 Aug 2017 11:22:43 +0000
reviewersdholbert, canaltinova
bugs1388255
milestone57.0a1
Bug 1388255 - Make nsStylePosition::mGridTemplate{Columns,Rows} a UniquePtr. r?dholbert,canaltinova MozReview-Commit-ID: 8SOE6sAavCX
js/src/devtools/rootAnalysis/analyzeHeapWrites.js
layout/generic/nsGridContainerFrame.cpp
layout/style/ServoBindings.cpp
layout/style/ServoBindings.h
layout/style/ServoBindings.toml
layout/style/nsComputedDOMStyle.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
--- a/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
+++ b/js/src/devtools/rootAnalysis/analyzeHeapWrites.js
@@ -177,18 +177,17 @@ function treatAsSafeArgument(entry, varN
         ["Gecko_DestroyClipPath", "aClip", null],
         ["Gecko_ResetFilters", "effects", null],
         ["Gecko_CopyFiltersFrom", "aDest", null],
         [/Gecko_CSSValue_Set/, "aCSSValue", null],
         ["Gecko_CSSValue_Drop", "aCSSValue", null],
         ["Gecko_CSSFontFaceRule_GetCssText", "aResult", null],
         ["Gecko_EnsureTArrayCapacity", "aArray", null],
         ["Gecko_ClearPODTArray", "aArray", null],
-        ["Gecko_SetStyleGridTemplateArrayLengths", "aValue", null],
-        ["Gecko_SetGridTemplateLineNamesLength", "aValue", null],
+        ["Gecko_SetStyleGridTemplate", "aGridTemplate", null],
         ["Gecko_ResizeTArrayForStrings", "aArray", null],
         ["Gecko_ClearAndResizeStyleContents", "aContent", null],
         [/Gecko_ClearAndResizeCounter/, "aContent", null],
         [/Gecko_CopyCounter.*?From/, "aContent", null],
         [/Gecko_SetContentDataImageValue/, "aList", null],
         [/Gecko_SetContentData/, "aContent", null],
         ["Gecko_SetCounterFunction", "aContent", null],
         [/Gecko_EnsureStyle.*?ArrayLength/, "aArray", null],
--- a/layout/generic/nsGridContainerFrame.cpp
+++ b/layout/generic/nsGridContainerFrame.cpp
@@ -1925,20 +1925,20 @@ private:
                   gfxContext&              aRenderingContext,
                   const ReflowInput* aReflowInput,
                   const nsStylePosition*   aGridStyle,
                   const WritingMode&       aWM)
     : mIter(aFrame, kPrincipalList)
     , mGridStyle(aGridStyle)
     , mCols(eLogicalAxisInline)
     , mRows(eLogicalAxisBlock)
-    , mColFunctions(mGridStyle->mGridTemplateColumns,
+    , mColFunctions(mGridStyle->GridTemplateColumns(),
                     mGridStyle->mGridAutoColumnsMin,
                     mGridStyle->mGridAutoColumnsMax)
-    , mRowFunctions(mGridStyle->mGridTemplateRows,
+    , mRowFunctions(mGridStyle->GridTemplateRows(),
                     mGridStyle->mGridAutoRowsMin,
                     mGridStyle->mGridAutoRowsMax)
     , mReflowInput(aReflowInput)
     , mRenderingContext(aRenderingContext)
     , mFrame(aFrame)
     , mSharedGridData(nullptr)
     , mBorderPadding(aWM)
     , mFragBStart(0)
@@ -2615,18 +2615,18 @@ void
 nsGridContainerFrame::InitImplicitNamedAreas(const nsStylePosition* aStyle)
 {
   ImplicitNamedAreas* areas = GetImplicitNamedAreas();
   if (areas) {
     // Clear it, but reuse the hashtable itself for now.  We'll remove it
     // below if it isn't needed anymore.
     areas->Clear();
   }
-  AddImplicitNamedAreas(aStyle->mGridTemplateColumns.mLineNameLists);
-  AddImplicitNamedAreas(aStyle->mGridTemplateRows.mLineNameLists);
+  AddImplicitNamedAreas(aStyle->GridTemplateColumns().mLineNameLists);
+  AddImplicitNamedAreas(aStyle->GridTemplateRows().mLineNameLists);
   if (areas && areas->Count() == 0) {
     DeleteProperty(ImplicitNamedAreasProperty());
   }
 }
 
 int32_t
 nsGridContainerFrame::Grid::ResolveLine(const nsStyleGridLine& aLine,
                                         int32_t aNth,
@@ -3096,26 +3096,26 @@ nsGridContainerFrame::Grid::PlaceGridIte
   auto areas = gridStyle->mGridTemplateAreas.get();
   uint32_t numRepeatCols = aState.mColFunctions.InitRepeatTracks(
                              gridStyle->mGridColumnGap,
                              aComputedMinSize.ISize(aState.mWM),
                              aComputedSize.ISize(aState.mWM),
                              aComputedMaxSize.ISize(aState.mWM));
   mGridColEnd = mExplicitGridColEnd =
     aState.mColFunctions.ComputeExplicitGridEnd(areas ? areas->mNColumns + 1 : 1);
-  LineNameMap colLineNameMap(gridStyle->mGridTemplateColumns, numRepeatCols);
+  LineNameMap colLineNameMap(gridStyle->GridTemplateColumns(), numRepeatCols);
 
   uint32_t numRepeatRows = aState.mRowFunctions.InitRepeatTracks(
                              gridStyle->mGridRowGap,
                              aComputedMinSize.BSize(aState.mWM),
                              aComputedSize.BSize(aState.mWM),
                              aComputedMaxSize.BSize(aState.mWM));
   mGridRowEnd = mExplicitGridRowEnd =
     aState.mRowFunctions.ComputeExplicitGridEnd(areas ? areas->NRows() + 1 : 1);
-  LineNameMap rowLineNameMap(gridStyle->mGridTemplateRows, numRepeatRows);
+  LineNameMap rowLineNameMap(gridStyle->GridTemplateRows(), numRepeatRows);
 
   // http://dev.w3.org/csswg/css-grid/#line-placement
   // Resolve definite positions per spec chap 9.2.
   int32_t minCol = 1;
   int32_t minRow = 1;
   aState.mGridItems.ClearAndRetainStorage();
   aState.mIter.Reset();
   for (; !aState.mIter.AtEnd(); aState.mIter.Next()) {
@@ -3298,17 +3298,17 @@ nsGridContainerFrame::Grid::PlaceGridIte
   }
 
   // Count empty 'auto-fit' tracks in the repeat() range.
   // |colAdjust| will have a count for each line in the grid of how many
   // tracks were empty between the start of the grid and that line.
   Maybe<nsTArray<uint32_t>> colAdjust;
   uint32_t numEmptyCols = 0;
   if (aState.mColFunctions.mHasRepeatAuto &&
-      !gridStyle->mGridTemplateColumns.mIsAutoFill &&
+      !gridStyle->GridTemplateColumns().mIsAutoFill &&
       aState.mColFunctions.NumRepeatTracks() > 0) {
     for (uint32_t col = aState.mColFunctions.mRepeatAutoStart,
            endRepeat = aState.mColFunctions.mRepeatAutoEnd,
            numColLines = mGridColEnd + 1;
          col < numColLines; ++col) {
       if (numEmptyCols) {
         (*colAdjust)[col] = numEmptyCols;
       }
@@ -3325,17 +3325,17 @@ nsGridContainerFrame::Grid::PlaceGridIte
                    repeatIndex);
         aState.mColFunctions.mRemovedRepeatTracks[repeatIndex] = true;
       }
     }
   }
   Maybe<nsTArray<uint32_t>> rowAdjust;
   uint32_t numEmptyRows = 0;
   if (aState.mRowFunctions.mHasRepeatAuto &&
-      !gridStyle->mGridTemplateRows.mIsAutoFill &&
+      !gridStyle->GridTemplateRows().mIsAutoFill &&
       aState.mRowFunctions.NumRepeatTracks() > 0) {
     for (uint32_t row = aState.mRowFunctions.mRepeatAutoStart,
            endRepeat = aState.mRowFunctions.mRepeatAutoEnd,
            numRowLines = mGridRowEnd + 1;
          row < numRowLines; ++row) {
       if (numEmptyRows) {
         (*rowAdjust)[row] = numEmptyRows;
       }
@@ -6201,17 +6201,17 @@ nsGridContainerFrame::Reflow(nsPresConte
     // Generate the line info properties. We need to provide the number of
     // repeat tracks produced in the reflow. Only explicit names are assigned
     // to lines here; the mozilla::dom::GridLines class will later extract
     // implicit names from grid areas and assign them to the appropriate lines.
 
     // Generate column lines first.
     uint32_t capacity = gridReflowInput.mCols.mSizes.Length();
     const nsStyleGridTemplate& gridColTemplate =
-      gridReflowInput.mGridStyle->mGridTemplateColumns;
+      gridReflowInput.mGridStyle->GridTemplateColumns();
     nsTArray<nsTArray<nsString>> columnLineNames(capacity);
     for (col = 0; col <= gridReflowInput.mCols.mSizes.Length(); col++) {
       // Offset col by the explicit grid offset, to get the original names.
       nsTArray<nsString> explicitNames =
         gridReflowInput.mCols.GetExplicitLineNamesAtIndex(
           gridColTemplate,
           gridReflowInput.mColFunctions,
           col - gridReflowInput.mColFunctions.mExplicitGridOffset);
@@ -6222,17 +6222,17 @@ nsGridContainerFrame::Reflow(nsPresConte
       Move(columnLineNames),
       gridColTemplate.mRepeatAutoLineNameListBefore,
       gridColTemplate.mRepeatAutoLineNameListAfter);
     SetProperty(GridColumnLineInfo(), columnLineInfo);
 
     // Generate row lines next.
     capacity = gridReflowInput.mRows.mSizes.Length();
     const nsStyleGridTemplate& gridRowTemplate =
-      gridReflowInput.mGridStyle->mGridTemplateRows;
+      gridReflowInput.mGridStyle->GridTemplateRows();
     nsTArray<nsTArray<nsString>> rowLineNames(capacity);
     for (row = 0; row <= gridReflowInput.mRows.mSizes.Length(); row++) {
       // Offset row by the explicit grid offset, to get the original names.
       nsTArray<nsString> explicitNames =
         gridReflowInput.mRows.GetExplicitLineNamesAtIndex(
           gridRowTemplate,
           gridReflowInput.mRowFunctions,
           row - gridReflowInput.mRowFunctions.mExplicitGridOffset);
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1722,40 +1722,47 @@ Gecko_ClearPODTArray(void* aArray, size_
   auto base =
     reinterpret_cast<nsTArray_base<nsTArrayInfallibleAllocator,
                                    nsTArray_CopyWithMemutils>*>(aArray);
 
   base->template ShiftData<nsTArrayInfallibleAllocator>(0, base->Length(), 0,
                                                         aElementSize, aElementAlign);
 }
 
-void Gecko_SetStyleGridTemplateArrayLengths(nsStyleGridTemplate* aValue,
-                                            uint32_t aTrackSizes)
-{
-  aValue->mMinTrackSizingFunctions.SetLength(aTrackSizes);
-  aValue->mMaxTrackSizingFunctions.SetLength(aTrackSizes);
-  aValue->mLineNameLists.SetLength(aTrackSizes + 1);
-}
-
-void Gecko_SetGridTemplateLineNamesLength(nsStyleGridTemplate* aValue,
-                                          uint32_t aNames)
-{
-  aValue->mLineNameLists.SetLength(aNames);
-}
-
 void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* aArray, uint32_t aLength)
 {
   aArray->SetLength(aLength);
 }
 
 void
-Gecko_CopyStyleGridTemplateValues(nsStyleGridTemplate* aGridTemplate,
+Gecko_SetStyleGridTemplate(UniquePtr<nsStyleGridTemplate>* aGridTemplate,
+                           nsStyleGridTemplate* aValue)
+{
+  aGridTemplate->reset(aValue);
+}
+
+nsStyleGridTemplate*
+Gecko_CreateStyleGridTemplate(uint32_t aTrackSizes, uint32_t aNameSize)
+{
+  nsStyleGridTemplate* result = new nsStyleGridTemplate;
+  result->mMinTrackSizingFunctions.SetLength(aTrackSizes);
+  result->mMaxTrackSizingFunctions.SetLength(aTrackSizes);
+  result->mLineNameLists.SetLength(aNameSize);
+  return result;
+}
+
+void
+Gecko_CopyStyleGridTemplateValues(UniquePtr<nsStyleGridTemplate>* aGridTemplate,
                                   const nsStyleGridTemplate* aOther)
 {
-  *aGridTemplate = *aOther;
+  if (aOther) {
+    *aGridTemplate = MakeUnique<nsStyleGridTemplate>(*aOther);
+  } else {
+    *aGridTemplate = nullptr;
+  }
 }
 
 mozilla::css::GridTemplateAreasValue*
 Gecko_NewGridTemplateAreasValue(uint32_t aAreas, uint32_t aTemplates, uint32_t aColumns)
 {
   RefPtr<mozilla::css::GridTemplateAreasValue> value = new mozilla::css::GridTemplateAreasValue;
   value->mNamedAreas.SetLength(aAreas);
   value->mTemplates.SetLength(aTemplates);
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -419,23 +419,23 @@ void Gecko_EnsureTArrayCapacity(void* ar
 // Same here, `array` must be an nsTArray<T>, for some T.
 //
 // Important note: Only valid for POD types, since destructors won't be run
 // otherwise. This is ensured with rust traits for the relevant structs.
 void Gecko_ClearPODTArray(void* array, size_t elem_size, size_t elem_align);
 
 void Gecko_ResizeTArrayForStrings(nsTArray<nsString>* array, uint32_t length);
 
-void Gecko_SetStyleGridTemplateArrayLengths(nsStyleGridTemplate* grid_template,
-                                            uint32_t track_sizes);
+void Gecko_SetStyleGridTemplate(mozilla::UniquePtr<nsStyleGridTemplate>* grid_template,
+                                nsStyleGridTemplate* value);
 
-void Gecko_SetGridTemplateLineNamesLength(nsStyleGridTemplate* grid_template,
-                                          uint32_t track_sizes);
+nsStyleGridTemplate* Gecko_CreateStyleGridTemplate(uint32_t track_sizes,
+                                                   uint32_t name_size);
 
-void Gecko_CopyStyleGridTemplateValues(nsStyleGridTemplate* grid_template,
+void Gecko_CopyStyleGridTemplateValues(mozilla::UniquePtr<nsStyleGridTemplate>* grid_template,
                                        const nsStyleGridTemplate* other);
 
 mozilla::css::GridTemplateAreasValue* Gecko_NewGridTemplateAreasValue(uint32_t areas,
                                                                       uint32_t templates,
                                                                       uint32_t columns);
 NS_DECL_THREADSAFE_FFI_REFCOUNTING(mozilla::css::GridTemplateAreasValue, GridTemplateAreasValue);
 
 // Clear the mContents, mCounterIncrements, or mCounterResets field in nsStyleContent. This is
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -363,16 +363,17 @@ whitelist-functions = ["Servo_.*", "Geck
 structs-types = [
     "mozilla::css::GridTemplateAreasValue",
     "mozilla::css::ErrorReporter",
     "mozilla::css::ImageValue",
     "mozilla::css::URLValue",
     "mozilla::css::URLValueData",
     "mozilla::MallocSizeOf",
     "mozilla::Side",
+    "mozilla::UniquePtr",
     "nsIContent",
     "nsIDocument",
     "nsIDocument_DocumentTheme",
     "RawGeckoAnimationPropertySegment",
     "RawGeckoComputedTiming",
     "RawGeckoCSSPropertyIDList",
     "RawGeckoDocument",
     "RawGeckoElement",
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -3103,33 +3103,34 @@ nsComputedDOMStyle::DoGetGridTemplateCol
   nsGridContainerFrame* gridFrame =
     nsGridContainerFrame::GetGridFrameWithComputedInfo(
       mContent->GetPrimaryFrame());
 
   if (gridFrame) {
     info = gridFrame->GetComputedTemplateColumns();
   }
 
-  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateColumns, info);
+  return GetGridTemplateColumnsRows(
+    StylePosition()->GridTemplateColumns(), info);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::DoGetGridTemplateRows()
 {
   const ComputedGridTrackInfo* info = nullptr;
 
   nsGridContainerFrame* gridFrame =
     nsGridContainerFrame::GetGridFrameWithComputedInfo(
       mContent->GetPrimaryFrame());
 
   if (gridFrame) {
     info = gridFrame->GetComputedTemplateRows();
   }
 
-  return GetGridTemplateColumnsRows(StylePosition()->mGridTemplateRows, info);
+  return GetGridTemplateColumnsRows(StylePosition()->GridTemplateRows(), info);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::GetGridLine(const nsStyleGridLine& aGridLine)
 {
   if (aGridLine.IsAuto()) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
     val->SetIdent(eCSSKeyword_auto);
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -8312,132 +8312,123 @@ AppendGridLineNames(const nsCSSValue& aV
       item->mValue.GetStringValue(*name);
       item = item->mNext;
     } while (item);
   }
 }
 
 static void
 SetGridTrackList(const nsCSSValue& aValue,
-                 nsStyleGridTemplate& aResult,
-                 const nsStyleGridTemplate& aParentValue,
+                 UniquePtr<nsStyleGridTemplate>& aResult,
+                 const nsStyleGridTemplate* aParentValue,
                  GeckoStyleContext* aStyleContext,
                  nsPresContext* aPresContext,
                  RuleNodeCacheConditions& aConditions)
 
 {
   switch (aValue.GetUnit()) {
   case eCSSUnit_Null:
     break;
 
   case eCSSUnit_Inherit:
     aConditions.SetUncacheable();
-    aResult = aParentValue;
+    if (aParentValue) {
+      aResult = MakeUnique<nsStyleGridTemplate>(*aParentValue);
+    } else {
+      aResult = nullptr;
+    }
     break;
 
   case eCSSUnit_Initial:
   case eCSSUnit_Unset:
   case eCSSUnit_None:
-    aResult.mIsSubgrid = false;
-    aResult.mLineNameLists.Clear();
-    aResult.mMinTrackSizingFunctions.Clear();
-    aResult.mMaxTrackSizingFunctions.Clear();
-    aResult.mRepeatAutoLineNameListBefore.Clear();
-    aResult.mRepeatAutoLineNameListAfter.Clear();
-    aResult.mRepeatAutoIndex = -1;
-    aResult.mIsAutoFill = false;
+    aResult = nullptr;
     break;
 
   default:
-    aResult.mLineNameLists.Clear();
-    aResult.mMinTrackSizingFunctions.Clear();
-    aResult.mMaxTrackSizingFunctions.Clear();
-    aResult.mRepeatAutoLineNameListBefore.Clear();
-    aResult.mRepeatAutoLineNameListAfter.Clear();
-    aResult.mRepeatAutoIndex = -1;
-    aResult.mIsAutoFill = false;
+    aResult = MakeUnique<nsStyleGridTemplate>();
     const nsCSSValueList* item = aValue.GetListValue();
     if (item->mValue.GetUnit() == eCSSUnit_Enumerated &&
         item->mValue.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID) {
       // subgrid <line-name-list>?
-      aResult.mIsSubgrid = true;
+      aResult->mIsSubgrid = true;
       item = item->mNext;
       for (int32_t i = 0; item && i < nsStyleGridLine::kMaxLine; ++i) {
         if (item->mValue.GetUnit() == eCSSUnit_Pair) {
           // This is a 'auto-fill' <name-repeat> expression.
           const nsCSSValuePair& pair = item->mValue.GetPairValue();
-          MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
+          MOZ_ASSERT(aResult->mRepeatAutoIndex == -1,
                      "can only have one <name-repeat> with auto-fill");
-          aResult.mRepeatAutoIndex = i;
-          aResult.mIsAutoFill = true;
+          aResult->mRepeatAutoIndex = i;
+          aResult->mIsAutoFill = true;
           MOZ_ASSERT(pair.mXValue.GetIntValue() == NS_STYLE_GRID_REPEAT_AUTO_FILL,
                      "unexpected repeat() enum value for subgrid");
           const nsCSSValueList* list = pair.mYValue.GetListValue();
-          AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
+          AppendGridLineNames(list->mValue, aResult->mRepeatAutoLineNameListBefore);
         } else {
           AppendGridLineNames(item->mValue,
-                              *aResult.mLineNameLists.AppendElement());
+                              *aResult->mLineNameLists.AppendElement());
         }
         item = item->mNext;
       }
     } else {
       // <track-list>
       // The list is expected to have odd number of items, at least 3
       // starting with a <line-names> (sub list of identifiers),
       // and alternating between that and <track-size>.
-      aResult.mIsSubgrid = false;
+      aResult->mIsSubgrid = false;
       for (int32_t line = 1;  ; ++line) {
         AppendGridLineNames(item->mValue,
-                            *aResult.mLineNameLists.AppendElement());
+                            *aResult->mLineNameLists.AppendElement());
         item = item->mNext;
 
         if (!item || line == nsStyleGridLine::kMaxLine) {
           break;
         }
 
         if (item->mValue.GetUnit() == eCSSUnit_Pair) {
           // This is a 'auto-fill' / 'auto-fit' <auto-repeat> expression.
           const nsCSSValuePair& pair = item->mValue.GetPairValue();
-          MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
+          MOZ_ASSERT(aResult->mRepeatAutoIndex == -1,
                      "can only have one <auto-repeat>");
-          aResult.mRepeatAutoIndex = line - 1;
+          aResult->mRepeatAutoIndex = line - 1;
           switch (pair.mXValue.GetIntValue()) {
             case NS_STYLE_GRID_REPEAT_AUTO_FILL:
-              aResult.mIsAutoFill = true;
+              aResult->mIsAutoFill = true;
               break;
             case NS_STYLE_GRID_REPEAT_AUTO_FIT:
-              aResult.mIsAutoFill = false;
+              aResult->mIsAutoFill = false;
               break;
             default:
               MOZ_ASSERT_UNREACHABLE("unexpected repeat() enum value");
           }
           const nsCSSValueList* list = pair.mYValue.GetListValue();
-          AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
+          AppendGridLineNames(list->mValue, aResult->mRepeatAutoLineNameListBefore);
           list = list->mNext;
-          nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
-          nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
+          nsStyleCoord& min = *aResult->mMinTrackSizingFunctions.AppendElement();
+          nsStyleCoord& max = *aResult->mMaxTrackSizingFunctions.AppendElement();
           SetGridTrackSize(list->mValue, min, max,
                            aStyleContext, aPresContext, aConditions);
           list = list->mNext;
-          AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListAfter);
+          AppendGridLineNames(list->mValue, aResult->mRepeatAutoLineNameListAfter);
         } else {
-          nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
-          nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
+          nsStyleCoord& min = *aResult->mMinTrackSizingFunctions.AppendElement();
+          nsStyleCoord& max = *aResult->mMaxTrackSizingFunctions.AppendElement();
           SetGridTrackSize(item->mValue, min, max,
                            aStyleContext, aPresContext, aConditions);
         }
 
         item = item->mNext;
         MOZ_ASSERT(item, "Expected a eCSSUnit_List of odd length");
       }
-      MOZ_ASSERT(!aResult.mMinTrackSizingFunctions.IsEmpty() &&
-                 aResult.mMinTrackSizingFunctions.Length() ==
-                 aResult.mMaxTrackSizingFunctions.Length() &&
-                 aResult.mMinTrackSizingFunctions.Length() + 1 ==
-                 aResult.mLineNameLists.Length(),
+      MOZ_ASSERT(!aResult->mMinTrackSizingFunctions.IsEmpty() &&
+                 aResult->mMinTrackSizingFunctions.Length() ==
+                 aResult->mMaxTrackSizingFunctions.Length() &&
+                 aResult->mMinTrackSizingFunctions.Length() + 1 ==
+                 aResult->mLineNameLists.Length(),
                  "Inconstistent array lengths for nsStyleGridTemplate");
     }
   }
 }
 
 static void
 SetGridTemplateAreas(const nsCSSValue& aValue,
                      RefPtr<css::GridTemplateAreasValue>* aResult,
@@ -8778,22 +8769,24 @@ nsRuleNode::ComputePositionData(void* aS
                          pos->mGridAutoRowsMin,
                          pos->mGridAutoRowsMax,
                          parentPos->mGridAutoRowsMin,
                          parentPos->mGridAutoRowsMax,
                          aContext, mPresContext, conditions);
 
   // grid-template-columns
   SetGridTrackList(*aRuleData->ValueForGridTemplateColumns(),
-                   pos->mGridTemplateColumns, parentPos->mGridTemplateColumns,
+                   pos->mGridTemplateColumns,
+                   parentPos->mGridTemplateColumns.get(),
                    aContext, mPresContext, conditions);
 
   // grid-template-rows
   SetGridTrackList(*aRuleData->ValueForGridTemplateRows(),
-                   pos->mGridTemplateRows, parentPos->mGridTemplateRows,
+                   pos->mGridTemplateRows,
+                   parentPos->mGridTemplateRows.get(),
                    aContext, mPresContext, conditions);
 
   // grid-tempate-areas
   SetGridTemplateAreas(*aRuleData->ValueForGridTemplateAreas(),
                        &pos->mGridTemplateAreas,
                        parentPos->mGridTemplateAreas,
                        conditions);
 
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -30,16 +30,17 @@
 
 #include "imgIRequest.h"
 #include "imgIContainer.h"
 #include "CounterStyleManager.h"
 
 #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
 #include "mozilla/dom/DocGroup.h"
 #include "mozilla/dom/ImageTracker.h"
+#include "mozilla/ClearOnShutdown.h"
 #include "mozilla/Likely.h"
 #include "nsIURI.h"
 #include "nsIDocument.h"
 #include <algorithm>
 #include "ImageLoader.h"
 
 using namespace mozilla;
 using namespace mozilla::dom;
@@ -1508,41 +1509,61 @@ nsStylePosition::nsStylePosition(const n
   , mJustifySelf(aSource.mJustifySelf)
   , mFlexDirection(aSource.mFlexDirection)
   , mFlexWrap(aSource.mFlexWrap)
   , mObjectFit(aSource.mObjectFit)
   , mOrder(aSource.mOrder)
   , mFlexGrow(aSource.mFlexGrow)
   , mFlexShrink(aSource.mFlexShrink)
   , mZIndex(aSource.mZIndex)
-  , mGridTemplateColumns(aSource.mGridTemplateColumns)
-  , mGridTemplateRows(aSource.mGridTemplateRows)
   , mGridTemplateAreas(aSource.mGridTemplateAreas)
   , mGridColumnStart(aSource.mGridColumnStart)
   , mGridColumnEnd(aSource.mGridColumnEnd)
   , mGridRowStart(aSource.mGridRowStart)
   , mGridRowEnd(aSource.mGridRowEnd)
   , mGridColumnGap(aSource.mGridColumnGap)
   , mGridRowGap(aSource.mGridRowGap)
 {
   MOZ_COUNT_CTOR(nsStylePosition);
+
+  if (aSource.mGridTemplateColumns) {
+    mGridTemplateColumns =
+      MakeUnique<nsStyleGridTemplate>(*aSource.mGridTemplateColumns);
+  }
+  if (aSource.mGridTemplateRows) {
+    mGridTemplateRows =
+      MakeUnique<nsStyleGridTemplate>(*aSource.mGridTemplateRows);
+  }
 }
 
 static bool
 IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2)
 {
   NS_FOR_CSS_SIDES(side) {
     if ((aSides1.GetUnit(side) == eStyleUnit_Auto) !=
         (aSides2.GetUnit(side) == eStyleUnit_Auto)) {
       return false;
     }
   }
   return true;
 }
 
+static bool
+IsGridTemplateEqual(const UniquePtr<nsStyleGridTemplate>& aOldData,
+                    const UniquePtr<nsStyleGridTemplate>& aNewData)
+{
+  if (aOldData == aNewData) {
+    return true;
+  }
+  if (!aOldData || !aNewData) {
+    return false;
+  }
+  return *aOldData == *aNewData;
+}
+
 nsChangeHint
 nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
                                 const nsStyleVisibility* aOldStyleVisibility) const
 {
   nsChangeHint hint = nsChangeHint(0);
 
   // Changes to "z-index" require a repaint.
   if (mZIndex != aNewData.mZIndex) {
@@ -1597,18 +1618,20 @@ nsStylePosition::CalcDifference(const ns
       mFlexWrap != aNewData.mFlexWrap) {
     return hint |
            nsChangeHint_AllReflowHints;
   }
 
   // Properties that apply to grid containers:
   // FIXME: only for grid containers
   // (ie. 'display: grid' or 'display: inline-grid')
-  if (mGridTemplateColumns != aNewData.mGridTemplateColumns ||
-      mGridTemplateRows != aNewData.mGridTemplateRows ||
+  if (!IsGridTemplateEqual(mGridTemplateColumns,
+                           aNewData.mGridTemplateColumns) ||
+      !IsGridTemplateEqual(mGridTemplateRows,
+                           aNewData.mGridTemplateRows) ||
       mGridTemplateAreas != aNewData.mGridTemplateAreas ||
       mGridAutoColumnsMin != aNewData.mGridAutoColumnsMin ||
       mGridAutoColumnsMax != aNewData.mGridAutoColumnsMax ||
       mGridAutoRowsMin != aNewData.mGridAutoRowsMin ||
       mGridAutoRowsMax != aNewData.mGridAutoRowsMax ||
       mGridAutoFlow != aNewData.mGridAutoFlow) {
     return hint |
            nsChangeHint_AllReflowHints;
@@ -1730,16 +1753,40 @@ nsStylePosition::UsedJustifySelf(nsStyle
   }
   if (MOZ_LIKELY(aParent)) {
     auto inheritedJustifyItems = aParent->StylePosition()->mJustifyItems;
     return inheritedJustifyItems & ~NS_STYLE_JUSTIFY_LEGACY;
   }
   return NS_STYLE_JUSTIFY_NORMAL;
 }
 
+static StaticAutoPtr<nsStyleGridTemplate> sDefaultGridTemplate;
+
+static const nsStyleGridTemplate&
+DefaultGridTemplate()
+{
+  if (!sDefaultGridTemplate) {
+    sDefaultGridTemplate = new nsStyleGridTemplate;
+    ClearOnShutdown(&sDefaultGridTemplate);
+  }
+  return *sDefaultGridTemplate;
+}
+
+const nsStyleGridTemplate&
+nsStylePosition::GridTemplateColumns() const
+{
+  return mGridTemplateColumns ? *mGridTemplateColumns : DefaultGridTemplate();
+}
+
+const nsStyleGridTemplate&
+nsStylePosition::GridTemplateRows() const
+{
+  return mGridTemplateRows ? *mGridTemplateRows : DefaultGridTemplate();
+}
+
 // --------------------
 // nsStyleTable
 //
 
 nsStyleTable::nsStyleTable(const nsPresContext* aContext)
   : mLayoutStrategy(NS_STYLE_TABLE_LAYOUT_AUTO)
   , mSpan(1)
 {
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1623,26 +1623,26 @@ struct nsStyleGridTemplate
 
   nsStyleGridTemplate()
     : mRepeatAutoIndex(-1)
     , mIsAutoFill(false)
     , mIsSubgrid(false)
   {
   }
 
-  inline bool operator!=(const nsStyleGridTemplate& aOther) const {
+  inline bool operator==(const nsStyleGridTemplate& aOther) const {
     return
-      mIsSubgrid != aOther.mIsSubgrid ||
-      mLineNameLists != aOther.mLineNameLists ||
-      mMinTrackSizingFunctions != aOther.mMinTrackSizingFunctions ||
-      mMaxTrackSizingFunctions != aOther.mMaxTrackSizingFunctions ||
-      mIsAutoFill != aOther.mIsAutoFill ||
-      mRepeatAutoIndex != aOther.mRepeatAutoIndex ||
-      mRepeatAutoLineNameListBefore != aOther.mRepeatAutoLineNameListBefore ||
-      mRepeatAutoLineNameListAfter != aOther.mRepeatAutoLineNameListAfter;
+      mIsSubgrid == aOther.mIsSubgrid &&
+      mLineNameLists == aOther.mLineNameLists &&
+      mMinTrackSizingFunctions == aOther.mMinTrackSizingFunctions &&
+      mMaxTrackSizingFunctions == aOther.mMaxTrackSizingFunctions &&
+      mIsAutoFill == aOther.mIsAutoFill &&
+      mRepeatAutoIndex == aOther.mRepeatAutoIndex &&
+      mRepeatAutoLineNameListBefore == aOther.mRepeatAutoLineNameListBefore &&
+      mRepeatAutoLineNameListAfter == aOther.mRepeatAutoLineNameListAfter;
   }
 
   bool HasRepeatAuto() const {
     return mRepeatAutoIndex != -1;
   }
 
   bool IsRepeatAutoIndex(uint32_t aIndex) const {
     MOZ_ASSERT(aIndex < uint32_t(2*nsStyleGridLine::kMaxLine));
@@ -1718,18 +1718,18 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   uint8_t       mJustifySelf;           // [reset] see nsStyleConsts.h
   uint8_t       mFlexDirection;         // [reset] see nsStyleConsts.h
   uint8_t       mFlexWrap;              // [reset] see nsStyleConsts.h
   uint8_t       mObjectFit;             // [reset] see nsStyleConsts.h
   int32_t       mOrder;                 // [reset] integer
   float         mFlexGrow;              // [reset] float
   float         mFlexShrink;            // [reset] float
   nsStyleCoord  mZIndex;                // [reset] integer, auto
-  nsStyleGridTemplate mGridTemplateColumns;
-  nsStyleGridTemplate mGridTemplateRows;
+  mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateColumns;
+  mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateRows;
 
   // nullptr for 'none'
   RefPtr<mozilla::css::GridTemplateAreasValue> mGridTemplateAreas;
 
   nsStyleGridLine mGridColumnStart;
   nsStyleGridLine mGridColumnEnd;
   nsStyleGridLine mGridRowStart;
   nsStyleGridLine mGridRowEnd;
@@ -1803,16 +1803,19 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   inline const nsStyleCoord& MaxBSize(mozilla::WritingMode aWM) const;
   inline bool ISizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MinISizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MaxISizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool BSizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MinBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
   inline bool MaxBSizeDependsOnContainer(mozilla::WritingMode aWM) const;
 
+  const nsStyleGridTemplate& GridTemplateColumns() const;
+  const nsStyleGridTemplate& GridTemplateRows() const;
+
 private:
   static bool WidthCoordDependsOnContainer(const nsStyleCoord &aCoord);
   static bool HeightCoordDependsOnContainer(const nsStyleCoord &aCoord)
     { return aCoord.HasPercent(); }
 };
 
 struct nsStyleTextOverflowSide
 {