diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 785323784c1..e0c3f551717 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -1729,7 +1729,7 @@ js_ContinueRecording(JSContext* cx, TraceRecorder* r, jsbytecode* oldpc, uintN& } /* does this branch go to an inner loop? */ Fragment* f = fragmento->getLoop(cx->fp->regs->pc); - if (nesting_enabled && f->code() && !((TreeInfo*)f->vmprivate)->globalSlots.length()) { + if (nesting_enabled && f && f->code() && !((TreeInfo*)f->vmprivate)->globalSlots.length()) { JS_ASSERT(f->vmprivate); /* call the inner tree */ GuardRecord* lr = js_ExecuteTree(cx, f, inlineCallCount); @@ -1945,6 +1945,8 @@ js_LoopEdge(JSContext* cx, jsbytecode* oldpc, uintN& inlineCallCount) f = cacheEntry->fragment; } else { f = tm->fragmento->getLoop(pc); + if (!f) + f = tm->fragmento->newLoop(pc); cacheEntry->pc = pc; cacheEntry->fragment = f; } diff --git a/js/src/nanojit/Fragmento.cpp b/js/src/nanojit/Fragmento.cpp index 4a0ee522a77..58bd58f5ddc 100644 --- a/js/src/nanojit/Fragmento.cpp +++ b/js/src/nanojit/Fragmento.cpp @@ -173,7 +173,14 @@ namespace nanojit while (!_frags->isEmpty()) { Fragment *f = _frags->removeLast(); - f->releaseTreeMem(this); + Fragment *peer = f->peer; + while (peer) { + Fragment *next = peer->peer; + peer->releaseTreeMem(this); + delete peer; + peer = next; + } + f->releaseTreeMem(this); delete f; } @@ -194,19 +201,22 @@ namespace nanojit return _core; } + Fragment* Fragmento::newLoop(const void* ip) + { + Fragment *f = newFrag(ip); + f->peer = _frags->get(ip); + _frags->put(ip, f); + f->anchor = f; + f->root = f; + f->kind = LoopTrace; + f->mergeCounts = new (_core->gc) BlockHist(_core->gc); + verbose_only( addLabel(f, "T", _frags->size()); ) + return f; + } + Fragment* Fragmento::getLoop(const void* ip) { - Fragment* f = _frags->get(ip); - if (!f) { - f = newFrag(ip); - _frags->put(ip, f); - f->anchor = f; - f->root = f; - f->kind = LoopTrace; - f->mergeCounts = new (_core->gc) BlockHist(_core->gc); - verbose_only( addLabel(f, "T", _frags->size()); ) - } - return f; + return _frags->get(ip); } #ifdef NJ_VERBOSE @@ -385,22 +395,27 @@ namespace nanojit for (int32_t i=0; iat(i); - fragstats stat = { 0,0,0,0,0 }; - dumpFragStats(f, 0, stat); - if (stat.lir) { - totalstat.lir += stat.lir; - totalstat.lirbytes += stat.lirbytes; + while (true) { + fragstats stat = { 0,0,0,0,0 }; + dumpFragStats(f, 0, stat); + if (stat.lir) { + totalstat.lir += stat.lir; + totalstat.lirbytes += stat.lirbytes; + } + uint64_t bothDur = stat.traceDur + stat.interpDur; + if (bothDur) { + totalstat.interpDur += stat.interpDur; + totalstat.traceDur += stat.traceDur; + totalstat.size += stat.size; + totaldur += bothDur; + while (durs.containsKey(bothDur)) bothDur++; + DurData d(f, stat.traceDur, stat.interpDur, stat.size); + durs.put(bothDur, d); + } + if (!f->peer) + break; + f = f->peer; } - uint64_t bothDur = stat.traceDur + stat.interpDur; - if (bothDur) { - totalstat.interpDur += stat.interpDur; - totalstat.traceDur += stat.traceDur; - totalstat.size += stat.size; - totaldur += bothDur; - while (durs.containsKey(bothDur)) bothDur++; - DurData d(f, stat.traceDur, stat.interpDur, stat.size); - durs.put(bothDur, d); - } } uint64_t totaltrace = totalstat.traceDur; int totalsize = totalstat.size; diff --git a/js/src/nanojit/Fragmento.h b/js/src/nanojit/Fragmento.h index 839aa9b77a4..0640614e1c8 100644 --- a/js/src/nanojit/Fragmento.h +++ b/js/src/nanojit/Fragmento.h @@ -94,6 +94,7 @@ namespace nanojit Page* pageAlloc(); void pageFree(Page* page); + Fragment* newLoop(const void* ip); Fragment* getLoop(const void* ip); void clearFrags(); // clear all fragments from the cache Fragment* getMerge(GuardRecord *lr, const void* ip); @@ -204,6 +205,7 @@ namespace nanojit DWB(Fragment*) anchor; DWB(Fragment*) root; DWB(Fragment*) parent; + DWB(Fragment*) peer; DWB(BlockHist*) mergeCounts; DWB(LirBuffer*) lirbuf; LIns* lastIns;