Bug 1010556 - Bump ASAN kTrustedScriptBuffer constant, to account for the new frame size. r=bholley
authorNicolas B. Pierron <nicolas.b.pierron@mozilla.com>
Mon, 02 Mar 2015 14:33:14 -0800
changeset 231508 fa16d24d530f347e9f4ae6de986e68d99c28e3cf
parent 231507 4829b02a11af16bd8850fb3b377cfa59abd46fef
child 231509 ced7bcaa0e52f86c6abc3b30226e48b2fe7cbd2d
push id28353
push usercbook@mozilla.com
push dateTue, 03 Mar 2015 12:54:59 +0000
treeherdermozilla-central@985070813323 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs1010556
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1010556 - Bump ASAN kTrustedScriptBuffer constant, to account for the new frame size. r=bholley
js/src/shell/js.cpp
js/xpconnect/src/XPCJSRuntime.cpp
js/xpconnect/tests/chrome/test_bug732665.xul
js/xpconnect/tests/chrome/test_bug732665_meta.js
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3204,16 +3204,28 @@ StackDump(JSContext *cx, unsigned argc, 
     }
 
     args.rval().setUndefined();
     return true;
 }
 #endif
 
 static bool
+StackPointerInfo(JSContext *cx, unsigned argc, Value *vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+
+    // Copy the truncated stack pointer to the result.  This value is not used
+    // as a pointer but as a way to measure frame-size from JS.
+    args.rval().setInt32(int32_t(reinterpret_cast<size_t>(&args) & 0xfffffff));
+    return true;
+}
+
+
+static bool
 Elapsed(JSContext *cx, unsigned argc, jsval *vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     if (args.length() == 0) {
         double d = 0.0;
         JSShellContextData *data = GetContextData(cx);
         if (data)
             d = PRMJ_Now() - data->startTime;
@@ -4892,16 +4904,21 @@ static const JSFunctionSpecWithHelp shel
     JS_FN_HELP("disableSingleStepProfiling", DisableSingleStepProfiling, 0, 0,
 "disableSingleStepProfiling()",
 "  Return the array of backtraces recorded by enableSingleStepProfiling."),
 
     JS_FN_HELP("isLatin1", IsLatin1, 1, 0,
 "isLatin1(s)",
 "  Return true iff the string's characters are stored as Latin1."),
 
+    JS_FN_HELP("stackPointerInfo", StackPointerInfo, 0, 0,
+"stackPointerInfo()",
+"  Return an int32 value which corresponds to the offset of the latest stack\n"
+"  pointer, such that one can take the differences of 2 to estimate a frame-size."),
+
     JS_FS_HELP_END
 };
 
 static const JSFunctionSpecWithHelp fuzzing_unsafe_functions[] = {
     JS_FN_HELP("clone", Clone, 1, 0,
 "clone(fun[, scope])",
 "  Clone function object."),
 
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -3320,18 +3320,18 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
     // number of heavy stack frames achievable gives us the following rough data,
     // ordered by the effective categories in which they are grouped in the
     // JS_SetNativeStackQuota call (which predates this analysis).
     //
     // (NB: These numbers may have drifted recently - see bug 938429)
     // OSX 64-bit Debug: 7MB stack, 636 stack frames => ~11.3k per stack frame
     // OSX64 Opt: 7MB stack, 2440 stack frames => ~3k per stack frame
     //
-    // Linux 32-bit Debug: 2MB stack, 447 stack frames => ~4.6k per stack frame
-    // Linux 64-bit Debug: 4MB stack, 501 stack frames => ~8.2k per stack frame
+    // Linux 32-bit Debug: 2MB stack, 426 stack frames => ~4.8k per stack frame
+    // Linux 64-bit Debug: 4MB stack, 455 stack frames => ~9.0k per stack frame
     //
     // Windows (Opt+Debug): 900K stack, 235 stack frames => ~3.4k per stack frame
     //
     // Linux 32-bit Opt: 1MB stack, 272 stack frames => ~3.8k per stack frame
     // Linux 64-bit Opt: 2MB stack, 316 stack frames => ~6.5k per stack frame
     //
     // We tune the trusted/untrusted quotas for each configuration to achieve our
     // invariants while attempting to minimize overhead. In contrast, our buffer
@@ -3353,19 +3353,19 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* 
     const size_t kStackQuota = 7 * 1024 * 1024;
     const size_t kTrustedScriptBuffer = 180 * 1024;
 #elif defined(MOZ_ASAN)
     // ASan requires more stack space due to red-zones, so give it double the
     // default (1MB on 32-bit, 2MB on 64-bit). ASAN stack frame measurements
     // were not taken at the time of this writing, so we hazard a guess that
     // ASAN builds have roughly thrice the stack overhead as normal builds.
     // On normal builds, the largest stack frame size we might encounter is
-    // 8.2k, so let's use a buffer of 8.2 * 3 * 10 = 246k.
+    // 9.0k (see above), so let's use a buffer of 9.0 * 3 * 10 = 270k.
     const size_t kStackQuota =  2 * kDefaultStackQuota;
-    const size_t kTrustedScriptBuffer = 246 * 1024;
+    const size_t kTrustedScriptBuffer = 270 * 1024;
 #elif defined(XP_WIN)
     // 1MB is the default stack size on Windows, so use 900k.
     // Windows PGO stack frames have unfortunately gotten pretty large lately. :-(
     const size_t kStackQuota = 900 * 1024;
     const size_t kTrustedScriptBuffer = (sizeof(size_t) == 8) ? 140 * 1024
                                                               : 80 * 1024;
     // The following two configurations are linux-only. Given the numbers above,
     // we use 50k and 100k trusted buffers on 32-bit and 64-bit respectively.
--- a/js/xpconnect/tests/chrome/test_bug732665.xul
+++ b/js/xpconnect/tests/chrome/test_bug732665.xul
@@ -62,15 +62,20 @@ https://bugzilla.mozilla.org/show_bug.cg
   // Exhaust the stack space in content, and then make sure we can still get 10
   // heavy frames in chrome.
   //
   // Note that sometimes, if we pass |0| to nearNativeStackLimit, we can end up
   // so close to the border in content that we can't even get ourselves together
   // enough to make the cross-compartment call. So rather than exhausting the
   // stack entirely and then checking for 10 chrome frames, we leave ourselves
   // one frame's worth, and check for 11.
+  //
+  // If this assertion fails, the current work-around so far is to measure
+  // again the worst frame size, by using the JS Shell to run
+  // test_bug732665_meta.js . This script will output numbers to update
+  // XPCJSRuntime.cpp comment, as well as the kTrustedScriptBuffer constant.
   contentSb.nnslChrome = chromeSb.nearNativeStackLimit;
   var nestedLimit = Cu.evalInSandbox("nearNativeStackLimit(1, function() { nestedLimit = nnslChrome(0);}); nestedLimit;", contentSb);
   ok(nestedLimit >= 11, "Chrome should be invokable from content script with an exhausted stack: " + nestedLimit);
 
   ]]>
   </script>
 </window>
new file mode 100644
--- /dev/null
+++ b/js/xpconnect/tests/chrome/test_bug732665_meta.js
@@ -0,0 +1,26 @@
+var bottom = stackPointerInfo();
+var top = bottom;
+
+function nearNativeStackLimit() {
+  function inner() {
+    try {
+      with ({}) { // keep things predictable -- stay in the interpreter
+        top = stackPointerInfo();
+        var stepsFromLimit = eval("inner()"); // Use eval to force a number of native stackframes to be created.
+      }
+      return stepsFromLimit + 1;
+    } catch(e) {
+      // It would be nice to check here that the exception is actually an
+      // over-recursion here. But doing so would require toString()ing the
+      // exception, which we may not have the stack space to do.
+      return 1;
+    }
+  }
+  return inner();
+}
+
+var nbFrames = nearNativeStackLimit();
+var frameSize = bottom - top;
+print("Max stack size:", frameSize, "bytes",
+      "\nMaximum number of frames:", nbFrames,
+      "\nAverage frame size:", Math.ceil(frameSize / nbFrames), "bytes");