| Index: Source/core/rendering/RenderGrid.cpp
 | 
| diff --git a/Source/core/rendering/RenderGrid.cpp b/Source/core/rendering/RenderGrid.cpp
 | 
| index 9de8da1819b6546d3b10c4c92cbe74e360e9ec30..86e84fae10379453d1c6c6678a48a950d2d74955 100644
 | 
| --- a/Source/core/rendering/RenderGrid.cpp
 | 
| +++ b/Source/core/rendering/RenderGrid.cpp
 | 
| @@ -146,6 +146,24 @@ private:
 | 
|      size_t m_childIndex;
 | 
|  };
 | 
|  
 | 
| +struct RenderGrid::GridSizingData {
 | 
| +    WTF_MAKE_NONCOPYABLE(GridSizingData);
 | 
| +public:
 | 
| +    GridSizingData(size_t gridColumnCount, size_t gridRowCount)
 | 
| +        : columnTracks(gridColumnCount)
 | 
| +        , rowTracks(gridRowCount)
 | 
| +    {
 | 
| +    }
 | 
| +
 | 
| +    Vector<GridTrack> columnTracks;
 | 
| +    Vector<GridTrack> rowTracks;
 | 
| +    Vector<size_t> contentSizedTracksIndex;
 | 
| +
 | 
| +    // Performance optimization: hold onto these Vectors until the end of Layout to avoid repeated malloc / free.
 | 
| +    Vector<LayoutUnit> distributeTrackVector;
 | 
| +    Vector<GridTrack*> filteredTracks;
 | 
| +};
 | 
| +
 | 
|  RenderGrid::RenderGrid(Element* element)
 | 
|      : RenderBlock(element)
 | 
|      , m_gridIsDirty(true)
 | 
| @@ -353,11 +371,11 @@ LayoutUnit RenderGrid::computePreferredTrackWidth(const GridLength& gridLength,
 | 
|      return 0;
 | 
|  }
 | 
|  
 | 
| -void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks)
 | 
| +void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, GridSizingData& sizingData)
 | 
|  {
 | 
|      LayoutUnit availableLogicalSpace = (direction == ForColumns) ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding);
 | 
| -    Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
 | 
| -    Vector<size_t> contentSizedTracks;
 | 
| +    Vector<GridTrack>& tracks = (direction == ForColumns) ? sizingData.columnTracks : sizingData.rowTracks;
 | 
| +    sizingData.contentSizedTracksIndex.shrink(0);
 | 
|      for (size_t i = 0; i < tracks.size(); ++i) {
 | 
|          GridTrack& track = tracks[i];
 | 
|          const GridTrackSize& trackSize = gridTrackSize(direction, i);
 | 
| @@ -370,11 +388,11 @@ void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction,
 | 
|          track.m_maxBreadth = std::max(track.m_maxBreadth, track.m_usedBreadth);
 | 
|  
 | 
|          if (trackSize.isContentSized())
 | 
| -            contentSizedTracks.append(i);
 | 
| +            sizingData.contentSizedTracksIndex.append(i);
 | 
|      }
 | 
|  
 | 
| -    if (!contentSizedTracks.isEmpty())
 | 
| -        resolveContentBasedTrackSizingFunctions(direction, columnTracks, rowTracks, contentSizedTracks, availableLogicalSpace);
 | 
| +    if (!sizingData.contentSizedTracksIndex.isEmpty())
 | 
| +        resolveContentBasedTrackSizingFunctions(direction, sizingData, availableLogicalSpace);
 | 
|  
 | 
|      for (size_t i = 0; i < tracks.size(); ++i) {
 | 
|          ASSERT(tracks[i].m_maxBreadth != infinity);
 | 
| @@ -389,7 +407,7 @@ void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction,
 | 
|      for (size_t i = 0; i < tracksSize; ++i)
 | 
|          tracksForDistribution[i] = tracks.data() + i;
 | 
|  
 | 
| -    distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, availableLogicalSpace);
 | 
| +    distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, sizingData, availableLogicalSpace);
 | 
|  
 | 
|      // 4. Grow all Grid tracks having a fraction as the MaxTrackSizingFunction.
 | 
|  
 | 
