mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1186982 - propagate OOM failures. r=h4writer
This commit is contained in:
parent
1c8912ad05
commit
1dd2c6a33a
24
js/src/jit-test/tests/ion/bug1186982.js
Normal file
24
js/src/jit-test/tests/ion/bug1186982.js
Normal file
@ -0,0 +1,24 @@
|
||||
if (!(this.resetOOMFailure && this.oomAtAllocation && this.gczeal && this.uneval))
|
||||
quit(0);
|
||||
|
||||
oomTest(((function() {
|
||||
try {
|
||||
gczeal(2)(uneval(this))
|
||||
} catch(e) {}
|
||||
})));
|
||||
function oomTest(f) {
|
||||
var i = 1;
|
||||
// Outer catch in case the inner catch fails due to OOM.
|
||||
try {
|
||||
do {
|
||||
try {
|
||||
oomAtAllocation(i);
|
||||
f();
|
||||
} catch (e) {}
|
||||
more = resetOOMFailure();
|
||||
i++;
|
||||
if (i > 1560)
|
||||
print(i);
|
||||
} while(more);
|
||||
} catch (e) {}
|
||||
}
|
@ -2138,6 +2138,7 @@ Assembler::allocEntry(size_t numInst, unsigned numPoolEntries,
|
||||
bool markAsBranch, bool loadToPC)
|
||||
{
|
||||
BufferOffset offs = m_buffer.allocEntry(numInst, numPoolEntries, inst, data, pe, markAsBranch);
|
||||
propagateOOM(offs.assigned());
|
||||
#ifdef JS_DISASM_ARM
|
||||
spewData(offs, numInst, loadToPC);
|
||||
#endif
|
||||
|
@ -131,8 +131,11 @@ struct Pool : public OldJitAllocPolicy
|
||||
unsigned numEntries_;
|
||||
// The available size of the poolData vector, in PoolAllocUnits.
|
||||
unsigned buffSize;
|
||||
// The content of the pool entries.
|
||||
// The content of the pool entries. Invariant: If poolData_ is nullptr then
|
||||
// buffSize will be zero and oom_ will return true.
|
||||
PoolAllocUnit* poolData_;
|
||||
// Flag that tracks OOM conditions.
|
||||
bool oom_;
|
||||
|
||||
// The limiting instruction and pool-entry pair. The instruction program
|
||||
// counter relative offset of this limiting instruction will go out of range
|
||||
@ -159,16 +162,23 @@ struct Pool : public OldJitAllocPolicy
|
||||
numEntries_(0),
|
||||
buffSize(8),
|
||||
poolData_(lifoAlloc.newArrayUninitialized<PoolAllocUnit>(buffSize)),
|
||||
oom_(false),
|
||||
limitingUser(),
|
||||
limitingUsee(INT_MIN),
|
||||
loadOffsets()
|
||||
{ }
|
||||
{
|
||||
if (poolData_ == nullptr) {
|
||||
buffSize = 0;
|
||||
oom_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
static const unsigned Garbage = 0xa5a5a5a5;
|
||||
Pool()
|
||||
: maxOffset_(Garbage), bias_(Garbage)
|
||||
{ }
|
||||
|
||||
// If poolData() returns nullptr then oom_ will also be true.
|
||||
PoolAllocUnit* poolData() const {
|
||||
return poolData_;
|
||||
}
|
||||
@ -181,6 +191,10 @@ struct Pool : public OldJitAllocPolicy
|
||||
return numEntries_ * sizeof(PoolAllocUnit);
|
||||
}
|
||||
|
||||
bool oom() const {
|
||||
return oom_;
|
||||
}
|
||||
|
||||
// Update the instruction/pool-entry pair that limits the position of the
|
||||
// pool. The nextInst is the actual offset of the new instruction being
|
||||
// allocated.
|
||||
@ -213,17 +227,22 @@ struct Pool : public OldJitAllocPolicy
|
||||
return offset >= maxOffset_;
|
||||
}
|
||||
|
||||
static const unsigned OOM_FAIL = unsigned(-1);
|
||||
|
||||
unsigned insertEntry(unsigned num, uint8_t* data, BufferOffset off, LifoAlloc& lifoAlloc) {
|
||||
if (oom_)
|
||||
return OOM_FAIL;
|
||||
if (numEntries_ + num >= buffSize) {
|
||||
// Grow the poolData_ vector.
|
||||
buffSize *= 2;
|
||||
PoolAllocUnit* tmp = lifoAlloc.newArrayUninitialized<PoolAllocUnit>(buffSize);
|
||||
if (poolData_ == nullptr) {
|
||||
buffSize = 0;
|
||||
return -1;
|
||||
unsigned newSize = buffSize*2;
|
||||
PoolAllocUnit* tmp = lifoAlloc.newArrayUninitialized<PoolAllocUnit>(newSize);
|
||||
if (tmp == nullptr) {
|
||||
oom_ = true;
|
||||
return OOM_FAIL;
|
||||
}
|
||||
mozilla::PodCopy(tmp, poolData_, numEntries_);
|
||||
poolData_ = tmp;
|
||||
buffSize = newSize;
|
||||
}
|
||||
mozilla::PodCopy(&poolData_[numEntries_], (PoolAllocUnit*)data, num);
|
||||
loadOffsets.append(off.getOffset());
|
||||
@ -236,8 +255,11 @@ struct Pool : public OldJitAllocPolicy
|
||||
numEntries_ = 0;
|
||||
buffSize = 8;
|
||||
poolData_ = static_cast<PoolAllocUnit*>(a.alloc(buffSize * sizeof(PoolAllocUnit)));
|
||||
if (poolData_ == nullptr)
|
||||
if (poolData_ == nullptr) {
|
||||
oom_ = true;
|
||||
buffSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
new (&loadOffsets) LoadOffsets;
|
||||
|
||||
@ -530,7 +552,10 @@ struct AssemblerBufferWithConstantPools : public AssemblerBuffer<SliceSize, Inst
|
||||
return this->getTail()->isNextBranch();
|
||||
}
|
||||
|
||||
int insertEntryForwards(unsigned numInst, unsigned numPoolEntries, uint8_t* inst, uint8_t* data) {
|
||||
static const unsigned OOM_FAIL = unsigned(-1);
|
||||
static const unsigned NO_DATA = unsigned(-2);
|
||||
|
||||
unsigned insertEntryForwards(unsigned numInst, unsigned numPoolEntries, uint8_t* inst, uint8_t* data) {
|
||||
size_t nextOffset = sizeExcludingCurrentPool();
|
||||
size_t poolOffset = nextOffset + (numInst + guardSize_ + headerSize_) * InstSize;
|
||||
|
||||
@ -550,16 +575,22 @@ struct AssemblerBufferWithConstantPools : public AssemblerBuffer<SliceSize, Inst
|
||||
|
||||
finishPool();
|
||||
if (this->oom())
|
||||
return uint32_t(-1);
|
||||
return OOM_FAIL;
|
||||
return insertEntryForwards(numInst, numPoolEntries, inst, data);
|
||||
}
|
||||
if (numPoolEntries)
|
||||
return pool_.insertEntry(numPoolEntries, data, this->nextOffset(), this->lifoAlloc_);
|
||||
if (numPoolEntries) {
|
||||
unsigned result = pool_.insertEntry(numPoolEntries, data, this->nextOffset(), this->lifoAlloc_);
|
||||
if (result == Pool::OOM_FAIL) {
|
||||
this->fail_oom();
|
||||
return OOM_FAIL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// The pool entry index is returned above when allocating an entry, but
|
||||
// when not allocating an entry a dummy value is returned - it is not
|
||||
// expected to be used by the caller.
|
||||
return UINT_MAX;
|
||||
return NO_DATA;
|
||||
}
|
||||
|
||||
public:
|
||||
@ -592,11 +623,12 @@ struct AssemblerBufferWithConstantPools : public AssemblerBuffer<SliceSize, Inst
|
||||
|
||||
// Insert the pool value.
|
||||
unsigned index = insertEntryForwards(numInst, numPoolEntries, inst, data);
|
||||
if (this->oom())
|
||||
return BufferOffset();
|
||||
|
||||
// Now to get an instruction to write.
|
||||
PoolEntry retPE;
|
||||
if (numPoolEntries) {
|
||||
if (this->oom())
|
||||
return BufferOffset();
|
||||
JitSpew(JitSpew_Pools, "[%d] Entry has index %u, offset %u", id, index,
|
||||
sizeExcludingCurrentPool());
|
||||
Asm::InsertIndexIntoTag(inst, index);
|
||||
@ -869,6 +901,11 @@ struct AssemblerBufferWithConstantPools : public AssemblerBuffer<SliceSize, Inst
|
||||
dest += numInsts;
|
||||
Pool* curPool = cur->pool;
|
||||
if (curPool != nullptr) {
|
||||
if (curPool->oom()) {
|
||||
this->fail_oom();
|
||||
return;
|
||||
}
|
||||
|
||||
// Have the repatcher move on to the next pool.
|
||||
curIndex++;
|
||||
// Copying the pool into place.
|
||||
|
Loading…
Reference in New Issue
Block a user