Commit d57b23ce authored by ggaren@apple.com's avatar ggaren@apple.com
Browse files

2011-02-15 Geoffrey Garen <ggaren@apple.com>

        Reviewed by Darin Adler.

        Moved MarkedBlock data members to the head of the block
        https://bugs.webkit.org/show_bug.cgi?id=54482
        
        This allows for a variable-sized tail, to accommodate oversized blocks.

        SunSpider reports no change.
        
        * runtime/JSCell.h:
        (JSC::JSCell::MarkedBlock::allocate):
        * runtime/MarkedBlock.cpp:
        (JSC::MarkedBlock::destroy):
        (JSC::MarkedBlock::MarkedBlock):
        (JSC::MarkedBlock::sweep):
        * runtime/MarkedBlock.h: Added missing element to the CELLS_PER_BLOCK
        calculation. This kind of error is why we want to migrate to the system
        described below.

        (JSC::roundUpToMultipleOf):
        (JSC::MarkedBlock::firstCell):
        (JSC::MarkedBlock::cells):
        (JSC::MarkedBlock::cellNumber): Use subtraction instead of masking to
        calculate cell number. The mask is no longer correct because the first
        cell is not at the head of the block.

        (JSC::MarkedBlock::forEach): Replaced m_cells data member with a cells()
        accessor. We want to use sizeof(MarkedBlock) to calculate the size of the
        block header, so we can't have an explicit data member to represent the block tail.
        
        Also replaced iteration from zero with iteration from startCell(), since
        the first N cells are now occupied by the header.

        * runtime/MarkedSpace.cpp:
        (JSC::MarkedSpace::MarkedSpace):
        (JSC::MarkedSpace::reset): Replaced iteration from zero as above.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@78605 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 66ef1f8d
2011-02-15 Geoffrey Garen <ggaren@apple.com>
Reviewed by Darin Adler.
Moved MarkedBlock data members to the head of the block
https://bugs.webkit.org/show_bug.cgi?id=54482
This allows for a variable-sized tail, to accommodate oversized blocks.
SunSpider reports no change.
* runtime/JSCell.h:
(JSC::JSCell::MarkedBlock::allocate):
* runtime/MarkedBlock.cpp:
(JSC::MarkedBlock::destroy):
(JSC::MarkedBlock::MarkedBlock):
(JSC::MarkedBlock::sweep):
* runtime/MarkedBlock.h: Added missing element to the CELLS_PER_BLOCK
calculation. This kind of error is why we want to migrate to the system
described below.
(JSC::roundUpToMultipleOf):
(JSC::MarkedBlock::firstCell):
(JSC::MarkedBlock::cells):
(JSC::MarkedBlock::cellNumber): Use subtraction instead of masking to
calculate cell number. The mask is no longer correct because the first
cell is not at the head of the block.
(JSC::MarkedBlock::forEach): Replaced m_cells data member with a cells()
accessor. We want to use sizeof(MarkedBlock) to calculate the size of the
block header, so we can't have an explicit data member to represent the block tail.
Also replaced iteration from zero with iteration from startCell(), since
the first N cells are now occupied by the header.
* runtime/MarkedSpace.cpp:
(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::reset): Replaced iteration from zero as above.
2011-02-15 Chris Rogers <crogers@google.com>
 
