зеркало из https://github.com/mozilla/pjs.git
Bug 513865 - nanojit: make LirReader::read() clearer and faster. r=gal.
--HG-- extra : convert_revision : d78bd673c8652d17489559744f4a221c78811286
This commit is contained in:
Родитель
6423135bfa
Коммит
3002dfbf77
|
@ -392,51 +392,37 @@ namespace nanojit
|
|||
LInsp LirReader::read()
|
||||
{
|
||||
NanoAssert(_i);
|
||||
LInsp cur = _i;
|
||||
uintptr_t i = uintptr_t(cur);
|
||||
LOpcode iop = ((LInsp)i)->opcode();
|
||||
LInsp ret = _i;
|
||||
|
||||
// We pass over skip instructions below. Also, the last instruction
|
||||
// for a fragment shouldn't be a skip(*). Therefore we shouldn't see
|
||||
// a skip here.
|
||||
//
|
||||
// (*) Actually, if the last *inserted* instruction exactly fills up a
|
||||
// page, a new page will be created, and thus the last *written*
|
||||
// instruction will be a skip -- the one needed for the cross-page
|
||||
// link. But the last *inserted* instruction is what is recorded and
|
||||
// used to initialise each LirReader, and that is what is seen here,
|
||||
// and therefore this assertion holds.
|
||||
// Check the invariant: _i never points to a skip.
|
||||
LOpcode iop = _i->opcode();
|
||||
NanoAssert(iop != LIR_skip);
|
||||
|
||||
do
|
||||
{
|
||||
// Nb: this switch is table-driven (because sizeof_LInsXYZ() is
|
||||
// table-driven) in most cases to avoid branch mispredictions --
|
||||
// if we do a vanilla switch on the iop or LInsRepKind the extra
|
||||
// branch mispredictions cause a small but noticeable slowdown.
|
||||
switch (iop)
|
||||
{
|
||||
default:
|
||||
i -= insSizes[((LInsp)i)->opcode()];
|
||||
break;
|
||||
|
||||
case LIR_skip:
|
||||
// Ignore the skip, move onto its predecessor.
|
||||
NanoAssert(((LInsp)i)->prevLIns() != (LInsp)i);
|
||||
i = uintptr_t(((LInsp)i)->prevLIns());
|
||||
break;
|
||||
|
||||
case LIR_start:
|
||||
// Once we hit here, this method shouldn't be called again.
|
||||
// The assertion at the top of this method checks this.
|
||||
_i = 0;
|
||||
return cur;
|
||||
}
|
||||
iop = ((LInsp)i)->opcode();
|
||||
#ifdef DEBUG
|
||||
if (iop == LIR_start) {
|
||||
// Once we hit here, this method shouldn't be called again.
|
||||
// The assertion at the top of this method checks this.
|
||||
// (In the non-debug case, _i ends up pointing to junk just
|
||||
// prior to the LIR_start, but it should be ok because,
|
||||
// again, this method shouldn't be called again.)
|
||||
_i = 0;
|
||||
return ret;
|
||||
}
|
||||
while (LIR_skip == iop);
|
||||
_i = (LInsp)i;
|
||||
return cur;
|
||||
else
|
||||
#endif
|
||||
{
|
||||
// Step back one instruction. Use a table lookup rather than a
|
||||
// switch to avoid branch mispredictions.
|
||||
_i = (LInsp)(uintptr_t(_i) - insSizes[iop]);
|
||||
}
|
||||
|
||||
// Ensure _i doesn't end up pointing to a skip.
|
||||
while (LIR_skip == _i->opcode()) {
|
||||
NanoAssert(_i->prevLIns() != _i);
|
||||
_i = _i->prevLIns();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// This is never called, but that's ok because it contains only static
|
||||
|
|
|
@ -1477,16 +1477,27 @@ namespace nanojit
|
|||
// concrete
|
||||
class LirReader : public LirFilter
|
||||
{
|
||||
LInsp _i; // current instruction that this decoder is operating on.
|
||||
LInsp _i; // next instruction to be read; invariant: is never a skip
|
||||
|
||||
public:
|
||||
LirReader(LInsp i) : LirFilter(0), _i(i) {
|
||||
NanoAssert(_i);
|
||||
LirReader(LInsp i) : LirFilter(0), _i(i)
|
||||
{
|
||||
// The last instruction for a fragment shouldn't be a skip.
|
||||
// (Actually, if the last *inserted* instruction exactly fills up
|
||||
// a chunk, a new chunk will be created, and thus the last *written*
|
||||
// instruction will be a skip -- the one needed for the
|
||||
// cross-chunk link. But the last *inserted* instruction is what
|
||||
// is recorded and used to initialise each LirReader, and that is
|
||||
// what is seen here, and therefore this assertion holds.)
|
||||
NanoAssert(i && !i->isop(LIR_skip));
|
||||
}
|
||||
virtual ~LirReader() {}
|
||||
|
||||
// LirReader i/f
|
||||
LInsp read(); // advance to the prior instruction
|
||||
// Returns next instruction and advances to the prior instruction.
|
||||
// Invariant: never returns a skip.
|
||||
LInsp read();
|
||||
|
||||
// Returns next instruction. Invariant: never returns a skip.
|
||||
LInsp pos() {
|
||||
return _i;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче