Bug 1155618 - Fix some places where OOM errors are not reported to the context r=terrence

This commit is contained in:
Jon Coppeard 2015-05-01 16:26:10 +01:00
parent 270fbaef21
commit 0d79eaae5d
13 changed files with 62 additions and 23 deletions

View File

@ -72,7 +72,10 @@ GCRuntime::checkAllocatorState(JSContext* cx, AllocKind kind)
// For testing out of memory conditions
if (js::oom::ShouldFailWithOOM()) {
ReportOutOfMemory(cx);
// If we are doing a fallible allocation, percolate up the OOM
// instead of reporting it.
if (allowGC)
ReportOutOfMemory(cx);
return false;
}

View File

@ -101,29 +101,38 @@ JSCompartment::~JSCompartment()
}
bool
JSCompartment::init(JSContext* cx)
JSCompartment::init(JSContext* maybecx)
{
/*
* maybecx is null when called to create the atoms compartment from
* JSRuntime::init().
*
* As a hack, we clear our timezone cache every time we create a new
* compartment. This ensures that the cache is always relatively fresh, but
* shouldn't interfere with benchmarks which create tons of date objects
* (unless they also create tons of iframes, which seems unlikely).
*/
if (cx)
cx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
if (maybecx)
maybecx->runtime()->dateTimeInfo.updateTimeZoneAdjustment();
if (!crossCompartmentWrappers.init(0))
if (!crossCompartmentWrappers.init(0)) {
if (maybecx)
ReportOutOfMemory(maybecx);
return false;
}
if (!regExps.init(maybecx))
return false;
if (!regExps.init(cx))
return false;
enumerators = NativeIterator::allocateSentinel(cx);
enumerators = NativeIterator::allocateSentinel(maybecx);
if (!enumerators)
return false;
if (!savedStacks_.init())
if (!savedStacks_.init()) {
if (maybecx)
ReportOutOfMemory(maybecx);
return false;
}
return true;
}

View File

@ -377,7 +377,7 @@ struct JSCompartment
JSCompartment(JS::Zone* zone, const JS::CompartmentOptions& options);
~JSCompartment();
bool init(JSContext* cx);
bool init(JSContext* maybecx);
/* Mark cross-compartment wrappers. */
void markCrossCompartmentWrappers(JSTracer* trc);

View File

@ -6456,8 +6456,10 @@ js::NewCompartment(JSContext* cx, Zone* zone, JSPrincipals* principals,
const JSPrincipals* trusted = rt->trustedPrincipals();
bool isSystem = principals && principals == trusted;
if (!zone->init(isSystem))
if (!zone->init(isSystem)) {
ReportOutOfMemory(cx);
return nullptr;
}
}
ScopedJSDeletePtr<JSCompartment> compartment(cx->new_<JSCompartment>(zone, options));

View File

@ -543,11 +543,14 @@ NativeIterator::allocateIterator(JSContext* cx, uint32_t slength, const AutoIdVe
}
NativeIterator*
NativeIterator::allocateSentinel(JSContext* cx)
NativeIterator::allocateSentinel(JSContext* maybecx)
{
NativeIterator* ni = js_pod_malloc<NativeIterator>();
if (!ni)
if (!ni) {
if (maybecx)
ReportOutOfMemory(maybecx);
return nullptr;
}
PodZero(ni);

View File

@ -102,7 +102,7 @@ struct NativeIterator
prev_ = nullptr;
}
static NativeIterator* allocateSentinel(JSContext* cx);
static NativeIterator* allocateSentinel(JSContext* maybecx);
static NativeIterator* allocateIterator(JSContext* cx, uint32_t slength,
const js::AutoIdVector& props);
void init(JSObject* obj, JSObject* iterObj, unsigned flags, uint32_t slength, uint32_t key);

View File

