Allocate the next page to be used in a lirbuf early to avoid running OOM during a page overflow (471316, r=danderson).

This commit is contained in:
Andreas Gal 2008-12-30 17:03:43 -08:00
Родитель 82688c9a74
Коммит fc407f7516
3 изменённых файлов: 49 добавлений и 21 удалений

Просмотреть файл

@ -112,13 +112,15 @@ namespace nanojit
// free all the memory and clear the stats
_frago->pagesRelease(_pages);
NanoAssert(!_pages.size());
_thresholdPage = 0;
_unused = 0;
_stats.lir = 0;
_noMem = 0;
for (int i = 0; i < NumSavedRegs; ++i)
savedRegs[i] = NULL;
explicitSavedRegs = false;
// pre-allocate the next page we will be using
_nextPage = pageAlloc();
NanoAssert(_nextPage || _noMem);
}
int32_t LirBuffer::insCount()
@ -152,24 +154,16 @@ namespace nanojit
{
LInsp before = _buf->next();
LInsp after = before+count+LIR_FAR_SLOTS;
if (!samepage(before,after+LirBuffer::LIR_BUF_THRESHOLD))
// transition to the next page?
if (!samepage(before,after))
{
if (!_buf->_thresholdPage)
{
// LIR_BUF_THRESHOLD away from a new page but pre-alloc it, setting noMem for early OOM detection
_buf->_thresholdPage = _buf->pageAlloc();
NanoAssert(_buf->_thresholdPage || _buf->_noMem);
}
// transition to the next page?
if (!samepage(before,after))
{
NanoAssert(_buf->_thresholdPage);
_buf->_unused = &_buf->_thresholdPage->lir[0];
_buf->_thresholdPage = 0; // pageAlloc() stored it in _pages already
// link LIR stream back to prior instruction (careful insLink relies on _unused...)
insLinkTo(LIR_skip, before-1);
}
// we don't want this to fail, so we always have a page in reserve
NanoAssert(_buf->_nextPage);
_buf->_unused = &_buf->_nextPage->lir[0];
// link LIR stream back to prior instruction (careful insLink relies on _unused...)
insLinkTo(LIR_skip, before-1);
_buf->_nextPage = _buf->pageAlloc();
NanoAssert(_buf->_nextPage || _buf->_noMem);
}
}

Просмотреть файл

@ -689,8 +689,6 @@ namespace nanojit
class LirBuffer : public avmplus::GCFinalizedObject
{
public:
static const uint32_t LIR_BUF_THRESHOLD = 1024/sizeof(LIns); // 1KB prior to running out of space we'll allocate a new page
DWB(Fragmento*) _frago;
LirBuffer(Fragmento* frago, const CallInfo* functions);
virtual ~LirBuffer();
@ -724,7 +722,7 @@ namespace nanojit
Page* pageAlloc();
PageList _pages;
Page* _thresholdPage; // allocated in preperation of a needing to growing the buffer
Page* _nextPage; // allocated in preperation of a needing to growing the buffer
LInsp _unused; // next unused instruction slot
int _noMem; // set if ran out of memory when writing to buffer
};

Просмотреть файл

@ -3886,6 +3886,42 @@ testDoubleComparison.jitstats = {
};
test(testDoubleComparison);
function testLirBufOOM()
{
var a = [
"12345678901234",
"123456789012",
"1234567890123456789012345678",
"12345678901234567890123456789012345678901234567890123456",
"f",
"$",
"",
"f()",
"(\\*)",
"b()",
"()",
"(#)",
"ABCDEFGHIJK",
"ABCDEFGHIJKLM",
"ABCDEFGHIJKLMNOPQ",
"ABCDEFGH",
"(.)",
"(|)",
"()$",
"/()",
"(.)$"
];
for (var j = 0; j < 200; ++j) {
var js = "" + j;
for (var i = 0; i < a.length; i++)
"".match(a[i] + js)
}
return "ok";
}
testLirBufOOM.expected = "ok";
test(testLirBufOOM);
/*****************************************************************************
* *
* _____ _ _ _____ ______ _____ _______ *