mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 605029 - ArenaHeader versus Arena<FreeCell> and other cleanups. r=wmccloskey
This commit is contained in:
parent
a61c26e2c0
commit
8b0d367736
@ -652,7 +652,7 @@ check-malloc-function-usage: $(filter-out %jsalloc.h %jscntxt.h %jsutil.h, $(ALL
|
||||
|
||||
# We desire these numbers to go down, not up. See "User guide to memory
|
||||
# management within SpiderMonkey" in jsutil.h.
|
||||
$(srcdir)/config/check_source_count.py OffTheBooks:: 53 \
|
||||
$(srcdir)/config/check_source_count.py OffTheBooks:: 52 \
|
||||
"in Makefile.in" "{cx,rt}->{new_,new_array,malloc_,calloc_,realloc_}" $^
|
||||
# This should go to zero, if possible.
|
||||
$(srcdir)/config/check_source_count.py UnwantedForeground:: 34 \
|
||||
|
@ -1064,7 +1064,7 @@ JSObject::makeDenseArraySlow(JSContext *cx)
|
||||
|
||||
/* Create a native scope. */
|
||||
JSObject *arrayProto = getProto();
|
||||
js::gc::FinalizeKind kind = js::gc::FinalizeKind(arena()->header()->thingKind);
|
||||
js::gc::FinalizeKind kind = js::gc::FinalizeKind(arenaHeader()->getThingKind());
|
||||
if (!InitScopeForObject(cx, this, &js_SlowArrayClass, arrayProto, kind))
|
||||
return false;
|
||||
|
||||
|
@ -47,6 +47,7 @@ namespace gc {
|
||||
|
||||
template <typename T> struct Arena;
|
||||
struct ArenaBitmap;
|
||||
struct ArenaHeader;
|
||||
struct MarkingDelay;
|
||||
struct Chunk;
|
||||
struct FreeCell;
|
||||
@ -64,7 +65,8 @@ struct Cell {
|
||||
static const size_t CellSize = size_t(1) << CellShift;
|
||||
static const size_t CellMask = CellSize - 1;
|
||||
|
||||
inline Arena<Cell> *arena() const;
|
||||
inline uintptr_t address() const;
|
||||
inline ArenaHeader *arenaHeader() const;
|
||||
inline Chunk *chunk() const;
|
||||
inline ArenaBitmap *bitmap() const;
|
||||
JS_ALWAYS_INLINE size_t cellIndex() const;
|
||||
@ -82,9 +84,12 @@ struct Cell {
|
||||
JS_ALWAYS_INLINE const js::gc::FreeCell *asFreeCell() const {
|
||||
return reinterpret_cast<const FreeCell *>(this);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
inline bool isAligned() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* FreeCell has always size 8 */
|
||||
struct FreeCell : Cell {
|
||||
union {
|
||||
FreeCell *link;
|
||||
@ -92,7 +97,7 @@ struct FreeCell : Cell {
|
||||
};
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(FreeCell) == 8);
|
||||
JS_STATIC_ASSERT(sizeof(FreeCell) == Cell::CellSize);
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
666
js/src/jsgc.cpp
666
js/src/jsgc.cpp
File diff suppressed because it is too large
Load Diff
421
js/src/jsgc.h
421
js/src/jsgc.h
@ -92,6 +92,7 @@ enum FinalizeKind {
|
||||
FINALIZE_OBJECT16_BACKGROUND,
|
||||
FINALIZE_OBJECT_LAST = FINALIZE_OBJECT16_BACKGROUND,
|
||||
FINALIZE_FUNCTION,
|
||||
FINALIZE_FUNCTION_AND_OBJECT_LAST = FINALIZE_FUNCTION,
|
||||
FINALIZE_SHAPE,
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
FINALIZE_XML,
|
||||
@ -102,18 +103,43 @@ enum FinalizeKind {
|
||||
FINALIZE_LIMIT
|
||||
};
|
||||
|
||||
const uintN JS_FINALIZE_OBJECT_LIMIT = 12;
|
||||
const size_t ArenaShift = 12;
|
||||
const size_t ArenaSize = size_t(1) << ArenaShift;
|
||||
const size_t ArenaMask = ArenaSize - 1;
|
||||
|
||||
template <typename T> struct Arena;
|
||||
|
||||
/* Every arena has a header. */
|
||||
struct ArenaHeader {
|
||||
JSCompartment *compartment;
|
||||
Arena<FreeCell> *next;
|
||||
ArenaHeader *next;
|
||||
FreeCell *freeList;
|
||||
|
||||
private:
|
||||
unsigned thingKind;
|
||||
|
||||
public:
|
||||
inline uintptr_t address() const;
|
||||
inline Chunk *chunk() const;
|
||||
inline ArenaBitmap *bitmap() const;
|
||||
|
||||
template <typename T>
|
||||
Arena<T> *getArena() {
|
||||
return reinterpret_cast<Arena<T> *>(address());
|
||||
}
|
||||
|
||||
unsigned getThingKind() const {
|
||||
return thingKind;
|
||||
}
|
||||
|
||||
void setThingKind(unsigned kind) {
|
||||
thingKind = kind;
|
||||
}
|
||||
|
||||
inline MarkingDelay *getMarkingDelay() const;
|
||||
|
||||
#ifdef DEBUG
|
||||
size_t thingSize;
|
||||
bool isUsed;
|
||||
bool hasFreeThings;
|
||||
JS_FRIEND_API(size_t) getThingSize() const;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -143,10 +169,6 @@ struct Things<T, N, 0, 0> {
|
||||
|
||||
template <typename T>
|
||||
struct Arena {
|
||||
static const size_t ArenaSize = 4096;
|
||||
|
||||
ArenaHeader aheader;
|
||||
|
||||
/*
|
||||
* Layout of an arena:
|
||||
* An arena is 4K. We want it to have a header followed by a list of T
|
||||
@ -171,35 +193,28 @@ struct Arena {
|
||||
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, ThingsPerArena, Filler1Size, Filler2Size> t;
|
||||
|
||||
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>, t.things) % sizeof(T) == 0);
|
||||
JS_STATIC_ASSERT(sizeof(Arena<T>) == ArenaSize);
|
||||
}
|
||||
|
||||
inline Chunk *chunk() const;
|
||||
inline size_t arenaIndex() const;
|
||||
inline FreeCell *buildFreeList();
|
||||
|
||||
inline ArenaHeader *header() { return &aheader; };
|
||||
|
||||
inline MarkingDelay *getMarkingDelay() const;
|
||||
inline ArenaBitmap *bitmap() const;
|
||||
|
||||
inline ConservativeGCTest mark(T *thing, JSTracer *trc);
|
||||
void markDelayedChildren(JSTracer *trc);
|
||||
inline bool inFreeList(void *thing) const;
|
||||
inline T *getAlignedThing(const void *thing);
|
||||
#ifdef DEBUG
|
||||
inline bool assureThingIsAligned(void *thing);
|
||||
#endif
|
||||
|
||||
void init(JSCompartment *compartment, unsigned thingKind);
|
||||
bool finalize(JSContext *cx);
|
||||
};
|
||||
|
||||
void FinalizeArena(Arena<FreeCell> *a);
|
||||
void FinalizeArena(ArenaHeader *aheader);
|
||||
|
||||
/*
|
||||
* Live objects are marked black. How many other additional colors are available
|
||||
@ -209,7 +224,7 @@ static const uint32 BLACK = 0;
|
||||
|
||||
/* An arena bitmap contains enough mark bits for all the cells in an arena. */
|
||||
struct ArenaBitmap {
|
||||
static const size_t BitCount = Arena<FreeCell>::ArenaSize / Cell::CellSize;
|
||||
static const size_t BitCount = ArenaSize / Cell::CellSize;
|
||||
static const size_t BitWords = BitCount / JS_BITS_PER_WORD;
|
||||
|
||||
uintptr_t bitmap[BitWords];
|
||||
@ -258,100 +273,76 @@ struct ArenaBitmap {
|
||||
};
|
||||
|
||||
/* Ensure that bitmap covers the whole arena. */
|
||||
JS_STATIC_ASSERT(Arena<FreeCell>::ArenaSize % Cell::CellSize == 0);
|
||||
JS_STATIC_ASSERT(ArenaSize % Cell::CellSize == 0);
|
||||
JS_STATIC_ASSERT(ArenaBitmap::BitCount % JS_BITS_PER_WORD == 0);
|
||||
|
||||
/* Marking delay is used to resume marking later when recursive marking uses too much stack. */
|
||||
/*
|
||||
* When recursive marking uses too much stack the marking is delayed and
|
||||
* the corresponding arenas are put into a stack using a linked via the
|
||||
* following per arena structure.
|
||||
*/
|
||||
struct MarkingDelay {
|
||||
Arena<Cell> *link;
|
||||
uintptr_t unmarkedChildren;
|
||||
jsuword start;
|
||||
ArenaHeader *link;
|
||||
|
||||
void init()
|
||||
{
|
||||
link = NULL;
|
||||
unmarkedChildren = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
static ArenaHeader *stackBottom() {
|
||||
return reinterpret_cast<ArenaHeader *>(ArenaSize);
|
||||
}
|
||||
};
|
||||
|
||||
struct EmptyArenaLists {
|
||||
/* Arenas with no internal freelist prepared. */
|
||||
Arena<FreeCell> *cellFreeList;
|
||||
ArenaHeader *cellFreeList;
|
||||
|
||||
/* Arenas with internal freelists prepared for a given finalize kind. */
|
||||
Arena<FreeCell> *freeLists[FINALIZE_LIMIT];
|
||||
ArenaHeader *freeLists[FINALIZE_LIMIT];
|
||||
|
||||
void init() {
|
||||
PodZero(this);
|
||||
}
|
||||
|
||||
Arena<FreeCell> *getOtherArena() {
|
||||
Arena<FreeCell> *arena = cellFreeList;
|
||||
if (arena) {
|
||||
cellFreeList = arena->header()->next;
|
||||
return arena;
|
||||
ArenaHeader *getOtherArena() {
|
||||
ArenaHeader *aheader = cellFreeList;
|
||||
if (aheader) {
|
||||
cellFreeList = aheader->next;
|
||||
return aheader;
|
||||
}
|
||||
for (int i = 0; i < FINALIZE_LIMIT; i++) {
|
||||
if ((arena = (Arena<FreeCell> *) freeLists[i])) {
|
||||
freeLists[i] = freeLists[i]->header()->next;
|
||||
return arena;
|
||||
aheader = freeLists[i];
|
||||
if (aheader) {
|
||||
freeLists[i] = aheader->next;
|
||||
return aheader;
|
||||
}
|
||||
}
|
||||
JS_NOT_REACHED("No arena");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Arena<T> *getTypedFreeList(unsigned thingKind);
|
||||
ArenaHeader *getTypedFreeList(unsigned thingKind) {
|
||||
JS_ASSERT(thingKind < FINALIZE_LIMIT);
|
||||
ArenaHeader *aheader = freeLists[thingKind];
|
||||
if (aheader)
|
||||
freeLists[thingKind] = aheader->next;
|
||||
return aheader;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline Arena<T> *getNext(JSCompartment *comp, unsigned thingKind);
|
||||
|
||||
template <typename T>
|
||||
inline void insert(Arena<T> *arena);
|
||||
void insert(ArenaHeader *aheader) {
|
||||
unsigned thingKind = aheader->getThingKind();
|
||||
aheader->next = freeLists[thingKind];
|
||||
freeLists[thingKind] = aheader;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline Arena<T> *
|
||||
EmptyArenaLists::getTypedFreeList(unsigned thingKind) {
|
||||
JS_ASSERT(thingKind < FINALIZE_LIMIT);
|
||||
Arena<T> *arena = (Arena<T>*) freeLists[thingKind];
|
||||
if (arena) {
|
||||
freeLists[thingKind] = freeLists[thingKind]->header()->next;
|
||||
return arena;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Arena<T> *
|
||||
EmptyArenaLists::getNext(JSCompartment *comp, unsigned thingKind) {
|
||||
Arena<T> *arena = getTypedFreeList<T>(thingKind);
|
||||
if (arena) {
|
||||
JS_ASSERT(arena->header()->isUsed == false);
|
||||
JS_ASSERT(arena->header()->thingSize == sizeof(T));
|
||||
#ifdef DEBUG
|
||||
arena->header()->isUsed = true;
|
||||
#endif
|
||||
arena->header()->thingKind = thingKind;
|
||||
arena->header()->compartment = comp;
|
||||
return arena;
|
||||
}
|
||||
arena = (Arena<T> *)getOtherArena();
|
||||
JS_ASSERT(arena->header()->isUsed == false);
|
||||
arena->init(comp, thingKind);
|
||||
return arena;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void
|
||||
EmptyArenaLists::insert(Arena<T> *arena) {
|
||||
unsigned thingKind = arena->header()->thingKind;
|
||||
JS_ASSERT(thingKind < FINALIZE_LIMIT);
|
||||
arena->header()->next = freeLists[thingKind];
|
||||
freeLists[thingKind] = (Arena<FreeCell> *) arena;
|
||||
}
|
||||
|
||||
/* The chunk header (located at the end of the chunk to preserve arena alignment). */
|
||||
struct ChunkInfo {
|
||||
Chunk *link;
|
||||
@ -366,9 +357,9 @@ struct ChunkInfo {
|
||||
|
||||
/* Chunks contain arenas and associated data structures (mark bitmap, delayed marking state). */
|
||||
struct Chunk {
|
||||
static const size_t BytesPerArena = sizeof(Arena<FreeCell>) +
|
||||
static const size_t BytesPerArena = ArenaSize +
|
||||
sizeof(ArenaBitmap) +
|
||||
sizeof(MarkingDelay);
|
||||
sizeof(sizeof(MarkingDelay));
|
||||
|
||||
static const size_t ArenasPerChunk = (GC_CHUNK_SIZE - sizeof(ChunkInfo)) / BytesPerArena;
|
||||
|
||||
@ -378,6 +369,21 @@ struct Chunk {
|
||||
|
||||
ChunkInfo info;
|
||||
|
||||
static Chunk *fromAddress(uintptr_t addr) {
|
||||
addr &= ~GC_CHUNK_MASK;
|
||||
return reinterpret_cast<Chunk *>(addr);
|
||||
}
|
||||
|
||||
static bool withinArenasRange(uintptr_t addr) {
|
||||
uintptr_t offset = addr & GC_CHUNK_MASK;
|
||||
return offset < ArenasPerChunk * ArenaSize;
|
||||
}
|
||||
|
||||
static size_t arenaIndex(uintptr_t addr) {
|
||||
JS_ASSERT(withinArenasRange(addr));
|
||||
return (addr & GC_CHUNK_MASK) >> ArenaShift;
|
||||
}
|
||||
|
||||
void clearMarkBitmap();
|
||||
bool init(JSRuntime *rt);
|
||||
|
||||
@ -386,30 +392,37 @@ struct Chunk {
|
||||
bool withinArenasRange(Cell *cell);
|
||||
|
||||
template <typename T>
|
||||
Arena<T> *allocateArena(JSContext *cx, unsigned thingKind);
|
||||
ArenaHeader *allocateArena(JSContext *cx, unsigned thingKind);
|
||||
|
||||
template <typename T>
|
||||
void releaseArena(Arena<T> *a);
|
||||
void releaseArena(ArenaHeader *aheader);
|
||||
|
||||
JSRuntime *getRuntime();
|
||||
};
|
||||
JS_STATIC_ASSERT(sizeof(Chunk) <= GC_CHUNK_SIZE);
|
||||
JS_STATIC_ASSERT(sizeof(Chunk) + Chunk::BytesPerArena > GC_CHUNK_SIZE);
|
||||
|
||||
Arena<Cell> *
|
||||
Cell::arena() const
|
||||
inline uintptr_t
|
||||
Cell::address() const
|
||||
{
|
||||
uintptr_t addr = uintptr_t(this);
|
||||
JS_ASSERT(addr % sizeof(FreeCell) == 0);
|
||||
addr &= ~(Arena<FreeCell>::ArenaSize - 1);
|
||||
return reinterpret_cast<Arena<Cell> *>(addr);
|
||||
JS_ASSERT(addr % Cell::CellSize == 0);
|
||||
JS_ASSERT(Chunk::withinArenasRange(addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
inline ArenaHeader *
|
||||
Cell::arenaHeader() const
|
||||
{
|
||||
uintptr_t addr = address();
|
||||
addr &= ~ArenaMask;
|
||||
return reinterpret_cast<ArenaHeader *>(addr);
|
||||
}
|
||||
|
||||
Chunk *
|
||||
Cell::chunk() const
|
||||
{
|
||||
uintptr_t addr = uintptr_t(this);
|
||||
JS_ASSERT(addr % sizeof(FreeCell) == 0);
|
||||
JS_ASSERT(addr % Cell::CellSize == 0);
|
||||
addr &= ~(GC_CHUNK_SIZE - 1);
|
||||
return reinterpret_cast<Chunk *>(addr);
|
||||
}
|
||||
@ -417,70 +430,60 @@ Cell::chunk() const
|
||||
ArenaBitmap *
|
||||
Cell::bitmap() const
|
||||
{
|
||||
return &chunk()->bitmaps[arena()->arenaIndex()];
|
||||
return &chunk()->bitmaps[Chunk::arenaIndex(address())];
|
||||
}
|
||||
|
||||
STATIC_POSTCONDITION_ASSUME(return < ArenaBitmap::BitCount)
|
||||
size_t
|
||||
Cell::cellIndex() const
|
||||
{
|
||||
return this->asFreeCell() - arena()->t.things[0].asFreeCell();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Chunk *
|
||||
Arena<T>::chunk() const
|
||||
{
|
||||
uintptr_t addr = uintptr_t(this);
|
||||
JS_ASSERT(addr % sizeof(FreeCell) == 0);
|
||||
addr &= ~(GC_CHUNK_SIZE - 1);
|
||||
return reinterpret_cast<Chunk *>(addr);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
size_t
|
||||
Arena<T>::arenaIndex() const
|
||||
{
|
||||
return reinterpret_cast<const Arena<FreeCell> *>(this) - chunk()->arenas;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
MarkingDelay *
|
||||
Arena<T>::getMarkingDelay() const
|
||||
{
|
||||
return &chunk()->markingDelay[arenaIndex()];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
ArenaBitmap *
|
||||
Arena<T>::bitmap() const
|
||||
{
|
||||
return &chunk()->bitmaps[arenaIndex()];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T *
|
||||
Arena<T>::getAlignedThing(const void *thing)
|
||||
{
|
||||
jsuword start = reinterpret_cast<jsuword>(&t.things[0]);
|
||||
jsuword offset = reinterpret_cast<jsuword>(thing) - start;
|
||||
offset -= offset % sizeof(T);
|
||||
return reinterpret_cast<T *>(start + offset);
|
||||
uintptr_t addr = address();
|
||||
return (addr & ArenaMask) >> Cell::CellShift;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
template <typename T>
|
||||
inline bool
|
||||
Arena<T>::assureThingIsAligned(void *thing)
|
||||
Cell::isAligned() const
|
||||
{
|
||||
return (getAlignedThing(thing) == thing);
|
||||
uintptr_t offset = address() & ArenaMask;
|
||||
return offset % arenaHeader()->getThingSize() == 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline uintptr_t
|
||||
ArenaHeader::address() const
|
||||
{
|
||||
uintptr_t addr = reinterpret_cast<uintptr_t>(this);
|
||||
JS_ASSERT(!(addr & ArenaMask));
|
||||
JS_ASSERT(Chunk::withinArenasRange(addr));
|
||||
return addr;
|
||||
}
|
||||
|
||||
inline Chunk *
|
||||
ArenaHeader::chunk() const
|
||||
{
|
||||
return Chunk::fromAddress(address());
|
||||
}
|
||||
|
||||
inline ArenaBitmap *
|
||||
ArenaHeader::bitmap() const
|
||||
{
|
||||
return &chunk()->bitmaps[Chunk::arenaIndex(address())];
|
||||
}
|
||||
|
||||
inline MarkingDelay *
|
||||
ArenaHeader::getMarkingDelay() const
|
||||
{
|
||||
return &chunk()->markingDelay[Chunk::arenaIndex(address())];
|
||||
}
|
||||
|
||||
static void
|
||||
AssertValidColor(const void *thing, uint32 color)
|
||||
{
|
||||
JS_ASSERT_IF(color, color < reinterpret_cast<const js::gc::FreeCell *>(thing)->arena()->header()->thingSize / sizeof(FreeCell));
|
||||
#ifdef DEBUG
|
||||
ArenaHeader *aheader = reinterpret_cast<const js::gc::Cell *>(thing)->arenaHeader();
|
||||
JS_ASSERT_IF(color, color < aheader->getThingSize() / Cell::CellSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
@ -508,15 +511,7 @@ Cell::unmark(uint32 color) const
|
||||
JSCompartment *
|
||||
Cell::compartment() const
|
||||
{
|
||||
return arena()->header()->compartment;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static inline
|
||||
Arena<T> *
|
||||
GetArena(Cell *cell)
|
||||
{
|
||||
return reinterpret_cast<Arena<T> *>(cell->arena());
|
||||
return arenaHeader()->compartment;
|
||||
}
|
||||
|
||||
#define JSTRACE_XML 3
|
||||
@ -580,15 +575,10 @@ GetGCThingRuntime(void *thing)
|
||||
return reinterpret_cast<FreeCell *>(thing)->chunk()->info.runtime;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
extern bool
|
||||
checkArenaListsForThing(JSCompartment *comp, jsuword thing);
|
||||
#endif
|
||||
|
||||
/* The arenas in a list have uniform kind. */
|
||||
struct ArenaList {
|
||||
Arena<FreeCell> *head; /* list start */
|
||||
Arena<FreeCell> *cursor; /* arena with free things */
|
||||
ArenaHeader *head; /* list start */
|
||||
ArenaHeader *cursor; /* arena with free things */
|
||||
volatile bool hasToBeFinalized;
|
||||
|
||||
inline void init() {
|
||||
@ -597,47 +587,35 @@ struct ArenaList {
|
||||
hasToBeFinalized = false;
|
||||
}
|
||||
|
||||
inline Arena<FreeCell> *getNextWithFreeList(JSContext *cx) {
|
||||
inline ArenaHeader *getNextWithFreeList() {
|
||||
JS_ASSERT(!hasToBeFinalized);
|
||||
Arena<FreeCell> *a;
|
||||
while (cursor != NULL) {
|
||||
ArenaHeader *aheader = cursor->header();
|
||||
a = cursor;
|
||||
while (cursor) {
|
||||
ArenaHeader *aheader = cursor;
|
||||
cursor = aheader->next;
|
||||
if (aheader->freeList)
|
||||
return a;
|
||||
return aheader;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
template <typename T>
|
||||
bool arenasContainThing(void *thing) {
|
||||
for (Arena<T> *a = (Arena<T> *) head; a; a = (Arena<T> *) a->header()->next) {
|
||||
JS_ASSERT(a->header()->isUsed);
|
||||
if (thing >= &a->t.things[0] && thing < &a->t.things[a->ThingsPerArena])
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool markedThingsInArenaList() {
|
||||
for (Arena<FreeCell> *a = (Arena<FreeCell> *) head; a; a = (Arena<FreeCell> *) a->header()->next) {
|
||||
if (!a->bitmap()->noBitsSet())
|
||||
for (ArenaHeader *aheader = head; aheader; aheader = aheader->next) {
|
||||
if (!aheader->bitmap()->noBitsSet())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline void insert(Arena<FreeCell> *a) {
|
||||
a->header()->next = head;
|
||||
head = a;
|
||||
inline void insert(ArenaHeader *aheader) {
|
||||
aheader->next = head;
|
||||
head = aheader;
|
||||
}
|
||||
|
||||
void releaseAll() {
|
||||
void releaseAll(unsigned thingKind) {
|
||||
while (head) {
|
||||
Arena<FreeCell> *next = head->header()->next;
|
||||
ArenaHeader *next = head->next;
|
||||
head->chunk()->releaseArena(head);
|
||||
head = next;
|
||||
}
|
||||
@ -646,7 +624,7 @@ struct ArenaList {
|
||||
}
|
||||
|
||||
inline bool isEmpty() const {
|
||||
return (head == NULL);
|
||||
return !head;
|
||||
}
|
||||
};
|
||||
|
||||
@ -664,17 +642,12 @@ struct FreeLists {
|
||||
} else {
|
||||
finalizables[kind] = NULL;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if (top && !top->link)
|
||||
top->arena()->header()->hasFreeThings = false;
|
||||
#endif
|
||||
}
|
||||
return top;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void populate(Arena<T> *a, uint32 thingKind) {
|
||||
finalizables[thingKind] = &a->header()->freeList;
|
||||
void populate(ArenaHeader *aheader, uint32 thingKind) {
|
||||
finalizables[thingKind] = &aheader->freeList;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -744,9 +717,7 @@ CheckGCFreeListLink(js::gc::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->arena() ==
|
||||
cell->link->arena());
|
||||
JS_ASSERT_IF(cell->link, cell->arenaHeader() == cell->link->arenaHeader());
|
||||
JS_ASSERT_IF(cell->link, cell < cell->link);
|
||||
}
|
||||
|
||||
@ -885,7 +856,7 @@ extern void
|
||||
js_DestroyScriptsToGC(JSContext *cx, JSCompartment *comp);
|
||||
|
||||
extern void
|
||||
FinalizeArenaList(JSContext *cx, js::gc::ArenaList *arenaList, js::gc::Arena<js::gc::FreeCell> *head);
|
||||
FinalizeArenaList(JSContext *cx, js::gc::ArenaList *arenaList, js::gc::ArenaHeader *head);
|
||||
|
||||
namespace js {
|
||||
|
||||
@ -914,15 +885,18 @@ class GCHelperThread {
|
||||
Vector<void **, 16, js::SystemAllocPolicy> freeVector;
|
||||
void **freeCursor;
|
||||
void **freeCursorEnd;
|
||||
Vector<void **, 16, js::SystemAllocPolicy> finalizeVector;
|
||||
void **finalizeCursor;
|
||||
void **finalizeCursorEnd;
|
||||
|
||||
struct FinalizeListAndHead {
|
||||
js::gc::ArenaList *list;
|
||||
js::gc::ArenaHeader *head;
|
||||
|
||||
};
|
||||
|
||||
Vector<FinalizeListAndHead, 64, js::SystemAllocPolicy> finalizeVector;
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
replenishAndFreeLater(void *ptr);
|
||||
|
||||
void replenishAndFinalizeLater(js::gc::ArenaList *list);
|
||||
|
||||
static void freeElementsAndArray(void **array, void **end) {
|
||||
JS_ASSERT(array <= end);
|
||||
for (void **p = array; p != end; ++p)
|
||||
@ -930,17 +904,6 @@ class GCHelperThread {
|
||||
js::Foreground::free_(array);
|
||||
}
|
||||
|
||||
void finalizeElementsAndArray(void **array, void **end) {
|
||||
JS_ASSERT(array <= end);
|
||||
for (void **p = array; p != end; p += 2) {
|
||||
js::gc::ArenaList *list = (js::gc::ArenaList *)*p;
|
||||
js::gc::Arena<js::gc::FreeCell> *head = (js::gc::Arena<js::gc::FreeCell> *)*(p+1);
|
||||
|
||||
FinalizeArenaList(cx, list, head);
|
||||
}
|
||||
js::Foreground::free_(array);
|
||||
}
|
||||
|
||||
static void threadMain(void* arg);
|
||||
|
||||
void threadLoop(JSRuntime *rt);
|
||||
@ -954,8 +917,6 @@ class GCHelperThread {
|
||||
shutdown(false),
|
||||
freeCursor(NULL),
|
||||
freeCursorEnd(NULL),
|
||||
finalizeCursor(NULL),
|
||||
finalizeCursorEnd(NULL),
|
||||
sweeping(false) { }
|
||||
|
||||
volatile bool sweeping;
|
||||
@ -976,19 +937,16 @@ class GCHelperThread {
|
||||
replenishAndFreeLater(ptr);
|
||||
}
|
||||
|
||||
void finalizeLater(js::gc::ArenaList *list) {
|
||||
bool finalizeLater(js::gc::ArenaList *list) {
|
||||
JS_ASSERT(!sweeping);
|
||||
JS_ASSERT(!list->hasToBeFinalized);
|
||||
if (!list->head)
|
||||
return;
|
||||
|
||||
return true;
|
||||
FinalizeListAndHead f = {list, list->head};
|
||||
if (!finalizeVector.append(f))
|
||||
return false;
|
||||
list->hasToBeFinalized = true;
|
||||
JS_ASSERT(!sweeping);
|
||||
if (finalizeCursor + 1 < finalizeCursorEnd) {
|
||||
*finalizeCursor++ = list;
|
||||
*finalizeCursor++ = list->head;
|
||||
} else {
|
||||
replenishAndFinalizeLater(list);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void setContext(JSContext *context) { cx = context; }
|
||||
@ -1119,9 +1077,9 @@ struct GCMarker : public JSTracer {
|
||||
|
||||
public:
|
||||
/* See comments before delayMarkingChildren is jsgc.cpp. */
|
||||
js::gc::Arena<js::gc::Cell> *unmarkedArenaStackTop;
|
||||
js::gc::ArenaHeader *unmarkedArenaStackTop;
|
||||
#ifdef DEBUG
|
||||
size_t markLaterCount;
|
||||
size_t markLaterArenas;
|
||||
#endif
|
||||
|
||||
#if defined(JS_DUMP_CONSERVATIVE_GC_ROOTS) || defined(JS_GCMETER)
|
||||
@ -1129,8 +1087,7 @@ struct GCMarker : public JSTracer {
|
||||
#endif
|
||||
|
||||
#ifdef JS_DUMP_CONSERVATIVE_GC_ROOTS
|
||||
struct ConservativeRoot { void *thing; uint32 thingKind; };
|
||||
Vector<ConservativeRoot, 0, SystemAllocPolicy> conservativeRoots;
|
||||
Vector<void *, 0, SystemAllocPolicy> conservativeRoots;
|
||||
const char *conservativeDumpFileName;
|
||||
|
||||
void dumpConservativeRoots();
|
||||
|
@ -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
|
||||
@ -114,7 +114,7 @@ GetGCThingTraceKind(const void *thing)
|
||||
if (JSAtom::isStatic(thing))
|
||||
return JSTRACE_STRING;
|
||||
const Cell *cell = reinterpret_cast<const Cell *>(thing);
|
||||
return GetFinalizableTraceKind(cell->arena()->header()->thingKind);
|
||||
return GetFinalizableTraceKind(cell->arenaHeader()->getThingKind());
|
||||
}
|
||||
|
||||
/* Capacity for slotsToThingKind */
|
||||
|
@ -77,14 +77,17 @@ Mark(JSTracer *trc, T *thing)
|
||||
JS_ASSERT(JS_IS_VALID_TRACE_KIND(GetGCThingTraceKind(thing)));
|
||||
JS_ASSERT(trc->debugPrinter || trc->debugPrintArg);
|
||||
|
||||
/* Per-Compartment GC only with GCMarker and no custom JSTracer */
|
||||
JS_ASSERT_IF(trc->context->runtime->gcCurrentCompartment, IS_GC_MARKING_TRACER(trc));
|
||||
JS_ASSERT(!JSAtom::isStatic(thing));
|
||||
JS_ASSERT(thing->asFreeCell()->isAligned());
|
||||
|
||||
JSRuntime *rt = trc->context->runtime;
|
||||
JS_ASSERT(thing->arena()->header()->compartment);
|
||||
JS_ASSERT(thing->arena()->header()->compartment->rt == rt);
|
||||
JS_ASSERT(thing->arenaHeader()->compartment);
|
||||
JS_ASSERT(thing->arenaHeader()->compartment->rt == rt);
|
||||
|
||||
/* Don't mark things outside a compartment if we are in a per-compartment GC */
|
||||
/*
|
||||
* Don't mark things outside a compartment if we are in a per-compartment
|
||||
* GC.
|
||||
*/
|
||||
if (!rt->gcCurrentCompartment || thing->compartment() == rt->gcCurrentCompartment) {
|
||||
if (IS_GC_MARKING_TRACER(trc))
|
||||
PushMarkStack(static_cast<GCMarker *>(trc), thing);
|
||||
@ -104,7 +107,6 @@ MarkString(JSTracer *trc, JSString *str)
|
||||
JS_ASSERT(str);
|
||||
if (str->isStaticAtom())
|
||||
return;
|
||||
JS_ASSERT(GetArena<JSString>((Cell *)str)->assureThingIsAligned((JSString *)str));
|
||||
Mark(trc, str);
|
||||
}
|
||||
|
||||
@ -122,13 +124,6 @@ MarkObject(JSTracer *trc, JSObject &obj, const char *name)
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(&obj);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
JS_ASSERT(GetArena<JSObject>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots2>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots4>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots8>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots12>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots16>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSFunction>((Cell *)&obj)->assureThingIsAligned(&obj));
|
||||
Mark(trc, &obj);
|
||||
}
|
||||
|
||||
@ -139,13 +134,6 @@ MarkObjectWithPrinter(JSTracer *trc, JSObject &obj, JSTraceNamePrinter printer,
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(&obj);
|
||||
JS_SET_TRACING_DETAILS(trc, printer, arg, index);
|
||||
JS_ASSERT(GetArena<JSObject>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots2>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots4>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots8>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots12>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSObject_Slots16>((Cell *)&obj)->assureThingIsAligned(&obj) ||
|
||||
GetArena<JSFunction>((Cell *)&obj)->assureThingIsAligned(&obj));
|
||||
Mark(trc, &obj);
|
||||
}
|
||||
|
||||
@ -155,19 +143,19 @@ MarkShape(JSTracer *trc, const Shape *shape, const char *name)
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(shape);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
JS_ASSERT(GetArena<Shape>((Cell *)shape)->assureThingIsAligned((void *)shape));
|
||||
Mark(trc, shape);
|
||||
}
|
||||
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
void
|
||||
MarkXML(JSTracer *trc, JSXML *xml, const char *name)
|
||||
{
|
||||
JS_ASSERT(trc);
|
||||
JS_ASSERT(xml);
|
||||
JS_SET_TRACING_NAME(trc, name);
|
||||
JS_ASSERT(GetArena<JSXML>(xml)->assureThingIsAligned(xml));
|
||||
Mark(trc, xml);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
PushMarkStack(GCMarker *gcmarker, JSXML *thing)
|
||||
|
@ -44,6 +44,8 @@
|
||||
#include "jsbuiltins.h"
|
||||
#include "jscompartment.h"
|
||||
|
||||
#include "jsgcinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
@ -72,7 +74,7 @@ ConservativeGCStats::dump(FILE *fp)
|
||||
fprintf(fp, " excluded, wrong tag: %lu\n", ULSTAT(counter[CGCT_WRONGTAG]));
|
||||
fprintf(fp, " excluded, not live: %lu\n", ULSTAT(counter[CGCT_NOTLIVE]));
|
||||
fprintf(fp, " valid GC things: %lu\n", ULSTAT(counter[CGCT_VALID]));
|
||||
fprintf(fp, " valid but not aligned: %lu\n", ULSTAT(counter[CGCT_VALIDWITHOFFSET]));
|
||||
fprintf(fp, " valid but not aligned: %lu\n", ULSTAT(unaligned));
|
||||
#undef ULSTAT
|
||||
}
|
||||
#endif
|
||||
@ -143,49 +145,6 @@ GetSizeAndThings(size_t &thingSize, size_t &thingsPerArena)
|
||||
thingsPerArena = Arena<T>::ThingsPerArena;
|
||||
}
|
||||
|
||||
#if defined JS_DUMP_CONSERVATIVE_GC_ROOTS
|
||||
void *
|
||||
GetAlignedThing(void *thing, int thingKind)
|
||||
{
|
||||
Cell *cell = (Cell *)thing;
|
||||
switch (thingKind) {
|
||||
case FINALIZE_OBJECT0:
|
||||
case FINALIZE_OBJECT0_BACKGROUND:
|
||||
return (void *)GetArena<JSObject>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_OBJECT2:
|
||||
case FINALIZE_OBJECT2_BACKGROUND:
|
||||
return (void *)GetArena<JSObject_Slots2>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_OBJECT4:
|
||||
case FINALIZE_OBJECT4_BACKGROUND:
|
||||
return (void *)GetArena<JSObject_Slots4>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_OBJECT8:
|
||||
case FINALIZE_OBJECT8_BACKGROUND:
|
||||
return (void *)GetArena<JSObject_Slots8>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_OBJECT12:
|
||||
case FINALIZE_OBJECT12_BACKGROUND:
|
||||
return (void *)GetArena<JSObject_Slots12>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_OBJECT16:
|
||||
case FINALIZE_OBJECT16_BACKGROUND:
|
||||
return (void *)GetArena<JSObject_Slots16>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_STRING:
|
||||
return (void *)GetArena<JSString>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_EXTERNAL_STRING:
|
||||
return (void *)GetArena<JSExternalString>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_SHORT_STRING:
|
||||
return (void *)GetArena<JSShortString>(cell)->getAlignedThing(thing);
|
||||
case FINALIZE_FUNCTION:
|
||||
return (void *)GetArena<JSFunction>(cell)->getAlignedThing(thing);
|
||||
#if JS_HAS_XML_SUPPORT
|
||||
case FINALIZE_XML:
|
||||
return (void *)GetArena<JSXML>(cell)->getAlignedThing(thing);
|
||||
#endif
|
||||
default:
|
||||
JS_NOT_REACHED("wrong kind");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void GetSizeAndThingsPerArena(int thingKind, size_t &thingSize, size_t &thingsPerArena)
|
||||
{
|
||||
switch (thingKind) {
|
||||
@ -366,16 +325,16 @@ GCMarker::dumpConservativeRoots()
|
||||
|
||||
conservativeStats.dump(fp);
|
||||
|
||||
for (ConservativeRoot *i = conservativeRoots.begin();
|
||||
i != conservativeRoots.end();
|
||||
++i) {
|
||||
fprintf(fp, " %p: ", i->thing);
|
||||
switch (GetFinalizableTraceKind(i->thingKind)) {
|
||||
for (void **thingp = conservativeRoots.begin(); thingp != conservativeRoots.end(); ++thingp) {
|
||||
void *thing = thingp;
|
||||
fprintf(fp, " %p: ", thing);
|
||||
|
||||
switch (GetGCThingTraceKind(thing)) {
|
||||
default:
|
||||
JS_NOT_REACHED("Unknown trace kind");
|
||||
|
||||
case JSTRACE_OBJECT: {
|
||||
JSObject *obj = (JSObject *) i->thing;
|
||||
JSObject *obj = (JSObject *) thing;
|
||||
fprintf(fp, "object %s", obj->getClass()->name);
|
||||
break;
|
||||
}
|
||||
@ -384,7 +343,7 @@ GCMarker::dumpConservativeRoots()
|
||||
break;
|
||||
}
|
||||
case JSTRACE_STRING: {
|
||||
JSString *str = (JSString *) i->thing;
|
||||
JSString *str = (JSString *) thing;
|
||||
if (str->isLinear()) {
|
||||
char buf[50];
|
||||
PutEscapedString(buf, sizeof buf, &str->asLinear(), '"');
|
||||
@ -396,7 +355,7 @@ GCMarker::dumpConservativeRoots()
|
||||
}
|
||||
# if JS_HAS_XML_SUPPORT
|
||||
case JSTRACE_XML: {
|
||||
JSXML *xml = (JSXML *) i->thing;
|
||||
JSXML *xml = (JSXML *) thing;
|
||||
fprintf(fp, "xml %u", (unsigned)xml->xml_class);
|
||||
break;
|
||||
}
|
||||
|
@ -63,7 +63,6 @@ namespace gc {
|
||||
*/
|
||||
enum ConservativeGCTest {
|
||||
CGCT_VALID,
|
||||
CGCT_VALIDWITHOFFSET, /* points within an object */
|
||||
CGCT_LOWBITSET, /* excluded because one of the low bits was set */
|
||||
CGCT_NOTARENA, /* not within arena range in a chunk */
|
||||
CGCT_NOTCHUNK, /* not within a valid chunk */
|
||||
@ -75,7 +74,9 @@ enum ConservativeGCTest {
|
||||
|
||||
struct ConservativeGCStats {
|
||||
uint32 counter[gc::CGCT_END]; /* ConservativeGCTest classification
|
||||
counters */
|
||||
counters */
|
||||
uint32 unaligned; /* number of valid but not aligned on
|
||||
thing start pointers */
|
||||
|
||||
void add(const ConservativeGCStats &another) {
|
||||
for (size_t i = 0; i != JS_ARRAY_LENGTH(counter); ++i)
|
||||
@ -129,10 +130,6 @@ UpdateCompartmentStats(JSCompartment *comp, unsigned thingKind, uint32 nlivearen
|
||||
uint32 nkilledArenas, uint32 nthings);
|
||||
#endif /* JS_GCMETER */
|
||||
|
||||
#if defined JS_DUMP_CONSERVATIVE_GC_ROOTS
|
||||
void *GetAlignedThing(void *thing, int thingKind);
|
||||
#endif
|
||||
|
||||
} //gc
|
||||
|
||||
#ifdef MOZ_GCTIMER
|
||||
|
@ -327,7 +327,7 @@ JSObject::setPrimitiveThis(const js::Value &pthis)
|
||||
inline /* gc::FinalizeKind */ unsigned
|
||||
JSObject::finalizeKind() const
|
||||
{
|
||||
return js::gc::FinalizeKind(arena()->header()->thingKind);
|
||||
return js::gc::FinalizeKind(arenaHeader()->getThingKind());
|
||||
}
|
||||
|
||||
inline size_t
|
||||
|
@ -1406,7 +1406,7 @@ FixProxy(JSContext *cx, JSObject *proxy, JSBool *bp)
|
||||
* Make a blank object from the recipe fix provided to us. This must have
|
||||
* number of fixed slots as the proxy so that we can swap their contents.
|
||||
*/
|
||||
gc::FinalizeKind kind = gc::FinalizeKind(proxy->arena()->header()->thingKind);
|
||||
gc::FinalizeKind kind = gc::FinalizeKind(proxy->arenaHeader()->getThingKind());
|
||||
JSObject *newborn = NewNonFunction<WithProto::Given>(cx, clasp, proto, parent, kind);
|
||||
if (!newborn)
|
||||
return false;
|
||||
|
@ -73,7 +73,7 @@ JSObject::getEmptyShape(JSContext *cx, js::Class *aclasp,
|
||||
|
||||
if (!emptyShapes) {
|
||||
emptyShapes = (js::EmptyShape**)
|
||||
cx->calloc_(sizeof(js::EmptyShape*) * js::gc::JS_FINALIZE_OBJECT_LIMIT);
|
||||
cx->calloc_(sizeof(js::EmptyShape*) * js::gc::FINALIZE_FUNCTION_AND_OBJECT_LAST);
|
||||
if (!emptyShapes)
|
||||
return NULL;
|
||||
|
||||
|
@ -91,7 +91,7 @@ using namespace js::gc;
|
||||
bool
|
||||
JSString::isShort() const
|
||||
{
|
||||
bool is_short = arena()->header()->thingKind == FINALIZE_SHORT_STRING;
|
||||
bool is_short = arenaHeader()->getThingKind() == FINALIZE_SHORT_STRING;
|
||||
JS_ASSERT_IF(is_short, isFlat());
|
||||
return is_short;
|
||||
}
|
||||
@ -106,7 +106,7 @@ JSString::isFixed() const
|
||||
bool
|
||||
JSString::isExternal() const
|
||||
{
|
||||
bool is_external = arena()->header()->thingKind == FINALIZE_EXTERNAL_STRING;
|
||||
bool is_external = arenaHeader()->getThingKind() == FINALIZE_EXTERNAL_STRING;
|
||||
JS_ASSERT_IF(is_external, isFixed());
|
||||
return is_external;
|
||||
}
|
||||
|
@ -551,10 +551,10 @@ inline void
|
||||
JSAtom::finalize(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(isAtom());
|
||||
if (arena()->header()->thingKind == js::gc::FINALIZE_STRING)
|
||||
if (arenaHeader()->getThingKind() == js::gc::FINALIZE_STRING)
|
||||
asFlat().finalize(rt);
|
||||
else
|
||||
JS_ASSERT(arena()->header()->thingKind == js::gc::FINALIZE_SHORT_STRING);
|
||||
JS_ASSERT(arenaHeader()->getThingKind() == js::gc::FINALIZE_SHORT_STRING);
|
||||
}
|
||||
|
||||
inline void
|
||||
|
Loading…
Reference in New Issue
Block a user