SSE2: Implement alignment for arena allocator
--HG-- branch : sse2
This commit is contained in:
parent
eee9ba0cae
commit
556a41afee
3 changed files with 21 additions and 11 deletions
|
@ -53,6 +53,7 @@ public:
|
||||||
uint getNumAllocatedBlocks() const { return _NumAlloc; }
|
uint getNumAllocatedBlocks() const { return _NumAlloc; }
|
||||||
private:
|
private:
|
||||||
class CChunk;
|
class CChunk;
|
||||||
|
NL_ALIGN(NL_DEFAULT_MEMORY_ALIGNMENT)
|
||||||
class CNode
|
class CNode
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -33,6 +33,9 @@ CFixedSizeAllocator::CFixedSizeAllocator(uint numBytesPerBlock, uint numBlockPer
|
||||||
_NumChunks = 0;
|
_NumChunks = 0;
|
||||||
nlassert(numBytesPerBlock > 1);
|
nlassert(numBytesPerBlock > 1);
|
||||||
_NumBytesPerBlock = numBytesPerBlock;
|
_NumBytesPerBlock = numBytesPerBlock;
|
||||||
|
const uint mask = NL_DEFAULT_MEMORY_ALIGNMENT - 1;
|
||||||
|
_NumBytesPerBlock = (_NumBytesPerBlock + mask) & ~mask;
|
||||||
|
nlassert(_NumBytesPerBlock >= numBytesPerBlock);
|
||||||
_NumBlockPerChunk = std::max(numBlockPerChunk, (uint) 3);
|
_NumBlockPerChunk = std::max(numBlockPerChunk, (uint) 3);
|
||||||
_NumAlloc = 0;
|
_NumAlloc = 0;
|
||||||
}
|
}
|
||||||
|
@ -67,12 +70,14 @@ void *CFixedSizeAllocator::alloc()
|
||||||
return _FreeSpace->unlink();
|
return _FreeSpace->unlink();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define aligned_offsetof(s, m) ((offsetof(s, m) + (NL_DEFAULT_MEMORY_ALIGNMENT - 1)) & ~(NL_DEFAULT_MEMORY_ALIGNMENT - 1))
|
||||||
|
|
||||||
// *****************************************************************************************************************
|
// *****************************************************************************************************************
|
||||||
void CFixedSizeAllocator::free(void *block)
|
void CFixedSizeAllocator::free(void *block)
|
||||||
{
|
{
|
||||||
if (!block) return;
|
if (!block) return;
|
||||||
/// get the node from the object
|
/// get the node from the object
|
||||||
CNode *node = (CNode *) ((uint8 *) block - offsetof(CNode, Next));
|
CNode *node = (CNode *) ((uint8 *) block - aligned_offsetof(CNode, Next));
|
||||||
//
|
//
|
||||||
nlassert(node->Chunk != NULL);
|
nlassert(node->Chunk != NULL);
|
||||||
nlassert(node->Chunk->Allocator == this);
|
nlassert(node->Chunk->Allocator == this);
|
||||||
|
@ -84,7 +89,9 @@ void CFixedSizeAllocator::free(void *block)
|
||||||
// *****************************************************************************************************************
|
// *****************************************************************************************************************
|
||||||
uint CFixedSizeAllocator::CChunk::getBlockSizeWithOverhead() const
|
uint CFixedSizeAllocator::CChunk::getBlockSizeWithOverhead() const
|
||||||
{
|
{
|
||||||
return std::max((uint)(sizeof(CNode) - offsetof(CNode, Next)),(uint)(Allocator->getNumBytesPerBlock())) + offsetof(CNode, Next);
|
nlctassert((sizeof(CNode) % NL_DEFAULT_MEMORY_ALIGNMENT) == 0);
|
||||||
|
return std::max((uint)(sizeof(CNode) - aligned_offsetof(CNode, Next)),
|
||||||
|
(uint)(Allocator->getNumBytesPerBlock())) + aligned_offsetof(CNode, Next);
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************
|
// *****************************************************************************************************************
|
||||||
|
@ -105,7 +112,7 @@ CFixedSizeAllocator::CChunk::~CChunk()
|
||||||
nlassert(NumFreeObjs == 0);
|
nlassert(NumFreeObjs == 0);
|
||||||
nlassert(Allocator->_NumChunks > 0);
|
nlassert(Allocator->_NumChunks > 0);
|
||||||
-- (Allocator->_NumChunks);
|
-- (Allocator->_NumChunks);
|
||||||
delete[] Mem;
|
aligned_free(Mem); //delete[] Mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************
|
// *****************************************************************************************************************
|
||||||
|
@ -115,7 +122,7 @@ void CFixedSizeAllocator::CChunk::init(CFixedSizeAllocator *alloc)
|
||||||
nlassert(alloc != NULL);
|
nlassert(alloc != NULL);
|
||||||
Allocator = alloc;
|
Allocator = alloc;
|
||||||
//
|
//
|
||||||
Mem = new uint8[getBlockSizeWithOverhead() * alloc->getNumBlockPerChunk()];
|
Mem = (uint8 *)aligned_malloc(getBlockSizeWithOverhead() * alloc->getNumBlockPerChunk(), NL_DEFAULT_MEMORY_ALIGNMENT); // new uint8[getBlockSizeWithOverhead() * alloc->getNumBlockPerChunk()];
|
||||||
//
|
//
|
||||||
getNode(0).Chunk = this;
|
getNode(0).Chunk = this;
|
||||||
getNode(0).Next = &getNode(1);
|
getNode(0).Next = &getNode(1);
|
||||||
|
@ -179,7 +186,7 @@ void *CFixedSizeAllocator::CNode::unlink()
|
||||||
*Prev = Next;
|
*Prev = Next;
|
||||||
nlassert(Chunk->NumFreeObjs > 0);
|
nlassert(Chunk->NumFreeObjs > 0);
|
||||||
Chunk->grab(); // tells the containing chunk that a node has been allocated
|
Chunk->grab(); // tells the containing chunk that a node has been allocated
|
||||||
return (void *) &Next;
|
return (void *)((uintptr_t)(this) + aligned_offsetof(CNode, Next)); //(void *) &Next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************
|
// *****************************************************************************************************************
|
||||||
|
|
|
@ -68,21 +68,23 @@ void *CObjectArenaAllocator::alloc(uint size)
|
||||||
if (size >= _MaxAllocSize)
|
if (size >= _MaxAllocSize)
|
||||||
{
|
{
|
||||||
// use standard allocator
|
// use standard allocator
|
||||||
uint8 *block = new uint8[size + sizeof(uint)]; // an additionnal uint is needed to store size of block
|
nlctassert(NL_DEFAULT_MEMORY_ALIGNMENT > sizeof(uint));
|
||||||
|
uint8 *block = (uint8 *)aligned_malloc(NL_DEFAULT_MEMORY_ALIGNMENT + size, NL_DEFAULT_MEMORY_ALIGNMENT); //new uint8[size + sizeof(uint)]; // an additionnal uint is needed to store size of block
|
||||||
if (!block) return NULL;
|
if (!block) return NULL;
|
||||||
#ifdef NL_DEBUG
|
#ifdef NL_DEBUG
|
||||||
_MemBlockToAllocID[block] = _AllocID;
|
_MemBlockToAllocID[block] = _AllocID;
|
||||||
#endif
|
#endif
|
||||||
*(uint *) block = size;
|
*(uint *) block = size;
|
||||||
return block + sizeof(uint);
|
return block + NL_DEFAULT_MEMORY_ALIGNMENT;
|
||||||
}
|
}
|
||||||
uint entry = ((size + (_Granularity - 1)) / _Granularity) ;
|
uint entry = ((size + (_Granularity - 1)) / _Granularity) ;
|
||||||
nlassert(entry < _ObjectSizeToAllocator.size());
|
nlassert(entry < _ObjectSizeToAllocator.size());
|
||||||
if (!_ObjectSizeToAllocator[entry])
|
if (!_ObjectSizeToAllocator[entry])
|
||||||
{
|
{
|
||||||
_ObjectSizeToAllocator[entry] = new CFixedSizeAllocator(entry * _Granularity + sizeof(uint), _MaxAllocSize / size); // an additionnal uint is needed to store size of block
|
_ObjectSizeToAllocator[entry] = new CFixedSizeAllocator(entry * _Granularity + NL_DEFAULT_MEMORY_ALIGNMENT, _MaxAllocSize / size); // an additionnal uint is needed to store size of block
|
||||||
}
|
}
|
||||||
void *block = _ObjectSizeToAllocator[entry]->alloc();
|
void *block = _ObjectSizeToAllocator[entry]->alloc();
|
||||||
|
nlassert(((uintptr_t)block % NL_DEFAULT_MEMORY_ALIGNMENT) == 0);
|
||||||
#ifdef NL_DEBUG
|
#ifdef NL_DEBUG
|
||||||
if (block)
|
if (block)
|
||||||
{
|
{
|
||||||
|
@ -91,14 +93,14 @@ void *CObjectArenaAllocator::alloc(uint size)
|
||||||
++_AllocID;
|
++_AllocID;
|
||||||
#endif
|
#endif
|
||||||
*(uint *) block = size;
|
*(uint *) block = size;
|
||||||
return (void *) ((uint8 *) block + sizeof(uint));
|
return (void *) ((uint8 *) block + NL_DEFAULT_MEMORY_ALIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// *****************************************************************************************************************
|
// *****************************************************************************************************************
|
||||||
void CObjectArenaAllocator::free(void *block)
|
void CObjectArenaAllocator::free(void *block)
|
||||||
{
|
{
|
||||||
if (!block) return;
|
if (!block) return;
|
||||||
uint8 *realBlock = (uint8 *) block - sizeof(uint); // a uint is used at start of block to give its size
|
uint8 *realBlock = (uint8 *) block - NL_DEFAULT_MEMORY_ALIGNMENT; // sizeof(uint); // a uint is used at start of block to give its size
|
||||||
uint size = *(uint *) realBlock;
|
uint size = *(uint *) realBlock;
|
||||||
if (size >= _MaxAllocSize)
|
if (size >= _MaxAllocSize)
|
||||||
{
|
{
|
||||||
|
@ -107,7 +109,7 @@ void CObjectArenaAllocator::free(void *block)
|
||||||
nlassert(it != _MemBlockToAllocID.end());
|
nlassert(it != _MemBlockToAllocID.end());
|
||||||
_MemBlockToAllocID.erase(it);
|
_MemBlockToAllocID.erase(it);
|
||||||
#endif
|
#endif
|
||||||
delete realBlock;
|
aligned_free(realBlock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint entry = ((size + (_Granularity - 1)) / _Granularity);
|
uint entry = ((size + (_Granularity - 1)) / _Granularity);
|
||||||
|
|
Loading…
Reference in a new issue