Bug 256180 layout part - Increase MAX_REFLOW_DEPTH to reduce the probability of content going silently missing. draft
authorHenri Sivonen <hsivonen@hsivonen.fi>
Thu, 14 Sep 2017 11:01:06 +0300
changeset 676675 7763023192880c57d3b6a4b50da0a6aac97250f0
parent 676674 5d407b66d6bef5f380d3cc03e528f5d53c22dc49
child 676676 420711685f9f7df9bd3b131d6747832d049bda51
child 677131 8fdccc218ebcef56f49f9e5eb0904190ab72a478
push id83579
push userbmo:hsivonen@hsivonen.fi
push dateMon, 09 Oct 2017 09:11:23 +0000
bugs256180
milestone58.0a1
Bug 256180 layout part - Increase MAX_REFLOW_DEPTH to reduce the probability of content going silently missing. MozReview-Commit-ID: 7Ui0tVlLEQM
layout/generic/nsIFrame.h
layout/reftests/bugs/256180-1-ref.html
layout/reftests/bugs/256180-1.html
layout/reftests/bugs/256180-2-ref.html
layout/reftests/bugs/256180-2.html
layout/reftests/bugs/256180-3-ref.html
layout/reftests/bugs/256180-3.html
layout/reftests/bugs/256180-4-ref.html
layout/reftests/bugs/256180-4.html
layout/reftests/bugs/reftest.list
layout/tools/reftest/reftest.jsm
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -8,17 +8,42 @@
 
 #ifndef nsIFrame_h___
 #define nsIFrame_h___
 
 #ifndef MOZILLA_INTERNAL_API
 #error This header/class should only be used within Mozilla code. It should not be used by extensions.
 #endif
 
-#define MAX_REFLOW_DEPTH 200
+#if (defined(XP_WIN) && !defined(HAVE_64BIT_BUILD)) || defined(ANDROID)
+// Blink's magic depth limit from its HTML parser (513) plus as much as fits in the
+// default run-time stack on armv7 Android on Dalvik when using display: block minus
+// a bit just to be sure. The Dalvik default stack crashes at 588. ART can do a few
+// frames more. Using the same number for 32-bit Windows for consistency. Over there,
+// Blink's magic depth of 513 doesn't fit in the default stack of 1 MB, but this magic
+// depth fits when the default is grown by mere 192 KB (tested in 64 KB increments).
+//
+// 32-bit Windows has a different limit compared to 64-bit desktop, because the
+// default stack size affects all threads and consumes address space. Fixing that
+// is bug 1257522.
+//
+// 32-bit Android on ARM already happens to have defaults that are close enough to
+// what makes sense as a temporary measure on Windows, so adjusting the Android
+// stack can be a follow-up. The stack on 64-bit ARM needs adjusting in any case
+// before 64-bit ARM can become tier-1. See bug 1400811.
+//
+// Ideally, we'd get rid of this smaller limit and make 32-bit Windows and Android
+// capable of working with the Linux/Mac/Win64 number below.
+#define MAX_REFLOW_DEPTH 585
+#else
+// Blink's magic depth limit from its HTML parser times two. Also just about fits
+// within the system default runtime stack limit of 8 MB on 64-bit Mac and Linux with
+// display: table-cell.
+#define MAX_REFLOW_DEPTH 1026
+#endif
 
 /* nsIFrame is in the process of being deCOMtaminated, i.e., this file is eventually
    going to be eliminated, and all callers will use nsFrame instead.  At the moment
    we're midway through this process, so you will see inlined functions and member
    variables in this file.  -dwh */
 
 #include <algorithm>
 #include <stdio.h>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-1-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>1026-deep display: table-cell</title>
