зеркало из https://github.com/mozilla/gecko-dev.git
Bug 957542 - Don't over-allocate dynamic slots of ArrayObject, r=bhackett,terrence
This commit is contained in:
Родитель
0477dcbeb0
Коммит
4bc7ae0025
|
@ -132,6 +132,9 @@ js::Nursery::isEmpty() const
|
|||
JSObject *
|
||||
js::Nursery::allocateObject(JSContext *cx, size_t size, size_t numDynamic)
|
||||
{
|
||||
/* Ensure there's enough space to replace the contents with a RelocationOverlay. */
|
||||
JS_ASSERT(size >= sizeof(RelocationOverlay));
|
||||
|
||||
/* Attempt to allocate slots contiguously after object, if possible. */
|
||||
if (numDynamic && numDynamic <= MaxNurserySlots) {
|
||||
size_t totalSize = size + sizeof(HeapSlot) * numDynamic;
|
||||
|
@ -166,9 +169,6 @@ js::Nursery::allocate(size_t size)
|
|||
JS_ASSERT(isEnabled());
|
||||
JS_ASSERT(!runtime()->isHeapBusy());
|
||||
|
||||
/* Ensure there's enough space to replace the contents with a RelocationOverlay. */
|
||||
JS_ASSERT(size >= sizeof(RelocationOverlay));
|
||||
|
||||
if (position() + size > currentEnd()) {
|
||||
if (currentChunk_ + 1 == numActiveChunks_)
|
||||
return nullptr;
|
||||
|
|
|
@ -4653,7 +4653,8 @@ IonBuilder::createCallObject(MDefinition *callee, MDefinition *scope)
|
|||
MInstruction *slots;
|
||||
if (templateObj->hasDynamicSlots()) {
|
||||
size_t nslots = JSObject::dynamicSlotsCount(templateObj->numFixedSlotsForCompilation(),
|
||||
templateObj->lastProperty()->slotSpan(templateObj->getClass()));
|
||||
templateObj->lastProperty()->slotSpan(templateObj->getClass()),
|
||||
templateObj->getClass());
|
||||
slots = MNewSlots::New(alloc(), nslots);
|
||||
} else {
|
||||
slots = MConstant::New(alloc(), NullValue());
|
||||
|
|
|
@ -2222,8 +2222,8 @@ JSObject::ReserveForTradeGuts(JSContext *cx, JSObject *aArg, JSObject *bArg,
|
|||
* other object.
|
||||
*/
|
||||
|
||||
unsigned adynamic = dynamicSlotsCount(reserved.newafixed, b->slotSpan());
|
||||
unsigned bdynamic = dynamicSlotsCount(reserved.newbfixed, a->slotSpan());
|
||||
unsigned adynamic = dynamicSlotsCount(reserved.newafixed, b->slotSpan(), b->getClass());
|
||||
unsigned bdynamic = dynamicSlotsCount(reserved.newbfixed, a->slotSpan(), a->getClass());
|
||||
|
||||
if (adynamic) {
|
||||
reserved.newaslots = cx->pod_malloc<HeapSlot>(adynamic);
|
||||
|
@ -2654,8 +2654,8 @@ JSObject::updateSlotsForSpan(ThreadSafeContext *cx,
|
|||
JS_ASSERT(cx->isThreadLocal(obj));
|
||||
JS_ASSERT(oldSpan != newSpan);
|
||||
|
||||
size_t oldCount = dynamicSlotsCount(obj->numFixedSlots(), oldSpan);
|
||||
size_t newCount = dynamicSlotsCount(obj->numFixedSlots(), newSpan);
|
||||
size_t oldCount = dynamicSlotsCount(obj->numFixedSlots(), oldSpan, obj->getClass());
|
||||
size_t newCount = dynamicSlotsCount(obj->numFixedSlots(), newSpan, obj->getClass());
|
||||
|
||||
if (oldSpan < newSpan) {
|
||||
if (oldCount < newCount && !JSObject::growSlots(cx, obj, oldCount, newCount))
|
||||
|
@ -2748,7 +2748,7 @@ JSObject::growSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount,
|
|||
{
|
||||
JS_ASSERT(cx->isThreadLocal(obj));
|
||||
JS_ASSERT(newCount > oldCount);
|
||||
JS_ASSERT(newCount >= SLOT_CAPACITY_MIN);
|
||||
JS_ASSERT_IF(!obj->is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
|
||||
|
||||
/*
|
||||
* Slot capacities are determined by the span of allocated objects. Due to
|
||||
|
@ -2834,7 +2834,7 @@ JSObject::shrinkSlots(ThreadSafeContext *cx, HandleObject obj, uint32_t oldCount
|
|||
return;
|
||||
}
|
||||
|
||||
JS_ASSERT(newCount >= SLOT_CAPACITY_MIN);
|
||||
JS_ASSERT_IF(!obj->is<ArrayObject>(), newCount >= SLOT_CAPACITY_MIN);
|
||||
|
||||
// Global slots may be read during off thread compilation, and updates to
|
||||
// their slot pointers need to be synchronized.
|
||||
|
|
|
@ -497,9 +497,14 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
|
|||
JS_ASSERT(js::gc::GetGCKindSlots(kind, type->clasp()) == shape->numFixedSlots());
|
||||
JS_ASSERT_IF(type->clasp()->flags & JSCLASS_BACKGROUND_FINALIZE, IsBackgroundFinalized(kind));
|
||||
JS_ASSERT_IF(type->clasp()->finalize, heap == js::gc::TenuredHeap);
|
||||
JS_ASSERT_IF(extantSlots, dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()));
|
||||
JS_ASSERT_IF(extantSlots, dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan(),
|
||||
type->clasp()));
|
||||
|
||||
const js::Class *clasp = type->clasp();
|
||||
size_t nDynamicSlots = 0;
|
||||
if (!extantSlots)
|
||||
nDynamicSlots = dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan(), clasp);
|
||||
|
||||
size_t nDynamicSlots = extantSlots ? 0 : dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan());
|
||||
JSObject *obj = js::NewGCObject<js::CanGC>(cx, kind, nDynamicSlots, heap);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
@ -510,7 +515,6 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
|
|||
obj->slots = extantSlots;
|
||||
obj->elements = js::emptyObjectElements;
|
||||
|
||||
const js::Class *clasp = type->clasp();
|
||||
if (clasp->hasPrivate())
|
||||
obj->privateRef(shape->numFixedSlots()) = nullptr;
|
||||
|
||||
|
@ -537,7 +541,7 @@ JSObject::createArray(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::
|
|||
* named properties stored in those fixed slots.
|
||||
*/
|
||||
JS_ASSERT(shape->numFixedSlots() == 0);
|
||||
size_t nDynamicSlots = dynamicSlotsCount(0, shape->slotSpan());
|
||||
size_t nDynamicSlots = dynamicSlotsCount(0, shape->slotSpan(), type->clasp());
|
||||
JSObject *obj = js::NewGCObject<js::CanGC>(cx, kind, nDynamicSlots, heap);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
|
|
|
@ -353,6 +353,24 @@ js::ObjectImpl::numFixedSlotsForCompilation() const
|
|||
return gc::GetGCKindSlots(kind, getClass());
|
||||
}
|
||||
|
||||
uint32_t
|
||||
js::ObjectImpl::dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class *clasp)
|
||||
{
|
||||
if (span <= nfixed)
|
||||
return 0;
|
||||
span -= nfixed;
|
||||
|
||||
// Increase the slots to SLOT_CAPACITY_MIN to decrease the likelihood
|
||||
// the dynamic slots need to get increased again. ArrayObjects ignore
|
||||
// this because slots are uncommon in that case.
|
||||
if (clasp != &ArrayObject::class_ && span <= SLOT_CAPACITY_MIN)
|
||||
return SLOT_CAPACITY_MIN;
|
||||
|
||||
uint32_t slots = mozilla::RoundUpPow2(span);
|
||||
MOZ_ASSERT(slots >= span);
|
||||
return slots;
|
||||
}
|
||||
|
||||
void
|
||||
js::ObjectImpl::markChildren(JSTracer *trc)
|
||||
{
|
||||
|
|
|
@ -1149,7 +1149,11 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
|||
bool slotInRange(uint32_t slot, SentinelAllowed sentinel = SENTINEL_NOT_ALLOWED) const;
|
||||
#endif
|
||||
|
||||
/* Minimum size for dynamically allocated slots. */
|
||||
/*
|
||||
* Minimum size for dynamically allocated slots in normal Objects.
|
||||
* ArrayObjects don't use this limit and can have a lower slot capacity,
|
||||
* since they normally don't have a lot of slots.
|
||||
*/
|
||||
static const uint32_t SLOT_CAPACITY_MIN = 8;
|
||||
|
||||
HeapSlot *fixedSlots() const {
|
||||
|
@ -1239,9 +1243,10 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
|||
|
||||
/* Compute dynamicSlotsCount() for this object. */
|
||||
uint32_t numDynamicSlots() const {
|
||||
return dynamicSlotsCount(numFixedSlots(), slotSpan());
|
||||
return dynamicSlotsCount(numFixedSlots(), slotSpan(), getClass());
|
||||
}
|
||||
|
||||
|
||||
Shape *nativeLookup(ExclusiveContext *cx, jsid id);
|
||||
Shape *nativeLookup(ExclusiveContext *cx, PropertyId pid) {
|
||||
return nativeLookup(cx, pid.asId());
|
||||
|
@ -1406,17 +1411,7 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
|||
* capacity is not stored explicitly, and the allocated size of the slot
|
||||
* array is kept in sync with this count.
|
||||
*/
|
||||
static uint32_t dynamicSlotsCount(uint32_t nfixed, uint32_t span) {
|
||||
if (span <= nfixed)
|
||||
return 0;
|
||||
span -= nfixed;
|
||||
if (span <= SLOT_CAPACITY_MIN)
|
||||
return SLOT_CAPACITY_MIN;
|
||||
|
||||
uint32_t slots = mozilla::RoundUpPow2(span);
|
||||
MOZ_ASSERT(slots >= span);
|
||||
return slots;
|
||||
}
|
||||
static uint32_t dynamicSlotsCount(uint32_t nfixed, uint32_t span, const Class *clasp);
|
||||
|
||||
/* Memory usage functions. */
|
||||
size_t tenuredSizeOfThis() const {
|
||||
|
|
Загрузка…
Ссылка в новой задаче