commit 998d878da24d0b2889cfff28337b20d9e8b74796
parent 476c551dc522acb523a09d2764bffb62098b96ed
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Fri, 17 Oct 2025 06:33:35 +0000
Bug 1994893 - Remove VerifyIncrementalReflow and co. r=layout-reviewers,TYLin
I bet nobody has used this since forever. Just running my local central build
(without the previous patch) with GECKO_VERIFY_REFLOW_FLAGS=verify stack
overflows, and it probably has at least for years.
Keeping this code around seems unnecessary.
Differential Revision: https://phabricator.services.mozilla.com/D268977
Diffstat:
2 files changed, 0 insertions(+), 509 deletions(-)
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -266,49 +266,6 @@ struct RangePaintInfo {
#undef NOISY
-// ----------------------------------------------------------------------
-
-#ifdef DEBUG
-// Set the environment variable GECKO_VERIFY_REFLOW_FLAGS to one or
-// more of the following flags (comma separated) for handy debug
-// output.
-static VerifyReflowFlags gVerifyReflowFlags;
-
-struct VerifyReflowFlagData {
- const char* name;
- VerifyReflowFlags bit;
-};
-
-static const VerifyReflowFlagData gFlags[] = {
- // clang-format off
- { "verify", VerifyReflowFlags::On },
- { "reflow", VerifyReflowFlags::Noisy },
- { "all", VerifyReflowFlags::All },
- { "list-commands", VerifyReflowFlags::DumpCommands },
- { "noisy-commands", VerifyReflowFlags::NoisyCommands },
- { "really-noisy-commands", VerifyReflowFlags::ReallyNoisyCommands },
- { "resize", VerifyReflowFlags::DuringResizeReflow },
- // clang-format on
-};
-
-# define NUM_VERIFY_REFLOW_FLAGS (sizeof(gFlags) / sizeof(gFlags[0]))
-
-static void ShowVerifyReflowFlags() {
- printf("Here are the available GECKO_VERIFY_REFLOW_FLAGS:\n");
- const VerifyReflowFlagData* flag = gFlags;
- const VerifyReflowFlagData* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
- while (flag < limit) {
- printf(" %s\n", flag->name);
- ++flag;
- }
- printf("Note: GECKO_VERIFY_REFLOW_FLAGS is a comma separated list of flag\n");
- printf("names (no whitespace)\n");
-}
-#endif
-
-//========================================================================
-//========================================================================
-//========================================================================
#ifdef MOZ_REFLOW_PERF
class ReflowCountMgr;
@@ -630,74 +587,6 @@ bool PresShell::sProcessInteractable = false;
Modifiers PresShell::sCurrentModifiers = MODIFIER_NONE;
-static bool gVerifyReflowEnabled;
-
-bool PresShell::GetVerifyReflowEnable() {
-#ifdef DEBUG
- static bool firstTime = true;
- if (firstTime) {
- firstTime = false;
- char* flags = PR_GetEnv("GECKO_VERIFY_REFLOW_FLAGS");
- if (flags) {
- bool error = false;
-
- for (;;) {
- char* comma = strchr(flags, ',');
- if (comma) *comma = '\0';
-
- bool found = false;
- const VerifyReflowFlagData* flag = gFlags;
- const VerifyReflowFlagData* limit = gFlags + NUM_VERIFY_REFLOW_FLAGS;
- while (flag < limit) {
- if (nsCRT::strcasecmp(flag->name, flags) == 0) {
- gVerifyReflowFlags |= flag->bit;
- found = true;
- break;
- }
- ++flag;
- }
-
- if (!found) error = true;
-
- if (!comma) break;
-
- *comma = ',';
- flags = comma + 1;
- }
-
- if (error) ShowVerifyReflowFlags();
- }
-
- if (VerifyReflowFlags::On & gVerifyReflowFlags) {
- gVerifyReflowEnabled = true;
-
- printf("Note: verifyreflow is enabled");
- if (VerifyReflowFlags::Noisy & gVerifyReflowFlags) {
- printf(" (noisy)");
- }
- if (VerifyReflowFlags::All & gVerifyReflowFlags) {
- printf(" (all)");
- }
- if (VerifyReflowFlags::DumpCommands & gVerifyReflowFlags) {
- printf(" (show reflow commands)");
- }
- if (VerifyReflowFlags::NoisyCommands & gVerifyReflowFlags) {
- printf(" (noisy reflow commands)");
- if (VerifyReflowFlags::ReallyNoisyCommands & gVerifyReflowFlags) {
- printf(" (REALLY noisy reflow commands)");
- }
- }
- printf("\n");
- }
- }
-#endif
- return gVerifyReflowEnabled;
-}
-
-void PresShell::SetVerifyReflowEnable(bool aEnabled) {
- gVerifyReflowEnabled = aEnabled;
-}
-
void PresShell::AddAutoWeakFrame(AutoWeakFrame* aWeakFrame) {
if (aWeakFrame->GetFrame()) {
aWeakFrame->GetFrame()->AddStateBits(NS_FRAME_EXTERNAL_REFERENCE);
@@ -1759,18 +1648,6 @@ nsresult PresShell::Initialize() {
mDidInitialize = true;
-#ifdef DEBUG
- if (VerifyReflowFlags::NoisyCommands & gVerifyReflowFlags) {
- if (mDocument) {
- nsIURI* uri = mDocument->GetDocumentURI();
- if (uri) {
- printf("*** PresShell::Initialize (this=%p, url='%s')\n", (void*)this,
- uri->GetSpecOrDefault().get());
- }
- }
- }
-#endif
-
// Get the root frame from the frame constructor.
// XXXbz it would be nice to move this somewhere else... like frame manager
// Init(), say. But we need to make sure our views are all set up by the
@@ -2726,23 +2603,6 @@ void PresShell::FrameNeedsReflow(nsIFrame* aFrame,
return;
}
-#ifdef DEBUG
- // printf("gShellCounter: %d\n", gShellCounter++);
- if (mInVerifyReflow) return;
-
- if (VerifyReflowFlags::NoisyCommands & gVerifyReflowFlags) {
- printf("\nPresShell@%p: frame %p needs reflow\n", (void*)this,
- (void*)aFrame);
- if (VerifyReflowFlags::ReallyNoisyCommands & gVerifyReflowFlags) {
- printf("Current content model:\n");
- Element* rootElement = mDocument->GetRootElement();
- if (rootElement) {
- rootElement->List(stdout, 0);
- }
- }
- }
-#endif
-
AutoTArray<nsIFrame*, 4> subtrees;
subtrees.AppendElement(aFrame);
@@ -10949,29 +10809,6 @@ bool PresShell::DoReflow(nsIFrame* target, bool aInterruptible,
return !interrupted;
}
-#ifdef DEBUG
-void PresShell::DoVerifyReflow() {
- if (GetVerifyReflowEnable()) {
- // First synchronously render what we have so far so that we can
- // see it.
- nsView* rootView = mViewManager->GetRootView();
- mViewManager->InvalidateView(rootView);
-
- FlushPendingNotifications(FlushType::Layout);
- mInVerifyReflow = true;
- bool ok = VerifyIncrementalReflow();
- mInVerifyReflow = false;
- if (VerifyReflowFlags::All & gVerifyReflowFlags) {
- printf("ProcessReflowCommands: finished (%s)\n", ok ? "ok" : "failed");
- }
-
- if (!mDirtyRoots.IsEmpty()) {
- printf("XXX yikes! reflow commands queued during verify-reflow\n");
- }
- }
-}
-#endif
-
// used with Telemetry metrics
#define NS_LONG_REFLOW_TIME_MS 5000
@@ -10990,12 +10827,6 @@ bool PresShell::ProcessReflowCommands(bool aInterruptible) {
auto timerStart = mozilla::TimeStamp::Now();
bool interrupted = false;
if (!mDirtyRoots.IsEmpty()) {
-#ifdef DEBUG
- if (VerifyReflowFlags::DumpCommands & gVerifyReflowFlags) {
- printf("ProcessReflowCommands: begin incremental reflow\n");
- }
-#endif
-
// If reflow is interruptible, then make a note of our deadline.
const PRIntervalTime deadline =
aInterruptible
@@ -11046,14 +10877,6 @@ bool PresShell::ProcessReflowCommands(bool aInterruptible) {
DidDoReflow(aInterruptible);
}
-#ifdef DEBUG
- if (VerifyReflowFlags::DumpCommands & gVerifyReflowFlags) {
- printf("\nPresShell::ProcessReflowCommands() finished: this=%p\n",
- (void*)this);
- }
- DoVerifyReflow();
-#endif
-
{
TimeDuration elapsed = TimeStamp::Now() - timerStart;
int32_t intElapsed = int32_t(elapsed.ToMilliseconds());
@@ -11236,323 +11059,7 @@ bool PresShell::DelayedKeyEvent::IsKeyPressEvent() {
return mEvent->mMessage == eKeyPress;
}
-// Start of DEBUG only code
-
-#ifdef DEBUG
-
-static void LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg) {
- nsAutoString n1, n2;
- if (k1) {
- k1->GetFrameName(n1);
- } else {
- n1.AssignLiteral(u"(null)");
- }
-
- if (k2) {
- k2->GetFrameName(n2);
- } else {
- n2.AssignLiteral(u"(null)");
- }
-
- printf("verifyreflow: %s %p != %s %p %s\n",
- NS_LossyConvertUTF16toASCII(n1).get(), (void*)k1,
- NS_LossyConvertUTF16toASCII(n2).get(), (void*)k2, aMsg);
-}
-
-static void LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg,
- const nsRect& r1, const nsRect& r2) {
- printf("VerifyReflow Error:\n");
- nsAutoString name;
-
- if (k1) {
- k1->GetFrameName(name);
- printf(" %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k1);
- }
- printf("{%d, %d, %d, %d} != \n", r1.x, r1.y, r1.width, r1.height);
-
- if (k2) {
- k2->GetFrameName(name);
- printf(" %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k2);
- }
- printf("{%d, %d, %d, %d}\n %s\n", r2.x, r2.y, r2.width, r2.height, aMsg);
-}
-
-static void LogVerifyMessage(nsIFrame* k1, nsIFrame* k2, const char* aMsg,
- const nsIntRect& r1, const nsIntRect& r2) {
- printf("VerifyReflow Error:\n");
- nsAutoString name;
-
- if (k1) {
- k1->GetFrameName(name);
- printf(" %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k1);
- }
- printf("{%d, %d, %d, %d} != \n", r1.x, r1.y, r1.width, r1.height);
-
- if (k2) {
- k2->GetFrameName(name);
- printf(" %s %p ", NS_LossyConvertUTF16toASCII(name).get(), (void*)k2);
- }
- printf("{%d, %d, %d, %d}\n %s\n", r2.x, r2.y, r2.width, r2.height, aMsg);
-}
-
-static bool CompareTrees(nsPresContext* aFirstPresContext,
- nsIFrame* aFirstFrame,
- nsPresContext* aSecondPresContext,
- nsIFrame* aSecondFrame) {
- if (!aFirstPresContext || !aFirstFrame || !aSecondPresContext ||
- !aSecondFrame)
- return true;
- // XXX Evil hack to reduce false positives; I can't seem to figure
- // out how to flush scrollbar changes correctly
- // if (aFirstFrame->IsScrollbarFrame())
- // return true;
- bool ok = true;
- const auto& childLists1 = aFirstFrame->ChildLists();
- const auto& childLists2 = aSecondFrame->ChildLists();
- auto iterLists1 = childLists1.begin();
- auto iterLists2 = childLists2.begin();
- do {
- const nsFrameList& kids1 = iterLists1 != childLists1.end()
- ? iterLists1->mList
- : nsFrameList::EmptyList();
- const nsFrameList& kids2 = iterLists2 != childLists2.end()
- ? iterLists2->mList
- : nsFrameList::EmptyList();
- int32_t l1 = kids1.GetLength();
- int32_t l2 = kids2.GetLength();
- if (l1 != l2) {
- ok = false;
- LogVerifyMessage(kids1.FirstChild(), kids2.FirstChild(),
- "child counts don't match: ");
- printf("%d != %d\n", l1, l2);
- if (!(VerifyReflowFlags::All & gVerifyReflowFlags)) {
- break;
- }
- }
-
- LayoutDeviceIntRect r1, r2;
- nsView* v1;
- nsView* v2;
- for (auto kids1Iter = kids1.begin(), kids2Iter = kids2.begin();;
- ++kids1Iter, ++kids2Iter) {
- nsIFrame* k1 = *kids1Iter;
- nsIFrame* k2 = *kids2Iter;
- if (((nullptr == k1) && (nullptr != k2)) ||
- ((nullptr != k1) && (nullptr == k2))) {
- ok = false;
- LogVerifyMessage(k1, k2, "child lists are different\n");
- break;
- } else if (nullptr != k1) {
- // Verify that the frames are the same size
- if (!k1->GetRect().IsEqualInterior(k2->GetRect())) {
- ok = false;
- LogVerifyMessage(k1, k2, "(frame rects)", k1->GetRect(),
- k2->GetRect());
- }
-
- // Make sure either both have views or neither have views; if they
- // do have views, make sure the views are the same size. If the
- // views have widgets, make sure they both do or neither does. If
- // they do, make sure the widgets are the same size.
- v1 = k1->GetView();
- v2 = k2->GetView();
- if (((nullptr == v1) && (nullptr != v2)) ||
- ((nullptr != v1) && (nullptr == v2))) {
- ok = false;
- LogVerifyMessage(k1, k2, "child views are not matched\n");
- } else if (nullptr != v1) {
- if (!v1->GetBounds().IsEqualInterior(v2->GetBounds())) {
- LogVerifyMessage(k1, k2, "(view rects)", v1->GetBounds(),
- v2->GetBounds());
- }
-
- nsIWidget* w1 = v1->GetWidget();
- nsIWidget* w2 = v2->GetWidget();
- if (((nullptr == w1) && (nullptr != w2)) ||
- ((nullptr != w1) && (nullptr == w2))) {
- ok = false;
- LogVerifyMessage(k1, k2, "child widgets are not matched\n");
- } else if (nullptr != w1) {
- r1 = w1->GetBounds();
- r2 = w2->GetBounds();
- if (!r1.IsEqualEdges(r2)) {
- LogVerifyMessage(k1, k2, "(widget rects)", r1.ToUnknownRect(),
- r2.ToUnknownRect());
- }
- }
- }
- if (!ok && !(VerifyReflowFlags::All & gVerifyReflowFlags)) {
- break;
- }
-
- // XXX Should perhaps compare their float managers.
-
- // Compare the sub-trees too
- if (!CompareTrees(aFirstPresContext, k1, aSecondPresContext, k2)) {
- ok = false;
- if (!(VerifyReflowFlags::All & gVerifyReflowFlags)) {
- break;
- }
- }
- } else {
- break;
- }
- }
- if (!ok && (!(VerifyReflowFlags::All & gVerifyReflowFlags))) {
- break;
- }
-
- ++iterLists1;
- ++iterLists2;
- const bool lists1Done = iterLists1 == childLists1.end();
- const bool lists2Done = iterLists2 == childLists2.end();
- if (lists1Done != lists2Done ||
- (!lists1Done && iterLists1->mID != iterLists2->mID)) {
- if (!(VerifyReflowFlags::All & gVerifyReflowFlags)) {
- ok = false;
- }
- LogVerifyMessage(kids1.FirstChild(), kids2.FirstChild(),
- "child list names are not matched: ");
- fprintf(stdout, "%s != %s\n",
- !lists1Done ? ChildListName(iterLists1->mID) : "(null)",
- !lists2Done ? ChildListName(iterLists2->mID) : "(null)");
- break;
- }
- } while (ok && iterLists1 != childLists1.end());
-
- return ok;
-}
-#endif
-
-#if 0
-static nsIFrame*
-FindTopFrame(nsIFrame* aRoot)
-{
- if (aRoot) {
- nsIContent* content = aRoot->GetContent();
- if (content) {
- nsAtom* tag;
- content->GetTag(tag);
- if (nullptr != tag) {
- NS_RELEASE(tag);
- return aRoot;
- }
- }
-
- // Try one of the children
- for (nsIFrame* kid : aRoot->PrincipalChildList()) {
- nsIFrame* result = FindTopFrame(kid);
- if (nullptr != result) {
- return result;
- }
- }
- }
- return nullptr;
-}
-#endif
-
#ifdef DEBUG
-
-// After an incremental reflow, we verify the correctness by doing a
-// full reflow into a fresh frame tree.
-bool PresShell::VerifyIncrementalReflow() {
- if (VerifyReflowFlags::Noisy & gVerifyReflowFlags) {
- printf("Building Verification Tree...\n");
- }
-
- // Create a presentation context to view the new frame tree
- auto cx = MakeRefPtr<nsRootPresContext>(
- mDocument, mPresContext->IsPaginated()
- ? nsPresContext::eContext_PrintPreview
- : nsPresContext::eContext_Galley);
-
- nsDeviceContext* dc = mPresContext->DeviceContext();
- nsresult rv = cx->Init(dc);
- NS_ENSURE_SUCCESS(rv, false);
-
- // Get our scrolling preference
- nsView* rootView = mViewManager->GetRootView();
- NS_ENSURE_TRUE(rootView->HasWidget(), false);
-
- // Create a new view manager.
- auto vm = MakeRefPtr<nsViewManager>(dc);
-
- // Create a child window of the parent that is our "root view/window"
- // Create a view
- nsRect tbounds = mPresContext->GetVisibleArea();
- nsView* view = vm->CreateView(tbounds, nullptr);
- NS_ENSURE_TRUE(view, false);
-
- // Setup hierarchical relationship in view manager
- vm->SetRootView(view);
-
- // Make the new presentation context the same size as our
- // presentation context.
- cx->SetVisibleArea(mPresContext->GetVisibleArea());
-
- RefPtr<PresShell> presShell = mDocument->CreatePresShell(cx, vm);
- NS_ENSURE_TRUE(presShell, false);
-
- // Note that after we create the shell, we must make sure to destroy it
- presShell->SetVerifyReflowEnable(
- false); // turn off verify reflow while we're
- // reflowing the test frame tree
- vm->SetPresShell(presShell);
- {
- nsAutoCauseReflowNotifier crNotifier(this);
- presShell->Initialize();
- }
- presShell->FlushPendingNotifications(FlushType::Layout);
- presShell->SetVerifyReflowEnable(
- true); // turn on verify reflow again now that
- // we're done reflowing the test frame tree
- // Force the non-primary presshell to unsuppress; it doesn't want to normally
- // because it thinks it's hidden
- presShell->mPaintingSuppressed = false;
- if (VerifyReflowFlags::Noisy & gVerifyReflowFlags) {
- printf("Verification Tree built, comparing...\n");
- }
-
- // Now that the document has been reflowed, use its frame tree to
- // compare against our frame tree.
- nsIFrame* root1 = mFrameConstructor->GetRootFrame();
- nsIFrame* root2 = presShell->GetRootFrame();
- bool ok = CompareTrees(mPresContext, root1, cx, root2);
- if (!ok && (VerifyReflowFlags::Noisy & gVerifyReflowFlags)) {
- printf("Verify reflow failed, primary tree:\n");
- root1->List(stdout);
- printf("Verification tree:\n");
- root2->List(stdout);
- }
-
-# if 0
- // Sample code for dumping page to png
- // XXX Needs to be made more flexible
- if (!ok) {
- nsString stra;
- static int num = 0;
- stra.AppendLiteral("C:\\mozilla\\mozilla\\debug\\filea");
- stra.AppendInt(num);
- stra.AppendLiteral(".png");
- gfxUtils::WriteAsPNG(presShell, stra);
- nsString strb;
- strb.AppendLiteral("C:\\mozilla\\mozilla\\debug\\fileb");
- strb.AppendInt(num);
- strb.AppendLiteral(".png");
- gfxUtils::WriteAsPNG(presShell, strb);
- ++num;
- }
-# endif
-
- presShell->EndObservingDocument();
- presShell->Destroy();
- if (VerifyReflowFlags::Noisy & gVerifyReflowFlags) {
- printf("Finished Verifying Reflow...\n");
- }
-
- return ok;
-}
-
// Layout debugging hooks
void PresShell::ListComputedStyles(FILE* out, int32_t aIndent) {
nsIFrame* rootFrame = GetRootFrame();
diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h
@@ -740,18 +740,6 @@ class PresShell final : public nsStubDocumentObserver,
*/
MOZ_CAN_RUN_SCRIPT void ReconstructFrames();
- /**
- * See if reflow verification is enabled. To enable reflow verification add
- * "verifyreflow:1" to your MOZ_LOG environment variable (any non-zero
- * debug level will work). Or, call SetVerifyReflowEnable with true.
- */
- static bool GetVerifyReflowEnable();
-
- /**
- * Set the verify-reflow enable flag.
- */
- static void SetVerifyReflowEnable(bool aEnabled);
-
nsIFrame* GetAbsoluteContainingBlock(nsIFrame* aFrame);
// https://drafts.csswg.org/css-anchor-position-1/#target
@@ -3182,11 +3170,7 @@ class PresShell final : public nsStubDocumentObserver,
VisibleFrames mApproximatelyVisibleFrames;
#ifdef DEBUG
- MOZ_CAN_RUN_SCRIPT_BOUNDARY bool VerifyIncrementalReflow();
- MOZ_CAN_RUN_SCRIPT_BOUNDARY void DoVerifyReflow();
void VerifyHasDirtyRootAncestor(nsIFrame* aFrame);
-
- bool mInVerifyReflow = false;
// The reflow root under which we're currently reflowing. Null when
// not in reflow.
nsIFrame* mCurrentReflowRoot = nullptr;