mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-08 12:37:37 +00:00
Bug 569422 - Remove unions from GC (r=luke)
This commit is contained in:
parent
9eb8ca7a24
commit
cc5230b13c
@ -78,6 +78,10 @@ struct Cell {
|
||||
JS_ALWAYS_INLINE js::gc::FreeCell *asFreeCell() {
|
||||
return reinterpret_cast<FreeCell *>(this);
|
||||
}
|
||||
|
||||
JS_ALWAYS_INLINE const js::gc::FreeCell *asFreeCell() const {
|
||||
return reinterpret_cast<const FreeCell *>(this);
|
||||
}
|
||||
};
|
||||
|
||||
/* FreeCell has always size 8 */
|
||||
|
@ -169,15 +169,15 @@ Arena<T>::init(JSCompartment *compartment, unsigned thingKind)
|
||||
{
|
||||
aheader.compartment = compartment;
|
||||
aheader.thingKind = thingKind;
|
||||
aheader.freeList = &t.things[0].cell;
|
||||
JS_ASSERT(sizeof(T) == sizeof(ThingOrCell<T>));
|
||||
ThingOrCell<T> *thing = &t.things[0];
|
||||
ThingOrCell<T> *last = &t.things[JS_ARRAY_LENGTH(t.things) - 1];
|
||||
char *p = (char *)&t.things[0];
|
||||
aheader.freeList = reinterpret_cast<FreeCell *>(p);
|
||||
T *thing = &t.things[0];
|
||||
T *last = &t.things[JS_ARRAY_LENGTH(t.things) - 1];
|
||||
while (thing < last) {
|
||||
thing->cell.link = &(thing + 1)->cell;
|
||||
thing->asFreeCell()->link = (thing + 1)->asFreeCell();
|
||||
++thing;
|
||||
}
|
||||
last->cell.link = NULL;
|
||||
last->asFreeCell()->link = NULL;
|
||||
#ifdef DEBUG
|
||||
aheader.thingSize = sizeof(T);
|
||||
aheader.isUsed = true;
|
||||
@ -213,7 +213,7 @@ Arena<T>::mark(T *thing, JSTracer *trc)
|
||||
{
|
||||
T *alignedThing = getAlignedThing(thing);
|
||||
|
||||
if (alignedThing > &t.things[ThingsPerArena-1].t || alignedThing < &t.things[0].t)
|
||||
if (alignedThing > &t.things[ThingsPerArena-1] || alignedThing < &t.things[0])
|
||||
return CGCT_NOTARENA;
|
||||
|
||||
if (!aheader.compartment || inFreeList(alignedThing))
|
||||
@ -1347,7 +1347,7 @@ void
|
||||
Arena<T>::markDelayedChildren(JSTracer *trc)
|
||||
{
|
||||
T* thing = (T *)getMarkingDelay()->start;
|
||||
T *thingsEnd = &t.things[ThingsPerArena-1].t;
|
||||
T *thingsEnd = &t.things[ThingsPerArena-1];
|
||||
JS_ASSERT(thing == getAlignedThing(thing));
|
||||
while (thing <= thingsEnd) {
|
||||
if (thing->isMarked())
|
||||
@ -1838,8 +1838,8 @@ FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
|
||||
FreeCell **tailp = &freeList;
|
||||
bool allClear = true;
|
||||
|
||||
T *thingsEnd = &a->t.things[a->ThingsPerArena-1].t;
|
||||
T *thing = &a->t.things[0].t;
|
||||
T *thingsEnd = &a->t.things[a->ThingsPerArena-1];
|
||||
T *thing = &a->t.things[0];
|
||||
thingsEnd++;
|
||||
|
||||
if (!nextFree) {
|
||||
@ -1896,14 +1896,14 @@ FinalizeArenaList(JSCompartment *comp, JSContext *cx, unsigned thingKind)
|
||||
* add the arena itself to the destroy list.
|
||||
*/
|
||||
JS_ASSERT(nfree == a->ThingsPerArena);
|
||||
JS_ASSERT((T *)tailp == &a->t.things[a->ThingsPerArena-1].t);
|
||||
JS_ASSERT((T *)tailp == &a->t.things[a->ThingsPerArena-1]);
|
||||
*tailp = NULL;
|
||||
header->freeList = freeList;
|
||||
#ifdef DEBUG
|
||||
header->hasFreeThings = true;
|
||||
#endif
|
||||
*ap = (header->next);
|
||||
JS_ASSERT((T *)header->freeList == &a->t.things[0].t);
|
||||
JS_ASSERT((T *)header->freeList == &a->t.things[0]);
|
||||
a->chunk()->releaseArena(a);
|
||||
METER(nkilledarenas++);
|
||||
} else {
|
||||
|
@ -117,40 +117,67 @@ struct ArenaHeader {
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
union ThingOrCell {
|
||||
T t;
|
||||
FreeCell cell;
|
||||
template <typename T, size_t N, size_t R1, size_t R2>
|
||||
struct Things {
|
||||
char filler1[R1];
|
||||
T things[N];
|
||||
char filler[R2];
|
||||
};
|
||||
|
||||
template <typename T, size_t N, size_t R>
|
||||
struct Things {
|
||||
ThingOrCell<T> things[N];
|
||||
char filler[R];
|
||||
template <typename T, size_t N, size_t R1>
|
||||
struct Things<T, N, R1, 0> {
|
||||
char filler1[R1];
|
||||
T things[N];
|
||||
};
|
||||
|
||||
template <typename T, size_t N, size_t R2>
|
||||
struct Things<T, N, 0, R2> {
|
||||
T things[N];
|
||||
char filler2[R2];
|
||||
};
|
||||
|
||||
template <typename T, size_t N>
|
||||
struct Things<T, N, 0> {
|
||||
ThingOrCell<T> things[N];
|
||||
struct Things<T, N, 0, 0> {
|
||||
T things[N];
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct Arena {
|
||||
static const size_t ArenaSize = 4096;
|
||||
|
||||
struct AlignedArenaHeader {
|
||||
T align[(sizeof(ArenaHeader) + sizeof(T) - 1) / sizeof(T)];
|
||||
};
|
||||
ArenaHeader aheader;
|
||||
|
||||
/* We want things in the arena to be aligned, so align the header. */
|
||||
union {
|
||||
ArenaHeader aheader;
|
||||
AlignedArenaHeader align;
|
||||
};
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* +-------------+-----+----+----+-----+----+-----+
|
||||
* | ArenaHeader | pad | T0 | T1 | ... | Tn | pad |
|
||||
* +-------------+-----+----+----+-----+----+-----+
|
||||
*
|
||||
* <----------------------------------------------> = 4096 bytes
|
||||
* <-----> = Filler1Size
|
||||
* <-------------------> = HeaderSize
|
||||
* <--------------------------> = SpaceAfterHeader
|
||||
* <-----> = Filler2Size
|
||||
*/
|
||||
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 ThingsPerArena = (ArenaSize - sizeof(AlignedArenaHeader)) / sizeof(T);
|
||||
static const size_t FillerSize = ArenaSize - sizeof(AlignedArenaHeader) - sizeof(T) * ThingsPerArena;
|
||||
Things<T, ThingsPerArena, FillerSize> t;
|
||||
Things<T, ThingsPerArena, Filler1Size, Filler2Size> t;
|
||||
|
||||
static void staticAsserts() {
|
||||
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;
|
||||
@ -170,7 +197,6 @@ struct Arena {
|
||||
|
||||
void init(JSCompartment *compartment, unsigned thingKind);
|
||||
};
|
||||
JS_STATIC_ASSERT(sizeof(Arena<FreeCell>) == 4096);
|
||||
|
||||
/*
|
||||
* Live objects are marked black. How many other additional colors are available
|
||||
@ -392,7 +418,7 @@ STATIC_POSTCONDITION_ASSUME(return < ArenaBitmap::BitCount)
|
||||
size_t
|
||||
Cell::cellIndex() const
|
||||
{
|
||||
return reinterpret_cast<const FreeCell *>(this) - reinterpret_cast<FreeCell *>(&arena()->t);
|
||||
return this->asFreeCell() - arena()->t.things[0].asFreeCell();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
@ -175,6 +175,9 @@ template <> struct IsPodType<double> { static const bool result = true;
|
||||
template <class T, size_t N> inline T *ArraySize(T (&)[N]) { return N; }
|
||||
template <class T, size_t N> inline T *ArrayEnd(T (&arr)[N]) { return arr + N; }
|
||||
|
||||
template <bool cond, typename T, T v1, T v2> struct If { static const T result = v1; };
|
||||
template <typename T, T v1, T v2> struct If<false, T, v1, v2> { static const T result = v2; };
|
||||
|
||||
} /* namespace tl */
|
||||
|
||||
/* Useful for implementing containers that assert non-reentrancy */
|
||||
|
Loading…
Reference in New Issue
Block a user