Bug 988950 - Store chunk location in the chunk trailer r=terrence

This commit is contained in:
Jon Coppeard 2014-04-26 09:30:04 +01:00
parent 7cd1de19e6
commit bcdfba286e
7 changed files with 86 additions and 4 deletions

View File

@ -26,6 +26,8 @@ CurrentThreadCanAccessZone(JS::Zone *zone);
namespace gc {
struct Cell;
const size_t ArenaShift = 12;
const size_t ArenaSize = size_t(1) << ArenaShift;
const size_t ArenaMask = ArenaSize - 1;
@ -39,9 +41,10 @@ const size_t CellSize = size_t(1) << CellShift;
const size_t CellMask = CellSize - 1;
/* These are magic constants derived from actual offsets in gc/Heap.h. */
const size_t ChunkMarkBitmapOffset = 1032368;
const size_t ChunkMarkBitmapOffset = 1032360;
const size_t ChunkMarkBitmapBits = 129024;
const size_t ChunkRuntimeOffset = ChunkSize - sizeof(void*);
const size_t ChunkLocationOffset = ChunkSize - sizeof(void*) - sizeof(uintptr_t);
/*
* Live objects are marked black. How many other additional colors are available
@ -51,6 +54,13 @@ const size_t ChunkRuntimeOffset = ChunkSize - sizeof(void*);
static const uint32_t BLACK = 0;
static const uint32_t GRAY = 1;
/*
* Constants used to indicate whether a chunk is part of the tenured heap or the
* nusery.
*/
const uintptr_t ChunkLocationNursery = 0;
const uintptr_t ChunkLocationTenuredHeap = 1;
} /* namespace gc */
} /* namespace js */
@ -164,6 +174,24 @@ IsInsideNursery(const JS::shadow::Runtime *runtime, const void *p)
#endif
}
MOZ_ALWAYS_INLINE bool
IsInsideNursery(const js::gc::Cell *cell)
{
#ifdef JSGC_GENERATIONAL
if (!cell)
return false;
uintptr_t addr = uintptr_t(cell);
addr &= ~js::gc::ChunkMask;
addr |= js::gc::ChunkLocationOffset;
uint32_t location = *reinterpret_cast<uint32_t *>(addr);
JS_ASSERT(location == gc::ChunkLocationNursery ||
location == gc::ChunkLocationTenuredHeap);
return location == gc::ChunkLocationNursery;
#else
return false;
#endif
}
} /* namespace gc */
} /* namespace js */

View File

@ -606,9 +606,18 @@ ArenaHeader::getThingSize() const
*/
struct ChunkTrailer
{
/* The index the chunk in the nursery, or LocationTenuredHeap. */
uint32_t location;
#if JS_BITS_PER_WORD == 64
uint32_t padding;
#endif
JSRuntime *runtime;
};
static_assert(sizeof(ChunkTrailer) == 2 * sizeof(uintptr_t), "ChunkTrailer size is incorrect.");
/* The chunk header (located at the end of the chunk to preserve arena alignment). */
struct ChunkInfo
{
@ -623,7 +632,7 @@ struct ChunkInfo
* Calculating sizes and offsets is simpler if sizeof(ChunkInfo) is
* architecture-independent.
*/
char padding[16];
char padding[20];
#endif
/*

View File

@ -904,7 +904,7 @@ js::Nursery::sweep(JSRuntime *rt)
/* Poison the nursery contents so touching a freed object will crash. */
JS_POISON((void *)start(), JS_SWEPT_NURSERY_PATTERN, NurserySize);
for (int i = 0; i < NumNurseryChunks; ++i)
chunk(i).trailer.runtime = runtime();
initChunk(i);
if (rt->gcZeal_ == ZealGenerationalGCValue) {
MOZ_ASSERT(numActiveChunks_ == NumNurseryChunks);

View File

@ -201,13 +201,19 @@ class Nursery
return reinterpret_cast<NurseryChunkLayout *>(start())[index];
}
MOZ_ALWAYS_INLINE void initChunk(int chunkno) {
NurseryChunkLayout &c = chunk(chunkno);
c.trailer.location = gc::ChunkLocationNursery;
c.trailer.runtime = runtime();
}
MOZ_ALWAYS_INLINE void setCurrentChunk(int chunkno) {
JS_ASSERT(chunkno < NumNurseryChunks);
JS_ASSERT(chunkno < numActiveChunks_);
currentChunk_ = chunkno;
position_ = chunk(chunkno).start();
currentEnd_ = chunk(chunkno).end();
chunk(chunkno).trailer.runtime = runtime();
initChunk(chunkno);
}
void updateDecommittedRegion() {

View File

@ -42,6 +42,7 @@ UNIFIED_SOURCES += [
'testIntern.cpp',
'testIntString.cpp',
'testIntTypesABI.cpp',
'testIsInsideNursery.cpp',
'testJSEvaluateScript.cpp',
'testLookup.cpp',
'testLooselyEqual.cpp',

View File

@ -0,0 +1,37 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "jsapi-tests/tests.h"
BEGIN_TEST(testIsInsideNursery)
{
/* Non-GC things are never inside the nursery. */
CHECK(!js::gc::IsInsideNursery(rt, rt));
CHECK(!js::gc::IsInsideNursery(rt, nullptr));
CHECK(!js::gc::IsInsideNursery(nullptr));
JS_GC(rt);
JS::RootedObject object(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
#ifdef JSGC_GENERATIONAL
/* Objects are initially allocated in the nursery. */
CHECK(js::gc::IsInsideNursery(rt, object));
CHECK(js::gc::IsInsideNursery(object));
#else
CHECK(!js::gc::IsInsideNursery(rt, object));
CHECK(!js::gc::IsInsideNursery(object));
#endif
JS_GC(rt);
CHECK(!js::gc::IsInsideNursery(rt, object));
CHECK(!js::gc::IsInsideNursery(object));
return true;
}
END_TEST(testIsInsideNursery)

View File

@ -796,6 +796,7 @@ Chunk::init(JSRuntime *rt)
/* Initialize the chunk info. */
info.age = 0;
info.trailer.location = ChunkLocationTenuredHeap;
info.trailer.runtime = rt;
/* The rest of info fields are initialized in PickChunk. */