| @@ -563,54 +581,54 @@ LayoutUnit RenderGrid::maxContentForChild(RenderBox* child, TrackSizingDirection
 | 
|      return logicalContentHeightForChild(child, columnTracks);
 | 
|  }
 | 
|  
 | 
| -void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, const Vector<size_t>& contentSizedTracks, LayoutUnit& availableLogicalSpace)
 | 
| +void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace)
 | 
|  {
 | 
|      // FIXME: Split the grid tracks into groups that doesn't overlap a <flex> grid track (crbug.com/235258).
 | 
|  
 | 
|      // FIXME: Per step 2 of the specification, we should order the grid items by increasing span.
 | 
|  
 | 
| -    for (size_t i = 0; i < contentSizedTracks.size(); ++i) {
 | 
| -        GridIterator iterator(m_grid, direction, contentSizedTracks[i]);
 | 
| +    for (size_t i = 0; i < sizingData.contentSizedTracksIndex.size(); ++i) {
 | 
| +        GridIterator iterator(m_grid, direction, sizingData.contentSizedTracksIndex[i]);
 | 
|          while (RenderBox* gridItem = iterator.nextGridItem()) {
 | 
| -            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
 | 
| -            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
 | 
| -            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
 | 
| -            resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, gridItem, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
 | 
| +            resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
 | 
| +            resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
 | 
| +            resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
 | 
| +            resolveContentBasedTrackSizingFunctionsForItems(direction, sizingData, gridItem, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
 | 
|          }
 | 
|  
 | 
| -        GridTrack& track = (direction == ForColumns) ? columnTracks[i] : rowTracks[i];
 | 
| +        GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[i] : sizingData.rowTracks[i];
 | 
|          if (track.m_maxBreadth == infinity)
 | 
|              track.m_maxBreadth = track.m_usedBreadth;
 | 
|      }
 | 
|  }
 | 
|  
 | 
| -void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
 | 
| +void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, GridSizingData& sizingData, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
 | 
|  {
 | 
|      const GridCoordinate coordinate = cachedGridCoordinate(gridItem);
 | 
|      const size_t initialTrackIndex = (direction == ForColumns) ? coordinate.columns.initialPositionIndex : coordinate.rows.initialPositionIndex;
 | 
|      const size_t finalTrackIndex = (direction == ForColumns) ? coordinate.columns.finalPositionIndex : coordinate.rows.finalPositionIndex;
 | 
|  
 | 
| -    Vector<GridTrack*> tracks;
 | 
| +    sizingData.filteredTracks.shrink(0);
 | 
|      for (size_t trackIndex = initialTrackIndex; trackIndex <= finalTrackIndex; ++trackIndex) {
 | 
|          const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex);
 | 
|          if (!(trackSize.*filterFunction)())
 | 
|              continue;
 | 
|  
 | 
| -        GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndex] : rowTracks[trackIndex];
 | 
| -        tracks.append(&track);
 | 
| +        GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndex] : sizingData.rowTracks[trackIndex];
 | 
| +        sizingData.filteredTracks.append(&track);
 | 
|      }
 | 
|  
 | 
| -    if (tracks.isEmpty())
 | 
| +    if (sizingData.filteredTracks.isEmpty())
 | 
|          return;
 | 
|  
 | 
| -    LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, columnTracks);
 | 
| +    LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, sizingData.columnTracks);
 | 
|      for (size_t trackIndexForSpace = initialTrackIndex; trackIndexForSpace <= finalTrackIndex; ++trackIndexForSpace) {
 | 
| -        GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndexForSpace] : rowTracks[trackIndexForSpace];
 | 
| +        GridTrack& track = (direction == ForColumns) ? sizingData.columnTracks[trackIndexForSpace] : sizingData.rowTracks[trackIndexForSpace];
 | 
|          additionalBreadthSpace -= (track.*trackGetter)();
 | 
|      }
 | 
|  
 | 
|      // FIXME: We should pass different values for |tracksForGrowthAboveMaxBreadth|.
 | 
| -    distributeSpaceToTracks(tracks, &tracks, trackGetter, trackGrowthFunction, additionalBreadthSpace);
 | 
| +    distributeSpaceToTracks(sizingData.filteredTracks, &sizingData.filteredTracks, trackGetter, trackGrowthFunction, sizingData, additionalBreadthSpace);
 | 
