X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/81345200c95645a1b0d2635520f96ad55dfde63f..HEAD:/heap/MarkedBlock.h diff --git a/heap/MarkedBlock.h b/heap/MarkedBlock.h index f2626b7..839099d 100644 --- a/heap/MarkedBlock.h +++ b/heap/MarkedBlock.h @@ -22,16 +22,13 @@ #ifndef MarkedBlock_h #define MarkedBlock_h -#include "BlockAllocator.h" -#include "HeapBlock.h" - #include "HeapOperation.h" +#include "IterationStatus.h" #include "WeakSet.h" #include #include #include #include -#include #include #include @@ -69,13 +66,14 @@ namespace JSC { // size is equal to the difference between the cell size and the object // size. - class MarkedBlock : public HeapBlock { + class MarkedBlock : public DoublyLinkedListNode { + friend class WTF::DoublyLinkedListNode; friend class LLIntOffsetsExtractor; friend struct VerifyMarkedOrRetired; public: static const size_t atomSize = 16; // bytes static const size_t atomShiftAmount = 4; // log_2(atomSize) FIXME: Change atomSize to 16. - static const size_t blockSize = 64 * KB; + static const size_t blockSize = 16 * KB; static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two. static const size_t atomsPerBlock = blockSize / atomSize; @@ -112,8 +110,8 @@ namespace JSC { ReturnType m_count; }; - enum DestructorType { None, ImmortalStructure, Normal }; - static MarkedBlock* create(DeadBlock*, MarkedAllocator*, size_t cellSize, DestructorType); + static MarkedBlock* create(MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction); + static void destroy(MarkedBlock*); static bool isAtomAligned(const void*); static MarkedBlock* blockFor(const void*); @@ -147,7 +145,6 @@ namespace JSC { // and was successfully cleared and false otherwise. bool clearNewlyAllocated(); void clearMarks(); - void clearRememberedSet(); template void clearMarksWithCollectionType(); @@ -155,7 +152,7 @@ namespace JSC { bool isEmpty(); size_t cellSize(); - DestructorType destructorType(); + bool needsDestruction() const; size_t size(); size_t capacity(); @@ -164,6 +161,7 @@ namespace JSC { bool testAndSetMarked(const void*); bool isLive(const JSCell*); bool isLiveCell(const void*); + bool isMarkedOrNewlyAllocated(const JSCell*); void setMarked(const void*); void clearMarked(const void*); @@ -176,13 +174,14 @@ namespace JSC { void setNewlyAllocated(const void*); void clearNewlyAllocated(const void*); + bool isAllocated() const; bool needsSweeping(); void didRetireBlock(const FreeList&); void willRemoveBlock(); - template void forEachCell(Functor&); - template void forEachLiveCell(Functor&); - template void forEachDeadCell(Functor&); + template IterationStatus forEachCell(Functor&); + template IterationStatus forEachLiveCell(Functor&); + template IterationStatus forEachDeadCell(Functor&); static ptrdiff_t offsetOfMarks() { return OBJECT_OFFSETOF(MarkedBlock, m_marks); } @@ -190,28 +189,30 @@ namespace JSC { static const size_t atomAlignmentMask = atomSize - 1; // atomSize must be a power of two. enum BlockState { New, FreeListed, Allocated, Marked, Retired }; - template FreeList sweepHelper(SweepMode = SweepOnly); + template FreeList sweepHelper(SweepMode = SweepOnly); typedef char Atom[atomSize]; - MarkedBlock(Region*, MarkedAllocator*, size_t cellSize, DestructorType); + MarkedBlock(MarkedAllocator*, size_t capacity, size_t cellSize, bool needsDestruction); Atom* atoms(); size_t atomNumber(const void*); - template void callDestructor(JSCell*); - template FreeList specializedSweep(); + void callDestructor(JSCell*); + template FreeList specializedSweep(); + MarkedBlock* m_prev; + MarkedBlock* m_next; + size_t m_atomsPerCell; size_t m_endAtom; // This is a fuzzy end. Always test for < m_endAtom. #if ENABLE(PARALLEL_GC) WTF::Bitmap m_marks; - WTF::Bitmap m_rememberedSet; #else WTF::Bitmap m_marks; - WTF::Bitmap m_rememberedSet; #endif - OwnPtr> m_newlyAllocated; + std::unique_ptr> m_newlyAllocated; - DestructorType m_destructorType; + size_t m_capacity; + bool m_needsDestruction; MarkedAllocator* m_allocator; BlockState m_state; WeakSet m_weakSet; @@ -321,9 +322,9 @@ namespace JSC { return m_atomsPerCell * atomSize; } - inline MarkedBlock::DestructorType MarkedBlock::destructorType() + inline bool MarkedBlock::needsDestruction() const { - return m_destructorType; + return m_needsDestruction; } inline size_t MarkedBlock::size() @@ -333,7 +334,7 @@ namespace JSC { inline size_t MarkedBlock::capacity() { - return region()->blockSize(); + return m_capacity; } inline size_t MarkedBlock::atomNumber(const void* p) @@ -341,26 +342,6 @@ namespace JSC { return (reinterpret_cast(p) - reinterpret_cast(this)) / atomSize; } - inline void MarkedBlock::setRemembered(const void* p) - { - m_rememberedSet.set(atomNumber(p)); - } - - inline void MarkedBlock::clearRemembered(const void* p) - { - m_rememberedSet.clear(atomNumber(p)); - } - - inline void MarkedBlock::atomicClearRemembered(const void* p) - { - m_rememberedSet.concurrentTestAndClear(atomNumber(p)); - } - - inline bool MarkedBlock::isRemembered(const void* p) - { - return m_rememberedSet.get(atomNumber(p)); - } - inline bool MarkedBlock::isMarked(const void* p) { return m_marks.get(atomNumber(p)); @@ -400,12 +381,18 @@ namespace JSC { inline bool MarkedBlock::clearNewlyAllocated() { if (m_newlyAllocated) { - m_newlyAllocated.clear(); + m_newlyAllocated = nullptr; return true; } return false; } + inline bool MarkedBlock::isMarkedOrNewlyAllocated(const JSCell* cell) + { + ASSERT(m_state == Retired || m_state == Marked); + return m_marks.get(atomNumber(cell)) || (m_newlyAllocated && isNewlyAllocated(cell)); + } + inline bool MarkedBlock::isLive(const JSCell* cell) { switch (m_state) { @@ -414,7 +401,7 @@ namespace JSC { case Retired: case Marked: - return m_marks.get(atomNumber(cell)) || (m_newlyAllocated && isNewlyAllocated(cell)); + return isMarkedOrNewlyAllocated(cell); case New: case FreeListed: @@ -441,34 +428,40 @@ namespace JSC { return isLive(static_cast(p)); } - template inline void MarkedBlock::forEachCell(Functor& functor) + template inline IterationStatus MarkedBlock::forEachCell(Functor& functor) { for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { JSCell* cell = reinterpret_cast_ptr(&atoms()[i]); - functor(cell); + if (functor(cell) == IterationStatus::Done) + return IterationStatus::Done; } + return IterationStatus::Continue; } - template inline void MarkedBlock::forEachLiveCell(Functor& functor) + template inline IterationStatus MarkedBlock::forEachLiveCell(Functor& functor) { for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { JSCell* cell = reinterpret_cast_ptr(&atoms()[i]); if (!isLive(cell)) continue; - functor(cell); + if (functor(cell) == IterationStatus::Done) + return IterationStatus::Done; } + return IterationStatus::Continue; } - template inline void MarkedBlock::forEachDeadCell(Functor& functor) + template inline IterationStatus MarkedBlock::forEachDeadCell(Functor& functor) { for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) { JSCell* cell = reinterpret_cast_ptr(&atoms()[i]); if (isLive(cell)) continue; - functor(cell); + if (functor(cell) == IterationStatus::Done) + return IterationStatus::Done; } + return IterationStatus::Continue; } inline bool MarkedBlock::needsSweeping() @@ -476,6 +469,11 @@ namespace JSC { return m_state == Marked; } + inline bool MarkedBlock::isAllocated() const + { + return m_state == Allocated; + } + } // namespace JSC namespace WTF {