Reviewed by Alexey Proskuryakov.
......
......@@ -407,14 +407,14 @@ namespace JSC {
do {
ASSERT(nextCell < CELLS_PER_BLOCK);
if (!m_marks.testAndSet(nextCell)) { // Always false for the last cell in the block
JSCell* cell = reinterpret_cast<JSCell*>(&m_cells[nextCell++]);
JSCell* cell = reinterpret_cast<JSCell*>(&cells()[nextCell++]);
cell->~JSCell();
return cell;
}
nextCell = m_marks.nextPossiblyUnset(nextCell);
} while (nextCell != CELLS_PER_BLOCK);
nextCell = 0;
nextCell = firstCell();
return 0;
}
......
......@@ -40,8 +40,8 @@ MarkedBlock* MarkedBlock::create(JSGlobalData* globalData)
void MarkedBlock::destroy(MarkedBlock* block)
{
for (size_t i = 0; i < CELLS_PER_BLOCK; ++i)
reinterpret_cast<JSCell*>(&block->m_cells[i])->~JSCell();
for (size_t i = block->firstCell(); i < CELLS_PER_BLOCK; ++i)
reinterpret_cast<JSCell*>(&block->cells()[i])->~JSCell();
block->m_allocation.deallocate();
}
......@@ -52,8 +52,8 @@ MarkedBlock::MarkedBlock(const PageAllocationAligned& allocation, JSGlobalData*
m_marks.set(CELLS_PER_BLOCK - 1);
Structure* dummyMarkableCellStructure = globalData->dummyMarkableCellStructure.get();
for (size_t i = 0; i < CELLS_PER_BLOCK; ++i)
new (&m_cells[i]) JSCell(dummyMarkableCellStructure);
for (size_t i = firstCell(); i < CELLS_PER_BLOCK; ++i)
new (&cells()[i]) JSCell(dummyMarkableCellStructure);
}
void MarkedBlock::sweep()
......@@ -62,11 +62,11 @@ void MarkedBlock::sweep()
Structure* dummyMarkableCellStructure = m_heap->globalData()->dummyMarkableCellStructure.get();
#endif
for (size_t i = 0; i < CELLS_PER_BLOCK; ++i) {
for (size_t i = firstCell(); i < CELLS_PER_BLOCK; ++i) {
if (m_marks.get(i))
continue;
JSCell* cell = reinterpret_cast<JSCell*>(&m_cells[i]);
JSCell* cell = reinterpret_cast<JSCell*>(&cells()[i]);
#if ENABLE(JSC_ZOMBIES)
if (!cell->isZombie()) {
const ClassInfo* info = cell->classInfo();
......
......@@ -34,6 +34,15 @@ namespace JSC {
class JSCell;
class JSGlobalData;
// Efficient implementation that takes advantage of powers of two.
template<size_t divisor> inline size_t roundUpToMultipleOf(size_t x)
{
COMPILE_ASSERT(divisor && !(divisor & (divisor - 1)), divisor_is_a_power_of_two);
size_t remainderMask = divisor - 1;
return (x + remainderMask) & ~remainderMask;
}
class MarkedBlock {
#if OS(WINCE) || OS(SYMBIAN) || PLATFORM(BREWMP)
static const size_t BLOCK_SIZE = 64 * 1024; // 64k
......@@ -41,8 +50,7 @@ namespace JSC {
static const size_t BLOCK_SIZE = 256 * 1024; // 256k
#endif
static const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1;
static const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK;
static const size_t BLOCK_MASK = ~(BLOCK_SIZE - 1);
static const size_t MINIMUM_CELL_SIZE = 64;
static const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0);
public:
......@@ -53,7 +61,7 @@ namespace JSC {
static const size_t CELL_MASK = CELL_SIZE - 1;
static const size_t CELL_ALIGN_MASK = ~CELL_MASK;
static const size_t BITS_PER_BLOCK = BLOCK_SIZE / CELL_SIZE;
static const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*) - sizeof(WTF::Bitmap<BITS_PER_BLOCK>)) / CELL_SIZE; // Division rounds down intentionally.
static const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(WTF::Bitmap<BITS_PER_BLOCK>) - sizeof(PageAllocationAligned) - sizeof(Heap*)) / CELL_SIZE; // Division rounds down intentionally.
struct CollectorCell {
FixedArray<double, CELL_ARRAY_LENGTH> memory;
......@@ -81,6 +89,8 @@ namespace JSC {
size_t size();
size_t capacity();
size_t firstCell();
size_t cellNumber(const void*);
bool isMarked(const void*);
bool testAndSetMarked(const void*);
......@@ -90,13 +100,23 @@ namespace JSC {
private:
MarkedBlock(const PageAllocationAligned&, JSGlobalData*);
CollectorCell* cells();
FixedArray<CollectorCell, CELLS_PER_BLOCK> m_cells;
WTF::Bitmap<BITS_PER_BLOCK> m_marks;
PageAllocationAligned m_allocation;
Heap* m_heap;
};
inline size_t MarkedBlock::firstCell()
{
return roundUpToMultipleOf<CELL_SIZE>(sizeof(MarkedBlock)) / CELL_SIZE;
}
inline MarkedBlock::CollectorCell* MarkedBlock::cells()
{
return reinterpret_cast<CollectorCell*>(this);
}
inline bool MarkedBlock::isCellAligned(const void* p)
{
return !((intptr_t)(p) & CELL_MASK);
......@@ -144,7 +164,7 @@ namespace JSC {
inline size_t MarkedBlock::cellNumber(const void* cell)
{
return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE;
return (reinterpret_cast<uintptr_t>(cell) - reinterpret_cast<uintptr_t>(this)) / CELL_SIZE;
}
inline bool MarkedBlock::isMarked(const void* cell)
......@@ -164,10 +184,10 @@ namespace JSC {
template <typename Functor> inline void MarkedBlock::forEach(Functor& functor)
{
for (size_t i = 0; i < CELLS_PER_BLOCK - 1; ++i) { // The last cell is a dummy place-holder.
for (size_t i = firstCell(); i < CELLS_PER_BLOCK - 1; ++i) { // The last cell is a dummy place-holder.
if (!m_marks.get(i))
continue;
functor(reinterpret_cast<JSCell*>(&m_cells[i]));
functor(reinterpret_cast<JSCell*>(&cells()[i]));
}
}
......
......@@ -35,6 +35,7 @@ MarkedSpace::MarkedSpace(JSGlobalData* globalData)
, m_globalData(globalData)
{
allocateBlock();
m_heap.nextCell = m_heap.collectorBlock(0)->firstCell();
}
void MarkedSpace::destroy()
......@@ -127,8 +128,8 @@ size_t MarkedSpace::capacity() const
void MarkedSpace::reset()
{
m_heap.nextCell = 0;
m_heap.nextBlock = 0;
m_heap.nextCell = m_heap.collectorBlock(0)->firstCell();
m_waterMark = 0;
#if ENABLE(JSC_ZOMBIES)
sweep();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment