зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1133254 - Dehandlify shape-updating object methods, allow setting multiple flags on an object at once, r=terrence.
This commit is contained in:
Родитель
c39aefe5a8
Коммит
abbe8bd95b
|
@ -1347,10 +1347,10 @@ JSFunction::initBoundFunction(JSContext *cx, HandleObject target, HandleValue th
|
||||||
if (!self->toDictionaryMode(cx))
|
if (!self->toDictionaryMode(cx))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!self->setFlag(cx, BaseShape::BOUND_FUNCTION))
|
if (!self->JSObject::setFlags(cx, BaseShape::BOUND_FUNCTION))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!NativeObject::setSlotSpan(cx, self, BOUND_FUNCTION_RESERVED_SLOTS + argslen))
|
if (!self->setSlotSpan(cx, BOUND_FUNCTION_RESERVED_SLOTS + argslen))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
self->setSlot(JSSLOT_BOUND_FUNCTION_TARGET, ObjectValue(*target));
|
self->setSlot(JSSLOT_BOUND_FUNCTION_TARGET, ObjectValue(*target));
|
||||||
|
|
|
@ -1038,7 +1038,7 @@ js::SetIntegrityLevel(JSContext *cx, HandleObject obj, IntegrityLevel level)
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(nobj->lastProperty()->slotSpan() == last->slotSpan());
|
MOZ_ASSERT(nobj->lastProperty()->slotSpan() == last->slotSpan());
|
||||||
JS_ALWAYS_TRUE(NativeObject::setLastProperty(cx, nobj, last));
|
JS_ALWAYS_TRUE(nobj->setLastProperty(cx, last));
|
||||||
} else {
|
} else {
|
||||||
RootedId id(cx);
|
RootedId id(cx);
|
||||||
Rooted<PropertyDescriptor> desc(cx);
|
Rooted<PropertyDescriptor> desc(cx);
|
||||||
|
@ -1845,7 +1845,7 @@ js::DeepCloneObjectLiteral(JSContext *cx, HandleNativeObject obj, NewObjectKind
|
||||||
MOZ_ASSERT(!obj->hasPrivate());
|
MOZ_ASSERT(!obj->hasPrivate());
|
||||||
RootedShape shape(cx, obj->lastProperty());
|
RootedShape shape(cx, obj->lastProperty());
|
||||||
size_t span = shape->slotSpan();
|
size_t span = shape->slotSpan();
|
||||||
clone->setLastProperty(cx, clone, shape);
|
clone->setLastProperty(cx, shape);
|
||||||
for (size_t i = 0; i < span; i++) {
|
for (size_t i = 0; i < span; i++) {
|
||||||
v = obj->getSlot(i);
|
v = obj->getSlot(i);
|
||||||
if (v.isObject()) {
|
if (v.isObject()) {
|
||||||
|
@ -2137,7 +2137,7 @@ js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
|
||||||
|
|
||||||
RootedShape newShape(cx, ReshapeForParentAndAllocKind(cx, srcObj->lastProperty(),
|
RootedShape newShape(cx, ReshapeForParentAndAllocKind(cx, srcObj->lastProperty(),
|
||||||
TaggedProto(proto), parent, kind));
|
TaggedProto(proto), parent, kind));
|
||||||
if (!newShape || !NativeObject::setLastProperty(cx, res, newShape))
|
if (!newShape || !res->setLastProperty(cx, newShape))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
@ -3139,7 +3139,7 @@ js::PreventExtensions(JSContext *cx, HandleObject obj, bool *succeeded)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
*succeeded = true;
|
*succeeded = true;
|
||||||
return obj->setFlag(cx, BaseShape::NOT_EXTENSIBLE, JSObject::GENERATE_SHAPE);
|
return obj->setFlags(cx, BaseShape::NOT_EXTENSIBLE, JSObject::GENERATE_SHAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -3234,7 +3234,7 @@ js::SetImmutablePrototype(ExclusiveContext *cx, HandleObject obj, bool *succeede
|
||||||
return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded);
|
return Proxy::setImmutablePrototype(cx->asJSContext(), obj, succeeded);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!obj->setFlag(cx, BaseShape::IMMUTABLE_PROTOTYPE))
|
if (!obj->setFlags(cx, BaseShape::IMMUTABLE_PROTOTYPE))
|
||||||
return false;
|
return false;
|
||||||
*succeeded = true;
|
*succeeded = true;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -189,16 +189,14 @@ class JSObject : public js::gc::Cell
|
||||||
inline void setInitialSlotsMaybeNonNative(js::HeapSlot *slots);
|
inline void setInitialSlotsMaybeNonNative(js::HeapSlot *slots);
|
||||||
inline void setInitialElementsMaybeNonNative(js::HeapSlot *elements);
|
inline void setInitialElementsMaybeNonNative(js::HeapSlot *elements);
|
||||||
|
|
||||||
protected:
|
|
||||||
enum GenerateShape {
|
enum GenerateShape {
|
||||||
GENERATE_NONE,
|
GENERATE_NONE,
|
||||||
GENERATE_SHAPE
|
GENERATE_SHAPE
|
||||||
};
|
};
|
||||||
|
|
||||||
bool setFlag(js::ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag,
|
bool setFlags(js::ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flags,
|
||||||
GenerateShape generateShape = GENERATE_NONE);
|
GenerateShape generateShape = GENERATE_NONE);
|
||||||
|
|
||||||
public:
|
|
||||||
/*
|
/*
|
||||||
* An object is a delegate if it is on another object's prototype or scope
|
* 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
|
* 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) {
|
bool setDelegate(js::ExclusiveContext *cx) {
|
||||||
return setFlag(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
|
return setFlags(cx, js::BaseShape::DELEGATE, GENERATE_SHAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isBoundFunction() const {
|
bool isBoundFunction() const {
|
||||||
|
@ -226,18 +224,18 @@ class JSObject : public js::gc::Cell
|
||||||
return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
|
return lastProperty()->hasObjectFlag(js::BaseShape::WATCHED);
|
||||||
}
|
}
|
||||||
bool setWatched(js::ExclusiveContext *cx) {
|
bool setWatched(js::ExclusiveContext *cx) {
|
||||||
return setFlag(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
|
return setFlags(cx, js::BaseShape::WATCHED, GENERATE_SHAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* See InterpreterFrame::varObj. */
|
/* See InterpreterFrame::varObj. */
|
||||||
inline bool isQualifiedVarObj();
|
inline bool isQualifiedVarObj();
|
||||||
bool setQualifiedVarObj(js::ExclusiveContext *cx) {
|
bool setQualifiedVarObj(js::ExclusiveContext *cx) {
|
||||||
return setFlag(cx, js::BaseShape::QUALIFIED_VAROBJ);
|
return setFlags(cx, js::BaseShape::QUALIFIED_VAROBJ);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool isUnqualifiedVarObj();
|
inline bool isUnqualifiedVarObj();
|
||||||
bool setUnqualifiedVarObj(js::ExclusiveContext *cx) {
|
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);
|
return lastProperty()->hasObjectFlag(js::BaseShape::UNCACHEABLE_PROTO);
|
||||||
}
|
}
|
||||||
bool setUncacheableProto(js::ExclusiveContext *cx) {
|
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);
|
return lastProperty()->hasObjectFlag(js::BaseShape::HAD_ELEMENTS_ACCESS);
|
||||||
}
|
}
|
||||||
bool setHadElementsAccess(js::ExclusiveContext *cx) {
|
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);
|
return lastProperty()->hasObjectFlag(js::BaseShape::ITERATED_SINGLETON);
|
||||||
}
|
}
|
||||||
bool setIteratedSingleton(js::ExclusiveContext *cx) {
|
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);
|
return lastProperty()->hasObjectFlag(js::BaseShape::NEW_SCRIPT_CLEARED);
|
||||||
}
|
}
|
||||||
bool setNewScriptCleared(js::ExclusiveContext *cx) {
|
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. */
|
/* Set a new prototype for an object with a singleton type. */
|
||||||
|
|
|
@ -614,11 +614,11 @@ GlobalObject::addIntrinsicValue(JSContext *cx, HandleId id, HandleValue value)
|
||||||
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
|
Rooted<UnownedBaseShape*> base(cx, last->base()->unowned());
|
||||||
|
|
||||||
StackShape child(base, id, slot, 0, 0);
|
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)
|
if (!shape)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!NativeObject::setLastProperty(cx, holder, shape))
|
if (!holder->setLastProperty(cx, shape))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
holder->setSlot(shape->slot(), value);
|
holder->setSlot(shape->slot(), value);
|
||||||
|
|
|
@ -39,9 +39,7 @@ inline void
|
||||||
NativeObject::removeLastProperty(ExclusiveContext *cx)
|
NativeObject::removeLastProperty(ExclusiveContext *cx)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(canRemoveLastProperty());
|
MOZ_ASSERT(canRemoveLastProperty());
|
||||||
RootedNativeObject self(cx, this);
|
JS_ALWAYS_TRUE(setLastProperty(cx, lastProperty()->previous()));
|
||||||
RootedShape prev(cx, lastProperty()->previous());
|
|
||||||
JS_ALWAYS_TRUE(setLastProperty(cx, self, prev));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
|
@ -335,8 +333,7 @@ CopyInitializerObject(JSContext *cx, HandlePlainObject baseobj, NewObjectKind ne
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
RootedObject metadata(cx, obj->getMetadata());
|
RootedObject metadata(cx, obj->getMetadata());
|
||||||
RootedShape lastProp(cx, baseobj->lastProperty());
|
if (!obj->setLastProperty(cx, baseobj->lastProperty()))
|
||||||
if (!NativeObject::setLastProperty(cx, obj, lastProp))
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (metadata && !JSObject::setMetadata(cx, obj, metadata))
|
if (metadata && !JSObject::setMetadata(cx, obj, metadata))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
@ -296,56 +296,55 @@ PropDesc::trace(JSTracer *trc)
|
||||||
gc::MarkValueRoot(trc, &set_, "PropDesc set");
|
gc::MarkValueRoot(trc, &set_, "PropDesc set");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ inline bool
|
inline bool
|
||||||
NativeObject::updateSlotsForSpan(ExclusiveContext *cx,
|
NativeObject::updateSlotsForSpan(ExclusiveContext *cx, size_t oldSpan, size_t newSpan)
|
||||||
HandleNativeObject obj, size_t oldSpan, size_t newSpan)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(oldSpan != newSpan);
|
MOZ_ASSERT(oldSpan != newSpan);
|
||||||
|
|
||||||
size_t oldCount = dynamicSlotsCount(obj->numFixedSlots(), oldSpan, obj->getClass());
|
size_t oldCount = dynamicSlotsCount(numFixedSlots(), oldSpan, getClass());
|
||||||
size_t newCount = dynamicSlotsCount(obj->numFixedSlots(), newSpan, obj->getClass());
|
size_t newCount = dynamicSlotsCount(numFixedSlots(), newSpan, getClass());
|
||||||
|
|
||||||
if (oldSpan < newSpan) {
|
if (oldSpan < newSpan) {
|
||||||
if (oldCount < newCount && !growSlots(cx, obj, oldCount, newCount))
|
if (oldCount < newCount && !growSlots(cx, oldCount, newCount))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (newSpan == oldSpan + 1)
|
if (newSpan == oldSpan + 1)
|
||||||
obj->initSlotUnchecked(oldSpan, UndefinedValue());
|
initSlotUnchecked(oldSpan, UndefinedValue());
|
||||||
else
|
else
|
||||||
obj->initializeSlotRange(oldSpan, newSpan - oldSpan);
|
initializeSlotRange(oldSpan, newSpan - oldSpan);
|
||||||
} else {
|
} else {
|
||||||
/* Trigger write barriers on the old slots before reallocating. */
|
/* Trigger write barriers on the old slots before reallocating. */
|
||||||
obj->prepareSlotRangeForOverwrite(newSpan, oldSpan);
|
prepareSlotRangeForOverwrite(newSpan, oldSpan);
|
||||||
obj->invalidateSlotRange(newSpan, oldSpan - newSpan);
|
invalidateSlotRange(newSpan, oldSpan - newSpan);
|
||||||
|
|
||||||
if (oldCount > newCount)
|
if (oldCount > newCount)
|
||||||
shrinkSlots(cx, obj, oldCount, newCount);
|
shrinkSlots(cx, oldCount, newCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
bool
|
||||||
NativeObject::setLastProperty(ExclusiveContext *cx, HandleNativeObject obj, HandleShape shape)
|
NativeObject::setLastProperty(ExclusiveContext *cx, Shape *shape)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!obj->inDictionaryMode());
|
MOZ_ASSERT(!inDictionaryMode());
|
||||||
MOZ_ASSERT(!shape->inDictionary());
|
MOZ_ASSERT(!shape->inDictionary());
|
||||||
MOZ_ASSERT(shape->compartment() == obj->compartment());
|
MOZ_ASSERT(shape->compartment() == compartment());
|
||||||
MOZ_ASSERT(shape->numFixedSlots() == obj->numFixedSlots());
|
MOZ_ASSERT(shape->numFixedSlots() == numFixedSlots());
|
||||||
MOZ_ASSERT(shape->getObjectClass() == obj->getClass());
|
MOZ_ASSERT(shape->getObjectClass() == getClass());
|
||||||
|
|
||||||
size_t oldSpan = obj->lastProperty()->slotSpan();
|
size_t oldSpan = lastProperty()->slotSpan();
|
||||||
size_t newSpan = shape->slotSpan();
|
size_t newSpan = shape->slotSpan();
|
||||||
|
|
||||||
if (oldSpan == newSpan) {
|
if (oldSpan == newSpan) {
|
||||||
obj->shape_ = shape;
|
shape_ = shape;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!updateSlotsForSpan(cx, obj, oldSpan, newSpan))
|
if (!updateSlotsForSpan(cx, oldSpan, newSpan))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
obj->shape_ = shape;
|
shape_ = shape;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,43 +382,42 @@ NativeObject::setLastPropertyMakeNonNative(Shape *shape)
|
||||||
shape_ = shape;
|
shape_ = shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
void
|
||||||
NativeObject::setLastPropertyMakeNative(ExclusiveContext *cx, HandleNativeObject obj,
|
NativeObject::setLastPropertyMakeNative(ExclusiveContext *cx, Shape *shape)
|
||||||
HandleShape shape)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(obj->getClass()->isNative());
|
MOZ_ASSERT(getClass()->isNative());
|
||||||
MOZ_ASSERT(!obj->lastProperty()->isNative());
|
MOZ_ASSERT(!lastProperty()->isNative());
|
||||||
MOZ_ASSERT(shape->isNative());
|
MOZ_ASSERT(shape->isNative());
|
||||||
MOZ_ASSERT(!obj->inDictionaryMode());
|
MOZ_ASSERT(!inDictionaryMode());
|
||||||
MOZ_ASSERT(!shape->inDictionary());
|
MOZ_ASSERT(!shape->inDictionary());
|
||||||
MOZ_ASSERT(shape->compartment() == obj->compartment());
|
MOZ_ASSERT(shape->compartment() == compartment());
|
||||||
|
|
||||||
obj->shape_ = shape;
|
shape_ = shape;
|
||||||
obj->slots_ = nullptr;
|
slots_ = nullptr;
|
||||||
obj->elements_ = emptyObjectElements;
|
elements_ = emptyObjectElements;
|
||||||
|
|
||||||
size_t oldSpan = shape->numFixedSlots();
|
size_t oldSpan = shape->numFixedSlots();
|
||||||
size_t newSpan = shape->slotSpan();
|
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.
|
// can't recover.
|
||||||
if (oldSpan != newSpan && !updateSlotsForSpan(cx, obj, oldSpan, newSpan))
|
if (oldSpan != newSpan && !updateSlotsForSpan(cx, oldSpan, newSpan))
|
||||||
CrashAtUnhandlableOOM("NativeObject::setLastPropertyMakeNative");
|
CrashAtUnhandlableOOM("NativeObject::setLastPropertyMakeNative");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
bool
|
||||||
NativeObject::setSlotSpan(ExclusiveContext *cx, HandleNativeObject obj, uint32_t span)
|
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)
|
if (oldSpan == span)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!updateSlotsForSpan(cx, obj, oldSpan, span))
|
if (!updateSlotsForSpan(cx, oldSpan, span))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
obj->lastProperty()->base()->setSlotSpan(span);
|
lastProperty()->base()->setSlotSpan(span);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -448,11 +446,11 @@ ReallocateSlots(ExclusiveContext *cx, JSObject *obj, HeapSlot *oldSlots,
|
||||||
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
|
return obj->zone()->pod_realloc<HeapSlot>(oldSlots, oldCount, newCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
bool
|
||||||
NativeObject::growSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount, uint32_t newCount)
|
NativeObject::growSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(newCount > oldCount);
|
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
|
* 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);
|
MOZ_ASSERT(newCount < NELEMENTS_LIMIT);
|
||||||
|
|
||||||
if (!oldCount) {
|
if (!oldCount) {
|
||||||
obj->slots_ = AllocateSlots(cx, obj, newCount);
|
slots_ = AllocateSlots(cx, this, newCount);
|
||||||
if (!obj->slots_)
|
if (!slots_)
|
||||||
return false;
|
return false;
|
||||||
Debug_SetSlotRangeToCrashOnTouch(obj->slots_, newCount);
|
Debug_SetSlotRangeToCrashOnTouch(slots_, newCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapSlot *newslots = ReallocateSlots(cx, obj, obj->slots_, oldCount, newCount);
|
HeapSlot *newslots = ReallocateSlots(cx, this, slots_, oldCount, newCount);
|
||||||
if (!newslots)
|
if (!newslots)
|
||||||
return false; /* Leave slots at its old size. */
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -490,25 +488,24 @@ FreeSlots(ExclusiveContext *cx, HeapSlot *slots)
|
||||||
js_free(slots);
|
js_free(slots);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void
|
void
|
||||||
NativeObject::shrinkSlots(ExclusiveContext *cx, HandleNativeObject obj,
|
NativeObject::shrinkSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount)
|
||||||
uint32_t oldCount, uint32_t newCount)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(newCount < oldCount);
|
MOZ_ASSERT(newCount < oldCount);
|
||||||
|
|
||||||
if (newCount == 0) {
|
if (newCount == 0) {
|
||||||
FreeSlots(cx, obj->slots_);
|
FreeSlots(cx, slots_);
|
||||||
obj->slots_ = nullptr;
|
slots_ = nullptr;
|
||||||
return;
|
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)
|
if (!newslots)
|
||||||
return; /* Leave slots at its old size. */
|
return; /* Leave slots at its old size. */
|
||||||
|
|
||||||
obj->slots_ = newslots;
|
slots_ = newslots;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool
|
/* static */ bool
|
||||||
|
@ -988,7 +985,7 @@ NativeObject::allocSlot(ExclusiveContext *cx, HandleNativeObject obj, uint32_t *
|
||||||
|
|
||||||
*slotp = slot;
|
*slotp = slot;
|
||||||
|
|
||||||
if (obj->inDictionaryMode() && !setSlotSpan(cx, obj, slot + 1))
|
if (obj->inDictionaryMode() && !obj->setSlotSpan(cx, slot + 1))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -399,12 +399,9 @@ class NativeObject : public JSObject
|
||||||
return getElementsHeader()->capacity;
|
return getElementsHeader()->capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Update the last property, keeping the number of allocated slots in sync
|
||||||
* Update the last property, keeping the number of allocated slots in sync
|
// with the object's new slot span.
|
||||||
* with the object's new slot span.
|
bool setLastProperty(ExclusiveContext *cx, Shape *shape);
|
||||||
*/
|
|
||||||
static bool setLastProperty(ExclusiveContext *cx,
|
|
||||||
HandleNativeObject obj, HandleShape shape);
|
|
||||||
|
|
||||||
// As for setLastProperty(), but allows the number of fixed slots to
|
// 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
|
// 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
|
// As for setLastProperty(), but changes the class associated with the
|
||||||
// object to a native one. The object's type has already been changed, and
|
// object to a native one. The object's type has already been changed, and
|
||||||
// this brings the shape into sync with it.
|
// this brings the shape into sync with it.
|
||||||
static void setLastPropertyMakeNative(ExclusiveContext *cx, HandleNativeObject obj,
|
void setLastPropertyMakeNative(ExclusiveContext *cx, Shape *shape);
|
||||||
HandleShape shape);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -447,7 +443,7 @@ class NativeObject : public JSObject
|
||||||
* Update the slot span directly for a dictionary object, and allocate
|
* Update the slot span directly for a dictionary object, and allocate
|
||||||
* slots to cover the new span if necessary.
|
* 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);
|
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 number of allocated slots is not stored explicitly, and changes to
|
||||||
* the slots must track changes in the slot span.
|
* the slots must track changes in the slot span.
|
||||||
*/
|
*/
|
||||||
static bool growSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount,
|
bool growSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount);
|
||||||
uint32_t newCount);
|
void shrinkSlots(ExclusiveContext *cx, uint32_t oldCount, uint32_t newCount);
|
||||||
static void shrinkSlots(ExclusiveContext *cx, HandleNativeObject obj, uint32_t oldCount,
|
|
||||||
uint32_t newCount);
|
|
||||||
|
|
||||||
bool hasDynamicSlots() const { return !!slots_; }
|
bool hasDynamicSlots() const { return !!slots_; }
|
||||||
|
|
||||||
|
@ -791,8 +785,7 @@ class NativeObject : public JSObject
|
||||||
static const uint32_t MAX_FIXED_SLOTS = 16;
|
static const uint32_t MAX_FIXED_SLOTS = 16;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static inline bool updateSlotsForSpan(ExclusiveContext *cx,
|
inline bool updateSlotsForSpan(ExclusiveContext *cx, size_t oldSpan, size_t newSpan);
|
||||||
HandleNativeObject obj, size_t oldSpan, size_t newSpan);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -334,7 +334,7 @@ JSObject::makeLazyGroup(JSContext *cx, HandleObject obj)
|
||||||
JSObject::setNewGroupUnknown(JSContext *cx, const js::Class *clasp, JS::HandleObject obj)
|
JSObject::setNewGroupUnknown(JSContext *cx, const js::Class *clasp, JS::HandleObject obj)
|
||||||
{
|
{
|
||||||
ObjectGroup::setDefaultNewGroupUnknown(cx, clasp, 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());
|
MOZ_ASSERT(obj->getProto() == p->value().group->proto().toObject());
|
||||||
|
|
||||||
RootedShape shape(cx, p->value().shape);
|
if (!obj->setLastProperty(cx, p->value().shape)) {
|
||||||
if (!NativeObject::setLastProperty(cx, obj, shape)) {
|
|
||||||
cx->clearPendingException();
|
cx->clearPendingException();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -387,7 +387,7 @@ NativeObject::getChildPropertyOnDictionary(ExclusiveContext *cx, HandleNativeObj
|
||||||
if (!shape)
|
if (!shape)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (childRoot->hasSlot() && childRoot->slot() >= obj->lastProperty()->base()->slotSpan()) {
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
shape->initDictionaryShape(*childRoot, obj->numFixedSlots(), &obj->shape_);
|
shape->initDictionaryShape(*childRoot, obj->numFixedSlots(), &obj->shape_);
|
||||||
|
@ -401,7 +401,7 @@ NativeObject::getChildProperty(ExclusiveContext *cx,
|
||||||
HandleNativeObject obj, HandleShape parent, StackShape &unrootedChild)
|
HandleNativeObject obj, HandleShape parent, StackShape &unrootedChild)
|
||||||
{
|
{
|
||||||
RootedGeneric<StackShape*> child(cx, &unrootedChild);
|
RootedGeneric<StackShape*> child(cx, &unrootedChild);
|
||||||
RootedShape shape(cx, getChildPropertyOnDictionary(cx, obj, parent, *child));
|
Shape *shape = getChildPropertyOnDictionary(cx, obj, parent, *child);
|
||||||
|
|
||||||
if (!obj->inDictionaryMode()) {
|
if (!obj->inDictionaryMode()) {
|
||||||
shape = cx->compartment()->propertyTree.getChild(cx, parent, *child);
|
shape = cx->compartment()->propertyTree.getChild(cx, parent, *child);
|
||||||
|
@ -409,7 +409,7 @@ NativeObject::getChildProperty(ExclusiveContext *cx,
|
||||||
return nullptr;
|
return nullptr;
|
||||||
//MOZ_ASSERT(shape->parent == parent);
|
//MOZ_ASSERT(shape->parent == parent);
|
||||||
//MOZ_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
|
//MOZ_ASSERT_IF(parent != lastProperty(), parent == lastProperty()->parent);
|
||||||
if (!setLastProperty(cx, obj, shape))
|
if (!obj->setLastProperty(cx, shape))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,7 +1026,7 @@ NativeObject::removeProperty(ExclusiveContext *cx, jsid id_)
|
||||||
/* static */ void
|
/* static */ void
|
||||||
NativeObject::clear(JSContext *cx, HandleNativeObject obj)
|
NativeObject::clear(JSContext *cx, HandleNativeObject obj)
|
||||||
{
|
{
|
||||||
RootedShape shape(cx, obj->lastProperty());
|
Shape *shape = obj->lastProperty();
|
||||||
MOZ_ASSERT(obj->inDictionaryMode() == shape->inDictionary());
|
MOZ_ASSERT(obj->inDictionaryMode() == shape->inDictionary());
|
||||||
|
|
||||||
while (shape->parent) {
|
while (shape->parent) {
|
||||||
|
@ -1038,7 +1038,7 @@ NativeObject::clear(JSContext *cx, HandleNativeObject obj)
|
||||||
if (obj->inDictionaryMode())
|
if (obj->inDictionaryMode())
|
||||||
shape->listp = &obj->shape_;
|
shape->listp = &obj->shape_;
|
||||||
|
|
||||||
JS_ALWAYS_TRUE(setLastProperty(cx, obj, shape));
|
JS_ALWAYS_TRUE(obj->setLastProperty(cx, shape));
|
||||||
|
|
||||||
++cx->runtime()->propertyRemovals;
|
++cx->runtime()->propertyRemovals;
|
||||||
obj->checkShapeConsistency();
|
obj->checkShapeConsistency();
|
||||||
|
@ -1205,12 +1205,12 @@ Shape::setObjectMetadata(JSContext *cx, JSObject *metadata, TaggedProto proto, S
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
JSObject::setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
|
JSObject::setFlags(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flags_,
|
||||||
GenerateShape generateShape)
|
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;
|
return true;
|
||||||
|
|
||||||
RootedObject self(cx, this);
|
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))
|
if (generateShape == GENERATE_SHAPE && !as<NativeObject>().generateOwnShape(cx))
|
||||||
return false;
|
return false;
|
||||||
StackBaseShape base(self->lastProperty());
|
StackBaseShape base(self->lastProperty());
|
||||||
base.flags |= flag;
|
base.flags |= flags;
|
||||||
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
|
UnownedBaseShape *nbase = BaseShape::getUnowned(cx, base);
|
||||||
if (!nbase)
|
if (!nbase)
|
||||||
return false;
|
return false;
|
||||||
|
@ -1229,7 +1229,7 @@ JSObject::setFlag(ExclusiveContext *cx, /*BaseShape::Flag*/ uint32_t flag_,
|
||||||
}
|
}
|
||||||
|
|
||||||
Shape *newShape =
|
Shape *newShape =
|
||||||
Shape::setObjectFlag(cx, flag, self->getTaggedProto(), self->lastProperty());
|
Shape::setObjectFlags(cx, flags, self->getTaggedProto(), self->lastProperty());
|
||||||
if (!newShape)
|
if (!newShape)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1256,13 +1256,13 @@ NativeObject::clearFlag(ExclusiveContext *cx, BaseShape::Flag flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ Shape *
|
/* 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;
|
return last;
|
||||||
|
|
||||||
StackBaseShape base(last);
|
StackBaseShape base(last);
|
||||||
base.flags |= flag;
|
base.flags |= flags;
|
||||||
|
|
||||||
RootedShape lastRoot(cx, last);
|
RootedShape lastRoot(cx, last);
|
||||||
return replaceLastProperty(cx, base, proto, lastRoot);
|
return replaceLastProperty(cx, base, proto, lastRoot);
|
||||||
|
|
|
@ -834,8 +834,8 @@ class Shape : public gc::TenuredCell
|
||||||
JSObject *obj, TaggedProto proto, Shape *last);
|
JSObject *obj, TaggedProto proto, Shape *last);
|
||||||
static Shape *setObjectMetadata(JSContext *cx,
|
static Shape *setObjectMetadata(JSContext *cx,
|
||||||
JSObject *metadata, TaggedProto proto, Shape *last);
|
JSObject *metadata, TaggedProto proto, Shape *last);
|
||||||
static Shape *setObjectFlag(ExclusiveContext *cx,
|
static Shape *setObjectFlags(ExclusiveContext *cx,
|
||||||
BaseShape::Flag flag, TaggedProto proto, Shape *last);
|
BaseShape::Flag flag, TaggedProto proto, Shape *last);
|
||||||
|
|
||||||
uint32_t getObjectFlags() const { return base()->getObjectFlags(); }
|
uint32_t getObjectFlags() const { return base()->getObjectFlags(); }
|
||||||
bool hasObjectFlag(BaseShape::Flag flag) const {
|
bool hasObjectFlag(BaseShape::Flag flag) const {
|
||||||
|
|
|
@ -197,7 +197,7 @@ UnboxedPlainObject::convertToNative(JSContext *cx)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
RootedNativeObject nobj(cx, &obj->as<PlainObject>());
|
RootedNativeObject nobj(cx, &obj->as<PlainObject>());
|
||||||
NativeObject::setLastPropertyMakeNative(cx, nobj, shape);
|
nobj->setLastPropertyMakeNative(cx, shape);
|
||||||
|
|
||||||
for (size_t i = 0; i < values.length(); i++)
|
for (size_t i = 0; i < values.length(); i++)
|
||||||
nobj->initSlotUnchecked(i, values[i]);
|
nobj->initSlotUnchecked(i, values[i]);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче