Bug 1491336 - Do not support delazification of functions which is optimized out. r=jorendorff a=pascalc
authorTooru Fujisawa <arai_a@mac.com>
Fri, 05 Oct 2018 21:21:38 +0900
changeset 490204 48810161314f521b66314cb4450a8c96d0994f7f
parent 490203 8027fae752ae41cf20c33607c0af3e02de03ae75
child 490205 0978af5fb8459b3e257aa8420fdbdd75444b0018
push id9947
push userapavel@mozilla.com
push dateMon, 08 Oct 2018 14:42:52 +0000
treeherdermozilla-beta@5517b5cb5a92 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff, pascalc
bugs1491336
milestone63.0
Bug 1491336 - Do not support delazification of functions which is optimized out. r=jorendorff a=pascalc
js/src/jit-test/tests/debug/Debugger-findScripts-optimized-out.js
js/src/js.msg
js/src/vm/Debugger.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Debugger-findScripts-optimized-out.js
@@ -0,0 +1,31 @@
+// Accessing Debugger.Script's properties which triggers delazification can
+// fail if the function for the script is optimized out.
+// It shouldn't crash but just throw an error.
+
+load(libdir + "asserts.js");
+
+var g = newGlobal();
+var dbg = new Debugger(g);
+g.eval(`
+function enclosing() {
+    (function g1() {});
+    (function* g2() {});
+    (async function g3() {});
+    (async function* g4() {});
+    () => {};
+    async () => {};
+}
+`);
+
+for (const s of dbg.findScripts()) {
+    if (!s.displayName) {
+        continue;
+    }
+
+    try {
+        s.lineCount;  // don't assert
+    } catch (exc) {
+        // If that didn't throw, it's fine. If it did, check the message.
+        assertEq(exc.message, "function is optimized out");
+    }
+}
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -470,16 +470,17 @@ MSG_DEF(JSMSG_DEBUG_LOOP,              0
 MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGEE,      2, JSEXN_ERR, "{0} is not a debuggee {1}")
 MSG_DEF(JSMSG_DEBUG_NOT_DEBUGGING,     0, JSEXN_ERR, "can't set breakpoint: script global is not a debuggee")
 MSG_DEF(JSMSG_DEBUG_NOT_IDLE,          0, JSEXN_ERR, "can't start debugging: a debuggee script is on the stack")
 MSG_DEF(JSMSG_DEBUG_NOT_LIVE,          1, JSEXN_ERR, "{0} is not live")
 MSG_DEF(JSMSG_DEBUG_NO_ENV_OBJECT,     0, JSEXN_TYPEERR, "declarative Environments don't have binding objects")
 MSG_DEF(JSMSG_DEBUG_PROTO,             2, JSEXN_TYPEERR, "{0}.prototype is not a valid {1} instance")
 MSG_DEF(JSMSG_DEBUG_WRONG_OWNER,       1, JSEXN_TYPEERR, "{0} belongs to a different Debugger")
 MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT,     1, JSEXN_ERR, "variable `{0}' has been optimized out")
+MSG_DEF(JSMSG_DEBUG_OPTIMIZED_OUT_FUN, 0, JSEXN_ERR, "function is optimized out")
 MSG_DEF(JSMSG_DEBUG_RESUMPTION_VALUE_DISALLOWED, 0, JSEXN_TYPEERR, "resumption values are disallowed in this hook")
 MSG_DEF(JSMSG_DEBUG_VARIABLE_NOT_FOUND,0, JSEXN_TYPEERR, "variable not found in environment")
 MSG_DEF(JSMSG_DEBUG_WRAPPER_IN_WAY,    3, JSEXN_TYPEERR, "{0} is {1}{2}a global object, but a direct reference is required")
 MSG_DEF(JSMSG_DEBUGGEE_WOULD_RUN,      2, JSEXN_DEBUGGEEWOULDRUN, "debuggee `{0}:{1}' would run")
 MSG_DEF(JSMSG_NOT_CALLABLE_OR_UNDEFINED, 0, JSEXN_TYPEERR, "value is not a function or undefined")
 MSG_DEF(JSMSG_NOT_TRACKING_ALLOCATIONS, 1, JSEXN_ERR, "Cannot call {0} without setting trackingAllocationSites to true")
 MSG_DEF(JSMSG_OBJECT_METADATA_CALLBACK_ALREADY_SET, 0, JSEXN_ERR, "Cannot track object allocation, because other tools are already doing so")
 MSG_DEF(JSMSG_QUERY_INNERMOST_WITHOUT_LINE_URL, 0, JSEXN_TYPEERR, "findScripts query object with 'innermost' property must have 'line' and either 'displayURL', 'url', or 'source'")
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5281,16 +5281,24 @@ DelazifyScript(JSContext* cx, Handle<Laz
 
     // JSFunction::getOrCreateScript requires the enclosing script not to be
     // lazified.
     MOZ_ASSERT(lazyScript->hasEnclosingLazyScript() || lazyScript->hasEnclosingScope());
     if (lazyScript->hasEnclosingLazyScript()) {
         Rooted<LazyScript*> enclosingLazyScript(cx, lazyScript->enclosingLazyScript());
         if (!DelazifyScript(cx, enclosingLazyScript))
             return nullptr;
+
+        if (!lazyScript->enclosingScriptHasEverBeenCompiled()) {
+            // It didn't work! Delazifying the enclosing script still didn't
+            // delazify this script. This happens when the function
+            // corresponding to this script was removed by constant folding.
+            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_DEBUG_OPTIMIZED_OUT_FUN);
+            return nullptr;
+        }
     }
     MOZ_ASSERT(lazyScript->enclosingScriptHasEverBeenCompiled());
 
     RootedFunction fun0(cx, lazyScript->functionNonDelazifying());
     AutoRealm ar(cx, fun0);
     RootedFunction fun(cx, LazyScript::functionDelazifying(cx, lazyScript));
     if (!fun)
         return nullptr;