|  }
 | 
|  
 | 
|  static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTrack* track2)
 | 
| @@ -618,12 +636,12 @@ static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTr
 | 
|      return (track1->m_maxBreadth - track1->m_usedBreadth) < (track2->m_maxBreadth - track2->m_usedBreadth);
 | 
|  }
 | 
|  
 | 
| -void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, LayoutUnit& availableLogicalSpace)
 | 
| +void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, GridSizingData& sizingData, LayoutUnit& availableLogicalSpace)
 | 
|  {
 | 
|      std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
 | 
|  
 | 
|      size_t tracksSize = tracks.size();
 | 
| -    Vector<LayoutUnit> updatedTrackBreadths(tracksSize);
 | 
| +    sizingData.distributeTrackVector.resize(tracksSize);
 | 
|  
 | 
|      for (size_t i = 0; i < tracksSize; ++i) {
 | 
|          GridTrack& track = *tracks[i];
 | 
| @@ -631,7 +649,7 @@ void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<Grid
 | 
|          LayoutUnit trackBreadth = (tracks[i]->*trackGetter)();
 | 
|          LayoutUnit growthShare = std::max(LayoutUnit(), std::min(availableLogicalSpaceShare, track.m_maxBreadth - trackBreadth));
 | 
|          // We should never shrink any grid track or else we can't guarantee we abide by our min-sizing function.
 | 
| -        updatedTrackBreadths[i] = trackBreadth + growthShare;
 | 
| +        sizingData.distributeTrackVector[i] = trackBreadth + growthShare;
 | 
|          availableLogicalSpace -= growthShare;
 | 
|      }
 | 
|  
 | 
| @@ -639,13 +657,13 @@ void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<Grid
 | 
|          tracksSize = tracksForGrowthAboveMaxBreadth->size();
 | 
|          for (size_t i = 0; i < tracksSize; ++i) {
 | 
|              LayoutUnit growthShare = availableLogicalSpace / (tracksSize - i);
 | 
| -            updatedTrackBreadths[i] += growthShare;
 | 
| +            sizingData.distributeTrackVector[i] += growthShare;
 | 
|              availableLogicalSpace -= growthShare;
 | 
|          }
 | 
|      }
 | 
|  
 | 
|      for (size_t i = 0; i < tracksSize; ++i) {
 | 
| -        LayoutUnit growth = updatedTrackBreadths[i] - (tracks[i]->*trackGetter)();
 | 
| +        LayoutUnit growth = sizingData.distributeTrackVector[i] - (tracks[i]->*trackGetter)();
 | 
|          if (growth >= 0)
 | 
|              (tracks[i]->*trackGrowthFunction)(growth);
 | 
|      }
 | 
| @@ -847,14 +865,13 @@ void RenderGrid::layoutGridItems()
 | 
|  {
 | 
|      placeItemsOnGrid();
 | 
|  
 | 
| -    Vector<GridTrack> columnTracks(gridColumnCount());
 | 
| -    Vector<GridTrack> rowTracks(gridRowCount());
 | 
| -    computedUsedBreadthOfGridTracks(ForColumns, columnTracks, rowTracks);
 | 
| -    ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, columnTracks));
 | 
| -    computedUsedBreadthOfGridTracks(ForRows, columnTracks, rowTracks);
 | 
| -    ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, rowTracks));
 | 
| +    GridSizingData sizingData(gridColumnCount(), gridRowCount());
 | 
| +    computedUsedBreadthOfGridTracks(ForColumns, sizingData);
 | 
| +    ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, sizingData.columnTracks));
 | 
| +    computedUsedBreadthOfGridTracks(ForRows, sizingData);
 | 
| +    ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, sizingData.rowTracks));
 | 
|  
 | 
| -    populateGridPositions(columnTracks, rowTracks);
 | 
| +    populateGridPositions(sizingData);
 | 
|  
 | 
|      for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
 | 
|          // Because the grid area cannot be styled, we don't need to adjust
 | 
| @@ -862,8 +879,8 @@ void RenderGrid::layoutGridItems()
 | 
|          LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
 | 
|          LayoutUnit oldOverrideContainingBlockContentLogicalHeight = child->hasOverrideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogicalHeight() : LayoutUnit();
 | 
|  
 | 
| -        LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, columnTracks);
 | 
