Bug 1342070 - Part 3: Disable optimization if devtools or profiler is used. r=till
authorTooru Fujisawa <arai_a@mac.com>
Tue, 17 Apr 2018 14:59:57 +0200
changeset 467634 e66e4b3ee60f04411e0df5d446794d4166c3ba80
parent 467633 f054209125461575f57ce0f1e6b962653c523572
child 467635 7674892ac2302b03c75cae1174bff06bffe280ea
push id9165
push userasasaki@mozilla.com
push dateThu, 26 Apr 2018 21:04:54 +0000
treeherdermozilla-beta@064c3804de2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstill
bugs1342070
milestone61.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 1342070 - Part 3: Disable optimization if devtools or profiler is used. r=till
js/src/builtin/Promise.cpp
--- a/js/src/builtin/Promise.cpp
+++ b/js/src/builtin/Promise.cpp
@@ -3049,21 +3049,49 @@ Promise_catch_impl(JSContext* cx, unsign
 
     FixedInvokeArgs<2> iargs(cx);
     iargs[0].setUndefined();
     iargs[1].set(args.get(0));
 
     return Call(cx, thenVal, args.thisv(), iargs, args.rval());
 }
 
+static MOZ_ALWAYS_INLINE bool
+IsPromiseThenOrCatchRetValImplicitlyUsed(JSContext* cx)
+{
+    // The returned promise of Promise#then and Promise#catch contains
+    // stack info if async stack is enabled.  Even if their return value is not
+    // used explicitly in the script, the stack info is observable in devtools
+    // and profilers.  We shouldn't apply the optimization not to allocate the
+    // returned Promise object if the it's implicitly used by them.
+    //
+    // FIXME: Once bug 1280819 gets fixed, we can use ShouldCaptureDebugInfo.
+    if (!cx->options().asyncStack())
+        return false;
+
+    // If devtools is opened, the current compartment will become debuggee.
+    if (cx->compartment()->isDebuggee())
+        return true;
+
+    // There are 2 profilers, and they can be independently enabled.
+    if (cx->runtime()->geckoProfiler().enabled())
+        return true;
+    if (JS::IsProfileTimelineRecordingEnabled())
+        return true;
+
+    // The stack is also observable from Error#stack, but we don't care since
+    // it's nonstandard feature.
+    return false;
+}
+
 // ES2016, 25.4.5.3.
 static bool
 Promise_catch_noRetVal(JSContext* cx, unsigned argc, Value* vp)
 {
-    return Promise_catch_impl(cx, argc, vp, false);
+    return Promise_catch_impl(cx, argc, vp, IsPromiseThenOrCatchRetValImplicitlyUsed(cx));
 }
 
 // ES2016, 25.4.5.3.
 static bool
 Promise_catch(JSContext* cx, unsigned argc, Value* vp)
 {
     return Promise_catch_impl(cx, argc, vp, true);
 }
@@ -3117,17 +3145,18 @@ Promise_then_impl(JSContext* cx, HandleV
     return true;
 }
 
 // ES2016, 25.4.5.3.
 bool
 Promise_then_noRetVal(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
-    return Promise_then_impl(cx, args.thisv(), args.get(0), args.get(1), args.rval(), false);
+    return Promise_then_impl(cx, args.thisv(), args.get(0), args.get(1), args.rval(),
+                             IsPromiseThenOrCatchRetValImplicitlyUsed(cx));
 }
 
 // ES2016, 25.4.5.3.
 static bool
 Promise_then(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return Promise_then_impl(cx, args.thisv(), args.get(0), args.get(1), args.rval(), true);