Read back registers used by inner tree relative to inner_sp (the adjusted sp value). Print frames we enter into and return to in Enter/LeaveFrame.
authorAndreas Gal <>
Wed, 13 Aug 2008 15:50:11 -0700
changeset 18138 1f1b2ed3a1692925802d1c958d1b6e246c69084b
parent 18135 7dd001982f576277d739c45206b3f84b9232c074
child 18139 b42fa8f98b1a41db47662cef159594dcd4ad270f
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)
Read back registers used by inner tree relative to inner_sp (the adjusted sp value). Print frames we enter into and return to in Enter/LeaveFrame.
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -640,17 +640,17 @@ TraceRecorder::TraceRecorder(JSContext* 
     lirbuf->sp = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, sp)), "sp");
     lirbuf->rp = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, rp)), "rp");
     cx_ins = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, cx)), "cx");
     gp_ins = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, gp)), "gp");
     eos_ins = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, eos)), "eos");
     eor_ins = addName(lir->insLoadi(lirbuf->state, offsetof(InterpState, eor)), "eor");
     /* read into registers all values on the stack and all globals we know so far */
-    import(ngslots, callDepth, globalTypeMap, stackTypeMap); 
+    import(lirbuf->sp, ngslots, callDepth, globalTypeMap, stackTypeMap); 
 #ifdef DEBUG
     delete verbose_filter;
     delete cse_filter;
