[INFER] Move containingSegment to StackSpace, fix uninitialized field, bug 646660.
authorBrian Hackett <bhackett1024@gmail.com>
Wed, 30 Mar 2011 17:24:34 -0700
changeset 75896 ca3aaca8c59083448afb82da0d10cbc41a6e4680
parent 75895 2c9b41f384eaf28a27e2c08c097ca80fc6a12818
child 75897 bc0a254d5c681bab517856f7749ee917ea5807ac
push id67
push userclegnitto@mozilla.com
push dateFri, 04 Nov 2011 22:39:41 +0000
treeherdermozilla-release@04778346a3b0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs646660
milestone2.0b13pre
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
[INFER] Move containingSegment to StackSpace, fix uninitialized field, bug 646660.
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsinterp.cpp
js/src/jsparse.cpp
js/src/methodjit/Retcon.cpp
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -109,39 +109,48 @@ using namespace js;
 using namespace js::gc;
 
 static const size_t ARENA_HEADER_SIZE_HACK = 40;
 static const size_t TEMP_POOL_CHUNK_SIZE = 4096 - ARENA_HEADER_SIZE_HACK;
 
 static void
 FreeContext(JSContext *cx);
 
-#ifdef DEBUG
 JS_REQUIRES_STACK bool
 StackSegment::contains(const JSStackFrame *fp) const
 {
     JS_ASSERT(inContext());
+
+    if (fp < initialFrame)
+        return false;
+
     JSStackFrame *start;
-    JSStackFrame *stop;
     if (isActive()) {
-        JS_ASSERT(cx->hasfp());
+        JS_ASSERT(cx->hasfp() && this == cx->activeSegment());
         start = cx->fp();
-        stop = cx->activeSegment()->initialFrame->prev();
     } else {
         JS_ASSERT(suspendedRegs && suspendedRegs->fp);
         start = suspendedRegs->fp;
-        stop = initialFrame->prev();
     }
-    for (JSStackFrame *f = start; f != stop; f = f->prev()) {
+
+    if (fp > start)
+        return false;
+
+#ifdef DEBUG
+    bool found = false;
+    JSStackFrame *stop = initialFrame->prev();
+    for (JSStackFrame *f = start; !found && f != stop; f = f->prev()) {
         if (f == fp)
-            return true;
+            found = true;
     }
-    return false;
+    JS_ASSERT(found);
+#endif
+
+    return true;
 }
-#endif
 
 JSStackFrame *
 StackSegment::computeNextFrame(JSStackFrame *fp) const
 {
     JS_ASSERT(contains(fp));
     JS_ASSERT(fp != getCurrentFrame());
 
     JSStackFrame *next = getCurrentFrame();
@@ -2050,46 +2059,23 @@ JSContext::generatorFor(JSStackFrame *fp
         if (genStack[i]->liveFrame() == fp)
             return genStack[i];
     }
     JS_NOT_REACHED("no matching generator");
     return NULL;
 }
 
 StackSegment *
-JSContext::containingSegment(const JSStackFrame *target)
+StackSpace::containingSegment(const JSStackFrame *target)
 {
-    /* The context may have nothing running. */
-    StackSegment *seg = currentSegment;
-    if (!seg)
-        return NULL;
-
-    /* The active segments's top frame is cx->regs->fp. */
-    if (regs) {
-        JS_ASSERT(regs->fp);
-        JS_ASSERT(activeSegment() == seg);
-        JSStackFrame *f = regs->fp;
-        JSStackFrame *stop = seg->getInitialFrame()->prev();
-        for (; f != stop; f = f->prev()) {
-            if (f == target)
-                return seg;
-        }
-        seg = seg->getPreviousInContext();
+    for (StackSegment *seg = currentSegment; seg; seg = seg->getPreviousInMemory()) {
+        if (seg->contains(target))
+            return seg;
     }
-
-    /* A suspended segment's top frame is its suspended frame. */
-    for (; seg; seg = seg->getPreviousInContext()) {
-        JSStackFrame *f = seg->getSuspendedFrame();
-        JSStackFrame *stop = seg->getInitialFrame()->prev();
-        for (; f != stop; f = f->prev()) {
-            if (f == target)
-                return seg;
-        }
-    }
-
+    JS_NOT_REACHED("frame not in stack space");
     return NULL;
 }
 
 JS_FRIEND_API(void)
 JSRuntime::onTooMuchMalloc()
 {
 #ifdef JS_THREADSAFE
     AutoLockGC lock(this);
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -411,19 +411,17 @@ class StackSegment
         return initialVarObj != NULL;
     }
 
     JSObject &getInitialVarObj() const {
         JS_ASSERT(inContext() && initialVarObj);
         return *initialVarObj;
     }
 
-#ifdef DEBUG
     JS_REQUIRES_STACK bool contains(const JSStackFrame *fp) const;
-#endif
 
     JSStackFrame *computeNextFrame(JSStackFrame *fp) const;
 };
 
 static const size_t VALUES_PER_STACK_SEGMENT = sizeof(StackSegment) / sizeof(Value);
 JS_STATIC_ASSERT(sizeof(StackSegment) % sizeof(Value) == 0);
 
 /* See StackSpace::pushInvokeArgs. */
@@ -720,16 +718,19 @@ class StackSpace
                         JSScript *script, uint32 *flags, InvokeFrameGuard *fg) const;
 
     void pushInvokeFrame(JSContext *cx, const CallArgs &args, InvokeFrameGuard *fg);
 
     /* These functions are called inside Execute, not Execute clients. */
     bool getExecuteFrame(JSContext *cx, JSScript *script, ExecuteFrameGuard *fg) const;
     void pushExecuteFrame(JSContext *cx, JSObject *initialVarObj, ExecuteFrameGuard *fg);
 
