JS_LOCK_GC(rt);
js_AllocGCThing(JSContext *cx, uintN flags){    JSBool tried_gc;    JSRuntime *rt;    JSGCThing *thing;    uint8 *flagp;#ifdef TOO_MUCH_GC    js_GC(cx, GC_KEEP_ATOMS);    tried_gc = JS_TRUE;#else    tried_gc = JS_FALSE;#endif    rt = cx->runtime;    JS_LOCK_GC(rt);    JS_ASSERT(!rt->gcRunning);    if (rt->gcRunning) {        METER(rt->gcStats.finalfail++);        JS_UNLOCK_GC(rt);        return NULL;    }    METER(rt->gcStats.alloc++);retry:    thing = rt->gcFreeList;    if (thing) {        rt->gcFreeList = thing->next;        flagp = thing->flagp;        METER(rt->gcStats.freelen--);        METER(rt->gcStats.recycle++);    } else {        if (rt->gcBytes < rt->gcMaxBytes &&            (tried_gc || rt->gcMallocBytes < rt->gcMaxBytes))        {            /*             * Inline form of JS_ARENA_ALLOCATE adapted to truncate the current             * arena's limit to a GC_PAGE_SIZE boundary, and to skip over every             * GC_PAGE_SIZE-byte-aligned thing (which is actually not a thing,             * it's a JSGCPageInfo record).             */            JSArenaPool *pool = &rt->gcArenaPool;            JSArena *a = pool->current;            size_t nb = sizeof(JSGCThing);            jsuword p = a->avail;            jsuword q = p + nb;            if (q > (a->limit & ~GC_PAGE_MASK)) {                thing = gc_new_arena(pool);            } else {                if ((p & GC_PAGE_MASK) == 0) {                    /* Beware, p points to a JSGCPageInfo record! */                    p = q;                    q += nb;                    JS_ArenaCountAllocation(pool, nb);                }                a->avail = q;                thing = (JSGCThing *)p;            }            JS_ArenaCountAllocation(pool, nb);        }        /* Consider doing a "last ditch" GC if thing couldn't be allocated. */        if (!thing) {            if (!tried_gc) {                JS_UNLOCK_GC(rt);                js_GC(cx, GC_KEEP_ATOMS);                tried_gc = JS_TRUE;                JS_LOCK_GC(rt);                METER(rt->gcStats.retry++);                goto retry;            }            METER(rt->gcStats.fail++);            JS_UNLOCK_GC(rt);            JS_ReportOutOfMemory(cx);            return NULL;        }        /* Find the flags pointer given thing's address. */        flagp = js_GetGCThingFlags(thing);    }    *flagp = (uint8)flags;    rt->gcBytes += sizeof(JSGCThing) + sizeof(uint8);    cx->newborn[flags & GCF_TYPEMASK] = thing;    /*     * Clear thing before unlocking in case a GC run is about to scan it,     * finding it via cx->newborn[].     */    thing->next = NULL;    thing->flagp = NULL;    JS_UNLOCK_GC(rt);    return thing;}