#pragma once
#include "AllocationFailureMode.h"
#include "AllocatorForMode.h"
#include "Allocator.h"
#include "MarkedBlock.h"
#include "MarkedSpace.h"
#include <wtf/text/CString.h>
namespace JSC {
class AlignedMemoryAllocator;
class HeapCellType;
class Subspace {
WTF_MAKE_NONCOPYABLE(Subspace);
WTF_MAKE_FAST_ALLOCATED;
public:
JS_EXPORT_PRIVATE Subspace(CString name, Heap&);
JS_EXPORT_PRIVATE virtual ~Subspace();
const char* name() const { return m_name.data(); }
MarkedSpace& space() const { return m_space; }
const CellAttributes& attributes() const;
HeapCellType* heapCellType() const { return m_heapCellType; }
AlignedMemoryAllocator* alignedMemoryAllocator() const { return m_alignedMemoryAllocator; }
void finishSweep(MarkedBlock::Handle&, FreeList*);
void destroy(VM&, JSCell*);
virtual Allocator allocatorFor(size_t, AllocatorForMode) = 0;
virtual void* allocate(VM&, size_t, GCDeferralContext*, AllocationFailureMode) = 0;
void prepareForAllocation();
void didCreateFirstDirectory(BlockDirectory* directory) { m_directoryForEmptyAllocation = directory; }
MarkedBlock::Handle* findEmptyBlockToSteal();
template<typename Func>
void forEachDirectory(const Func&);
Ref<SharedTask<BlockDirectory*()>> parallelDirectorySource();
template<typename Func>
void forEachMarkedBlock(const Func&);
template<typename Func>
void forEachNotEmptyMarkedBlock(const Func&);
JS_EXPORT_PRIVATE Ref<SharedTask<MarkedBlock::Handle*()>> parallelNotEmptyMarkedBlockSource();
template<typename Func>
void forEachPreciseAllocation(const Func&);
template<typename Func>
void forEachMarkedCell(const Func&);
template<typename Func>
Ref<SharedTask<void(SlotVisitor&)>> forEachMarkedCellInParallel(const Func&);
template<typename Func>
void forEachLiveCell(const Func&);
void sweepBlocks();
Subspace* nextSubspaceInAlignedMemoryAllocator() const { return m_nextSubspaceInAlignedMemoryAllocator; }
void setNextSubspaceInAlignedMemoryAllocator(Subspace* subspace) { m_nextSubspaceInAlignedMemoryAllocator = subspace; }
virtual void didResizeBits(unsigned newSize);
virtual void didRemoveBlock(unsigned blockIndex);
virtual void didBeginSweepingToFreeList(MarkedBlock::Handle*);
bool isIsoSubspace() const { return m_isIsoSubspace; }
protected:
void initialize(HeapCellType*, AlignedMemoryAllocator*);
MarkedSpace& m_space;
HeapCellType* m_heapCellType { nullptr };
AlignedMemoryAllocator* m_alignedMemoryAllocator { nullptr };
BlockDirectory* m_firstDirectory { nullptr };
BlockDirectory* m_directoryForEmptyAllocation { nullptr }; SentinelLinkedList<PreciseAllocation, PackedRawSentinelNode<PreciseAllocation>> m_preciseAllocations;
Subspace* m_nextSubspaceInAlignedMemoryAllocator { nullptr };
CString m_name;
bool m_isIsoSubspace { false };
protected:
uint8_t m_remainingLowerTierCellCount { 0 };
};
}