Bug 1330339 - Ensure wasm debug is enabled when observesFrame is queried. r?luke draft
authorYury Delendik <ydelendik@mozilla.com>
Thu, 12 Jan 2017 09:21:05 -0600
changeset 460649 948b0b343f342567cdd5cfc64190f19903959d4f
parent 460618 91f5293e9a89056565493ed5073c3842b0ee9fdc
child 542096 a9af7dfcb04b5fcede17c86c45827f5adb876bd6
push id41443
push userydelendik@mozilla.com
push dateFri, 13 Jan 2017 13:50:01 +0000
reviewersluke
bugs1330339
milestone53.0a1
Bug 1330339 - Ensure wasm debug is enabled when observesFrame is queried. r?luke MozReview-Commit-ID: 7zbwMtA3uIZ
js/src/jit-test/tests/debug/bug1330339.js
js/src/vm/Debugger.cpp
js/src/vm/Stack.h
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/bug1330339.js
@@ -0,0 +1,36 @@
+// |jit-test| test-also-wasm-baseline; error: TestComplete
+
+if (!wasmIsSupported())
+     throw "TestComplete";
+
+let module = new WebAssembly.Module(wasmTextToBinary(`
+    (module
+        (import "global" "func")
+        (func (export "test")
+         call 0 ;; calls the import, which is func #0
+        )
+    )
+`));
+
+let imports = {
+  global: {
+    func: function () {
+        let g = newGlobal();
+        let dbg = new Debugger(g);
+        dbg.onExceptionUnwind = function (frame) {
+            frame.older;
+        };
+        g.eval("throw new Error();");
+    }
+  }
+};
+let instance = new WebAssembly.Instance(module, imports);
+
+try {
+    instance.exports.test();
+    assertEq(false, true);
+} catch (e) {
+    assertEq(e.constructor.name, 'Error');
+}
+
+throw "TestComplete";
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -6292,18 +6292,22 @@ bool
 Debugger::observesFrame(const FrameIter& iter) const
 {
     // Skip frames not yet fully initialized during their prologue.
     if (iter.isInterp() && iter.isFunctionFrame()) {
         const Value& thisVal = iter.interpFrame()->thisArgument();
         if (thisVal.isMagic() && thisVal.whyMagic() == JS_IS_CONSTRUCTING)
             return false;
     }
-    if (iter.isWasm())
+    if (iter.isWasm()) {
+        // Skip frame of wasm instances we cannot observe.
+        if (!iter.wasmDebugEnabled())
+            return false;
         return observesWasm(iter.wasmInstance());
+    }
     return observesScript(iter.script());
 }
 
 bool
 Debugger::observesScript(JSScript* script) const
 {
     if (!enabled)
         return false;
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1806,16 +1806,18 @@ class FrameIter
     JSAtom* functionDisplayAtom() const;
     bool mutedErrors() const;
 
     bool hasScript() const { return !isWasm(); }
 
     // -----------------------------------------------------------
     //  The following functions can only be called when isWasm()
     // -----------------------------------------------------------
+
+    inline bool wasmDebugEnabled() const;
     inline wasm::Instance* wasmInstance() const;
 
     // -----------------------------------------------------------
     // The following functions can only be called when hasScript()
     // -----------------------------------------------------------
 
     inline JSScript* script() const;
 
@@ -2051,21 +2053,29 @@ FrameIter::script() const
     if (data_.state_ == INTERP)
         return interpFrame()->script();
     MOZ_ASSERT(data_.state_ == JIT);
     if (data_.jitFrames_.isIonJS())
         return ionInlineFrames_.script();
     return data_.jitFrames_.script();
 }
 
+inline bool
+FrameIter::wasmDebugEnabled() const
+{
+    MOZ_ASSERT(!done());
+    MOZ_ASSERT(data_.state_ == WASM);
+    return data_.wasmFrames_.debugEnabled();
+}
+
 inline wasm::Instance*
 FrameIter::wasmInstance() const
 {
     MOZ_ASSERT(!done());
-    MOZ_ASSERT(data_.state_ == WASM);
+    MOZ_ASSERT(data_.state_ == WASM && wasmDebugEnabled());
     return data_.wasmFrames_.instance();
 }
 
 inline bool
 FrameIter::isIon() const
 {
     return isJit() && data_.jitFrames_.isIonJS();
 }