Bug 1107937 - Part 2: Correctly rematerialize CallObjects on heavyweight function frames. (r=jandem)
authorShu-yu Guo <shu@rfrn.org>
Tue, 09 Dec 2014 23:10:37 -0800
changeset 218958 cec0200ec01e5f5ac75161d3f53e98ab530c14bd
parent 218957 a03085803e4da4f63d54b7a961a57e7983c41d76
child 218959 263322550d0a37858bc0aeb9561c6a4275a87da4
push id52697
push usershu@rfrn.org
push dateWed, 10 Dec 2014 07:11:22 +0000
treeherdermozilla-inbound@170231ba4950 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1107937
milestone37.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 1107937 - Part 2: Correctly rematerialize CallObjects on heavyweight function frames. (r=jandem)
js/src/jit/RematerializedFrame.cpp
js/src/jit/RematerializedFrame.h
js/src/vm/Stack-inl.h
--- a/js/src/jit/RematerializedFrame.cpp
+++ b/js/src/jit/RematerializedFrame.cpp
@@ -66,19 +66,29 @@ RematerializedFrame::RematerializeInline
                                                InlineFrameIterator &iter,
                                                Vector<RematerializedFrame *> &frames)
 {
     if (!frames.resize(iter.frameCount()))
         return false;
 
     while (true) {
         size_t frameNo = iter.frameNo();
-        frames[frameNo] = RematerializedFrame::New(cx, top, iter);
-        if (!frames[frameNo])
+        RematerializedFrame *frame = RematerializedFrame::New(cx, top, iter);
+        if (!frame)
             return false;
+        if (frame->scopeChain()) {
+            // Frames are often rematerialized with the cx inside a Debugger's
+            // compartment. To create CallObjects, we need to be in that
+            // frame's compartment.
+            AutoCompartment ac(cx, frame->scopeChain());
+            if (!EnsureHasScopeObjects(cx, frame))
+                return false;
+        }
+
+        frames[frameNo] = frame;
 
         if (!iter.more())
             break;
         ++iter;
     }
 
     return true;
 }
@@ -108,16 +118,36 @@ RematerializedFrame::callObj() const
 
     JSObject *scope = scopeChain();
     while (!scope->is<CallObject>())
         scope = scope->enclosingScope();
     return scope->as<CallObject>();
 }
 
 void
+RematerializedFrame::pushOnScopeChain(ScopeObject &scope)
+{
+    MOZ_ASSERT(*scopeChain() == scope.enclosingScope() ||
+               *scopeChain() == scope.as<CallObject>().enclosingScope().as<DeclEnvObject>().enclosingScope());
+    scopeChain_ = &scope;
+}
+
+bool
+RematerializedFrame::initFunctionScopeObjects(JSContext *cx)
+{
+    MOZ_ASSERT(isNonEvalFunctionFrame());
+    MOZ_ASSERT(fun()->isHeavyweight());
+    CallObject *callobj = CallObject::createForFunction(cx, this);
+    if (!callobj)
+        return false;
+    pushOnScopeChain(*callobj);
+    return true;
+}
+
+void
 RematerializedFrame::mark(JSTracer *trc)
 {
     gc::MarkScriptRoot(trc, &script_, "remat ion frame script");
     gc::MarkObjectRoot(trc, &scopeChain_, "remat ion frame scope chain");
     gc::MarkValueRoot(trc, &returnValue_, "remat ion frame return value");
     gc::MarkValueRoot(trc, &thisValue_, "remat ion frame this");
     gc::MarkValueRootRange(trc, slots_, slots_ + numActualArgs_ + script_->nfixed(),
                            "remat ion frame stack");
--- a/js/src/jit/RematerializedFrame.h
+++ b/js/src/jit/RematerializedFrame.h
@@ -98,18 +98,23 @@ class RematerializedFrame
     }
     bool inlined() const {
         return frameNo_ > 0;
     }
 
     JSObject *scopeChain() const {
         return scopeChain_;
     }
+    void pushOnScopeChain(ScopeObject &scope);
+    bool initFunctionScopeObjects(JSContext *cx);
+
     bool hasCallObj() const {
-        return maybeFun() && fun()->isHeavyweight();
+        return maybeFun() &&
+               fun()->isHeavyweight() &&
+               scopeChain()->is<CallObject>();
     }
     CallObject &callObj() const;
 
     bool hasArgsObj() const {
         return !!argsObj_;
     }
     ArgumentsObject &argsObj() const {
         MOZ_ASSERT(hasArgsObj());
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -458,17 +458,19 @@ AbstractFramePtr::callObj() const
     return asRematerializedFrame()->callObj();
 }
 
 inline bool
 AbstractFramePtr::initFunctionScopeObjects(JSContext *cx)
 {
     if (isInterpreterFrame())
         return asInterpreterFrame()->initFunctionScopeObjects(cx);
-    return asBaselineFrame()->initFunctionScopeObjects(cx);
+    if (isBaselineFrame())
+        return asBaselineFrame()->initFunctionScopeObjects(cx);
+    return asRematerializedFrame()->initFunctionScopeObjects(cx);
 }
 
 inline JSCompartment *
 AbstractFramePtr::compartment() const
 {
     return scopeChain()->compartment();
 }