Bug 496319: correctly unpack FrameInfo::argc, r=mrbkap
authorDavid Mandelin <dmandelin@mozilla.com>
Thu, 04 Jun 2009 15:19:59 -0700
changeset 28949 6a29797e88e75ce0b423561a74f32d824c6af131
parent 28948 fb21a3a1218078d3335f7e7ac34fda68b02c40fa
child 28950 e7c61fb767c7a249e00510f716cdec835c334a5d
push id7346
push userrsayre@mozilla.com
push dateFri, 05 Jun 2009 04:07:23 +0000
treeherderautoland@d2b77efac151 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs496319
milestone1.9.2a1pre
Bug 496319: correctly unpack FrameInfo::argc, r=mrbkap
js/src/jstracer.cpp
js/src/jstracer.h
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -1845,17 +1845,17 @@ FlushNativeGlobalFrame(JSContext* cx, un
     return mp - mp_base;
 }
 
 /*
  * Helper for js_GetUpvarOnTrace.
  */
 static uint32 
 GetUpvarOnTraceTail(InterpState* state, uint32 cookie,
-                    uint32 nativeStackFramePos, uint8* typemap, double* result)
+                    int32 nativeStackFramePos, uint8* typemap, double* result)
 {
     uintN slot = UPVAR_FRAME_SLOT(cookie);
     slot = (slot == CALLEE_UPVAR_SLOT) ? 0 : 2/*callee,this*/ + slot;
     *result = state->stackBase[nativeStackFramePos + slot];
     return typemap[slot];
 }
 
 /*
@@ -1881,20 +1881,20 @@ js_GetUpvarOnTrace(JSContext* cx, uint32
         uintN calleeLevel = fun->u.i.script->staticLevel;
         if (calleeLevel == upvarLevel) {
             /*
              * Now find the upvar's value in the native stack.
              * nativeStackFramePos is the offset of the start of the 
              * activation record corresponding to *fip in the native
              * stack.
              */
-            uintN nativeStackFramePos = state->callstackBase[0]->spoffset;
+            int32 nativeStackFramePos = state->callstackBase[0]->spoffset;
             for (FrameInfo** fip2 = state->callstackBase; fip2 <= fip; fip2++)
                 nativeStackFramePos += (*fip2)->spdist;
-            nativeStackFramePos -= (2 + (*fip)->argc);
+            nativeStackFramePos -= (2 + (*fip)->get_argc());
             uint8* typemap = (uint8*) (fi+1);
             return GetUpvarOnTraceTail(state, cookie, nativeStackFramePos,
                                        typemap, result);
         }
     }
 
     if (state->outermostTree->script->staticLevel == upvarLevel) {
         return GetUpvarOnTraceTail(state, cookie, 0, 
@@ -3532,17 +3532,17 @@ js_SynthesizeFrame(JSContext* cx, const 
 
     uintN nframeslots = JS_HOWMANY(sizeof(JSInlineFrame), sizeof(jsval));
     JSScript* script = fun->u.i.script;
     size_t nbytes = (nframeslots + script->nslots) * sizeof(jsval);
 
     /* Code duplicated from inline_call: case in js_Interpret (FIXME). */
     JSArena* a = cx->stackPool.current;
     void* newmark = (void*) a->avail;
-    uintN argc = fi.argc & 0x7fff;
+    uintN argc = fi.get_argc();
     jsval* vp = fp->slots + fi.spdist - (2 + argc);
     uintN missing = 0;
     jsval* newsp;
 
     if (fun->nargs > argc) {
         const JSFrameRegs& regs = *fp->regs;
 
         newsp = vp + 2 + fun->nargs;
@@ -3591,17 +3591,17 @@ js_SynthesizeFrame(JSContext* cx, const 
 
     newifp->frame.callobj = NULL;
     newifp->frame.argsobj = NULL;
     newifp->frame.varobj = NULL;
     newifp->frame.script = script;
     newifp->frame.callee = fi.callee; // Roll with a potentially stale callee for now.
     newifp->frame.fun = fun;
 
-    bool constructing = (fi.argc & 0x8000) != 0;
+    bool constructing = fi.is_constructing();
     newifp->frame.argc = argc;
     newifp->callerRegs.pc = fi.pc;
     newifp->callerRegs.sp = fp->slots + fi.spdist;
     fp->imacpc = fi.imacpc;
 
 #ifdef DEBUG
     if (fi.block != fp->blockChain) {
         for (JSObject* obj = fi.block; obj != fp->blockChain; obj = STOBJ_GET_PARENT(obj))
@@ -8584,17 +8584,17 @@ TraceRecorder::interpretedFunctionCall(j
     if (argc >= 0x8000)
         ABORT_TRACE("too many arguments");
 
     fi->callee = JSVAL_TO_OBJECT(fval);
     fi->block = fp->blockChain;
     fi->pc = fp->regs->pc;
     fi->imacpc = fp->imacpc;
     fi->spdist = fp->regs->sp - fp->slots;
-    fi->argc = argc | (constructing ? 0x8000 : 0);
+    fi->set_argc(argc, constructing);
     fi->spoffset = 2 /*callee,this*/ + fp->argc;
 
     unsigned callDepth = getCallDepth();
     if (callDepth >= treeInfo->maxCallDepth)
         treeInfo->maxCallDepth = callDepth + 1;
     if (callDepth == 0)
         fi->spoffset = 2 /*callee,this*/ + argc - fi->spdist;
 
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -300,28 +300,41 @@ static inline uint8* getFullTypeMap(nano
 }
 
 struct FrameInfo {
     JSObject*       callee;     // callee function object
     JSObject*       block;      // caller block chain head
     jsbytecode*     pc;         // caller fp->regs->pc
     jsbytecode*     imacpc;     // caller fp->imacpc
     uint16          spdist;     // distance from fp->slots to fp->regs->sp at JSOP_CALL
-    uint16          argc;       // actual argument count, may be < fun->nargs
+
+    /*
+     * Bit  15 (0x8000) is a flag that is set if constructing (called through new).
+     * Bits 0-14 are the actual argument count. This may be less than fun->nargs.
+     */
+    uint16          argc;
 
     /*
      * Stack pointer adjustment needed for navigation of native stack in
      * js_GetUpvarOnTrace. spoffset is the number of slots in the native
      * stack frame for the caller *before* the slots covered by spdist.
      * This may be negative if the caller is the top level script.
      * The key fact is that if we let 'cpos' be the start of the caller's
      * native stack frame, then (cpos + spoffset) points to the first 
      * non-argument slot in the callee's native stack frame.
      */
     int32          spoffset;
+
+    // Safer accessors for argc.
+    enum { CONSTRUCTING_MASK = 0x8000 };
+    void   set_argc(uint16 argc, bool constructing) {
+        this->argc = argc | (constructing ? CONSTRUCTING_MASK : 0);
+    }
+    uint16 get_argc() const { return argc & ~CONSTRUCTING_MASK; }
+    bool   is_constructing() const { return (argc & CONSTRUCTING_MASK) != 0; }
 };
 
 struct UnstableExit
 {
     nanojit::Fragment* fragment;
     VMSideExit* exit;
     UnstableExit* next;
 };