From 8f8b62c8455181d78ffd5ffaafcf7f43693c0392 Mon Sep 17 00:00:00 2001 From: Igor Bukanov Date: Fri, 22 Apr 2011 00:47:46 +0200 Subject: [PATCH] bug 656261 - better GC arena layout. r=wmccloskey --HG-- extra : rebase_source : d6b63d38ef586c7e1d7141c8e0859fe026803a5d --- js/src/jscell.h | 27 +---- js/src/jscompartment.cpp | 3 +- js/src/jsgc.cpp | 221 +++++++++++++++------------------------ js/src/jsgc.h | 169 +++++++++++++++--------------- js/src/jsgcmark.cpp | 4 +- js/src/jsgcstats.cpp | 59 +---------- js/src/jsstr.h | 4 +- 7 files changed, 174 insertions(+), 313 deletions(-) diff --git a/js/src/jscell.h b/js/src/jscell.h index 10a096d69e0..85db38d6273 100644 --- a/js/src/jscell.h +++ b/js/src/jscell.h @@ -45,11 +45,8 @@ struct JSCompartment; namespace js { namespace gc { -template struct Arena; struct ArenaHeader; -struct MarkingDelay; struct Chunk; -struct FreeCell; /* * Live objects are marked black. How many other additional colors are available @@ -58,13 +55,8 @@ struct FreeCell; static const uint32 BLACK = 0; /* - * A GC cell is the base class for GC Things like JSObject, JSShortString, - * JSFunction, JSXML and for an empty cell called FreeCell. It helps avoiding - * casts from an Object to a Cell whenever we call GC related mark functions. - * Cell is not the base Class for JSString because static initialization - * (used for unitStringTables) does not work with inheritance. + * A GC cell is the base class for all GC things. */ - struct Cell { static const size_t CellShift = 3; static const size_t CellSize = size_t(1) << CellShift; @@ -80,28 +72,11 @@ struct Cell { inline JSCompartment *compartment() const; - JS_ALWAYS_INLINE js::gc::FreeCell *asFreeCell() { - return reinterpret_cast(this); - } - - JS_ALWAYS_INLINE const js::gc::FreeCell *asFreeCell() const { - return reinterpret_cast(this); - } - #ifdef DEBUG inline bool isAligned() const; #endif }; -struct FreeCell : Cell { - union { - FreeCell *link; - double data; - }; -}; - -JS_STATIC_ASSERT(sizeof(FreeCell) == Cell::CellSize); - } /* namespace gc */ } /* namespace js */ diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index ecc336cdc4c..782a3b51158 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -118,8 +118,7 @@ JSCompartment::init() chunk = NULL; for (unsigned i = 0; i < FINALIZE_LIMIT; i++) arenas[i].init(); - for (unsigned i = 0; i < FINALIZE_LIMIT; i++) - freeLists.finalizables[i] = NULL; + freeLists.init(); if (!crossCompartmentWrappers.init()) return false; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 0241e2cd30e..132603ce728 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -141,7 +141,6 @@ FinalizeKind slotsToThingKind[] = { JS_STATIC_ASSERT(JS_ARRAY_LENGTH(slotsToThingKind) == SLOTS_TO_THING_KIND_LIMIT); -#ifdef DEBUG const uint8 GCThingSizeMap[] = { sizeof(JSObject), /* FINALIZE_OBJECT0 */ sizeof(JSObject), /* FINALIZE_OBJECT0_BACKGROUND */ @@ -162,80 +161,59 @@ const uint8 GCThingSizeMap[] = { #endif sizeof(JSShortString), /* FINALIZE_SHORT_STRING */ sizeof(JSString), /* FINALIZE_STRING */ - sizeof(JSString), /* FINALIZE_EXTERNAL_STRING */ + sizeof(JSExternalString), /* FINALIZE_EXTERNAL_STRING */ }; JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GCThingSizeMap) == FINALIZE_LIMIT); -JS_FRIEND_API(size_t) -ArenaHeader::getThingSize() const -{ - return GCThingSizeMap[getThingKind()]; -} -#endif - -/* Initialize the arena and setup the free list. */ -template -inline FreeCell * -Arena::buildFreeList() -{ - T *first = &t.things[0]; - T *last = &t.things[JS_ARRAY_LENGTH(t.things) - 1]; - for (T *thing = first; thing != last;) { - T *following = thing + 1; - thing->asFreeCell()->link = following->asFreeCell(); - thing = following; - } - last->asFreeCell()->link = NULL; - return first->asFreeCell(); -} - template inline bool -Arena::finalize(JSContext *cx) +Arena::finalize(JSContext *cx) { JS_ASSERT(aheader.compartment); JS_ASSERT(!aheader.getMarkingDelay()->link); - FreeCell *nextFree = aheader.freeList; + uintptr_t nextFree = reinterpret_cast(aheader.freeList); FreeCell *freeList = NULL; FreeCell **tailp = &freeList; bool allClear = true; - T *thingsEnd = &t.things[ThingsPerArena-1]; - T *thing = &t.things[0]; - thingsEnd++; + uintptr_t thing = thingsStart(sizeof(T)); + uintptr_t end = thingsEnd(); if (!nextFree) { - nextFree = thingsEnd->asFreeCell(); + nextFree = end; } else { - JS_ASSERT(thing->asFreeCell() <= nextFree); - JS_ASSERT(nextFree < thingsEnd->asFreeCell()); + JS_ASSERT(thing <= nextFree); + JS_ASSERT(nextFree < end); } - for (;; thing++) { - if (thing->asFreeCell() == nextFree) { - if (thing == thingsEnd) + for (;; thing += sizeof(T)) { + if (thing == nextFree) { + if (thing == end) break; - nextFree = nextFree->link; - if (!nextFree) { - nextFree = thingsEnd->asFreeCell(); + FreeCell *nextLink = reinterpret_cast(nextFree)->link; + if (!nextLink) { + nextFree = end; } else { - JS_ASSERT(thing->asFreeCell() < nextFree); - JS_ASSERT(nextFree < thingsEnd->asFreeCell()); + nextFree = reinterpret_cast(nextLink); + JS_ASSERT(thing < nextFree); + JS_ASSERT(nextFree < end); } - } else if (thing->asFreeCell()->isMarked()) { - allClear = false; - continue; } else { - thing->finalize(cx); + T *t = reinterpret_cast(thing); + if (t->isMarked()) { + allClear = false; + continue; + } + t->finalize(cx); #ifdef DEBUG - memset(thing, JS_FREE_PATTERN, sizeof(T)); + memset(t, JS_FREE_PATTERN, sizeof(T)); #endif } - FreeCell *t = thing->asFreeCell(); - *tailp = t; - tailp = &t->link; + FreeCell *freeCell = reinterpret_cast(thing); + *tailp = freeCell; + tailp = &freeCell->link; } #ifdef DEBUG @@ -243,21 +221,21 @@ Arena::finalize(JSContext *cx) unsigned nfree = 0; if (freeList) { JS_ASSERT(tailp != &freeList); - FreeCell *t = freeList; + FreeCell *freeCell = freeList; for (;;) { ++nfree; - if (&t->link == tailp) + if (&freeCell->link == tailp) break; - JS_ASSERT(t < t->link); - t = t->link; + JS_ASSERT(freeCell < freeCell->link); + freeCell = freeCell->link; } } if (allClear) { - JS_ASSERT(nfree == ThingsPerArena); - JS_ASSERT(freeList == static_cast(&t.things[0])); - JS_ASSERT(tailp == &t.things[ThingsPerArena-1].asFreeCell()->link); + JS_ASSERT(nfree == Arena::thingsPerArena(sizeof(T))); + JS_ASSERT(freeList->address() == thingsStart(sizeof(T))); + JS_ASSERT(tailp == &reinterpret_cast(end - sizeof(T))->link); } else { - JS_ASSERT(nfree < ThingsPerArena); + JS_ASSERT(nfree < Arena::thingsPerArena(sizeof(T))); } #endif *tailp = NULL; @@ -275,7 +253,7 @@ FinalizeArenas(JSContext *cx, ArenaHeader **listHeadp) { ArenaHeader **ap = listHeadp; while (ArenaHeader *aheader = *ap) { - bool allClear = aheader->getArena()->finalize(cx); + bool allClear = aheader->getArena()->finalize(cx); if (allClear) { *ap = aheader->next; aheader->chunk()->releaseArena(aheader); @@ -350,7 +328,33 @@ Chunk::withinArenasRange(Cell *cell) return false; } -template +/* Turn arena cells into a free list starting from the first thing. */ +template +static inline FreeCell * +BuildFreeList(ArenaHeader *aheader) +{ + uintptr_t thing = aheader->getArena()->thingsStart(thingSize); + uintptr_t end = aheader->getArena()->thingsEnd(); + FreeCell *first = reinterpret_cast(thing); + FreeCell **prevp = &first->link; + + for (thing += thingSize; thing != end; thing += thingSize) { + JS_ASSERT(thing < end); + FreeCell *cell = reinterpret_cast(thing); + + /* + * Here prevp points to the link field of the previous cell in the + * list. Write the address of the following cell into it. + */ + *prevp = cell; + prevp = &cell->link; + } + + *prevp = NULL; + return first; +} + +template ArenaHeader * Chunk::allocateArena(JSContext *cx, unsigned thingKind) { @@ -359,7 +363,7 @@ Chunk::allocateArena(JSContext *cx, unsigned thingKind) ArenaHeader *aheader = info.emptyArenaLists.getTypedFreeList(thingKind); if (!aheader) { aheader = info.emptyArenaLists.getOtherArena(); - aheader->freeList = aheader->getArena()->buildFreeList(); + aheader->freeList = BuildFreeList(aheader); } JS_ASSERT(!aheader->compartment); JS_ASSERT(!aheader->getMarkingDelay()->link); @@ -636,12 +640,12 @@ MarkArenaPtrConservatively(JSTracer *trc, ArenaHeader *aheader, uintptr_t addr) JS_ASSERT(aheader->compartment); JS_ASSERT(sizeof(T) == aheader->getThingSize()); - uintptr_t offset = (addr & ArenaMask) - Arena::FirstThingOffset; - if (offset >= Arena::ThingsSpan) + uintptr_t offset = addr & ArenaMask; + if (offset < Arena::thingsStartOffset(sizeof(T))) return CGCT_NOTARENA; /* addr can point inside the thing so we must align the address. */ - uintptr_t shift = offset % sizeof(T); + uintptr_t shift = (offset - Arena::thingsStartOffset(sizeof(T))) % sizeof(T); T *thing = reinterpret_cast(addr - shift); if (InFreeList(aheader, thing)) @@ -1099,22 +1103,6 @@ JSCompartment::reduceGCTriggerBytes(uint32 amount) { namespace js { namespace gc { -void -FreeLists::purge() -{ - /* - * Return the free list back to the arena so the GC finalization will not - * run the finalizers over unitialized bytes from free things. - */ - for (FreeCell **p = finalizables; p != JS_ARRAY_END(finalizables); ++p) { - if (FreeCell *thing = *p) { - JS_ASSERT(!thing->arenaHeader()->freeList); - thing->arenaHeader()->freeList = thing; - *p = NULL; - } - } -} - inline ArenaHeader * ArenaList::searchForFreeArena() { @@ -1126,7 +1114,7 @@ ArenaList::searchForFreeArena() return NULL; } -template +template inline ArenaHeader * ArenaList::getArenaWithFreeList(JSContext *cx, unsigned thingKind) { @@ -1192,7 +1180,7 @@ ArenaList::getArenaWithFreeList(JSContext *cx, unsigned thingKind) * to the head of the list before the cursor to prevent checking the arena * for the free things. */ - ArenaHeader *aheader = chunk->allocateArena(cx, thingKind); + ArenaHeader *aheader = chunk->allocateArena(cx, thingKind); aheader->next = head; if (cursor == &head) cursor = &aheader->next; @@ -1381,7 +1369,8 @@ RefillTypedFreeList(JSContext *cx, unsigned thingKind) if (Cell *thing = compartment->freeLists.getNext(thingKind)) return thing; } - ArenaHeader *aheader = compartment->arenas[thingKind].getArenaWithFreeList(cx, thingKind); + ArenaHeader *aheader = + compartment->arenas[thingKind].getArenaWithFreeList(cx, thingKind); if (aheader) { JS_ASSERT(sizeof(T) == aheader->getThingSize()); return compartment->freeLists.populate(aheader, thingKind); @@ -1545,15 +1534,19 @@ GCMarker::delayMarkingChildren(const void *thing) METER_UPDATE_MAX(cell->compartment()->rt->gcStats.maxunmarked, markLaterArenas); } -template static void -MarkDelayedChilderen(JSTracer *trc, ArenaHeader *aheader) +MarkDelayedChildren(JSTracer *trc, ArenaHeader *aheader) { - Arena *a = aheader->getArena(); - T *end = &a->t.things[Arena::ThingsPerArena]; - for (T* thing = &a->t.things[0]; thing != end; ++thing) { - if (thing->isMarked()) - js::gc::MarkChildren(trc, thing); + unsigned traceKind = GetFinalizableTraceKind(aheader->getThingKind()); + size_t thingSize = aheader->getThingSize(); + Arena *a = aheader->getArena(); + uintptr_t end = a->thingsEnd(); + for (uintptr_t thing = a->thingsStart(thingSize); thing != end; thing += thingSize) { + Cell *t = reinterpret_cast(thing); + if (t->isMarked()) { + JS_SET_TRACING_NAME(trc, "delayed marking thing"); + js::gc::MarkKind(trc, t, traceKind); + } } } @@ -1574,55 +1567,7 @@ GCMarker::markDelayedChildren() JS_ASSERT(markLaterArenas); markLaterArenas--; #endif - - switch (aheader->getThingKind()) { - case FINALIZE_OBJECT0: - case FINALIZE_OBJECT0_BACKGROUND: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_OBJECT2: - case FINALIZE_OBJECT2_BACKGROUND: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_OBJECT4: - case FINALIZE_OBJECT4_BACKGROUND: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_OBJECT8: - case FINALIZE_OBJECT8_BACKGROUND: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_OBJECT12: - case FINALIZE_OBJECT12_BACKGROUND: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_OBJECT16: - case FINALIZE_OBJECT16_BACKGROUND: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_STRING: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_EXTERNAL_STRING: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_SHORT_STRING: - JS_NOT_REACHED("no delayed marking"); - break; - case FINALIZE_FUNCTION: - MarkDelayedChilderen(this, aheader); - break; - case FINALIZE_SHAPE: - MarkDelayedChilderen(this, aheader); - break; -#if JS_HAS_XML_SUPPORT - case FINALIZE_XML: - MarkDelayedChilderen(this, aheader); - break; -#endif - default: - JS_NOT_REACHED("wrong thingkind"); - } + MarkDelayedChildren(this, aheader); } JS_ASSERT(!markLaterArenas); } diff --git a/js/src/jsgc.h b/js/src/jsgc.h index 143008126ff..1859f7a3fc6 100644 --- a/js/src/jsgc.h +++ b/js/src/jsgc.h @@ -77,6 +77,9 @@ struct Shape; namespace gc { +struct Arena; +struct MarkingDelay; + /* The kind of GC thing with a finalizer. */ enum FinalizeKind { FINALIZE_OBJECT0, @@ -104,6 +107,8 @@ enum FinalizeKind { FINALIZE_LIMIT }; +extern JS_FRIEND_DATA(const uint8) GCThingSizeMap[]; + const size_t ArenaShift = 12; const size_t ArenaSize = size_t(1) << ArenaShift; const size_t ArenaMask = ArenaSize - 1; @@ -119,7 +124,19 @@ const size_t ArenaBitmapBits = ArenaCellCount; const size_t ArenaBitmapBytes = ArenaBitmapBits / 8; const size_t ArenaBitmapWords = ArenaBitmapBits / JS_BITS_PER_WORD; -template struct Arena; + +struct FreeCell : Cell { + FreeCell *link; + + void checkLink() { + /* + * The GC things on the free lists come from one arena and the things + * on the free list are linked in ascending address order. + */ + JS_ASSERT_IF(link, arenaHeader() == link->arenaHeader()); + JS_ASSERT_IF(link, this < link); + } +}; /* Every arena has a header. */ struct ArenaHeader { @@ -134,9 +151,8 @@ struct ArenaHeader { inline uintptr_t address() const; inline Chunk *chunk() const; - template - Arena *getArena() { - return reinterpret_cast *>(address()); + Arena *getArena() { + return reinterpret_cast(address()); } unsigned getThingKind() const { @@ -149,9 +165,9 @@ struct ArenaHeader { inline MarkingDelay *getMarkingDelay() const; -#ifdef DEBUG - JS_FRIEND_API(size_t) getThingSize() const; -#endif + size_t getThingSize() const { + return GCThingSizeMap[getThingKind()]; + } #if defined DEBUG || defined JS_GCMETER static size_t CountListLength(const ArenaHeader *aheader) { @@ -163,74 +179,50 @@ struct ArenaHeader { #endif }; -template -struct Things { - char filler1[R1]; - T things[N]; - char filler[R2]; -}; - -template -struct Things { - char filler1[R1]; - T things[N]; -}; - -template -struct Things { - T things[N]; - char filler2[R2]; -}; - -template -struct Things { - T things[N]; -}; - -template struct Arena { /* * Layout of an arena: - * An arena is 4K. We want it to have a header followed by a list of T - * objects. However, each object should be aligned to a sizeof(T)-boundary. - * To achieve this, we pad before and after the object array. + * An arena is 4K in size and 4K-aligned. It starts with the ArenaHeader + * descriptor followed by some pad bytes. The remainder of the arena is + * filled with the array of T things. The pad bytes ensure that the thing + * array ends exactly at the end of the arena. * - * +-------------+-----+----+----+-----+----+-----+ - * | ArenaHeader | pad | T0 | T1 | ... | Tn | pad | - * +-------------+-----+----+----+-----+----+-----+ + * +-------------+-----+----+----+-----+----+ + * | ArenaHeader | pad | T0 | T1 | ... | Tn | + * +-------------+-----+----+----+-----+----+ * - * <----------------------------------------------> = 4096 bytes - * <-----> = Filler1Size - * <-------------------> = HeaderSize - * <--------------------------> = SpaceAfterHeader - * <-----> = Filler2Size + * <----------------------------------------> = ArenaSize bytes + * <-------------------> = thingsStartOffset */ - static const size_t Filler1Size = - tl::If< sizeof(ArenaHeader) % sizeof(T) == 0, size_t, - 0, - sizeof(T) - sizeof(ArenaHeader) % sizeof(T) >::result; - static const size_t HeaderSize = sizeof(ArenaHeader) + Filler1Size; - static const size_t SpaceAfterHeader = ArenaSize - HeaderSize; - static const size_t Filler2Size = SpaceAfterHeader % sizeof(T); - static const size_t ThingsPerArena = SpaceAfterHeader / sizeof(T); - static const size_t FirstThingOffset = HeaderSize; - static const size_t ThingsSpan = ThingsPerArena * sizeof(T); - ArenaHeader aheader; - Things t; + uint8_t data[ArenaSize - sizeof(ArenaHeader)]; static void staticAsserts() { - /* - * Everything we store in the heap must be a multiple of the cell - * size. - */ - JS_STATIC_ASSERT(sizeof(T) % Cell::CellSize == 0); - JS_STATIC_ASSERT(offsetof(Arena, t.things) % sizeof(T) == 0); - JS_STATIC_ASSERT(sizeof(Arena) == ArenaSize); + JS_STATIC_ASSERT(sizeof(Arena) == ArenaSize); } - inline FreeCell *buildFreeList(); + static size_t thingsPerArena(size_t thingSize) { + JS_ASSERT(thingSize % Cell::CellSize == 0); + return (ArenaSize - sizeof(ArenaHeader)) / thingSize; + } + static size_t thingsStartOffset(size_t thingSize) { + return ArenaSize - thingsPerArena(thingSize) * thingSize; + } + + uintptr_t address() const { + return aheader.address(); + } + + uintptr_t thingsStart(size_t thingSize) { + return address() | thingsStartOffset(thingSize); + } + + uintptr_t thingsEnd() { + return address() + ArenaSize; + } + + template bool finalize(JSContext *cx); }; @@ -242,8 +234,7 @@ struct Arena { struct MarkingDelay { ArenaHeader *link; - void init() - { + void init() { link = NULL; } @@ -251,7 +242,7 @@ struct MarkingDelay { * To separate arenas without things to mark later from the arena at the * marked delay stack bottom we use for the latter a special sentinel * value. We set it to the header for the second arena in the chunk - * starting the 0 address. + * starting at the 0 address. */ static ArenaHeader *stackBottom() { return reinterpret_cast(ArenaSize); @@ -382,7 +373,7 @@ JS_STATIC_ASSERT(ArenaBitmapBytes * ArenasPerChunk == sizeof(ChunkBitmap)); * marking state). */ struct Chunk { - Arena arenas[ArenasPerChunk]; + Arena arenas[ArenasPerChunk]; ChunkBitmap bitmap; MarkingDelay markingDelay[ArenasPerChunk]; ChunkInfo info; @@ -407,7 +398,7 @@ struct Chunk { bool hasAvailableArenas(); bool withinArenasRange(Cell *cell); - template + template ArenaHeader *allocateArena(JSContext *cx, unsigned thingKind); void releaseArena(ArenaHeader *aheader); @@ -447,7 +438,8 @@ Cell::chunk() const inline bool Cell::isAligned() const { - uintptr_t offset = address() & ArenaMask; + /* Things ends at the arena end. */ + uintptr_t offset = ArenaSize - (address() & ArenaMask); return offset % arenaHeader()->getThingSize() == 0; } #endif @@ -579,7 +571,7 @@ GetGCThingTraceKind(const void *thing); static inline JSRuntime * GetGCThingRuntime(void *thing) { - return reinterpret_cast(thing)->chunk()->info.runtime; + return reinterpret_cast(thing)->chunk()->info.runtime; } /* The arenas in a list have uniform kind. */ @@ -632,7 +624,7 @@ class ArenaList { inline ArenaHeader *searchForFreeArena(); - template + template inline ArenaHeader *getArenaWithFreeList(JSContext *cx, unsigned thingKind); template @@ -692,17 +684,6 @@ class ArenaList { } }; -inline void -CheckGCFreeListLink(FreeCell *cell) -{ - /* - * The GC things on the free lists come from one arena and the things on - * the free list are linked in ascending address order. - */ - JS_ASSERT_IF(cell->link, cell->arenaHeader() == cell->link->arenaHeader()); - JS_ASSERT_IF(cell->link, cell < cell->link); -} - /* * For a given arena, finalizables[thingKind] points to the next object to be * allocated. It gets initialized, in RefillTypedFreeList, to the first free @@ -717,12 +698,29 @@ CheckGCFreeListLink(FreeCell *cell) struct FreeLists { FreeCell *finalizables[FINALIZE_LIMIT]; - void purge(); + void init() { + for (size_t i = 0; i < JS_ARRAY_LENGTH(finalizables); i++) + finalizables[i] = NULL; + } + + void purge() { + /* + * Return the free list back to the arena so the GC finalization will + * not run the finalizers over unitialized bytes from free things. + */ + for (FreeCell **p = finalizables; p != JS_ARRAY_END(finalizables); ++p) { + if (FreeCell *thing = *p) { + JS_ASSERT(!thing->arenaHeader()->freeList); + thing->arenaHeader()->freeList = thing; + *p = NULL; + } + } + } FreeCell *getNext(unsigned kind) { FreeCell *top = finalizables[kind]; if (top) { - CheckGCFreeListLink(top); + top->checkLink(); finalizables[kind] = top->link; } return top; @@ -730,8 +728,7 @@ struct FreeLists { Cell *populate(ArenaHeader *aheader, uint32 thingKind) { FreeCell *cell = aheader->freeList; - JS_ASSERT(cell); - CheckGCFreeListLink(cell); + cell->checkLink(); aheader->freeList = NULL; finalizables[thingKind] = cell->link; return cell; diff --git a/js/src/jsgcmark.cpp b/js/src/jsgcmark.cpp index ff2f12cd093..6d8aff5010f 100644 --- a/js/src/jsgcmark.cpp +++ b/js/src/jsgcmark.cpp @@ -1,4 +1,4 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 @@ -107,7 +107,7 @@ Mark(JSTracer *trc, T *thing) JS_ASSERT(trc->debugPrinter || trc->debugPrintArg); JS_ASSERT(!JSAtom::isStatic(thing)); - JS_ASSERT(thing->asFreeCell()->isAligned()); + JS_ASSERT(thing->isAligned()); JSRuntime *rt = trc->context->runtime; JS_ASSERT(thing->arenaHeader()->compartment); diff --git a/js/src/jsgcstats.cpp b/js/src/jsgcstats.cpp index beee5f3dbbb..78e35195046 100644 --- a/js/src/jsgcstats.cpp +++ b/js/src/jsgcstats.cpp @@ -147,61 +147,6 @@ static const char *const GC_ARENA_NAMES[] = { }; JS_STATIC_ASSERT(JS_ARRAY_LENGTH(GC_ARENA_NAMES) == FINALIZE_LIMIT); -template -static inline void -GetSizeAndThings(size_t &thingSize, size_t &thingsPerArena) -{ - thingSize = sizeof(T); - thingsPerArena = Arena::ThingsPerArena; -} - -void GetSizeAndThingsPerArena(int thingKind, size_t &thingSize, size_t &thingsPerArena) -{ - switch (thingKind) { - case FINALIZE_OBJECT0: - case FINALIZE_OBJECT0_BACKGROUND: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_OBJECT2: - case FINALIZE_OBJECT2_BACKGROUND: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_OBJECT4: - case FINALIZE_OBJECT4_BACKGROUND: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_OBJECT8: - case FINALIZE_OBJECT8_BACKGROUND: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_OBJECT12: - case FINALIZE_OBJECT12_BACKGROUND: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_OBJECT16: - case FINALIZE_OBJECT16_BACKGROUND: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_EXTERNAL_STRING: - case FINALIZE_STRING: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_SHORT_STRING: - GetSizeAndThings(thingSize, thingsPerArena); - break; - case FINALIZE_FUNCTION: - GetSizeAndThings(thingSize, thingsPerArena); - break; -#if JS_HAS_XML_SUPPORT - case FINALIZE_XML: - GetSizeAndThings(thingSize, thingsPerArena); - break; -#endif - default: - JS_NOT_REACHED("wrong kind"); - } -} - void DumpArenaStats(JSGCArenaStats *stp, FILE *fp) { @@ -213,8 +158,8 @@ DumpArenaStats(JSGCArenaStats *stp, FILE *fp) JSGCArenaStats *st = &stp[i]; if (st->maxarenas == 0) continue; - size_t thingSize = 0, thingsPerArena = 0; - GetSizeAndThingsPerArena(i, thingSize, thingsPerArena); + size_t thingSize = GCThingSizeMap[i]; + size_t thingsPerArena = Arena::thingsPerArena(thingSize); fprintf(fp, "%s arenas (thing size %lu, %lu things per arena):\n", GC_ARENA_NAMES[i], UL(thingSize), UL(thingsPerArena)); diff --git a/js/src/jsstr.h b/js/src/jsstr.h index 0977fca5919..e9f14b3a36c 100644 --- a/js/src/jsstr.h +++ b/js/src/jsstr.h @@ -516,11 +516,11 @@ JS_STATIC_ASSERT(sizeof(JSInlineString) == sizeof(JSString)); class JSShortString : public JSInlineString { - /* This can be any value that is a multiple of sizeof(gc::FreeCell). */ + /* This can be any value that is a multiple of Cell::CellSize. */ static const size_t INLINE_EXTENSION_CHARS = sizeof(JSString::Data) / sizeof(jschar); static void staticAsserts() { - JS_STATIC_ASSERT(INLINE_EXTENSION_CHARS % sizeof(js::gc::FreeCell) == 0); + JS_STATIC_ASSERT(INLINE_EXTENSION_CHARS % js::gc::Cell::CellSize == 0); JS_STATIC_ASSERT(MAX_SHORT_LENGTH + 1 == (sizeof(JSShortString) - offsetof(JSShortString, d.inlineStorage)) / sizeof(jschar));