Bug 1133254 - Dehandlify shape-updating object methods, allow setting multiple flags on an object at once, r=terrence.

This commit is contained in:
Brian Hackett 2015-02-18 08:08:36 -07:00
parent aa56f5a6fc
commit 02bb5aa67c
11 changed files with 102 additions and 118 deletions

View File

@ -1347,10 +1347,10 @@ JSFunction::initBoundFunction(JSContext *cx, HandleObject target, HandleValue th
if (!self->toDictionaryMode(cx))
return false;
if (!self->setFlag(cx, BaseShape::BOUND_FUNCTION))
if (!self->JSObject::setFlags(cx, BaseShape::BOUND_FUNCTION))
return false;
if (!NativeObject::setSlotSpan(cx, self, BOUND_FUNCTION_RESERVED_SLOTS + argslen))
if (!self->setSlotSpan(cx, BOUND_FUNCTION_RESERVED_SLOTS + argslen))
return false;
self->setSlot(JSSLOT_BOUND_FUNCTION_TARGET, ObjectValue(*target));

View File

@ -1038,7 +1038,7 @@ js::SetIntegrityLevel(JSContext *cx, HandleObject obj, IntegrityLevel level)
}
MOZ_ASSERT(nobj->lastProperty()->slotSpan() == last->slotSpan());
JS_ALWAYS_TRUE(NativeObject::setLastProperty(cx, nobj, last));
JS_ALWAYS_TRUE(nobj->setLastProperty(cx, last));
} else {
RootedId id(cx);
Rooted<PropertyDescriptor> desc(cx);
@ -1845,7 +1845,7 @@ js::DeepCloneObjectLiteral(JSContext *cx, HandleNativeObject obj, NewObjectKind
MOZ_ASSERT(!obj->hasPrivate());
RootedShape shape(cx, obj->lastProperty());
size_t span = shape->slotSpan();
clone->setLastProperty(cx, clone, shape);
clone->setLastProperty(cx, shape);
for (size_t i = 0; i < span; i++) {
v = obj->getSlot(i);
if (v.isObject()) {
@ -2137,7 +2137,7 @@ js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
RootedShape newShape(cx, ReshapeForParentAndAllocKind(cx, srcObj->lastProperty(),
TaggedProto(proto), parent, kind));
if (!newShape || !NativeObject::setLastProperty(cx, res, newShape))
if (!newShape || !res->setLastProperty(cx, newShape))
return nullptr;
return res;
@ -3139,7 +3139,7 @@ js::PreventExtensions(JSContext *cx, HandleObject obj, bool *succeeded)
return false;
*succeeded = true;
return obj->setFlag(cx, BaseShape::NOT_EXTENSIBLE, JSObject::GENERATE_SHAPE);
return obj->setFlags(cx, BaseShape::NOT_EXTENSIBLE, JSObject::GENERATE_SHAPE);
}
bool
@ -3234,7 +3234,7 @@ js::SetImmutablePrototype(ExclusiveContext *cx, HandleObject obj, bool *succeede
return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded);
}
if (!obj->setFlag(cx, BaseShape::IMMUTABLE_PROTOTYPE))
if (!obj->setFlags(cx, BaseShape::IMMUTABLE_PROTOTYPE))
return false;
*succeeded = true;
return true;

View File

@ -189,16 +189,14 @@ class JSObject : public js::gc::Cell
inline void setInitialSlotsMaybeNonNative(js::HeapSlot *slots);
inline void setInitialElementsMaybeNonNative(js::HeapSlot *elements);
protected:
enum GenerateShape {
GENERATE_NONE,
GENERATE_SHAPE
};
bool setFlag(js::ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag,
GenerateShape generateShape = GENERATE_NONE);
bool setFlags(js::ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flags,
GenerateShape generateShape = GENERATE_NONE);
public:
/*
* An object is a delegate if it is on another object's prototype or scope
* chain, and therefore the delegate might be asked implicitly to get or
@ -213,7 +211,7 @@ class JSObject : public js::gc::Cell
}
bool setDelegate(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
return setFlags(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
}
bool isBoundFunction() const {
@ -226,18 +224,18 @@ class JSObject : public js::gc::Cell
return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
}
bool setWatched(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
return setFlags(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
}
/* See InterpreterFrame::varObj. */
inline bool isQualifiedVarObj();
bool setQualifiedVarObj(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::QUALIFIED_VAROBJ);
return setFlags(cx, js::BaseShape::QUALIFIED_VAROBJ);
}
inline bool isUnqualifiedVarObj();
bool setUnqualifiedVarObj(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::UNQUALIFIED_VAROBJ);
return setFlags(cx, js::BaseShape::UNQUALIFIED_VAROBJ);
}
/*
@ -250,7 +248,7 @@ class JSObject : public js::gc::Cell
return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
}
bool setUncacheableProto(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
return setFlags(cx, js::BaseShape::UNCACHEABLE_PROTO, GENERATE_SHAPE);
}
/*
@ -261,7 +259,7 @@ class JSObject : public js::gc::Cell
return lastProperty()->hasObjectFlag(js::BaseShape::HAD_ELEMENTS_ACCESS);
}
bool setHadElementsAccess(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::HAD_ELEMENTS_ACCESS);
return setFlags(cx, js::BaseShape::HAD_ELEMENTS_ACCESS);
}
/*
@ -397,7 +395,7 @@ class JSObject : public js::gc::Cell
return lastProperty()->hasObjectFlag(js::BaseShape::ITERATED_SINGLETON);
}
bool setIteratedSingleton(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::ITERATED_SINGLETON);
return setFlags(cx, js::BaseShape::ITERATED_SINGLETON);
}
/*
@ -414,7 +412,7 @@ class JSObject : public js::gc::Cell
return lastProperty()->hasObjectFlag(js::BaseShape::NEW_SCRIPT_CLEARED);
}
bool setNewScriptCleared(js::ExclusiveContext *cx) {
return setFlag(cx, js::BaseShape::NEW_SCRIPT_CLEARED);
return setFlags(cx, js::BaseShape::NEW_SCRIPT_CLEARED);
}
/* Set a new prototype for an object with a singleton type. */

