Fixed from brendan for counting disparity between nativeStackSlots and FORALL_SLOTS_IN_PENDING_FRAMES.
authorDavid Anderson <danderson@mozilla.com>
Wed, 13 Aug 2008 17:09:16 -0700
changeset 18144 8f3c8fb8c7162c8eac0c088c8be1e49cd894e2db
parent 18132 bc8a7ed3e87a6367f38f2f56a06375ce086bd1be
child 18145 3794c4f36b2737c631631b75beb5647a7fbc6420
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.1a2pre
Fixed from brendan for counting disparity between nativeStackSlots and FORALL_SLOTS_IN_PENDING_FRAMES. Added debug code to catch future disparities.
js/src/jstracer.cpp
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -246,40 +246,16 @@ Oracle::markStackSlotUndemotable(JSScrip
 bool 
 Oracle::isStackSlotUndemotable(JSScript* script, jsbytecode* ip, unsigned slot) const
 {
     uint32 hash = uint32(ip) + (slot << 5);
     hash %= ORACLE_SIZE;
     return _dontDemote.get(hash);
 }
 
-/* Calculate the total number of native frame slots we need from this frame
-   all the way back to the entry frame, including the current stack usage. */
-static unsigned
-nativeStackSlots(unsigned callDepth, JSStackFrame* fp)
-{
-    unsigned slots = 0;
-    for (;;) {
-        unsigned operands = fp->regs->sp - StackBase(fp);
-        JS_ASSERT(operands <= fp->script->nslots - fp->script->nfixed);
-        slots += operands;
-        if (fp->callee)
-            slots += fp->script->nfixed;
-        if (callDepth-- == 0) {
-            if (fp->callee) {
-                unsigned nargs = JS_MAX(fp->fun->nargs, fp->argc);
-                slots += 1/*this*/ + nargs;
-            }
-            return slots;
-        }
-        fp = fp->down;
-    }
-    JS_NOT_REACHED("nativeStackSlots");
-}
-
 static LIns* demote(LirWriter *out, LInsp i)
 {
     if (i->isCall())
         return callArgN(i,0);
     if (i->isop(LIR_i2f) || i->isop(LIR_u2f))
         return i->oprnd1();
     if (i->isconst())
         return i;
@@ -555,16 +531,52 @@ public:
     JS_END_MACRO
 
 #define FORALL_SLOTS(cx, ngslots, gslots, callDepth, code)                    \
     JS_BEGIN_MACRO                                                            \
         FORALL_GLOBAL_SLOTS(cx, ngslots, gslots, code);                       \
         FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth, code);                  \
     JS_END_MACRO
 
+/* Calculate the total number of native frame slots we need from this frame
+   all the way back to the entry frame, including the current stack usage. */
+static unsigned
+nativeStackSlots(JSContext *cx, unsigned callDepth, JSStackFrame* fp)
+{
+    unsigned slots = 0;
+#if defined _DEBUG
+    unsigned int origCallDepth = callDepth;
+#endif
+    for (;;) {
+        unsigned operands = fp->regs->sp - StackBase(fp);
+        JS_ASSERT(operands <= fp->script->nslots - fp->script->nfixed);
+        slots += operands;
+        if (fp->callee)
+            slots += fp->script->nfixed;
+        if (callDepth-- == 0) {
+            if (fp->callee) {
+                unsigned nargs = JS_MAX(fp->fun->nargs, fp->argc);
+                slots += 1/*this*/ + nargs;
+            }
+#if defined _DEBUG
+            unsigned int m = 0;
+            FORALL_SLOTS_IN_PENDING_FRAMES(cx, origCallDepth, m++);
+            JS_ASSERT(m == slots);
+#endif
+            return slots;
+        }
+        JSStackFrame* fp2 = fp;
+        fp = fp->down;
+        int missing = fp2->fun->nargs - fp2->argc;
+        if (missing > 0)
+            slots += missing;
+    }
+    JS_NOT_REACHED("nativeStackSlots");
+}
+
 /* Capture the typemap for the selected slots of the global object. */
 void
 TypeMap::captureGlobalTypes(JSContext* cx, SlotList& slots)
 {
     unsigned ngslots = slots.length();
     uint16* gslots = slots.data();
     setLength(ngslots);
     uint8* map = data();
@@ -576,17 +588,17 @@ TypeMap::captureGlobalTypes(JSContext* c
         *m++ = type;
     );
 }
 
 /* Capture the typemap for the currently pending stack frames. */
 void 
 TypeMap::captureStackTypes(JSContext* cx, unsigned callDepth)
 {
-    setLength(nativeStackSlots(callDepth, cx->fp));
+    setLength(nativeStackSlots(cx, callDepth, cx->fp));
     uint8* map = data();
     uint8* m = map;
     FORALL_SLOTS_IN_PENDING_FRAMES(cx, callDepth,
         uint8 type = getCoercedType(*vp);
         if ((type == JSVAL_INT) && oracle.isStackSlotUndemotable(cx->fp->script,
                 cx->fp->regs->pc, unsigned(m - map)))
             type = JSVAL_DOUBLE;
         *m++ = type;
@@ -1147,17 +1159,17 @@ struct FrameInfo {
 
 SideExit*
 TraceRecorder::snapshot(ExitType exitType)
 {
     JSStackFrame* fp = cx->fp;
     if (exitType == BRANCH_EXIT && js_IsLoopExit(cx, fp->script, fp->regs->pc))
         exitType = LOOP_EXIT;
     /* generate the entry map and stash it in the trace */
-    unsigned stackSlots = nativeStackSlots(callDepth, fp);
+    unsigned stackSlots = nativeStackSlots(cx, callDepth, fp);
     /* its sufficient to track the native stack use here since all stores above the
        stack watermark defined by guards are killed. */
     trackNativeStackUse(stackSlots + 1);
     /* reserve space for the type map */
     unsigned ngslots = treeInfo->globalSlots.length();
     LIns* data = lir_buf_writer->skip((stackSlots + ngslots) * sizeof(uint8));
     /* setup side exit structure */
     memset(&exit, 0, sizeof(exit));
@@ -1327,17 +1339,17 @@ TraceRecorder::emitTreeCall(Fragment* in
     TreeInfo* ti = (TreeInfo*)inner->vmprivate;
     /* The inner tree expects to be called from the current scope. If the outer tree (this
        trace is currently inside a function inlining code (calldepth > 0), we have to advance
        the native stack pointer such that we match what the inner trace expects to see. We
        move it back when we come out of the inner tree call. */
     if (callDepth > 0) {
         /* Calculate the amount we have to lift the native stack pointer by to compensate for
            any outer frames that the inner tree doesn't expect but the outer tree has. */
-        unsigned sp_adj = nativeStackSlots(callDepth - 1, cx->fp->down) * sizeof(double);
+        unsigned sp_adj = nativeStackSlots(cx, callDepth - 1, cx->fp->down) * sizeof(double);
         /* Guard that we have enough stack space for the tree we are trying to call on top
            of the new value for sp. */
         LIns* sp_top = lir->ins2i(LIR_add, lirbuf->sp, sp_adj + 
                 ti->maxNativeStackSlots * sizeof(double));
         guard(true, lir->ins2(LIR_lt, sp_top, eos_ins), OOM_EXIT);
         /* We have enough space, so adjust sp to its new level. */
         lir->insStorei(lir->ins2i(LIR_add, lirbuf->sp, sp_adj), 
                 lirbuf->state, offsetof(InterpState, sp));
@@ -1564,17 +1576,17 @@ js_RecordTree(JSContext* cx, JSTraceMoni
     /* we shouldn't have any interned globals for a new tree */
     JS_ASSERT(!ti->globalSlots.length());
     
     /* capture the coerced type of each active slot in the stack type map */
     ti->stackTypeMap.captureStackTypes(cx, 0/*callDepth*/);
     
     /* determine the native frame layout at the entry point */
     unsigned entryNativeStackSlots = ti->stackTypeMap.length();
-    JS_ASSERT(entryNativeStackSlots == nativeStackSlots(0/*callDepth*/, cx->fp));
+    JS_ASSERT(entryNativeStackSlots == nativeStackSlots(cx, 0/*callDepth*/, cx->fp));
     ti->entryNativeStackSlots = entryNativeStackSlots;
     ti->nativeStackBase = (entryNativeStackSlots -
             (cx->fp->regs->sp - StackBase(cx->fp))) * sizeof(double);
     ti->maxNativeStackSlots = entryNativeStackSlots;
     ti->maxCallDepth = 0;
 
     /* create the list of global properties we want to intern */
     ti->globalShape = OBJ_SCOPE(JS_GetGlobalForObject(cx, cx->fp->scopeChain))->shape;
@@ -1739,19 +1751,19 @@ js_ExecuteTree(JSContext* cx, Fragment* 
     cx->gcDontBlock = JS_FALSE;
 
     for (int32 i = 0; i < lr->calldepth; i++)
         js_SynthesizeFrame(cx, callstack[i]);
 
     SideExit* e = lr->exit;
     JSStackFrame* fp = cx->fp;
     JS_ASSERT((e->sp_adj / sizeof(double)) + ti->entryNativeStackSlots >=
-              nativeStackSlots(lr->calldepth, fp));
+              nativeStackSlots(cx, lr->calldepth, fp));
     fp->regs->sp += (e->sp_adj / sizeof(double)) + ti->entryNativeStackSlots -
-                    nativeStackSlots(lr->calldepth, fp);
+                    nativeStackSlots(cx, lr->calldepth, fp);
     fp->regs->pc = (jsbytecode*)lr->from->root->ip + e->ip_adj;
 
 #if defined(DEBUG) && defined(NANOJIT_IA32)
     printf("leaving trace at %s:%u@%u, exitType=%d, sp=%p, ip=%p, cycles=%llu\n",
            fp->script->filename, js_PCToLineNumber(cx, fp->script, fp->regs->pc),
            fp->regs->pc - fp->script->code,
            lr->exit->exitType,
            state.sp, lr->jmp,