| -        LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChild(child, ForRows, rowTracks);
 | 
| +        LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, sizingData.columnTracks);
 | 
| +        LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChild(child, ForRows, sizingData.rowTracks);
 | 
|  
 | 
|          SubtreeLayoutScope layoutScope(child);
 | 
|          if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth || (child->hasRelativeLogicalHeight() && oldOverrideContainingBlockContentLogicalHeight != overrideContainingBlockContentLogicalHeight))
 | 
| @@ -879,7 +896,7 @@ void RenderGrid::layoutGridItems()
 | 
|          // now, just size as if we were a regular child.
 | 
|          child->layoutIfNeeded();
 | 
|  
 | 
| -        child->setLogicalLocation(findChildLogicalPosition(child, columnTracks, rowTracks));
 | 
| +        child->setLogicalLocation(findChildLogicalPosition(child, sizingData));
 | 
|  
 | 
|          // If the child moved, we have to repaint it as well as any floating/positioned
 | 
|          // descendants. An exception is if we need a layout. In this case, we know we're going to
 | 
| @@ -888,8 +905,8 @@ void RenderGrid::layoutGridItems()
 | 
|              child->repaintDuringLayoutIfMoved(oldChildRect);
 | 
|      }
 | 
|  
 | 
| -    for (size_t i = 0; i < rowTracks.size(); ++i)
 | 
| -        setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);
 | 
| +    for (size_t i = 0; i < sizingData.rowTracks.size(); ++i)
 | 
| +        setLogicalHeight(logicalHeight() + sizingData.rowTracks[i].m_usedBreadth);
 | 
|  
 | 
|      // FIXME: We should handle min / max logical height.
 | 
|  
 | 
| @@ -1118,24 +1135,24 @@ LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox* child, TrackSizi
 | 
|      return gridAreaBreadth;
 | 
|  }
 | 
|  
 | 
| -void RenderGrid::populateGridPositions(const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)
 | 
| +void RenderGrid::populateGridPositions(const GridSizingData& sizingData)
 | 
|  {
 | 
| -    m_columnPositions.resize(columnTracks.size() + 1);
 | 
| +    m_columnPositions.resize(sizingData.columnTracks.size() + 1);
 | 
|      m_columnPositions[0] = borderAndPaddingStart();
 | 
|      for (size_t i = 0; i < m_columnPositions.size() - 1; ++i)
 | 
| -        m_columnPositions[i + 1] = m_columnPositions[i] + columnTracks[i].m_usedBreadth;
 | 
| +        m_columnPositions[i + 1] = m_columnPositions[i] + sizingData.columnTracks[i].m_usedBreadth;
 | 
|  
 | 
| -    m_rowPositions.resize(rowTracks.size() + 1);
 | 
| +    m_rowPositions.resize(sizingData.rowTracks.size() + 1);
 | 
|      m_rowPositions[0] = borderAndPaddingBefore();
 | 
|      for (size_t i = 0; i < m_rowPositions.size() - 1; ++i)
 | 
| -        m_rowPositions[i + 1] = m_rowPositions[i] + rowTracks[i].m_usedBreadth;
 | 
| +        m_rowPositions[i + 1] = m_rowPositions[i] + sizingData.rowTracks[i].m_usedBreadth;
 | 
|  }
 | 
|  
 | 
| -LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)
 | 
| +LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const GridSizingData& sizingData)
 | 
|  {
 | 
|      const GridCoordinate& coordinate = cachedGridCoordinate(child);
 | 
| -    ASSERT(coordinate.columns.initialPositionIndex < columnTracks.size());
 | 
| -    ASSERT(coordinate.rows.initialPositionIndex < rowTracks.size());
 | 
| +    ASSERT(coordinate.columns.initialPositionIndex < sizingData.columnTracks.size());
 | 
| +    ASSERT(coordinate.rows.initialPositionIndex < sizingData.rowTracks.size());
 | 
|  
 | 
|      // The grid items should be inside the grid container's border box, that's why they need to be shifted.
 | 
|      return LayoutPoint(m_columnPositions[coordinate.columns.initialPositionIndex] + marginStartForChild(child), m_rowPositions[coordinate.rows.initialPositionIndex] + marginBeforeForChild(child));
 | 
| 
 |