View File

@ -614,11 +614,11 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
StackShape child(base, id, slot, 0, 0);
RootedShape shape(cx, cx->compartment()->propertyTree.getChild(cx, last, child));
Shape *shape = cx->compartment()->propertyTree.getChild(cx, last, child);
if (!shape)
return false;
if (!NativeObject::setLastProperty(cx, holder, shape))
if (!holder->setLastProperty(cx, shape))
return false;
holder->setSlot(shape->slot(), value);

View File

@ -39,9 +39,7 @@ inline void
NativeObject::removeLastProperty(ExclusiveContext *cx)
{
MOZ_ASSERT(canRemoveLastProperty());
RootedNativeObject self(cx, this);
RootedShape prev(cx, lastProperty()->previous());
JS_ALWAYS_TRUE(setLastProperty(cx, self, prev));
JS_ALWAYS_TRUE(setLastProperty(cx, lastProperty()->previous()));
}
inline bool
@ -335,8 +333,7 @@ CopyInitializerObject(JSContext *cx, HandlePlainObject baseobj, NewObjectKind ne
return nullptr;
RootedObject metadata(cx, obj->getMetadata());
RootedShape lastProp(cx, baseobj->lastProperty());
if (!NativeObject::setLastProperty(cx, obj, lastProp))
if (!obj->setLastProperty(cx, baseobj->lastProperty()))
return nullptr;
if (metadata && !JSObject::setMetadata(cx, obj, metadata))
return nullptr;

View File

@ -296,56 +296,55 @@ PropDesc::trace(JSTracer *trc)
gc::MarkValueRoot(trc, &set_, "PropDesc set");
}
/* static */ inline bool
NativeObject::updateSlotsForSpan(ExclusiveContext *cx,
HandleNativeObject obj, size_t oldSpan, size_t newSpan)
inline bool
NativeObject::updateSlotsForSpan(ExclusiveContext *cx, size_t oldSpan, size_t newSpan)
{
MOZ_ASSERT(oldSpan != newSpan);
size_t oldCount = dynamicSlotsCount(obj->numFixedSlots(), oldSpan, obj->getClass());
size_t newCount = dynamicSlotsCount(obj->numFixedSlots(), newSpan, obj->getClass());
size_t oldCount = dynamicSlotsCount(numFixedSlots(), oldSpan, getClass());
size_t newCount = dynamicSlotsCount(numFixedSlots(), newSpan, getClass());
if (oldSpan < newSpan) {
if (oldCount < newCount && !growSlots(cx, obj, oldCount, newCount))
if (oldCount < newCount && !growSlots(cx, oldCount, newCount))
return false;
if (newSpan == oldSpan + 1)
obj->initSlotUnchecked(oldSpan, UndefinedValue());
initSlotUnchecked(oldSpan, UndefinedValue());
else
obj->initializeSlotRange(oldSpan, newSpan - oldSpan);
initializeSlotRange(oldSpan, newSpan - oldSpan);
} else {
/* Trigger write barriers on the old slots before reallocating. */
obj->prepareSlotRangeForOverwrite(newSpan, oldSpan);
obj->invalidateSlotRange(newSpan, oldSpan - newSpan);
prepareSlotRangeForOverwrite(newSpan, oldSpan);
invalidateSlotRange(newSpan, oldSpan - newSpan);
if (oldCount > newCount)
shrinkSlots(cx, obj, oldCount, newCount);
shrinkSlots(cx, oldCount, newCount);
}
return true;
}
/* static */ bool
NativeObject::setLastProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleShape shape)
bool
NativeObject::setLastProperty(ExclusiveContext *cx, Shape *shape)
{
MOZ_ASSERT(!obj->inDictionaryMode());
MOZ_ASSERT(!inDictionaryMode());
MOZ_ASSERT(!shape->inDictionary());
MOZ_ASSERT(shape->compartment() == obj->compartment());
MOZ_ASSERT(shape->numFixedSlots() == obj->numFixedSlots());
MOZ_ASSERT(shape->getObjectClass() == obj->getClass());
MOZ_ASSERT(shape->compartment() == compartment());
MOZ_ASSERT(shape->numFixedSlots() == numFixedSlots());
MOZ_ASSERT(shape->getObjectClass() == getClass());
size_t oldSpan = obj->lastProperty()->slotSpan();
size_t oldSpan = lastProperty()->slotSpan();
size_t newSpan = shape->slotSpan();
if (oldSpan == newSpan) {
obj->shape_ = shape;
shape_ = shape;
return true;
}
if (!updateSlotsForSpan(cx, obj, oldSpan, newSpan))
if (!updateSlotsForSpan(cx, oldSpan, newSpan))
return false;
obj->shape_ = shape;
shape_ = shape;
return true;
}
@ -383,43 +382,42 @@ NativeObject::setLastPropertyMakeNonNative(Shape *shape)
shape_ = shape;
}
/* static */ void
NativeObject::setLastPropertyMakeNative(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape shape)
void
NativeObject::setLastPropertyMakeNative(ExclusiveContext *cx, Shape *shape)
{
MOZ_ASSERT(obj->getClass()->isNative());
MOZ_ASSERT(!obj->lastProperty()->isNative());
MOZ_ASSERT(getClass()->isNative());
MOZ_ASSERT(!lastProperty()->isNative());
MOZ_ASSERT(shape->isNative());
MOZ_ASSERT(!obj->inDictionaryMode());
MOZ_ASSERT(!inDictionaryMode());
MOZ_ASSERT(!shape->inDictionary());
MOZ_ASSERT(shape->compartment() == obj->compartment());
MOZ_ASSERT(shape->compartment() == compartment());
obj->shape_ = shape;
obj->slots_ = nullptr;
obj->elements_ = emptyObjectElements;
shape_ = shape;
slots_ = nullptr;
elements_ = emptyObjectElements;
size_t oldSpan = shape->numFixedSlots();
size_t newSpan = shape->slotSpan();
// A failures at this point will leave the object as a mutant, and we
// A failure at this point will leave the object as a mutant, and we
// can't recover.
if (oldSpan != newSpan && !updateSlotsForSpan(cx, obj, oldSpan, newSpan))
if (oldSpan != newSpan && !updateSlotsForSpan(cx, oldSpan, newSpan))
CrashAtUnhandlableOOM("NativeObject::setLastPropertyMakeNative");
}
/* static */ bool
NativeObject::setSlotSpan(ExclusiveContext *cx, HandleNativeObject obj, uint32_t span)
bool
NativeObject::setSlotSpan(ExclusiveContext *cx, uint32_t span)
{
MOZ_ASSERT(obj->inDictionaryMode());
MOZ_ASSERT(inDictionaryMode());
size_t oldSpan = obj->lastProperty()->base()->slotSpan();
size_t oldSpan = lastProperty()->base()->slotSpan();
if (oldSpan == span)
return true;
if (!updateSlotsForSpan(cx, obj, oldSpan, span))
if (!updateSlotsForSpan(cx, oldSpan, span))
return false;
obj->lastProperty()->base()->setSlotSpan(span);
lastProperty()->base()->setSlotSpan(span);
return true;
}
@ -448,11 +446,11 @@ ReallocateSlots(ExclusiveContext *cx, JSObject *obj, HeapSlot *oldSlots,
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
}
/* static */ bool
NativeObject::growSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount, uint32_t newCount)
bool
NativeObject::growSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount)
{
MOZ_ASSERT(newCount > oldCount);
MOZ_ASSERT_IF(!obj->is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
MOZ_ASSERT_IF(!is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
/*
* Slot capacities are determined by the span of allocated objects. Due to
@ -463,20 +461,20 @@ NativeObject::growSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t o
MOZ_ASSERT(newCount < NELEMENTS_LIMIT);
if (!oldCount) {
obj->slots_ = AllocateSlots(cx, obj, newCount);
if (!obj->slots_)
slots_ = AllocateSlots(cx, this, newCount);
if (!slots_)
return false;
Debug_SetSlotRangeToCrashOnTouch(obj->slots_, newCount);
Debug_SetSlotRangeToCrashOnTouch(slots_, newCount);
return true;
}
HeapSlot *newslots = ReallocateSlots(cx, obj, obj->slots_, oldCount, newCount);
HeapSlot *newslots = ReallocateSlots(cx, this, slots_, oldCount, newCount);
if (!newslots)
return false; /* Leave slots at its old size. */
obj->slots_ = newslots;
slots_ = newslots;
Debug_SetSlotRangeToCrashOnTouch(obj->slots_ + oldCount, newCount - oldCount);
Debug_SetSlotRangeToCrashOnTouch(slots_ + oldCount, newCount - oldCount);
return true;
}
@ -490,25 +488,24 @@ FreeSlots(ExclusiveContext *cx, HeapSlot *slots)
js_free(slots);
}
/* static */ void
NativeObject::shrinkSlots(ExclusiveContext *cx, HandleNativeObject obj,
uint32_t oldCount, uint32_t newCount)
void
NativeObject::shrinkSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount)
{
MOZ_ASSERT(newCount < oldCount);
if (newCount == 0) {
FreeSlots(cx, obj->slots_);
obj->slots_ = nullptr;
FreeSlots(cx, slots_);
slots_ = nullptr;
return;
}
MOZ_ASSERT_IF(!obj->is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
MOZ_ASSERT_IF(!is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
HeapSlot *newslots = ReallocateSlots(cx, obj, obj->slots_, oldCount, newCount);
HeapSlot *newslots = ReallocateSlots(cx, this, slots_, oldCount, newCount);
if (!newslots)
return; /* Leave slots at its old size. */
obj->slots_ = newslots;
slots_ = newslots;
}
/* static */ bool
@ -988,7 +985,7 @@ NativeObject::allocSlot(ExclusiveContext *cx, HandleNativeObject obj, uint32_t *
*slotp = slot;
if (obj->inDictionaryMode() && !setSlotSpan(cx, obj, slot + 1))
if (obj->inDictionaryMode() && !obj->setSlotSpan(cx, slot + 1))
return false;
return true;

View File

@ -399,12 +399,9 @@ class NativeObject : public JSObject
return getElementsHeader()->capacity;
}
/*
* Update the last property, keeping the number of allocated slots in sync
* with the object's new slot span.
*/
static bool setLastProperty(ExclusiveContext *cx,
HandleNativeObject obj, HandleShape shape);
// Update the last property, keeping the number of allocated slots in sync
// with the object's new slot span.
bool setLastProperty(ExclusiveContext *cx, Shape *shape);
// As for setLastProperty(), but allows the number of fixed slots to
// change. This can only be used when fixed slots are being erased from the
@ -420,8 +417,7 @@ class NativeObject : public JSObject
// As for setLastProperty(), but changes the class associated with the
// object to a native one. The object's type has already been changed, and
// this brings the shape into sync with it.
static void setLastPropertyMakeNative(ExclusiveContext *cx, HandleNativeObject obj,
HandleShape shape);
void setLastPropertyMakeNative(ExclusiveContext *cx, Shape *shape);
protected:
#ifdef DEBUG
@ -447,7 +443,7 @@ class NativeObject : public JSObject
* Update the slot span directly for a dictionary object, and allocate
* slots to cover the new span if necessary.
*/
static bool setSlotSpan(ExclusiveContext *cx, HandleNativeObject obj, uint32_t span);
bool setSlotSpan(ExclusiveContext *cx, uint32_t span);
bool toDictionaryMode(ExclusiveContext *cx);
@ -590,10 +586,8 @@ class NativeObject : public JSObject
* The number of allocated slots is not stored explicitly, and changes to
* the slots must track changes in the slot span.
*/
static bool growSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount,
uint32_t newCount);
static void shrinkSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount,
uint32_t newCount);
bool growSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount);
void shrinkSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount);
bool hasDynamicSlots() const { return !!slots_; }
@ -791,8 +785,7 @@ class NativeObject : public JSObject
static const uint32_t MAX_FIXED_SLOTS = 16;
protected:
static inline bool updateSlotsForSpan(ExclusiveContext *cx,
HandleNativeObject obj, size_t oldSpan, size_t newSpan);
inline bool updateSlotsForSpan(ExclusiveContext *cx, size_t oldSpan, size_t newSpan);
public:
/*

View File

@ -334,7 +334,7 @@ JSObject::makeLazyGroup(JSContext *cx, HandleObject obj)
JSObject::setNewGroupUnknown(JSContext *cx, const js::Class *clasp, JS::HandleObject obj)
{
ObjectGroup::setDefaultNewGroupUnknown(cx, clasp, obj);
return obj->setFlag(cx, BaseShape::NEW_GROUP_UNKNOWN);
return obj->setFlags(cx, BaseShape::NEW_GROUP_UNKNOWN);
}
/////////////////////////////////////////////////////////////////////
@ -1057,8 +1057,7 @@ ObjectGroup::newPlainObject(JSContext *cx, IdValuePair *properties, size_t nprop
}
MOZ_ASSERT(obj->getProto() == p->value().group->proto().toObject());
RootedShape shape(cx, p->value().shape);
if (!NativeObject::setLastProperty(cx, obj, shape)) {
if (!obj->setLastProperty(cx, p->value().shape)) {
cx->clearPendingException();
return nullptr;
}

View File

@ -387,7 +387,7 @@ NativeObject::getChildPropertyOnDictionary(ExclusiveContext *cx, HandleNativeObj
if (!shape)
return nullptr;
if (childRoot->hasSlot() && childRoot->slot() >= obj->lastProperty()->base()->slotSpan()) {
if (!setSlotSpan(cx, obj, childRoot->slot() + 1))
if (!obj->setSlotSpan(cx, childRoot->slot() + 1))
return nullptr;
}
shape->initDictionaryShape(*childRoot, obj->numFixedSlots(), &obj->shape_);
@ -401,7 +401,7 @@ NativeObject::getChildProperty(ExclusiveContext *cx,
HandleNativeObject obj, HandleShape parent, StackShape &unrootedChild)
{
RootedGeneric<StackShape*> child(cx, &unrootedChild);
RootedShape shape(cx, getChildPropertyOnDictionary(cx, obj, parent, *child));
Shape *shape = getChildPropertyOnDictionary(cx, obj, parent, *child);
if (!obj->inDictionaryMode()) {
shape = cx->compartment()->propertyTree.getChild(cx, parent, *child);
@ -409,7 +409,7 @@ NativeObject::getChildProperty(ExclusiveContext *cx,
return nullptr;
//MOZ_ASSERT(shape->parent == parent);
//MOZ_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
if (!setLastProperty(cx, obj, shape))
if (!obj->setLastProperty(cx, shape))
return nullptr;
}
@ -1026,7 +1026,7 @@ NativeObject::removeProperty(ExclusiveContext *cx, jsid id_)
/* static */ void
NativeObject::clear(JSContext *cx, HandleNativeObject obj)
{
RootedShape shape(cx, obj->lastProperty());
Shape *shape = obj->lastProperty();
MOZ_ASSERT(obj->inDictionaryMode() == shape->inDictionary());
while (shape->parent) {
@ -1038,7 +1038,7 @@ NativeObject::clear(JSContext *cx, HandleNativeObject obj)
if (obj->inDictionaryMode())
shape->listp = &obj->shape_;
JS_ALWAYS_TRUE(setLastProperty(cx, obj, shape));
JS_ALWAYS_TRUE(obj->setLastProperty(cx, shape));
++cx->runtime()->propertyRemovals;
obj->checkShapeConsistency();
@ -1205,12 +1205,12 @@ Shape::setObjectMetadata(JSContext *cx, JSObject *metadata, TaggedProto proto, S
}
bool
JSObject::setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
GenerateShape generateShape)
JSObject::setFlags(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flags_,
GenerateShape generateShape)
{
BaseShape::Flag flag = (BaseShape::Flag) flag_;
BaseShape::Flag flags = (BaseShape::Flag) flags_;
if (lastProperty()->getObjectFlags() & flag)
if ((lastProperty()->getObjectFlags() & flags) == flags)
return true;
RootedObject self(cx, this);
@ -1219,7 +1219,7 @@ JSObject::setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
if (generateShape == GENERATE_SHAPE && !as<NativeObject>().generateOwnShape(cx))
return false;
StackBaseShape base(self->lastProperty());
base.flags |= flag;
base.flags |= flags;
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
if (!nbase)
return false;
@ -1229,7 +1229,7 @@ JSObject::setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
}
Shape *newShape =
Shape::setObjectFlag(cx, flag, self->getTaggedProto(), self->lastProperty());
Shape::setObjectFlags(cx, flags, self->getTaggedProto(), self->lastProperty());
if (!newShape)
return false;
@ -1256,13 +1256,13 @@ NativeObject::clearFlag(ExclusiveContext *cx, BaseShape::Flag flag)
}
/* static */ Shape *
Shape::setObjectFlag(ExclusiveContext *cx, BaseShape::Flag flag, TaggedProto proto, Shape *last)
Shape::setObjectFlags(ExclusiveContext *cx, BaseShape::Flag flags, TaggedProto proto, Shape *last)
{
if (last->getObjectFlags() & flag)
if ((last->getObjectFlags() & flags) == flags)
return last;
StackBaseShape base(last);
base.flags |= flag;
base.flags |= flags;
RootedShape lastRoot(cx, last);
return replaceLastProperty(cx, base, proto, lastRoot);

View File

@ -834,8 +834,8 @@ class Shape : public gc::TenuredCell
JSObject *obj, TaggedProto proto, Shape *last);
static Shape *setObjectMetadata(JSContext *cx,
JSObject *metadata, TaggedProto proto, Shape *last);
static Shape *setObjectFlag(ExclusiveContext *cx,
BaseShape::Flag flag, TaggedProto proto, Shape *last);
static Shape *setObjectFlags(ExclusiveContext *cx,
BaseShape::Flag flag, TaggedProto proto, Shape *last);
uint32_t getObjectFlags() const { return base()->getObjectFlags(); }
bool hasObjectFlag(BaseShape::Flag flag) const {

View File

@ -197,7 +197,7 @@ UnboxedPlainObject::convertToNative(JSContext *cx)
return false;
RootedNativeObject nobj(cx, &obj->as<PlainObject>());
NativeObject::setLastPropertyMakeNative(cx, nobj, shape);
nobj->setLastPropertyMakeNative(cx, shape);
for (size_t i = 0; i < values.length(); i++)
nobj->initSlotUnchecked(i, values[i]);