@ -1592,8 +1592,10 @@ ScriptSource::chars(JSContext* cx, UncompressedSourceCache::AutoHoldEntry& holde
const size_t nbytes = sizeof(char16_t) * (length_ + 1);
char16_t* decompressed = static_cast<char16_t*>(js_malloc(nbytes));
if (!decompressed)
if (!decompressed) {
JS_ReportOutOfMemory(cx);
return nullptr;
}
if (!DecompressString((const unsigned char*) compressedData(), compressedBytes(),
reinterpret_cast<unsigned char*>(decompressed), nbytes)) {

View File

@ -340,8 +340,10 @@ InflateUTF8StringHelper(JSContext* cx, const UTF8Chars src, CountAction countAct
return TwoByteCharsZ();
char16_t* dst = cx->pod_malloc<char16_t>(*outlen + 1); // +1 for NUL
if (!dst)
if (!dst) {
ReportOutOfMemory(cx);
return TwoByteCharsZ();
}
if (isAscii) {
size_t srclen = src.length();

View File

@ -473,6 +473,7 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
if (!table || !table->init()) {
js_delete(table);
table = nullptr;
ReportOutOfMemory(cx);
return nullptr;
}
}
@ -524,8 +525,10 @@ ObjectGroup::defaultNewGroup(ExclusiveContext* cx, const Class* clasp,
if (!group)
return nullptr;
if (!table->add(p, ObjectGroupCompartment::NewEntry(group, associated)))
if (!table->add(p, ObjectGroupCompartment::NewEntry(group, associated))) {
ReportOutOfMemory(cx);
return nullptr;
}
ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, associated);
@ -581,6 +584,7 @@ ObjectGroup::lazySingletonGroup(ExclusiveContext* cx, const Class* clasp, Tagged
if (!table) {
table = cx->new_<ObjectGroupCompartment::NewTable>();
if (!table || !table->init()) {
ReportOutOfMemory(cx);
js_delete(table);
table = nullptr;
return nullptr;
@ -605,8 +609,10 @@ ObjectGroup::lazySingletonGroup(ExclusiveContext* cx, const Class* clasp, Tagged
if (!group)
return nullptr;
if (!table->add(p, ObjectGroupCompartment::NewEntry(group, nullptr)))
if (!table->add(p, ObjectGroupCompartment::NewEntry(group, nullptr))) {
ReportOutOfMemory(cx);
return nullptr;
}
ObjectGroupCompartment::newTablePostBarrier(cx, table, clasp, proto, nullptr);

View File

@ -900,6 +900,9 @@ RegExpCompartment::init(JSContext* cx)
void
RegExpCompartment::sweep(JSRuntime* rt)
{
if (!set_.initialized())
return;
for (Set::Enum e(set_); !e.empty(); e.popFront()) {
RegExpShared* shared = e.front();

View File

@ -60,8 +60,11 @@ NewObjectCache::newObjectFromHit(JSContext* cx, EntryIndex entryIndex, gc::Initi
NativeObject* obj = static_cast<NativeObject*>(Allocate<JSObject, NoGC>(cx, entry->kind, 0,
heap, group->clasp()));
if (!obj)
if (!obj) {
// It's expected that this can return nullptr.
cx->recoverFromOutOfMemory();
return nullptr;
}
copyCachedToObject(obj, templateObj, entry->kind);

View File

@ -1247,8 +1247,10 @@ BaseShape::getUnowned(ExclusiveContext* cx, StackBaseShape& base)
{
BaseShapeSet& table = cx->compartment()->baseShapes;
if (!table.initialized() && !table.init())
if (!table.initialized() && !table.init()) {
ReportOutOfMemory(cx);
return nullptr;
}
DependentAddPtr<BaseShapeSet> p(cx, table, base);
if (p)
@ -1480,8 +1482,10 @@ EmptyShape::getInitialShape(ExclusiveContext* cx, const Class* clasp, TaggedProt
InitialShapeSet& table = cx->compartment()->initialShapes;
if (!table.initialized() && !table.init())
if (!table.initialized() && !table.init()) {
ReportOutOfMemory(cx);
return nullptr;
}
typedef InitialShapeEntry::Lookup Lookup;
DependentAddPtr<InitialShapeSet>

View File

@ -263,8 +263,10 @@ InterpreterStack::allocateFrame(JSContext* cx, size_t size)
}
uint8_t* buffer = reinterpret_cast<uint8_t*>(allocator_.alloc(size));
if (!buffer)
if (!buffer) {
ReportOutOfMemory(cx);
return nullptr;
}
frameCount_++;
return buffer;