+</head>
+<body>
+<h1>1026-element-deep display: table-cell</h1>
+<p>Actual depth (including text leaves): 1027
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-1.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>1026-element-deep display: table-cell</title>
+<script>
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+function count() {
+    var depth = 0;
+    var deepest = 0;
+    var current = document;
+    var next = null;
+    outer: for (;;) {
+        if ((next = current.firstChild)) {
+            depth++;
+            if (depth > deepest) {
+                deepest = depth;
+            }
+            current = next;
+            continue;
+        }
+        for (;;) {
+            if ((next = current.nextSibling)) {
+                current = next;
+                break;
+            }
+            current = current.parentNode;
+            depth--;
+            if (current == document) {
+                break outer;
+            }
+        }
+    }
+
+    var h1 = document.getElementsByTagName("h1")[0];
+    var p = document.createElement("p");
+    var t = document.createTextNode("Actual depth (including text leaves): " + deepest);
+    p.appendChild(t);
+    h1.parentNode.insertBefore(p, h1.nextSibling);
+}
+
+function deep() {
+    var t = document.createTextNode("PASS");
+    var div = document.createElement("div");
+    div.appendChild(t);
+    for (var i = 0; i < 1023; i++) {
+        var another = document.createElement("div");
+        another.appendChild(div);
+        div = another;
+    }
+    document.body.appendChild(div);
+    count();
+}
+
+window.addEventListener('DOMContentLoaded', deep, false);
+</script>
+<style>
+    div {
+        display: table-cell;
+    }
+</style>
+</head>
+<body>
+<h1>1026-element-deep display: table-cell</h1>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-2-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>585-deep display: table-cell</title>
+</head>
+<body>
+<h1>585-element-deep display: table-cell</h1>
+<p>Actual depth (including text leaves): 586
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-2.html
@@ -0,0 +1,68 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>585-element-deep display: table-cell</title>
+<script>
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+function count() {
+    var depth = 0;
+    var deepest = 0;
+    var current = document;
+    var next = null;
+    outer: for (;;) {
+        if ((next = current.firstChild)) {
+            depth++;
+            if (depth > deepest) {
+                deepest = depth;
+            }
+            current = next;
+            continue;
+        }
+        for (;;) {
+            if ((next = current.nextSibling)) {
+                current = next;
+                break;
+            }
+            current = current.parentNode;
+            depth--;
+            if (current == document) {
+                break outer;
+            }
+        }
+    }
+
+    var h1 = document.getElementsByTagName("h1")[0];
+    var p = document.createElement("p");
+    var t = document.createTextNode("Actual depth (including text leaves): " + deepest);
+    p.appendChild(t);
+    h1.parentNode.insertBefore(p, h1.nextSibling);
+}
+
+function deep() {
+    var t = document.createTextNode("PASS");
+    var div = document.createElement("div");
+    div.appendChild(t);
+    for (var i = 0; i < 582; i++) {
+        var another = document.createElement("div");
+        another.appendChild(div);
+        div = another;
+    }
+    document.body.appendChild(div);
+    count();
+}
+
+window.addEventListener('DOMContentLoaded', deep, false);
+</script>
+<style>
+    div {
+        display: table-cell;
+    }
+</style>
+</head>
+<body>
+<h1>585-element-deep display: table-cell</h1>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-3-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>1026-deep display: block</title>
+</head>
+<body>
+<h1>1026-element-deep display: block</h1>
+<p>Actual depth (including text leaves): 1027
+<div>PASS</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-3.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>1026-element-deep display: block</title>
+<script>
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+function count() {
+    var depth = 0;
+    var deepest = 0;
+    var current = document;
+    var next = null;
+    outer: for (;;) {
+        if ((next = current.firstChild)) {
+            depth++;
+            if (depth > deepest) {
+                deepest = depth;
+            }
+            current = next;
+            continue;
+        }
+        for (;;) {
+            if ((next = current.nextSibling)) {
+                current = next;
+                break;
+            }
+            current = current.parentNode;
+            depth--;
+            if (current == document) {
+                break outer;
+            }
+        }
+    }
+
+    var h1 = document.getElementsByTagName("h1")[0];
+    var p = document.createElement("p");
+    var t = document.createTextNode("Actual depth (including text leaves): " + deepest);
+    p.appendChild(t);
+    h1.parentNode.insertBefore(p, h1.nextSibling);
+}
+
+function deep() {
+    var t = document.createTextNode("PASS");
+    var div = document.createElement("div");
+    div.appendChild(t);
+    for (var i = 0; i < 1023; i++) {
+        var another = document.createElement("div");
+        another.appendChild(div);
+        div = another;
+    }
+    document.body.appendChild(div);
+    count();
+}
+
+window.addEventListener('DOMContentLoaded', deep, false);
+</script>
+</head>
+<body>
+<h1>1026-element-deep display: block</h1>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-4-ref.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="utf-8">
+    <title>585-deep display: block</title>
+</head>
+<body>
+<h1>585-element-deep display: block</h1>
+<p>Actual depth (including text leaves): 586
+<div>PASS</div>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/bugs/256180-4.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<title>585-element-deep display: block</title>
+<script>
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/publicdomain/zero/1.0/
+
+function count() {
+    var depth = 0;
+    var deepest = 0;
+    var current = document;
+    var next = null;
+    outer: for (;;) {
+        if ((next = current.firstChild)) {
+            depth++;
+            if (depth > deepest) {
+                deepest = depth;
+            }
+            current = next;
+            continue;
+        }
+        for (;;) {
+            if ((next = current.nextSibling)) {
+                current = next;
+                break;
+            }
+            current = current.parentNode;
+            depth--;
+            if (current == document) {
+                break outer;
+            }
+        }
+    }
+
+    var h1 = document.getElementsByTagName("h1")[0];
+    var p = document.createElement("p");
+    var t = document.createTextNode("Actual depth (including text leaves): " + deepest);
+    p.appendChild(t);
+    h1.parentNode.insertBefore(p, h1.nextSibling);
+}
+
+function deep() {
+    var t = document.createTextNode("PASS");
+    var div = document.createElement("div");
+    div.appendChild(t);
+    for (var i = 0; i < 582; i++) {
+        var another = document.createElement("div");
+        another.appendChild(div);
+        div = another;
+    }
+    document.body.appendChild(div);
+    count();
+}
+
+window.addEventListener('DOMContentLoaded', deep, false);
+</script>
+</head>
+<body>
+<h1>585-element-deep display: block</h1>
+</body>
+</html>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -33,16 +33,27 @@ HTTP(..) == 10209-3.html 10209-3-ref.htm
 == 18217-zorder-1.html 18217-zorder-ref.html
 == 18217-zorder-2.html 18217-zorder-ref.html
 == 18217-zorder-3.html 18217-zorder-ref-inline.html
 == 18217-zorder-4.html 18217-zorder-ref-inline-table.html
 == 18217-zorder-5.html 18217-zorder-ref-inline-table.html
 == 23604-1.html 23604-1-ref.html
 == 23604-2.html 23604-2-ref.html
 != 24998-1.html 24998-1-ref.html
