mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +00:00
Bug 1001359 - Store chunk location in the chunk trailer r=terrence DONTBUILD
This commit is contained in:
parent
951dc3c11a
commit
3e7f2297f0
@ -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 */
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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() {
|
||||
|
@ -42,6 +42,7 @@ UNIFIED_SOURCES += [
|
||||
'testIntern.cpp',
|
||||
'testIntString.cpp',
|
||||
'testIntTypesABI.cpp',
|
||||
'testIsInsideNursery.cpp',
|
||||
'testJSEvaluateScript.cpp',
|
||||
'testLookup.cpp',
|
||||
'testLooselyEqual.cpp',
|
||||
|
37
js/src/jsapi-tests/testIsInsideNursery.cpp
Normal file
37
js/src/jsapi-tests/testIsInsideNursery.cpp
Normal 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)
|
@ -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. */
|
||||
|
Loading…
Reference in New Issue
Block a user