sm-ext-dhooks2/DynamicHooks/thirdparty/AsmJit/base/zone.cpp

194 lines
4.7 KiB
C++

// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Export]
#define ASMJIT_EXPORTS
// [Dependencies]
#include "../base/utils.h"
#include "../base/zone.h"
#include <stdarg.h>
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! Zero size block used by `Zone` that doesn't have any memory allocated.
static const Zone::Block Zone_zeroBlock = {
nullptr, nullptr, nullptr, nullptr, { 0 }
};
// ============================================================================
// [asmjit::Zone - Construction / Destruction]
// ============================================================================
Zone::Zone(size_t blockSize) noexcept {
_block = const_cast<Zone::Block*>(&Zone_zeroBlock);
_blockSize = blockSize;
}
Zone::~Zone() noexcept {
reset(true);
}
// ============================================================================
// [asmjit::Zone - Reset]
// ============================================================================
void Zone::reset(bool releaseMemory) noexcept {
Block* cur = _block;
// Can't be altered.
if (cur == &Zone_zeroBlock)
return;
if (releaseMemory) {
// Since cur can be in the middle of the double-linked list, we have to
// traverse to both directions `prev` and `next` separately.
Block* next = cur->next;
do {
Block* prev = cur->prev;
ASMJIT_FREE(cur);
cur = prev;
} while (cur != nullptr);
cur = next;
while (cur != nullptr) {
next = cur->next;
ASMJIT_FREE(cur);
cur = next;
}
_block = const_cast<Zone::Block*>(&Zone_zeroBlock);
}
else {
while (cur->prev != nullptr)
cur = cur->prev;
cur->pos = cur->data;
_block = cur;
}
}
// ============================================================================
// [asmjit::Zone - Alloc]
// ============================================================================
void* Zone::_alloc(size_t size) noexcept {
Block* curBlock = _block;
size_t blockSize = Utils::iMax<size_t>(_blockSize, size);
// The `_alloc()` method can only be called if there is not enough space
// in the current block, see `alloc()` implementation for more details.
ASMJIT_ASSERT(curBlock == &Zone_zeroBlock || curBlock->getRemainingSize() < size);
// If the `Zone` has been reset the current block doesn't have to be the
// last one. Check if there is a block that can be used instead of allocating
// a new one. If there is a `next` block it's completely unused, we don't have
// to check for remaining bytes.
Block* next = curBlock->next;
if (next != nullptr && next->getBlockSize() >= size) {
next->pos = next->data + size;
_block = next;
return static_cast<void*>(next->data);
}
// Prevent arithmetic overflow.
if (blockSize > ~static_cast<size_t>(0) - sizeof(Block))
return nullptr;
Block* newBlock = static_cast<Block*>(ASMJIT_ALLOC(sizeof(Block) - sizeof(void*) + blockSize));
if (newBlock == nullptr)
return nullptr;
newBlock->pos = newBlock->data + size;
newBlock->end = newBlock->data + blockSize;
newBlock->prev = nullptr;
newBlock->next = nullptr;
if (curBlock != &Zone_zeroBlock) {
newBlock->prev = curBlock;
curBlock->next = newBlock;
// Does only happen if there is a next block, but the requested memory
// can't fit into it. In this case a new buffer is allocated and inserted
// between the current block and the next one.
if (next != nullptr) {
newBlock->next = next;
next->prev = newBlock;
}
}
_block = newBlock;
return static_cast<void*>(newBlock->data);
}
void* Zone::allocZeroed(size_t size) noexcept {
void* p = alloc(size);
if (p != nullptr)
::memset(p, 0, size);
return p;
}
void* Zone::dup(const void* data, size_t size) noexcept {
if (data == nullptr)
return nullptr;
if (size == 0)
return nullptr;
void* m = alloc(size);
if (m == nullptr)
return nullptr;
::memcpy(m, data, size);
return m;
}
char* Zone::sdup(const char* str) noexcept {
if (str == nullptr)
return nullptr;
size_t len = ::strlen(str);
if (len == 0)
return nullptr;
// Include NULL terminator and limit string length.
if (++len > 256)
len = 256;
char* m = static_cast<char*>(alloc(len));
if (m == nullptr)
return nullptr;
::memcpy(m, str, len);
m[len - 1] = '\0';
return m;
}
char* Zone::sformat(const char* fmt, ...) noexcept {
if (fmt == nullptr)
return nullptr;
char buf[512];
size_t len;
va_list ap;
va_start(ap, fmt);
len = vsnprintf(buf, ASMJIT_ARRAY_SIZE(buf) - 1, fmt, ap);
buf[len++] = 0;
va_end(ap);
return static_cast<char*>(dup(buf, len));
}
} // asmjit namespace
// [Api-End]
#include "../apiend.h"