mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 966040 - Allocate dynamic slots for createObject and createArray in the nursery in GGC; r=jonco
This commit is contained in:
parent
efa144a708
commit
d319eb321c
@ -129,6 +129,37 @@ js::Nursery::isEmpty() const
|
||||
return position() == currentStart_;
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::Nursery::allocateObject(JSContext *cx, size_t size, size_t numDynamic)
|
||||
{
|
||||
/* Attempt to allocate slots contiguously after object, if possible. */
|
||||
if (numDynamic && numDynamic <= MaxNurserySlots) {
|
||||
size_t totalSize = size + sizeof(HeapSlot) * numDynamic;
|
||||
JSObject *obj = static_cast<JSObject *>(allocate(totalSize));
|
||||
if (obj) {
|
||||
obj->setInitialSlots(reinterpret_cast<HeapSlot *>(size_t(obj) + size));
|
||||
return obj;
|
||||
}
|
||||
/* If we failed to allocate as a block, retry with out-of-line slots. */
|
||||
}
|
||||
|
||||
HeapSlot *slots = nullptr;
|
||||
if (numDynamic) {
|
||||
slots = allocateHugeSlots(cx, numDynamic);
|
||||
if (MOZ_UNLIKELY(!slots))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JSObject *obj = static_cast<JSObject *>(allocate(size));
|
||||
|
||||
if (obj)
|
||||
obj->setInitialSlots(slots);
|
||||
else
|
||||
freeSlots(cx, slots);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
void *
|
||||
js::Nursery::allocate(size_t size)
|
||||
{
|
||||
|
@ -79,10 +79,10 @@ class Nursery
|
||||
}
|
||||
|
||||
/*
|
||||
* Allocate and return a pointer to a new GC thing. Returns nullptr if the
|
||||
* Nursery is full.
|
||||
* Allocate and return a pointer to a new GC object with its |slots|
|
||||
* pointer pre-filled. Returns nullptr if the Nursery is full.
|
||||
*/
|
||||
void *allocate(size_t size);
|
||||
JSObject *allocateObject(JSContext *cx, size_t size, size_t numDynamic);
|
||||
|
||||
/* Allocate a slots array for the given object. */
|
||||
HeapSlot *allocateSlots(JSContext *cx, JSObject *obj, uint32_t nslots);
|
||||
@ -183,7 +183,7 @@ class Nursery
|
||||
HugeSlotsSet hugeSlots;
|
||||
|
||||
/* The maximum number of slots allowed to reside inline in the nursery. */
|
||||
static const size_t MaxNurserySlots = 100;
|
||||
static const size_t MaxNurserySlots = 128;
|
||||
|
||||
/* The amount of space in the mapped nursery available to allocations. */
|
||||
static const size_t NurseryChunkUsableSize = gc::ChunkSize - sizeof(gc::ChunkTrailer);
|
||||
@ -253,6 +253,9 @@ class Nursery
|
||||
|
||||
struct TenureCountCache;
|
||||
|
||||
/* Common internal allocator function. */
|
||||
void *allocate(size_t size);
|
||||
|
||||
/*
|
||||
* Move the object at |src| in the Nursery to an already-allocated cell
|
||||
* |dst| in Tenured.
|
||||
|
@ -35,7 +35,7 @@ JSObject *
|
||||
jit::NewGCThingPar(ForkJoinContext *cx, gc::AllocKind allocKind)
|
||||
{
|
||||
JS_ASSERT(ForkJoinContext::current() == cx);
|
||||
return js_NewGCObject<NoGC>(cx, allocKind, gc::TenuredHeap);
|
||||
return js::NewGCObject<NoGC>(cx, allocKind, 0, gc::TenuredHeap);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -102,7 +102,7 @@ InvokeFunction(JSContext *cx, HandleObject obj0, uint32_t argc, Value *argv, Val
|
||||
JSObject *
|
||||
NewGCObject(JSContext *cx, gc::AllocKind allocKind, gc::InitialHeap initialHeap)
|
||||
{
|
||||
return js_NewGCObject<CanGC>(cx, allocKind, initialHeap);
|
||||
return js::NewGCObject<CanGC>(cx, allocKind, 0, initialHeap);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -379,27 +379,26 @@ typedef CompartmentsIterT<GCZoneGroupIter> GCCompartmentGroupIter;
|
||||
* Attempt to allocate a new GC thing out of the nursery. If there is not enough
|
||||
* room in the nursery or there is an OOM, this method will return nullptr.
|
||||
*/
|
||||
template <typename T, AllowGC allowGC>
|
||||
inline T *
|
||||
TryNewNurseryGCThing(ThreadSafeContext *cxArg, size_t thingSize)
|
||||
template <AllowGC allowGC>
|
||||
inline JSObject *
|
||||
TryNewNurseryObject(ThreadSafeContext *cxArg, size_t thingSize, size_t nDynamicSlots)
|
||||
{
|
||||
/* TODO: Integrate PJS with generational GC. */
|
||||
JSContext *cx = cxArg->asJSContext();
|
||||
|
||||
JS_ASSERT(!IsAtomsCompartment(cx->compartment()));
|
||||
JSRuntime *rt = cx->runtime();
|
||||
Nursery &nursery = rt->gcNursery;
|
||||
T *t = static_cast<T *>(nursery.allocate(thingSize));
|
||||
if (t)
|
||||
return t;
|
||||
JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots);
|
||||
if (obj)
|
||||
return obj;
|
||||
if (allowGC && !rt->mainThread.suppressGC) {
|
||||
MinorGC(cx, JS::gcreason::OUT_OF_NURSERY);
|
||||
|
||||
/* Exceeding gcMaxBytes while tenuring can disable the Nursery. */
|
||||
if (nursery.isEnabled()) {
|
||||
t = static_cast<T *>(nursery.allocate(thingSize));
|
||||
JS_ASSERT(t);
|
||||
return t;
|
||||
JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots);
|
||||
JS_ASSERT(obj);
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
@ -459,9 +458,9 @@ CheckIncrementalZoneState(ThreadSafeContext *cx, T *t)
|
||||
* in the partially initialized thing.
|
||||
*/
|
||||
|
||||
template <typename T, AllowGC allowGC>
|
||||
inline T *
|
||||
AllocateObject(ThreadSafeContext *cx, AllocKind kind, InitialHeap heap)
|
||||
template <AllowGC allowGC>
|
||||
inline JSObject *
|
||||
AllocateObject(ThreadSafeContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap)
|
||||
{
|
||||
size_t thingSize = Arena::thingSize(kind);
|
||||
|
||||
@ -471,18 +470,31 @@ AllocateObject(ThreadSafeContext *cx, AllocKind kind, InitialHeap heap)
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (cx->hasNursery() && ShouldNurseryAllocate(cx->nursery(), kind, heap)) {
|
||||
T *t = TryNewNurseryGCThing<T, allowGC>(cx, thingSize);
|
||||
if (t)
|
||||
return t;
|
||||
JSObject *obj = TryNewNurseryObject<allowGC>(cx, thingSize, nDynamicSlots);
|
||||
if (obj)
|
||||
return obj;
|
||||
}
|
||||
#endif
|
||||
|
||||
T *t = static_cast<T *>(cx->allocator()->arenas.allocateFromFreeList(kind, thingSize));
|
||||
if (!t)
|
||||
t = static_cast<T *>(js::gc::ArenaLists::refillFreeList<allowGC>(cx, kind));
|
||||
HeapSlot *slots = nullptr;
|
||||
if (nDynamicSlots) {
|
||||
slots = cx->pod_malloc<HeapSlot>(nDynamicSlots);
|
||||
if (MOZ_UNLIKELY(!slots))
|
||||
return nullptr;
|
||||
js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
|
||||
}
|
||||
|
||||
CheckIncrementalZoneState(cx, t);
|
||||
return t;
|
||||
JSObject *obj = static_cast<JSObject *>(cx->allocator()->arenas.allocateFromFreeList(kind, thingSize));
|
||||
if (!obj)
|
||||
obj = static_cast<JSObject *>(js::gc::ArenaLists::refillFreeList<allowGC>(cx, kind));
|
||||
|
||||
if (obj)
|
||||
obj->setInitialSlots(slots);
|
||||
else
|
||||
js_free(slots);
|
||||
|
||||
CheckIncrementalZoneState(cx, obj);
|
||||
return obj;
|
||||
}
|
||||
|
||||
template <typename T, AllowGC allowGC>
|
||||
@ -506,6 +518,14 @@ AllocateNonObject(ThreadSafeContext *cx)
|
||||
|
||||
} /* namespace gc */
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSObject *
|
||||
NewGCObject(js::ThreadSafeContext *cx, js::gc::AllocKind kind, size_t nDynamicSlots, js::gc::InitialHeap heap)
|
||||
{
|
||||
JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
|
||||
return js::gc::AllocateObject<allowGC>(cx, kind, nDynamicSlots, heap);
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline jit::JitCode *
|
||||
NewJitCode(js::ThreadSafeContext *cx)
|
||||
@ -522,14 +542,6 @@ NewTypeObject(js::ThreadSafeContext *cx)
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSObject *
|
||||
js_NewGCObject(js::ThreadSafeContext *cx, js::gc::AllocKind kind, js::gc::InitialHeap heap)
|
||||
{
|
||||
JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
|
||||
return js::gc::AllocateObject<JSObject, allowGC>(cx, kind, heap);
|
||||
}
|
||||
|
||||
template <js::AllowGC allowGC>
|
||||
inline JSString *
|
||||
js_NewGCString(js::ThreadSafeContext *cx)
|
||||
|
@ -499,31 +499,15 @@ JSObject::create(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::Initi
|
||||
JS_ASSERT_IF(type->clasp()->finalize, heap == js::gc::TenuredHeap);
|
||||
JS_ASSERT_IF(extantSlots, dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan()));
|
||||
|
||||
js::HeapSlot *slots = extantSlots;
|
||||
if (!slots) {
|
||||
size_t nDynamicSlots = dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan());
|
||||
if (nDynamicSlots) {
|
||||
slots = cx->pod_malloc<js::HeapSlot>(nDynamicSlots);
|
||||
if (!slots)
|
||||
return nullptr;
|
||||
js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
|
||||
}
|
||||
}
|
||||
|
||||
JSObject *obj = js_NewGCObject<js::CanGC>(cx, kind, heap);
|
||||
if (!obj) {
|
||||
js_free(slots);
|
||||
size_t nDynamicSlots = extantSlots ? 0 : dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan());
|
||||
JSObject *obj = js::NewGCObject<js::CanGC>(cx, kind, nDynamicSlots, heap);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (slots && heap != js::gc::TenuredHeap)
|
||||
cx->asJSContext()->runtime()->gcNursery.notifyInitialSlots(obj, slots);
|
||||
#endif
|
||||
|
||||
obj->shape_.init(shape);
|
||||
obj->type_.init(type);
|
||||
obj->slots = slots;
|
||||
if (extantSlots)
|
||||
obj->slots = extantSlots;
|
||||
obj->elements = js::emptyObjectElements;
|
||||
|
||||
const js::Class *clasp = type->clasp();
|
||||
@ -553,37 +537,15 @@ JSObject::createArray(js::ExclusiveContext *cx, js::gc::AllocKind kind, js::gc::
|
||||
* named properties stored in those fixed slots.
|
||||
*/
|
||||
JS_ASSERT(shape->numFixedSlots() == 0);
|
||||
|
||||
/*
|
||||
* The array initially stores its elements inline, there must be enough
|
||||
* space for an elements header.
|
||||
*/
|
||||
JS_ASSERT(js::gc::GetGCKindSlots(kind) >= js::ObjectElements::VALUES_PER_HEADER);
|
||||
|
||||
js::HeapSlot *slots = nullptr;
|
||||
if (size_t nDynamicSlots = dynamicSlotsCount(shape->numFixedSlots(), shape->slotSpan())) {
|
||||
slots = cx->pod_malloc<js::HeapSlot>(nDynamicSlots);
|
||||
if (!slots)
|
||||
return nullptr;
|
||||
js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
|
||||
}
|
||||
|
||||
JSObject *obj = js_NewGCObject<js::CanGC>(cx, kind, heap);
|
||||
if (!obj) {
|
||||
js_free(slots);
|
||||
size_t nDynamicSlots = dynamicSlotsCount(0, shape->slotSpan());
|
||||
JSObject *obj = js::NewGCObject<js::CanGC>(cx, kind, nDynamicSlots, heap);
|
||||
if (!obj)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (slots && heap != js::gc::TenuredHeap)
|
||||
cx->asJSContext()->runtime()->gcNursery.notifyInitialSlots(obj, slots);
|
||||
#endif
|
||||
|
||||
uint32_t capacity = js::gc::GetGCKindSlots(kind) - js::ObjectElements::VALUES_PER_HEADER;
|
||||
|
||||
obj->shape_.init(shape);
|
||||
obj->type_.init(type);
|
||||
obj->slots = slots;
|
||||
obj->setFixedElements();
|
||||
new (obj->getElementsHeader()) js::ObjectElements(capacity, length);
|
||||
|
||||
|
@ -1521,6 +1521,9 @@ class ObjectImpl : public gc::BarrieredCell<ObjectImpl>
|
||||
return privateRef(nfixed);
|
||||
}
|
||||
|
||||
/* GC Accessors */
|
||||
void setInitialSlots(HeapSlot *newSlots) { slots = newSlots; }
|
||||
|
||||
/* JIT Accessors */
|
||||
static size_t offsetOfShape() { return offsetof(ObjectImpl, shape_); }
|
||||
HeapPtrShape *addressOfShape() { return &shape_; }
|
||||
|
@ -58,7 +58,7 @@ NewObjectCache::newObjectFromHit(JSContext *cx, EntryIndex entry_, js::gc::Initi
|
||||
if (cx->runtime()->upcomingZealousGC())
|
||||
return nullptr;
|
||||
|
||||
JSObject *obj = js_NewGCObject<NoGC>(cx, entry->kind, heap);
|
||||
JSObject *obj = js::NewGCObject<NoGC>(cx, entry->kind, 0, heap);
|
||||
if (obj) {
|
||||
copyCachedToObject(obj, templateObj, entry->kind);
|
||||
probes::CreateObject(cx, obj);
|
||||
|
Loading…
Reference in New Issue
Block a user