Bug 966912 - Part 3: UnwindScope uses static scope chain, not stack depth r=luke
authorAndy Wingo <wingo@igalia.com>
Tue, 04 Feb 2014 18:18:24 +0100
changeset 166882 3fe176961eae758891ce89b867ad7b491a601d7a
parent 166881 92a2cc62f2f944a9253381149ad7aea54695f2d9
child 166883 eb6b668f23888d5cae331d4e85cd6f893731b884
push id39327
push userwingo@igalia.com
push dateWed, 05 Feb 2014 11:21:50 +0000
treeherdermozilla-inbound@eb6b668f2388 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs966912
milestone30.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 966912 - Part 3: UnwindScope uses static scope chain, not stack depth r=luke
js/src/jit/IonFrames.cpp
js/src/jit/VMFunctions.cpp
js/src/vm/Interpreter.cpp
js/src/vm/Interpreter.h
js/src/vm/ScopeObject.h
--- a/js/src/jit/IonFrames.cpp
+++ b/js/src/jit/IonFrames.cpp
@@ -507,17 +507,17 @@ HandleExceptionBaseline(JSContext *cx, c
         // See the big comment in TryNoteIter::settle for more info.
         JS_ASSERT(frame.baselineFrame()->numValueSlots() >= script->nfixed());
         size_t stackDepth = frame.baselineFrame()->numValueSlots() - script->nfixed();
         if (tn->stackDepth > stackDepth)
             continue;
 
         // Unwind scope chain (pop block objects).
         if (cx->isExceptionPending())
-            UnwindScope(cx, si, tn->stackDepth);
+            UnwindScope(cx, si, script->main() + tn->start);
 
         // Compute base pointer and stack pointer.
         rfe->framePointer = frame.fp() - BaselineFrame::FramePointerOffset;
         rfe->stackPointer = rfe->framePointer - BaselineFrame::Size() -
             (script->nfixed() + tn->stackDepth) * sizeof(Value);
 
         switch (tn->kind) {
           case JSTRY_CATCH:
--- a/js/src/jit/VMFunctions.cpp
+++ b/js/src/jit/VMFunctions.cpp
@@ -730,17 +730,17 @@ DebugPrologue(JSContext *cx, BaselineFra
     }
 }
 
 bool
 DebugEpilogue(JSContext *cx, BaselineFrame *frame, jsbytecode *pc, bool ok)
 {
     // Unwind scope chain to stack depth 0.
     ScopeIter si(frame, pc, cx);
-    UnwindScope(cx, si, 0);
+    UnwindScope(cx, si, frame->script()->main());
 
     // If ScriptDebugEpilogue returns |true| we have to return the frame's
     // return value. If it returns |false|, the debugger threw an exception.
     // In both cases we have to pop debug scopes.
     ok = ScriptDebugEpilogue(cx, frame, pc, ok);
 
     if (frame->isNonEvalFunctionFrame()) {
         JS_ASSERT_IF(ok, frame->hasReturnValue());
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -850,46 +850,48 @@ EnterWith(JSContext *cx, AbstractFramePt
                                                            staticWith);
     if (!withobj)
         return false;
 
     frame.pushOnScopeChain(*withobj);
     return true;
 }
 
-/* Unwind block and scope chains to match the given depth. */
+// Unwind scope chain and iterator to match the static scope corresponding to
+// the given bytecode position.
 void
-js::UnwindScope(JSContext *cx, ScopeIter &si, uint32_t stackDepth)
+js::UnwindScope(JSContext *cx, ScopeIter &si, jsbytecode *pc)
 {
-    for (; !si.done(); ++si) {
+    if (si.done())
+        return;
+
+    Rooted<NestedScopeObject *> staticScope(cx, si.frame().script()->getStaticScope(pc));
+
+    for (; si.staticScope() != staticScope; ++si) {
         switch (si.type()) {
           case ScopeIter::Block:
-            if (si.staticBlock().stackDepth() < stackDepth)
-                return;
             if (cx->compartment()->debugMode())
                 DebugScopes::onPopBlock(cx, si);
             if (si.staticBlock().needsClone())
                 si.frame().popBlock(cx);
             break;
           case ScopeIter::With:
-            if (si.scope().as<DynamicWithObject>().stackDepth() < stackDepth)
-                return;
             si.frame().popWith(cx);
             break;
           case ScopeIter::Call:
           case ScopeIter::StrictEvalScope:
             break;
         }
     }
 }
 
 static void
 ForcedReturn(JSContext *cx, ScopeIter &si, FrameRegs &regs)
 {
-    UnwindScope(cx, si, 0);
+    UnwindScope(cx, si, regs.fp()->script()->main());
     regs.setToEndOfScript();
 }
 
 static void
 ForcedReturn(JSContext *cx, FrameRegs &regs)
 {
     ScopeIter si(regs.fp(), regs.pc, cx);
     ForcedReturn(cx, si, regs);
@@ -1004,17 +1006,17 @@ HandleError(JSContext *cx, FrameRegs &re
                 MOZ_ASSUME_UNREACHABLE("Invalid trap status");
             }
         }
 
         RootedValue exception(cx);
         for (TryNoteIter tni(cx, regs); !tni.done(); ++tni) {
             JSTryNote *tn = *tni;
 
-            UnwindScope(cx, si, tn->stackDepth);
+            UnwindScope(cx, si, regs.fp()->script()->main() + tn->start);
 
             /*
              * Set pc to the first bytecode after the the try note to point
              * to the beginning of catch or finally or to [enditer] closing
              * the for-in loop.
              */
             regs.pc = regs.fp()->script()->main() + tn->start + tn->length;
             regs.sp = regs.spForStackDepth(tn->stackDepth);
--- a/js/src/vm/Interpreter.h
+++ b/js/src/vm/Interpreter.h
@@ -313,19 +313,20 @@ extern JSType
 TypeOfObject(JSObject *obj);
 
 extern JSType
 TypeOfValue(const Value &v);
 
 extern bool
 HasInstance(JSContext *cx, HandleObject obj, HandleValue v, bool *bp);
 
-/* Unwind block and scope chains to match the given depth. */
+// Unwind scope chain and iterator to match the static scope corresponding to
+// the given bytecode position.
 extern void
-UnwindScope(JSContext *cx, ScopeIter &si, uint32_t stackDepth);
+UnwindScope(JSContext *cx, ScopeIter &si, jsbytecode *pc);
 
 /*
  * Unwind for an uncatchable exception. This means not running finalizers, etc;
  * just preserving the basic engine stack invariants.
  */
 extern void
 UnwindForUncatchableException(JSContext *cx, const FrameRegs &regs);
 
--- a/js/src/vm/ScopeObject.h
+++ b/js/src/vm/ScopeObject.h
@@ -624,16 +624,17 @@ class ScopeIter
     /* If !done(): */
 
     ScopeIter &operator++();
 
     AbstractFramePtr frame() const { JS_ASSERT(!done()); return frame_; }
     Type type() const { JS_ASSERT(!done()); return type_; }
     bool hasScopeObject() const { JS_ASSERT(!done()); return hasScopeObject_; }
     ScopeObject &scope() const;
+    NestedScopeObject* staticScope() const { return staticScope_; }
 
     StaticBlockObject &staticBlock() const {
         JS_ASSERT(type() == Block);
         return staticScope_->as<StaticBlockObject>();
     }
 
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
 };