JSObject* js::Allocate(ExclusiveContext* cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap, const Class* clasp) { static_assert(mozilla::IsConvertible<T*, JSObject*>::value, "must be JSObject derived"); MOZ_ASSERT(IsObjectAllocKind(kind)); size_t thingSize = Arena::thingSize(kind); MOZ_ASSERT(thingSize == Arena::thingSize(kind)); MOZ_ASSERT(thingSize >= sizeof(JSObject_Slots0)); static_assert(sizeof(JSObject_Slots0) >= CellSize, "All allocations must be at least the allocator-imposed minimum size."); MOZ_ASSERT_IF(nDynamicSlots != 0, clasp->isNative() || clasp->isProxy()); // Off-main-thread alloc cannot trigger GC or make runtime assertions. if (!cx->isJSContext()) { JSObject* obj = GCRuntime::tryNewTenuredObject<NoGC>(cx, kind, thingSize, nDynamicSlots); if (MOZ_UNLIKELY(allowGC && !obj)) ReportOutOfMemory(cx); return obj; } JSContext* ncx = cx->asJSContext(); JSRuntime* rt = ncx->runtime(); if (!rt->gc.checkAllocatorState<allowGC>(ncx, kind)) return nullptr; if (ncx->nursery().isEnabled() && heap != TenuredHeap) { JSObject* obj = rt->gc.tryNewNurseryObject<allowGC>(ncx, thingSize, nDynamicSlots, clasp); if (obj) return obj; // Our most common non-jit allocation path is NoGC; thus, if we fail the // alloc and cannot GC, we *must* return nullptr here so that the caller // will do a CanGC allocation to clear the nursery. Failing to do so will // cause all allocations on this path to land in Tenured, and we will not // get the benefit of the nursery. if (!allowGC) return nullptr; } return GCRuntime::tryNewTenuredObject<allowGC>(cx, kind, thingSize, nDynamicSlots); }