Add the concept of peer fragments to nanojit. Each loop fragment can have a number of peer fragments, which we can use to have several different specialized variants of a loop (i.e. for different types). The makefile doesn't pick up the change to Fragmento.h, so make sure you clobber by hand or you will end up wasting an hour of your life in gdb (like me.)

This commit is contained in:
Andreas Gal 2008-08-15 20:15:47 -07:00
parent 10a24ff80c
commit 7b954b5cd7
3 changed files with 47 additions and 28 deletions

View File

@ -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;
}

View File

@ -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; i<count; i++)
{
Fragment *f = _frags->at(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;

View File

@ -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;