+    /* Get the segment which contains the target frame. */
+    js::StackSegment *containingSegment(const JSStackFrame *target);
+
     /*
      * Since RAII cannot be used for inline frames, callers must manually
      * call pushInlineFrame/popInlineFrame.
      */
     inline JSStackFrame *getInlineFrame(JSContext *cx, Value *sp, uintN nactual,
                                         JSFunction *fun, JSScript *script,
                                         uint32 *flags) const;
     inline void pushInlineFrame(JSContext *cx, JSScript *script, JSStackFrame *fp,
@@ -1761,22 +1762,16 @@ struct JSContext
     void popSegmentAndFrame();
 
     /* Mark the top segment as suspended, without pushing a new one. */
     void saveActiveSegment();
 
     /* Undoes calls to suspendActiveSegment. */
     void restoreSegment();
 
-    /*
-     * Perform a linear search of all frames in all segments in the given context
-     * for the given frame, returning the segment, if found, and null otherwise.
-     */
-    js::StackSegment *containingSegment(const JSStackFrame *target);
-
     /* Search the call stack for the nearest frame with static level targetLevel. */
     JSStackFrame *findFrameAtLevel(uintN targetLevel) const {
         JSStackFrame *fp = regs->fp;
         while (true) {
             JS_ASSERT(fp && fp->isScriptFrame());
             if (fp->script()->staticLevel == targetLevel)
                 break;
             fp = fp->prev();
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -111,17 +111,17 @@ using namespace js::types;
 JSObject *const JSStackFrame::sInvalidScopeChain = (JSObject *)0xbeef;
 #endif
 
 jsbytecode *
 JSStackFrame::pc(JSContext *cx, JSStackFrame *next, JSInlinedSite **pinlined)
 {
     JS_ASSERT_IF(next, next->prev_ == this);
 
-    StackSegment *seg = cx->containingSegment(this);
+    StackSegment *seg = cx->stack().containingSegment(this);
     JSFrameRegs *regs = seg->getCurrentRegs();
     if (regs->fp == this) {
         if (pinlined)
             *pinlined = regs->inlined;
         return regs->pc;
     }
 
     if (!next)
@@ -999,17 +999,17 @@ Execute(JSContext *cx, JSObject *chain, 
          * We want to call |prev->varobj()|, but this requires knowing the
          * CallStackSegment of |prev|. If |prev == cx->fp()|, the callstack is
          * simply the context's active callstack, so we can use
          * |prev->varobj(cx)|.  When |prev != cx->fp()|, we need to do a slow
          * linear search. Luckily, this only happens with EvaluateInFrame.
          */
         initialVarObj = (prev == cx->maybefp())
                         ? &prev->varobj(cx)
-                        : &prev->varobj(cx->containingSegment(prev));
+                        : &prev->varobj(cx->stack().containingSegment(prev));
     } else {
         /* The scope chain could be anything, so innerize just in case. */
         JSObject *innerizedChain = chain;
         OBJ_TO_INNER_OBJECT(cx, innerizedChain);
         if (!innerizedChain)
             return false;
 
         /* If we were handed a non-native object, complain bitterly. */
--- a/js/src/jsparse.cpp
+++ b/js/src/jsparse.cpp
@@ -186,17 +186,17 @@ JSParseNode::clear()
 
 Parser::Parser(JSContext *cx, JSPrincipals *prin, JSStackFrame *cfp)
   : js::AutoGCRooter(cx, PARSER),
     context(cx),
     aleFreeList(NULL),
     tokenStream(cx),
     principals(NULL),
     callerFrame(cfp),
-    callerVarObj(cfp ? &cfp->varobj(cx->containingSegment(cfp)) : NULL),
+    callerVarObj(cfp ? &cfp->varobj(cx->stack().containingSegment(cfp)) : NULL),
     nodeList(NULL),
     functionCount(0),
     traceListHead(NULL),
     tc(NULL),
     keepAtoms(cx->runtime)
 {
     js::PodArrayZero(tempFreeList);
     setPrincipals(prin);
--- a/js/src/methodjit/Retcon.cpp
+++ b/js/src/methodjit/Retcon.cpp
@@ -330,17 +330,17 @@ ExpandInlineFrames(JSContext *cx, bool a
         return;
     }
 
     for (VMFrame *f = cx->compartment->jaegerCompartment->activeFrame();
          f != NULL;
          f = f->previous) {
 
         if (f->regs.inlined) {
-            StackSegment *seg = cx->containingSegment(f->fp());
+            StackSegment *seg = cx->stack().containingSegment(f->fp());
             JSFrameRegs *regs = seg->getCurrentRegs();
             if (regs->fp == f->fp()) {
                 JS_ASSERT(regs == &f->regs);
                 mjit::Recompiler::expandInlineFrames(cx, f->fp(), f->regs.inlined, NULL, f);
             } else {
                 JSStackFrame *nnext = seg->computeNextFrame(f->fp());
                 mjit::Recompiler::expandInlineFrames(cx, f->fp(), f->regs.inlined, nnext, f);
             }
@@ -441,16 +441,17 @@ Recompiler::recompile()
                 next = fp;
                 continue;
             }
 
             // Remember every frame for each type of JIT'd code.
             PatchableFrame frame;
             frame.fp = fp;
             frame.pc = fp->pc(cx, next);
+            frame.scriptedCall = false;
 
             if (next) {
                 // check for a scripted call returning into the recompiled script.
                 // this misses scanning the entry fp, which cannot return directly
                 // into JIT code.
                 void **addr = next->addressOfNativeReturnAddress();
 
                 if (!*addr) {