+# Debug builds and ASAN builds have larger stack frames, so skipped.
+# 32-bit Windows doesn't have enough run-time stack to deal with the test, so skipped.
+skip-if(isDebugBuild||AddressSanitizer||(winWidget&&(!is64Bit))) == 256180-1.html 256180-1-ref.html
+# Debug builds have larger stack frames, so skipped.
+# 32-bit Windows doesn't have enough run-time stack to deal with the test, so skipped.
+skip-if(isDebugBuild||(winWidget&&(!is64Bit))) == 256180-2.html 256180-2-ref.html
+# Debug builds and ASAN builds have larger stack frames, so skipped.
+# 32-bit Windows doesn't have enough run-time stack to deal with the test, so skipped.
+skip-if(isDebugBuild||AddressSanitizer||(winWidget&&(!is64Bit))) == 256180-3.html 256180-3-ref.html
+# Debug builds have larger stack frames, so skipped.
+skip-if(isDebugBuild) == 256180-4.html 256180-4-ref.html
 == 25888-1l.html 25888-1l-ref.html
 != 25888-1l.html 25888-1l-notref.html
 == 25888-1r.html 25888-1r-ref.html
 != 25888-1r.html 25888-1r-notref.html
 == 25888-2l.html 25888-2l-ref.html
 == 25888-2r.html 25888-2r-ref.html
 == 25888-3l.html 25888-3l-ref.html
 == 25888-3r.html 25888-3r-ref.html
--- a/layout/tools/reftest/reftest.jsm
+++ b/layout/tools/reftest/reftest.jsm
@@ -729,16 +729,18 @@ function BuildConditionSandbox(aURL) {
     // Shortcuts for widget toolkits.
     sandbox.Android = xr.OS == "Android";
     sandbox.cocoaWidget = xr.widgetToolkit == "cocoa";
     sandbox.gtkWidget = xr.widgetToolkit == "gtk2"
                         || xr.widgetToolkit == "gtk3";
     sandbox.qtWidget = xr.widgetToolkit == "qt";
     sandbox.winWidget = xr.widgetToolkit == "windows";
 
+    sandbox.is64Bit = xr.is64Bit;
+
     // Scrollbars that are semi-transparent. See bug 1169666.
     sandbox.transparentScrollbars = xr.widgetToolkit == "gtk3";
 
     if (sandbox.Android) {
         var sysInfo = CC["@mozilla.org/system-info;1"].getService(CI.nsIPropertyBag2);
 
         // This is currently used to distinguish Android 4.0.3 (SDK version 15)
         // and later from Android 2.x