js/src/jsgcinlines.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jsgcinlines.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,642 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jsgcinlines_h
    1.11 +#define jsgcinlines_h
    1.12 +
    1.13 +#include "jsgc.h"
    1.14 +
    1.15 +#include "gc/Zone.h"
    1.16 +
    1.17 +namespace js {
    1.18 +
    1.19 +class Shape;
    1.20 +
    1.21 +/*
    1.22 + * This auto class should be used around any code that might cause a mark bit to
    1.23 + * be set on an object in a dead zone. See AutoMaybeTouchDeadZones
    1.24 + * for more details.
    1.25 + */
    1.26 +struct AutoMarkInDeadZone
    1.27 +{
    1.28 +    AutoMarkInDeadZone(JS::Zone *zone)
    1.29 +      : zone(zone),
    1.30 +        scheduled(zone->scheduledForDestruction)
    1.31 +    {
    1.32 +        JSRuntime *rt = zone->runtimeFromMainThread();
    1.33 +        if (rt->gcManipulatingDeadZones && zone->scheduledForDestruction) {
    1.34 +            rt->gcObjectsMarkedInDeadZones++;
    1.35 +            zone->scheduledForDestruction = false;
    1.36 +        }
    1.37 +    }
    1.38 +
    1.39 +    ~AutoMarkInDeadZone() {
    1.40 +        zone->scheduledForDestruction = scheduled;
    1.41 +    }
    1.42 +
    1.43 +  private:
    1.44 +    JS::Zone *zone;
    1.45 +    bool scheduled;
    1.46 +};
    1.47 +
    1.48 +inline Allocator *const
    1.49 +ThreadSafeContext::allocator()
    1.50 +{
    1.51 +    JS_ASSERT_IF(isJSContext(), &asJSContext()->zone()->allocator == allocator_);
    1.52 +    return allocator_;
    1.53 +}
    1.54 +
    1.55 +template <typename T>
    1.56 +inline bool
    1.57 +ThreadSafeContext::isThreadLocal(T thing) const
    1.58 +{
    1.59 +    if (!isForkJoinContext())
    1.60 +        return true;
    1.61 +
    1.62 +    if (!IsInsideNursery(runtime_, thing) &&
    1.63 +        allocator_->arenas.containsArena(runtime_, thing->arenaHeader()))
    1.64 +    {
    1.65 +        // GC should be suppressed in preparation for mutating thread local
    1.66 +        // objects, as we don't want to trip any barriers.
    1.67 +        JS_ASSERT(!thing->zoneFromAnyThread()->needsBarrier());
    1.68 +        JS_ASSERT(!thing->runtimeFromAnyThread()->needsBarrier());
    1.69 +
    1.70 +        return true;
    1.71 +    }
    1.72 +
    1.73 +    return false;
    1.74 +}
    1.75 +
    1.76 +namespace gc {
    1.77 +
    1.78 +static inline AllocKind
    1.79 +GetGCObjectKind(const Class *clasp)
    1.80 +{
    1.81 +    if (clasp == FunctionClassPtr)
    1.82 +        return JSFunction::FinalizeKind;
    1.83 +    uint32_t nslots = JSCLASS_RESERVED_SLOTS(clasp);
    1.84 +    if (clasp->flags & JSCLASS_HAS_PRIVATE)
    1.85 +        nslots++;
    1.86 +    return GetGCObjectKind(nslots);
    1.87 +}
    1.88 +
    1.89 +#ifdef JSGC_GENERATIONAL
    1.90 +inline bool
    1.91 +ShouldNurseryAllocate(const Nursery &nursery, AllocKind kind, InitialHeap heap)
    1.92 +{
    1.93 +    return nursery.isEnabled() && IsNurseryAllocable(kind) && heap != TenuredHeap;
    1.94 +}
    1.95 +#endif
    1.96 +
    1.97 +inline JSGCTraceKind
    1.98 +GetGCThingTraceKind(const void *thing)
    1.99 +{
   1.100 +    JS_ASSERT(thing);
   1.101 +    const Cell *cell = static_cast<const Cell *>(thing);
   1.102 +#ifdef JSGC_GENERATIONAL
   1.103 +    if (IsInsideNursery(cell->runtimeFromAnyThread(), cell))
   1.104 +        return JSTRACE_OBJECT;
   1.105 +#endif
   1.106 +    return MapAllocToTraceKind(cell->tenuredGetAllocKind());
   1.107 +}
   1.108 +
   1.109 +static inline void
   1.110 +GCPoke(JSRuntime *rt)
   1.111 +{
   1.112 +    rt->gcPoke = true;
   1.113 +
   1.114 +#ifdef JS_GC_ZEAL
   1.115 +    /* Schedule a GC to happen "soon" after a GC poke. */
   1.116 +    if (rt->gcZeal() == js::gc::ZealPokeValue)
   1.117 +        rt->gcNextScheduled = 1;
   1.118 +#endif
   1.119 +}
   1.120 +
   1.121 +class ArenaIter
   1.122 +{
   1.123 +    ArenaHeader *aheader;
   1.124 +    ArenaHeader *remainingHeader;
   1.125 +
   1.126 +  public:
   1.127 +    ArenaIter() {
   1.128 +        init();
   1.129 +    }
   1.130 +
   1.131 +    ArenaIter(JS::Zone *zone, AllocKind kind) {
   1.132 +        init(zone, kind);
   1.133 +    }
   1.134 +
   1.135 +    void init() {
   1.136 +        aheader = nullptr;
   1.137 +        remainingHeader = nullptr;
   1.138 +    }
   1.139 +
   1.140 +    void init(ArenaHeader *aheaderArg) {
   1.141 +        aheader = aheaderArg;
   1.142 +        remainingHeader = nullptr;
   1.143 +    }
   1.144 +
   1.145 +    void init(JS::Zone *zone, AllocKind kind) {
   1.146 +        aheader = zone->allocator.arenas.getFirstArena(kind);
   1.147 +        remainingHeader = zone->allocator.arenas.getFirstArenaToSweep(kind);
   1.148 +        if (!aheader) {
   1.149 +            aheader = remainingHeader;
   1.150 +            remainingHeader = nullptr;
   1.151 +        }
   1.152 +    }
   1.153 +
   1.154 +    bool done() {
   1.155 +        return !aheader;
   1.156 +    }
   1.157 +
   1.158 +    ArenaHeader *get() {
   1.159 +        return aheader;
   1.160 +    }
   1.161 +
   1.162 +    void next() {
   1.163 +        aheader = aheader->next;
   1.164 +        if (!aheader) {
   1.165 +            aheader = remainingHeader;
   1.166 +            remainingHeader = nullptr;
   1.167 +        }
   1.168 +    }
   1.169 +};
   1.170 +
   1.171 +class CellIterImpl
   1.172 +{
   1.173 +    size_t firstThingOffset;
   1.174 +    size_t thingSize;
   1.175 +    ArenaIter aiter;
   1.176 +    FreeSpan firstSpan;
   1.177 +    const FreeSpan *span;
   1.178 +    uintptr_t thing;
   1.179 +    Cell *cell;
   1.180 +
   1.181 +  protected:
   1.182 +    CellIterImpl() {
   1.183 +    }
   1.184 +
   1.185 +    void initSpan(JS::Zone *zone, AllocKind kind) {
   1.186 +        JS_ASSERT(zone->allocator.arenas.isSynchronizedFreeList(kind));
   1.187 +        firstThingOffset = Arena::firstThingOffset(kind);
   1.188 +        thingSize = Arena::thingSize(kind);
   1.189 +        firstSpan.initAsEmpty();
   1.190 +        span = &firstSpan;
   1.191 +        thing = span->first;
   1.192 +    }
   1.193 +
   1.194 +    void init(ArenaHeader *singleAheader) {
   1.195 +        initSpan(singleAheader->zone, singleAheader->getAllocKind());
   1.196 +        aiter.init(singleAheader);
   1.197 +        next();
   1.198 +        aiter.init();
   1.199 +    }
   1.200 +
   1.201 +    void init(JS::Zone *zone, AllocKind kind) {
   1.202 +        initSpan(zone, kind);
   1.203 +        aiter.init(zone, kind);
   1.204 +        next();
   1.205 +    }
   1.206 +
   1.207 +  public:
   1.208 +    bool done() const {
   1.209 +        return !cell;
   1.210 +    }
   1.211 +
   1.212 +    template<typename T> T *get() const {
   1.213 +        JS_ASSERT(!done());
   1.214 +        return static_cast<T *>(cell);
   1.215 +    }
   1.216 +
   1.217 +    Cell *getCell() const {
   1.218 +        JS_ASSERT(!done());
   1.219 +        return cell;
   1.220 +    }
   1.221 +
   1.222 +    void next() {
   1.223 +        for (;;) {
   1.224 +            if (thing != span->first)
   1.225 +                break;
   1.226 +            if (MOZ_LIKELY(span->hasNext())) {
   1.227 +                thing = span->last + thingSize;
   1.228 +                span = span->nextSpan();
   1.229 +                break;
   1.230 +            }
   1.231 +            if (aiter.done()) {
   1.232 +                cell = nullptr;
   1.233 +                return;
   1.234 +            }
   1.235 +            ArenaHeader *aheader = aiter.get();
   1.236 +            firstSpan = aheader->getFirstFreeSpan();
   1.237 +            span = &firstSpan;
   1.238 +            thing = aheader->arenaAddress() | firstThingOffset;
   1.239 +            aiter.next();
   1.240 +        }
   1.241 +        cell = reinterpret_cast<Cell *>(thing);
   1.242 +        thing += thingSize;
   1.243 +    }
   1.244 +};
   1.245 +
   1.246 +class CellIterUnderGC : public CellIterImpl
   1.247 +{
   1.248 +  public:
   1.249 +    CellIterUnderGC(JS::Zone *zone, AllocKind kind) {
   1.250 +#ifdef JSGC_GENERATIONAL
   1.251 +        JS_ASSERT(zone->runtimeFromAnyThread()->gcNursery.isEmpty());
   1.252 +#endif
   1.253 +        JS_ASSERT(zone->runtimeFromAnyThread()->isHeapBusy());
   1.254 +        init(zone, kind);
   1.255 +    }
   1.256 +
   1.257 +    CellIterUnderGC(ArenaHeader *aheader) {
   1.258 +        JS_ASSERT(aheader->zone->runtimeFromAnyThread()->isHeapBusy());
   1.259 +        init(aheader);
   1.260 +    }
   1.261 +};
   1.262 +
   1.263 +class CellIter : public CellIterImpl
   1.264 +{
   1.265 +    ArenaLists *lists;
   1.266 +    AllocKind kind;
   1.267 +#ifdef DEBUG
   1.268 +    size_t *counter;
   1.269 +#endif
   1.270 +  public:
   1.271 +    CellIter(JS::Zone *zone, AllocKind kind)
   1.272 +      : lists(&zone->allocator.arenas),
   1.273 +        kind(kind)
   1.274 +    {
   1.275 +        /*
   1.276 +         * We have a single-threaded runtime, so there's no need to protect
   1.277 +         * against other threads iterating or allocating. However, we do have
   1.278 +         * background finalization; we have to wait for this to finish if it's
   1.279 +         * currently active.
   1.280 +         */
   1.281 +        if (IsBackgroundFinalized(kind) &&
   1.282 +            zone->allocator.arenas.needBackgroundFinalizeWait(kind))
   1.283 +        {
   1.284 +            gc::FinishBackgroundFinalize(zone->runtimeFromMainThread());
   1.285 +        }
   1.286 +
   1.287 +#ifdef JSGC_GENERATIONAL
   1.288 +        /* Evict the nursery before iterating so we can see all things. */
   1.289 +        JSRuntime *rt = zone->runtimeFromMainThread();
   1.290 +        if (!rt->gcNursery.isEmpty())
   1.291 +            MinorGC(rt, JS::gcreason::EVICT_NURSERY);
   1.292 +#endif
   1.293 +
   1.294 +        if (lists->isSynchronizedFreeList(kind)) {
   1.295 +            lists = nullptr;
   1.296 +        } else {
   1.297 +            JS_ASSERT(!zone->runtimeFromMainThread()->isHeapBusy());
   1.298 +            lists->copyFreeListToArena(kind);
   1.299 +        }
   1.300 +
   1.301 +#ifdef DEBUG
   1.302 +        /* Assert that no GCs can occur while a CellIter is live. */
   1.303 +        counter = &zone->runtimeFromAnyThread()->noGCOrAllocationCheck;
   1.304 +        ++*counter;
   1.305 +#endif
   1.306 +
   1.307 +        init(zone, kind);
   1.308 +    }
   1.309 +
   1.310 +    ~CellIter() {
   1.311 +#ifdef DEBUG
   1.312 +        JS_ASSERT(*counter > 0);
   1.313 +        --*counter;
   1.314 +#endif
   1.315 +        if (lists)
   1.316 +            lists->clearFreeListInArena(kind);
   1.317 +    }
   1.318 +};
   1.319 +
   1.320 +class GCZonesIter
   1.321 +{
   1.322 +  private:
   1.323 +    ZonesIter zone;
   1.324 +
   1.325 +  public:
   1.326 +    GCZonesIter(JSRuntime *rt) : zone(rt, WithAtoms) {
   1.327 +        if (!zone->isCollecting())
   1.328 +            next();
   1.329 +    }
   1.330 +
   1.331 +    bool done() const { return zone.done(); }
   1.332 +
   1.333 +    void next() {
   1.334 +        JS_ASSERT(!done());
   1.335 +        do {
   1.336 +            zone.next();
   1.337 +        } while (!zone.done() && !zone->isCollecting());
   1.338 +    }
   1.339 +
   1.340 +    JS::Zone *get() const {
   1.341 +        JS_ASSERT(!done());
   1.342 +        return zone;
   1.343 +    }
   1.344 +
   1.345 +    operator JS::Zone *() const { return get(); }
   1.346 +    JS::Zone *operator->() const { return get(); }
   1.347 +};
   1.348 +
   1.349 +typedef CompartmentsIterT<GCZonesIter> GCCompartmentsIter;
   1.350 +
   1.351 +/* Iterates over all zones in the current zone group. */
   1.352 +class GCZoneGroupIter {
   1.353 +  private:
   1.354 +    JS::Zone *current;
   1.355 +
   1.356 +  public:
   1.357 +    GCZoneGroupIter(JSRuntime *rt) {
   1.358 +        JS_ASSERT(rt->isHeapBusy());
   1.359 +        current = rt->gcCurrentZoneGroup;
   1.360 +    }
   1.361 +
   1.362 +    bool done() const { return !current; }
   1.363 +
   1.364 +    void next() {
   1.365 +        JS_ASSERT(!done());
   1.366 +        current = current->nextNodeInGroup();
   1.367 +    }
   1.368 +
   1.369 +    JS::Zone *get() const {
   1.370 +        JS_ASSERT(!done());
   1.371 +        return current;
   1.372 +    }
   1.373 +
   1.374 +    operator JS::Zone *() const { return get(); }
   1.375 +    JS::Zone *operator->() const { return get(); }
   1.376 +};
   1.377 +
   1.378 +typedef CompartmentsIterT<GCZoneGroupIter> GCCompartmentGroupIter;
   1.379 +
   1.380 +#ifdef JSGC_GENERATIONAL
   1.381 +/*
   1.382 + * Attempt to allocate a new GC thing out of the nursery. If there is not enough
   1.383 + * room in the nursery or there is an OOM, this method will return nullptr.
   1.384 + */
   1.385 +template <AllowGC allowGC>
   1.386 +inline JSObject *
   1.387 +TryNewNurseryObject(ThreadSafeContext *cxArg, size_t thingSize, size_t nDynamicSlots)
   1.388 +{
   1.389 +    JSContext *cx = cxArg->asJSContext();
   1.390 +
   1.391 +    JS_ASSERT(!IsAtomsCompartment(cx->compartment()));
   1.392 +    JSRuntime *rt = cx->runtime();
   1.393 +    Nursery &nursery = rt->gcNursery;
   1.394 +    JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots);
   1.395 +    if (obj)
   1.396 +        return obj;
   1.397 +    if (allowGC && !rt->mainThread.suppressGC) {
   1.398 +        MinorGC(cx, JS::gcreason::OUT_OF_NURSERY);
   1.399 +
   1.400 +        /* Exceeding gcMaxBytes while tenuring can disable the Nursery. */
   1.401 +        if (nursery.isEnabled()) {
   1.402 +            JSObject *obj = nursery.allocateObject(cx, thingSize, nDynamicSlots);
   1.403 +            JS_ASSERT(obj);
   1.404 +            return obj;
   1.405 +        }
   1.406 +    }
   1.407 +    return nullptr;
   1.408 +}
   1.409 +#endif /* JSGC_GENERATIONAL */
   1.410 +
   1.411 +static inline bool
   1.412 +PossiblyFail()
   1.413 +{
   1.414 +    JS_OOM_POSSIBLY_FAIL();
   1.415 +    return true;
   1.416 +}
   1.417 +
   1.418 +template <AllowGC allowGC>
   1.419 +static inline bool
   1.420 +CheckAllocatorState(ThreadSafeContext *cx, AllocKind kind)
   1.421 +{
   1.422 +    if (!cx->isJSContext())
   1.423 +        return true;
   1.424 +
   1.425 +    JSContext *ncx = cx->asJSContext();
   1.426 +    JSRuntime *rt = ncx->runtime();
   1.427 +#if defined(JS_GC_ZEAL) || defined(DEBUG)
   1.428 +    JS_ASSERT_IF(rt->isAtomsCompartment(ncx->compartment()),
   1.429 +                 kind == FINALIZE_STRING ||
   1.430 +                 kind == FINALIZE_FAT_INLINE_STRING ||
   1.431 +                 kind == FINALIZE_JITCODE);
   1.432 +    JS_ASSERT(!rt->isHeapBusy());
   1.433 +    JS_ASSERT(!rt->noGCOrAllocationCheck);
   1.434 +#endif
   1.435 +
   1.436 +    // For testing out of memory conditions
   1.437 +    if (!PossiblyFail()) {
   1.438 +        js_ReportOutOfMemory(cx);
   1.439 +        return false;
   1.440 +    }
   1.441 +
   1.442 +    if (allowGC) {
   1.443 +#ifdef JS_GC_ZEAL
   1.444 +        if (rt->needZealousGC())
   1.445 +            js::gc::RunDebugGC(ncx);
   1.446 +#endif
   1.447 +
   1.448 +        if (rt->interrupt) {
   1.449 +            // Invoking the interrupt callback can fail and we can't usefully
   1.450 +            // handle that here. Just check in case we need to collect instead.
   1.451 +            js::gc::GCIfNeeded(ncx);
   1.452 +        }
   1.453 +    }
   1.454 +
   1.455 +    return true;
   1.456 +}
   1.457 +
   1.458 +template <typename T>
   1.459 +static inline void
   1.460 +CheckIncrementalZoneState(ThreadSafeContext *cx, T *t)
   1.461 +{
   1.462 +#ifdef DEBUG
   1.463 +    if (!cx->isJSContext())
   1.464 +        return;
   1.465 +
   1.466 +    Zone *zone = cx->asJSContext()->zone();
   1.467 +    JS_ASSERT_IF(t && zone->wasGCStarted() && (zone->isGCMarking() || zone->isGCSweeping()),
   1.468 +                 t->arenaHeader()->allocatedDuringIncremental);
   1.469 +#endif
   1.470 +}
   1.471 +
   1.472 +/*
   1.473 + * Allocate a new GC thing. After a successful allocation the caller must
   1.474 + * fully initialize the thing before calling any function that can potentially
   1.475 + * trigger GC. This will ensure that GC tracing never sees junk values stored
   1.476 + * in the partially initialized thing.
   1.477 + */
   1.478 +
   1.479 +template <AllowGC allowGC>
   1.480 +inline JSObject *
   1.481 +AllocateObject(ThreadSafeContext *cx, AllocKind kind, size_t nDynamicSlots, InitialHeap heap)
   1.482 +{
   1.483 +    size_t thingSize = Arena::thingSize(kind);
   1.484 +
   1.485 +    JS_ASSERT(thingSize == Arena::thingSize(kind));
   1.486 +    if (!CheckAllocatorState<allowGC>(cx, kind))
   1.487 +        return nullptr;
   1.488 +
   1.489 +#ifdef JSGC_GENERATIONAL
   1.490 +    if (cx->hasNursery() && ShouldNurseryAllocate(cx->nursery(), kind, heap)) {
   1.491 +        JSObject *obj = TryNewNurseryObject<allowGC>(cx, thingSize, nDynamicSlots);
   1.492 +        if (obj)
   1.493 +            return obj;
   1.494 +    }
   1.495 +#endif
   1.496 +
   1.497 +    HeapSlot *slots = nullptr;
   1.498 +    if (nDynamicSlots) {
   1.499 +        slots = cx->pod_malloc<HeapSlot>(nDynamicSlots);
   1.500 +        if (MOZ_UNLIKELY(!slots))
   1.501 +            return nullptr;
   1.502 +        js::Debug_SetSlotRangeToCrashOnTouch(slots, nDynamicSlots);
   1.503 +    }
   1.504 +
   1.505 +    JSObject *obj = static_cast<JSObject *>(cx->allocator()->arenas.allocateFromFreeList(kind, thingSize));
   1.506 +    if (!obj)
   1.507 +        obj = static_cast<JSObject *>(js::gc::ArenaLists::refillFreeList<allowGC>(cx, kind));
   1.508 +
   1.509 +    if (obj)
   1.510 +        obj->setInitialSlots(slots);
   1.511 +    else
   1.512 +        js_free(slots);
   1.513 +
   1.514 +    CheckIncrementalZoneState(cx, obj);
   1.515 +    return obj;
   1.516 +}
   1.517 +
   1.518 +template <typename T, AllowGC allowGC>
   1.519 +inline T *
   1.520 +AllocateNonObject(ThreadSafeContext *cx)
   1.521 +{
   1.522 +    AllocKind kind = MapTypeToFinalizeKind<T>::kind;
   1.523 +    size_t thingSize = sizeof(T);
   1.524 +
   1.525 +    JS_ASSERT(thingSize == Arena::thingSize(kind));
   1.526 +    if (!CheckAllocatorState<allowGC>(cx, kind))
   1.527 +        return nullptr;
   1.528 +
   1.529 +    T *t = static_cast<T *>(cx->allocator()->arenas.allocateFromFreeList(kind, thingSize));
   1.530 +    if (!t)
   1.531 +        t = static_cast<T *>(js::gc::ArenaLists::refillFreeList<allowGC>(cx, kind));
   1.532 +
   1.533 +    CheckIncrementalZoneState(cx, t);
   1.534 +    return t;
   1.535 +}
   1.536 +
   1.537 +/*
   1.538 + * When allocating for initialization from a cached object copy, we will
   1.539 + * potentially destroy the cache entry we want to copy if we allow GC. On the
   1.540 + * other hand, since these allocations are extremely common, we don't want to
   1.541 + * delay GC from these allocation sites. Instead we allow the GC, but still
   1.542 + * fail the allocation, forcing the non-cached path.
   1.543 + */
   1.544 +template <AllowGC allowGC>
   1.545 +inline JSObject *
   1.546 +AllocateObjectForCacheHit(JSContext *cx, AllocKind kind, InitialHeap heap)
   1.547 +{
   1.548 +#ifdef JSGC_GENERATIONAL
   1.549 +    if (ShouldNurseryAllocate(cx->nursery(), kind, heap)) {
   1.550 +        size_t thingSize = Arena::thingSize(kind);
   1.551 +
   1.552 +        JS_ASSERT(thingSize == Arena::thingSize(kind));
   1.553 +        if (!CheckAllocatorState<NoGC>(cx, kind))
   1.554 +            return nullptr;
   1.555 +
   1.556 +        JSObject *obj = TryNewNurseryObject<NoGC>(cx, thingSize, 0);
   1.557 +        if (!obj && allowGC) {
   1.558 +            MinorGC(cx, JS::gcreason::OUT_OF_NURSERY);
   1.559 +            return nullptr;
   1.560 +        }
   1.561 +        return obj;
   1.562 +    }
   1.563 +#endif
   1.564 +
   1.565 +    JSObject *obj = AllocateObject<NoGC>(cx, kind, 0, heap);
   1.566 +    if (!obj && allowGC) {
   1.567 +        MaybeGC(cx);
   1.568 +        return nullptr;
   1.569 +    }
   1.570 +
   1.571 +    return obj;
   1.572 +}
   1.573 +
   1.574 +} /* namespace gc */
   1.575 +
   1.576 +template <js::AllowGC allowGC>
   1.577 +inline JSObject *
   1.578 +NewGCObject(js::ThreadSafeContext *cx, js::gc::AllocKind kind, size_t nDynamicSlots, js::gc::InitialHeap heap)
   1.579 +{
   1.580 +    JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
   1.581 +    return js::gc::AllocateObject<allowGC>(cx, kind, nDynamicSlots, heap);
   1.582 +}
   1.583 +
   1.584 +template <js::AllowGC allowGC>
   1.585 +inline jit::JitCode *
   1.586 +NewJitCode(js::ThreadSafeContext *cx)
   1.587 +{
   1.588 +    return gc::AllocateNonObject<jit::JitCode, allowGC>(cx);
   1.589 +}
   1.590 +
   1.591 +inline
   1.592 +types::TypeObject *
   1.593 +NewTypeObject(js::ThreadSafeContext *cx)
   1.594 +{
   1.595 +    return gc::AllocateNonObject<types::TypeObject, js::CanGC>(cx);
   1.596 +}
   1.597 +
   1.598 +} /* namespace js */
   1.599 +
   1.600 +template <js::AllowGC allowGC>
   1.601 +inline JSString *
   1.602 +js_NewGCString(js::ThreadSafeContext *cx)
   1.603 +{
   1.604 +    return js::gc::AllocateNonObject<JSString, allowGC>(cx);
   1.605 +}
   1.606 +
   1.607 +template <js::AllowGC allowGC>
   1.608 +inline JSFatInlineString *
   1.609 +js_NewGCFatInlineString(js::ThreadSafeContext *cx)
   1.610 +{
   1.611 +    return js::gc::AllocateNonObject<JSFatInlineString, allowGC>(cx);
   1.612 +}
   1.613 +
   1.614 +inline JSExternalString *
   1.615 +js_NewGCExternalString(js::ThreadSafeContext *cx)
   1.616 +{
   1.617 +    return js::gc::AllocateNonObject<JSExternalString, js::CanGC>(cx);
   1.618 +}
   1.619 +
   1.620 +inline JSScript *
   1.621 +js_NewGCScript(js::ThreadSafeContext *cx)
   1.622 +{
   1.623 +    return js::gc::AllocateNonObject<JSScript, js::CanGC>(cx);
   1.624 +}
   1.625 +
   1.626 +inline js::LazyScript *
   1.627 +js_NewGCLazyScript(js::ThreadSafeContext *cx)
   1.628 +{
   1.629 +    return js::gc::AllocateNonObject<js::LazyScript, js::CanGC>(cx);
   1.630 +}
   1.631 +
   1.632 +inline js::Shape *
   1.633 +js_NewGCShape(js::ThreadSafeContext *cx)
   1.634 +{
   1.635 +    return js::gc::AllocateNonObject<js::Shape, js::CanGC>(cx);
   1.636 +}
   1.637 +
   1.638 +template <js::AllowGC allowGC>
   1.639 +inline js::BaseShape *
   1.640 +js_NewGCBaseShape(js::ThreadSafeContext *cx)
   1.641 +{
   1.642 +    return js::gc::AllocateNonObject<js::BaseShape, allowGC>(cx);
   1.643 +}
   1.644 +
   1.645 +#endif /* jsgcinlines_h */

mercurial