@@ -1023,30 +1023,30 @@ TraceRecorder::import(LIns* base, ptrdif
     static const char* typestr[] = {
         "object", "int", "double", "3", "string", "5", "boolean", "any"
     printf("import vp=%p name=%s type=%s flags=%d\n", p, name, typestr[t & 7], t >> 3);
-TraceRecorder::import(unsigned ngslots, unsigned callDepth, 
+TraceRecorder::import(LIns* sp, unsigned ngslots, unsigned callDepth, 
                       uint8* globalTypeMap, uint8* stackTypeMap)
     /* the first time we compile a tree this will be empty as we add entries lazily */
     uint16* gslots = treeInfo->;
     uint8* m = globalTypeMap;
     FORALL_GLOBAL_SLOTS(cx, ngslots, gslots,
         import(gp_ins, nativeGlobalOffset(vp), vp, *m, vpname, vpnum, NULL);
     ptrdiff_t offset = -treeInfo->nativeStackBase;
     m = stackTypeMap;
-        import(lirbuf->sp, offset, vp, *m, vpname, vpnum, fp);
+        import(sp, offset, vp, *m, vpname, vpnum, fp);
         m++; offset += sizeof(double);
 /* Lazily import a global slot if we don't already have it in the tracker. */
 TraceRecorder::lazilyImportGlobalSlot(unsigned slot)
@@ -1324,49 +1324,50 @@ TraceRecorder::closeLoop(Fragmento* frag
 /* Record a call to an inner tree. */
 TraceRecorder::emitTreeCall(Fragment* inner, GuardRecord* lr)
     TreeInfo* ti = (TreeInfo*)inner->vmprivate;
+    LIns* inner_sp = lirbuf->sp;
     /* 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);
+        ptrdiff_t sp_adj = nativeStackOffset(&cx->fp->argv[-1]);
         /* Calculate the amount we have to lift the call stack by */
-        unsigned rp_adj = callDepth * sizeof(FrameInfo);
+        ptrdiff_t rp_adj = callDepth * sizeof(FrameInfo);
         /* 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);
         /* Guard that we have enough call stack space. */
         LIns* rp_top = lir->ins2i(LIR_add, lirbuf->rp, rp_adj + 
                 ti->maxCallDepth * sizeof(FrameInfo));
         guard(true, lir->ins2(LIR_lt, rp_top, eor_ins), OOM_EXIT);
         /* We have enough space, so adjust sp and rp to their new level. */
-        lir->insStorei(lir->ins2i(LIR_add, lirbuf->sp, sp_adj), 
+        lir->insStorei(inner_sp = lir->ins2i(LIR_add, lirbuf->sp, sp_adj), 
                 lirbuf->state, offsetof(InterpState, sp));
         lir->insStorei(lir->ins2i(LIR_add, lirbuf->rp, rp_adj),
                 lirbuf->state, offsetof(InterpState, rp));
     /* Invoke the inner tree. */
     LIns* args[] = { lir->insImmPtr(inner), lirbuf->state }; /* reverse order */
     LIns* ret = lir->insCall(F_CallTree, args);
     /* Make a note that we now depend on that tree. */
     /* Read back all registers, in case the called tree changed any of them. */
     SideExit* exit = lr->exit;
-    import(exit->numGlobalSlots, exit->calldepth, 
+    import(inner_sp, exit->numGlobalSlots, exit->calldepth, 
            exit->typeMap, exit->typeMap + exit->numGlobalSlots);
     /* Restore sp and rp to their original values (we still have them in a register). */
     if (callDepth > 0) {
         lir->insStorei(lirbuf->sp, lirbuf->state, offsetof(InterpState, sp));
         lir->insStorei(lirbuf->rp, lirbuf->state, offsetof(InterpState, rp));
     /* Guard that we come out of the inner tree along the same side exit we came out when
        we called the inner tree at recording time. */
@@ -2635,16 +2636,19 @@ TraceRecorder::clearFrameSlotsFromCache(
         nativeFrameTracker.set(vp, (LIns*)0);
     for (vp = &fp->slots[0], vpstop = &fp->slots[fp->script->nslots]; vp < vpstop; ++vp)
         nativeFrameTracker.set(vp, (LIns*)0);
+#ifdef DEBUG
+    printf("EnterFrame %s\n", js_AtomToPrintableString(cx, cx->fp->fun->atom));
     if (++callDepth >= MAX_CALLDEPTH)
         ABORT_TRACE("exceeded maximum call depth");
     JSStackFrame* fp = cx->fp;
     LIns* void_ins = lir->insImm(JSVAL_TO_BOOLEAN(JSVAL_VOID));
     jsval* vp = &fp->argv[fp->argc];
     jsval* vpstop = vp + (fp->fun->nargs - fp->argc);
     while (vp < vpstop) {
@@ -2658,16 +2662,19 @@ TraceRecorder::record_EnterFrame()
     while (vp < vpstop)
         set(vp++, void_ins, true);
     return true;
+#ifdef DEBUG
+    printf("LeaveFrame (back to %s)\n", js_AtomToPrintableString(cx, cx->fp->fun->atom));
     if (callDepth-- <= 0)
         return false;
     // LeaveFrame gets called after the interpreter popped the frame and
     // stored rval, so cx->fp not cx->fp->down, and -1 not 0.
     atoms = cx->fp->script->atomMap.vector;
     stack(-1, rval_ins);
     return true;
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -220,17 +220,18 @@ class TraceRecorder {
     nanojit::LIns*          rval_ins;
     nanojit::SideExit       exit;
     bool isGlobal(jsval* p) const;
     ptrdiff_t nativeStackOffset(jsval* p) const;
     ptrdiff_t nativeGlobalOffset(jsval* p) const;
     void import(nanojit::LIns* base, ptrdiff_t offset, jsval* p, uint8& t, 
                 const char *prefix, uintN index, JSStackFrame *fp);
-    void import(unsigned ngslots, unsigned callDepth, uint8* globalTypeMap, uint8* stackTypeMap);
+    void import(nanojit::LIns* sp, unsigned ngslots, unsigned callDepth, 
+                uint8* globalTypeMap, uint8* stackTypeMap);
     void trackNativeStackUse(unsigned slots);
     bool lazilyImportGlobalSlot(unsigned slot);
     nanojit::LIns* guard(bool expected, nanojit::LIns* cond, nanojit::ExitType exitType);
     nanojit::LIns* addName(nanojit::LIns* ins, const char* name);
     nanojit::LIns* get(jsval* p);