Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(670)

Unified Diff: third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp

Issue 2735823005: Implement a non-recursive PrePaint treewalk (Closed)
Patch Set: Faster, cleaner Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 7adecea88839413b0e1330aa2849047a6175db28..5265863cd33056e9ad38747b541769346b5d8c16 100644
--- a/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
+++ b/third_party/WebKit/Source/core/paint/PrePaintTreeWalk.cpp
@@ -79,6 +79,40 @@ void PrePaintTreeWalk::walk(FrameView& frameView,
frameView.clearNeedsPaintPropertyUpdate();
}
+// |PrePaintTreeWalkContext| is large and can cause stack overflows when used
+// in a recursive treewalk (see: https://crbug.com/698653). This function
+// implements an iterative pre-order tree walk of the layout tree where the
+// stack is maintained using heap allocations in a Vector.
+void PrePaintTreeWalk::walk(const LayoutView& view,
+ const PrePaintTreeWalkContext& parentContext) {
+ Vector<PrePaintTreeWalkContext> stack;
pdr. 2017/03/08 01:04:59 This has a bug: when the vector resizes, parent po
+ stack.push_back(parentContext);
+
+ const LayoutObject* object = &view;
+ while (object) {
+ if (!shouldEndWalkBefore(*object, stack.back())) {
+ stack.push_back(stack.back());
+ walkObject(*object, stack.back());
+ if (const auto* child = object->slowFirstChild()) {
+ object = child;
+ continue;
+ }
+ stack.pop_back();
+ }
+
+ while (object && !object->nextSibling()) {
+ object->getMutableForPainting().clearPaintFlags();
+ stack.pop_back();
+ object = object->parent();
+ }
+
+ if (object) {
+ object->getMutableForPainting().clearPaintFlags();
+ object = object->nextSibling();
+ }
+ }
+}
+
static void updateAuxiliaryObjectProperties(const LayoutObject& object,
PrePaintTreeWalkContext& context) {
if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
@@ -232,11 +266,11 @@ bool PrePaintTreeWalk::shouldEndWalkBefore(
.shouldCheckForPaintInvalidationRegardlessOfPaintInvalidationState());
}
-void PrePaintTreeWalk::walk(const LayoutObject& object,
- const PrePaintTreeWalkContext& parentContext) {
- PrePaintTreeWalkContext context(parentContext);
+void PrePaintTreeWalk::walkObject(const LayoutObject& object,
+ PrePaintTreeWalkContext& context) {
+ DCHECK(!shouldEndWalkBefore(object, context));
- if (shouldEndWalkBefore(object, parentContext))
+ if (object.isLayoutMultiColumnSpannerPlaceholder())
return;
// This must happen before updatePropertiesForSelf, because the latter reads
@@ -252,30 +286,20 @@ void PrePaintTreeWalk::walk(const LayoutObject& object,
invalidatePaintLayerOptimizationsIfNeeded(object, context);
- for (const LayoutObject* child = object.slowFirstChild(); child;
- child = child->nextSibling()) {
- if (child->isLayoutMultiColumnSpannerPlaceholder()) {
- child->getMutableForPainting().clearPaintFlags();
- continue;
- }
- walk(*child, context);
- }
-
if (object.isLayoutPart()) {
const LayoutPart& layoutPart = toLayoutPart(object);
FrameViewBase* frameViewBase = layoutPart.widget();
if (frameViewBase && frameViewBase->isFrameView()) {
- context.treeBuilderContext.current.paintOffset +=
+ PrePaintTreeWalkContext frameViewContext(context);
+ frameViewContext.treeBuilderContext.current.paintOffset +=
layoutPart.replacedContentRect().location() -
frameViewBase->frameRect().location();
- context.treeBuilderContext.current.paintOffset =
- roundedIntPoint(context.treeBuilderContext.current.paintOffset);
- walk(*toFrameView(frameViewBase), context);
+ frameViewContext.treeBuilderContext.current.paintOffset = roundedIntPoint(
+ frameViewContext.treeBuilderContext.current.paintOffset);
+ walk(*toFrameView(frameViewBase), frameViewContext);
}
// TODO(pdr): Investigate RemoteFrameView (crbug.com/579281).
}
-
- object.getMutableForPainting().clearPaintFlags();
}
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/core/paint/PrePaintTreeWalk.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698