From ee2ae70d76011a455e8ac581bd26720e68278d2b Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Thu, 24 Apr 2014 01:59:38 -0700 Subject: [PATCH] Bug 716647 - Part 5 1/2: Support rematerialized frames in DebugScopes::updateLiveScope. (r=jimb) --- .../tests/debug/Environment-getVariable-13.js | 47 +++++++++++++++++++ js/src/jit/RematerializedFrame.cpp | 3 +- js/src/jit/RematerializedFrame.h | 10 ++++ js/src/vm/ScopeObject.cpp | 6 +-- js/src/vm/Stack-inl.h | 10 +++- 5 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 js/src/jit-test/tests/debug/Environment-getVariable-13.js diff --git a/js/src/jit-test/tests/debug/Environment-getVariable-13.js b/js/src/jit-test/tests/debug/Environment-getVariable-13.js new file mode 100644 index 000000000000..87ceaa16554f --- /dev/null +++ b/js/src/jit-test/tests/debug/Environment-getVariable-13.js @@ -0,0 +1,47 @@ +// Tests that we can use debug scopes with Ion frames. +// +// Unfortunately these tests are brittle. They depend on opaque JIT heuristics +// kicking in. + +load(libdir + "jitopts.js"); + +if (!jitTogglesMatch(Opts_Ion2NoParallelCompilation)) + quit(0); + +withJitOptions(Opts_Ion2NoParallelCompilation, function () { + var g = newGlobal(); + var dbg = new Debugger; + + // Note that this *depends* on CCW scripted functions being opaque to Ion + // optimization and not deoptimizing the frames below the call to toggle. + g.toggle = function toggle(d) { + if (d) { + dbg.addDebuggee(g); + var frame = dbg.getNewestFrame(); + assertEq(frame.implementation, "ion"); + // g is heavyweight but its call object is optimized out, because its + // arguments and locals are unaliased. + // + // Calling frame.environment here should make a fake debug scope that + // gets things directly from the frame. Calling frame.arguments doesn't + // go through the scope object and reads directly off the frame. Assert + // that the two are equal. + assertEq(frame.environment.getVariable("x"), frame.arguments[1]); + } + }; + + g.eval("" + function f(d, x) { g(d, x); }); + g.eval("" + function g(d, x) { + for (var i = 0; i < 200; i++); + function inner() { i = 42; }; + toggle(d); + // Use x so it doesn't get optimized out. + x++; + }); + + g.eval("(" + function test() { + for (i = 0; i < 5; i++) + f(false, 42); + f(true, 42); + } + ")();"); +}); diff --git a/js/src/jit/RematerializedFrame.cpp b/js/src/jit/RematerializedFrame.cpp index 915031d656a9..a8a95503393c 100644 --- a/js/src/jit/RematerializedFrame.cpp +++ b/js/src/jit/RematerializedFrame.cpp @@ -29,7 +29,8 @@ struct CopyValueToRematerializedFrame }; RematerializedFrame::RematerializedFrame(JSContext *cx, uint8_t *top, InlineFrameIterator &iter) - : top_(top), + : prevUpToDate_(false), + top_(top), frameNo_(iter.frameNo()), numActualArgs_(iter.numActualArgs()), script_(iter.script()) diff --git a/js/src/jit/RematerializedFrame.h b/js/src/jit/RematerializedFrame.h index 7b3e254215c9..0a0174b2e50e 100644 --- a/js/src/jit/RematerializedFrame.h +++ b/js/src/jit/RematerializedFrame.h @@ -24,6 +24,9 @@ namespace jit { // class RematerializedFrame { + // See DebugScopes::updateLiveScopes. + bool prevUpToDate_; + // The fp of the top frame associated with this possibly inlined frame. uint8_t *top_; @@ -43,6 +46,13 @@ class RematerializedFrame public: static RematerializedFrame *New(JSContext *cx, uint8_t *top, InlineFrameIterator &iter); + bool prevUpToDate() const { + return prevUpToDate_; + } + void setPrevUpToDate() { + prevUpToDate_ = true; + } + uint8_t *top() const { return top_; } diff --git a/js/src/vm/ScopeObject.cpp b/js/src/vm/ScopeObject.cpp index 90eafdd41ed0..a23a4a6234e3 100644 --- a/js/src/vm/ScopeObject.cpp +++ b/js/src/vm/ScopeObject.cpp @@ -2017,11 +2017,7 @@ DebugScopes::updateLiveScopes(JSContext *cx) * the flag for us, at exactly the time when execution resumes fp->prev(). */ for (AllFramesIter i(cx); !i.done(); ++i) { - /* - * Debug-mode currently disables Ion compilation in the compartment of - * the debuggee. - */ - if (i.isIon()) + if (!i.hasUsableAbstractFramePtr()) continue; AbstractFramePtr frame = i.abstractFramePtr(); diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index 36d2dfb79129..2e71604d8de0 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -823,7 +823,9 @@ AbstractFramePtr::prevUpToDate() const if (isInterpreterFrame()) return asInterpreterFrame()->prevUpToDate(); #ifdef JS_ION - return asBaselineFrame()->prevUpToDate(); + if (isBaselineFrame()) + return asBaselineFrame()->prevUpToDate(); + return asRematerializedFrame()->prevUpToDate(); #else MOZ_ASSUME_UNREACHABLE("Invalid frame"); #endif @@ -836,7 +838,11 @@ AbstractFramePtr::setPrevUpToDate() const return; } #ifdef JS_ION - asBaselineFrame()->setPrevUpToDate(); + if (isBaselineFrame()) { + asBaselineFrame()->setPrevUpToDate(); + return; + } + asRematerializedFrame()->setPrevUpToDate(); #else MOZ_ASSUME_UNREACHABLE("Invalid frame"); #endif