Bug 989503 - Recover cleanly after OOM while adding type object properties, r=jandem.

This commit is contained in:
Brian Hackett 2014-04-03 08:27:51 -07:00
parent 5043e365c5
commit 6a6f9ba4bd
3 changed files with 58 additions and 70 deletions

View File

@ -2730,62 +2730,54 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, JSObject *obj, Shap
}
}
bool
TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop)
void
TypeObject::updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *types)
{
JS_ASSERT(!*pprop);
Property *base = cx->typeLifoAlloc().new_<Property>(id);
if (!base)
return false;
if (singleton() && singleton()->isNative()) {
/*
* Fill the property in with any type the object already has in an own
* property. We are only interested in plain native properties and
* dense elements which don't go through a barrier when read by the VM
* or jitcode.
*/
if (JSID_IS_VOID(id)) {
/* Go through all shapes on the object to get integer-valued properties. */
RootedShape shape(cx, singleton()->lastProperty());
while (!shape->isEmptyShape()) {
if (JSID_IS_VOID(IdToTypeId(shape->propid())))
UpdatePropertyType(cx, &base->types, singleton(), shape, true);
shape = shape->previous();
}
/* Also get values of any dense elements in the object. */
for (size_t i = 0; i < singleton()->getDenseInitializedLength(); i++) {
const Value &value = singleton()->getDenseElement(i);
if (!value.isMagic(JS_ELEMENTS_HOLE)) {
Type type = GetValueType(value);
base->types.TypeSet::addType(type, &cx->typeLifoAlloc());
}
}
} else if (!JSID_IS_EMPTY(id)) {
RootedId rootedId(cx, id);
Shape *shape = singleton()->nativeLookup(cx, rootedId);
if (shape)
UpdatePropertyType(cx, &base->types, singleton(), shape, false);
}
if (singleton()->watched()) {
/*
* Mark the property as non-data, to inhibit optimizations on it
* and avoid bypassing the watchpoint handler.
*/
base->types.setNonDataProperty(cx);
}
}
*pprop = base;
InferSpew(ISpewOps, "typeSet: %sT%p%s property %s %s",
InferSpewColor(&base->types), &base->types, InferSpewColorReset(),
InferSpewColor(types), types, InferSpewColorReset(),
TypeObjectString(this), TypeIdString(id));
return true;
if (!singleton() || !singleton()->isNative())
return;
/*
* Fill the property in with any type the object already has in an own
* property. We are only interested in plain native properties and
* dense elements which don't go through a barrier when read by the VM
* or jitcode.
*/
if (JSID_IS_VOID(id)) {
/* Go through all shapes on the object to get integer-valued properties. */
RootedShape shape(cx, singleton()->lastProperty());
while (!shape->isEmptyShape()) {
if (JSID_IS_VOID(IdToTypeId(shape->propid())))
UpdatePropertyType(cx, types, singleton(), shape, true);
shape = shape->previous();
}
/* Also get values of any dense elements in the object. */
for (size_t i = 0; i < singleton()->getDenseInitializedLength(); i++) {
const Value &value = singleton()->getDenseElement(i);
if (!value.isMagic(JS_ELEMENTS_HOLE)) {
Type type = GetValueType(value);
types->TypeSet::addType(type, &cx->typeLifoAlloc());
}
}
} else if (!JSID_IS_EMPTY(id)) {
RootedId rootedId(cx, id);
Shape *shape = singleton()->nativeLookup(cx, rootedId);
if (shape)
UpdatePropertyType(cx, types, singleton(), shape, false);
}
if (singleton()->watched()) {
/*
* Mark the property as non-data, to inhibit optimizations on it
* and avoid bypassing the watchpoint handler.
*/
types->setNonDataProperty(cx);
}
}
bool

View File

@ -1108,7 +1108,7 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
/* Helpers */
bool addProperty(ExclusiveContext *cx, jsid id, Property **pprop);
void updateNewPropertyTypes(ExclusiveContext *cx, jsid id, HeapTypeSet *types);
bool addDefiniteProperties(ExclusiveContext *cx, JSObject *obj);
bool matchDefiniteProperties(HandleObject obj);
void addPrototype(JSContext *cx, TypeObject *proto);

View File

@ -1238,6 +1238,12 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id)
if (HeapTypeSet *types = maybeGetProperty(id))
return types;
Property *base = cx->typeLifoAlloc().new_<Property>(id);
if (!base) {
markUnknown(cx);
return nullptr;
}
uint32_t propertyCount = basePropertyCount();
Property **pprop = HashSetInsert<jsid,Property,Property>
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
@ -1249,28 +1255,18 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id)
JS_ASSERT(!*pprop);
setBasePropertyCount(propertyCount);
if (!addProperty(cx, id, pprop)) {
markUnknown(cx);
return nullptr;
}
*pprop = base;
updateNewPropertyTypes(cx, id, &base->types);
if (propertyCount == OBJECT_FLAG_PROPERTY_COUNT_LIMIT) {
// We hit the maximum number of properties the object can have, mark
// the object unknown so that new properties will not be added in the
// future.
markUnknown(cx);
/*
* Return an arbitrary property in the object, as all have unknown
* type and are treated as non-data properties.
*/
unsigned count = getPropertyCount();
for (unsigned i = 0; i < count; i++) {
if (Property *prop = getProperty(i))
return &prop->types;
}
MOZ_ASSUME_UNREACHABLE("Missing property");
}
return &(*pprop)->types;
return &base->types;
}
inline HeapTypeSet *