#ifndef CopiedAllocator_h
#define CopiedAllocator_h
#include "CopiedBlock.h"
#include <wtf/CheckedBoolean.h>
namespace JSC {
class CopiedAllocator {
public:
CopiedAllocator();
bool fastPathShouldSucceed(size_t bytes) const;
CheckedBoolean tryAllocate(size_t bytes, void** outPtr);
CheckedBoolean tryAllocateDuringCopying(size_t bytes, void** outPtr);
CheckedBoolean tryReallocate(void *oldPtr, size_t oldBytes, size_t newBytes);
void* forceAllocate(size_t bytes);
CopiedBlock* resetCurrentBlock();
void setCurrentBlock(CopiedBlock*);
size_t currentCapacity();
bool isValid() const { return !!m_currentBlock; }
CopiedBlock* currentBlock() { return m_currentBlock; }
size_t m_currentRemaining;
char* m_currentPayloadEnd;
CopiedBlock* m_currentBlock;
};
inline CopiedAllocator::CopiedAllocator()
: m_currentRemaining(0)
, m_currentPayloadEnd(0)
, m_currentBlock(0)
{
}
inline bool CopiedAllocator::fastPathShouldSucceed(size_t bytes) const
{
ASSERT(is8ByteAligned(reinterpret_cast<void*>(bytes)));
return bytes <= m_currentRemaining;
}
inline CheckedBoolean CopiedAllocator::tryAllocate(size_t bytes, void** outPtr)
{
ASSERT(is8ByteAligned(reinterpret_cast<void*>(bytes)));
size_t currentRemaining = m_currentRemaining;
if (bytes > currentRemaining)
return false;
currentRemaining -= bytes;
m_currentRemaining = currentRemaining;
*outPtr = m_currentPayloadEnd - currentRemaining - bytes;
ASSERT(is8ByteAligned(*outPtr));
return true;
}
inline CheckedBoolean CopiedAllocator::tryAllocateDuringCopying(size_t bytes, void** outPtr)
{
if (!tryAllocate(bytes, outPtr))
return false;
m_currentBlock->reportLiveBytesDuringCopying(bytes);
return true;
}
inline CheckedBoolean CopiedAllocator::tryReallocate(
void* oldPtr, size_t oldBytes, size_t newBytes)
{
ASSERT(is8ByteAligned(oldPtr));
ASSERT(is8ByteAligned(reinterpret_cast<void*>(oldBytes)));
ASSERT(is8ByteAligned(reinterpret_cast<void*>(newBytes)));
ASSERT(newBytes > oldBytes);
size_t additionalBytes = newBytes - oldBytes;
size_t currentRemaining = m_currentRemaining;
if (m_currentPayloadEnd - currentRemaining - oldBytes != static_cast<char*>(oldPtr))
return false;
if (additionalBytes > currentRemaining)
return false;
m_currentRemaining = currentRemaining - additionalBytes;
return true;
}
inline void* CopiedAllocator::forceAllocate(size_t bytes)
{
void* result = 0; CheckedBoolean didSucceed = tryAllocate(bytes, &result);
ASSERT(didSucceed);
return result;
}
inline CopiedBlock* CopiedAllocator::resetCurrentBlock()
{
CopiedBlock* result = m_currentBlock;
if (result) {
result->m_remaining = m_currentRemaining;
m_currentBlock = 0;
m_currentRemaining = 0;
m_currentPayloadEnd = 0;
}
return result;
}
inline void CopiedAllocator::setCurrentBlock(CopiedBlock* newBlock)
{
ASSERT(!m_currentBlock);
m_currentBlock = newBlock;
ASSERT(newBlock);
m_currentRemaining = newBlock->m_remaining;
m_currentPayloadEnd = newBlock->payloadEnd();
}
inline size_t CopiedAllocator::currentCapacity()
{
if (!m_currentBlock)
return 0;
return m_currentBlock->capacity();
}
}
#endif