Index: third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
diff --git a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
index de39a5d41e74fd464e64ec46bf7c7bd58e124c73..bf339c75be25aa053e7c3c8cf958451a9c1f6024 100644 |
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp |
@@ -235,23 +235,27 @@ bool PrePaintTreeWalk::shouldEndWalkBefore( |
void PrePaintTreeWalk::walk(const LayoutObject& object, |
const PrePaintTreeWalkContext& parentContext) { |
- PrePaintTreeWalkContext context(parentContext); |
- |
if (shouldEndWalkBefore(object, parentContext)) |
return; |
+ // PrePaintTreeWalkContext is large and can lead to stack overflows when |
+ // recursion is deep so this context object is allocated on the heap. |
+ // See: https://crbug.com/698653. |
+ std::unique_ptr<PrePaintTreeWalkContext> context = |
+ WTF::wrapUnique(new PrePaintTreeWalkContext(parentContext)); |
+ |
// This must happen before updatePropertiesForSelf, because the latter reads |
// some of the state computed here. |
- updateAuxiliaryObjectProperties(object, context); |
+ updateAuxiliaryObjectProperties(object, *context); |
m_propertyTreeBuilder.updatePropertiesForSelf(object, |
- context.treeBuilderContext); |
+ context->treeBuilderContext); |
m_paintInvalidator.invalidatePaintIfNeeded(object, |
- context.paintInvalidatorContext); |
- m_propertyTreeBuilder.updatePropertiesForChildren(object, |
- context.treeBuilderContext); |
+ context->paintInvalidatorContext); |
+ m_propertyTreeBuilder.updatePropertiesForChildren( |
+ object, context->treeBuilderContext); |
- invalidatePaintLayerOptimizationsIfNeeded(object, context); |
+ invalidatePaintLayerOptimizationsIfNeeded(object, *context); |
for (const LayoutObject* child = object.slowFirstChild(); child; |
child = child->nextSibling()) { |
@@ -259,19 +263,19 @@ void PrePaintTreeWalk::walk(const LayoutObject& object, |
child->getMutableForPainting().clearPaintFlags(); |
continue; |
} |
- walk(*child, context); |
+ walk(*child, *context); |
} |
if (object.isLayoutPart()) { |
const LayoutPart& layoutPart = toLayoutPart(object); |
FrameViewBase* frameViewBase = layoutPart.frameViewBase(); |
if (frameViewBase && frameViewBase->isFrameView()) { |
- context.treeBuilderContext.current.paintOffset += |
+ context->treeBuilderContext.current.paintOffset += |
layoutPart.replacedContentRect().location() - |
frameViewBase->frameRect().location(); |
- context.treeBuilderContext.current.paintOffset = |
- roundedIntPoint(context.treeBuilderContext.current.paintOffset); |
- walk(*toFrameView(frameViewBase), context); |
+ context->treeBuilderContext.current.paintOffset = |
+ roundedIntPoint(context->treeBuilderContext.current.paintOffset); |
+ walk(*toFrameView(frameViewBase), *context); |
} |
// TODO(pdr): Investigate RemoteFrameView (crbug.com/579281). |
} |