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

221 lines
6.7 KiB
C++

// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// [Guard]
#ifndef _ASMJIT_BASE_ZONE_H
#define _ASMJIT_BASE_ZONE_H
// [Dependencies]
#include "../base/globals.h"
// [Api-Begin]
#include "../apibegin.h"
namespace asmjit {
//! \addtogroup asmjit_base
//! \{
// ============================================================================
// [asmjit::Zone]
// ============================================================================
//! Zone memory allocator.
//!
//! Zone is an incremental memory allocator that allocates memory by simply
//! incrementing a pointer. It allocates blocks of memory by using standard
//! C library `malloc/free`, but divides these blocks into smaller segments
//! requirested by calling `Zone::alloc()` and friends.
//!
//! Zone memory allocators are designed to allocate data of short lifetime. The
//! data used by `Assembler` and `Compiler` has a very short lifetime, thus, is
//! allocated by `Zone`. The advantage is that `Zone` can free all of the data
//! allocated at once by calling `reset()` or by `Zone` destructor.
class Zone {
public:
//! \internal
//!
//! A single block of memory.
struct Block {
// ------------------------------------------------------------------------
// [Accessors]
// ------------------------------------------------------------------------
//! Get the size of the block.
ASMJIT_INLINE size_t getBlockSize() const noexcept {
return (size_t)(end - data);
}
//! Get count of remaining bytes in the block.
ASMJIT_INLINE size_t getRemainingSize() const noexcept {
return (size_t)(end - pos);
}
// ------------------------------------------------------------------------
// [Members]
// ------------------------------------------------------------------------
//! Current data pointer (pointer to the first available byte).
uint8_t* pos;
//! End data pointer (pointer to the first invalid byte).
uint8_t* end;
//! Link to the previous block.
Block* prev;
//! Link to the next block.
Block* next;
//! Data.
uint8_t data[sizeof(void*)];
};
enum {
//! Zone allocator overhead.
kZoneOverhead =
kMemAllocOverhead
+ static_cast<int>(sizeof(Block) - sizeof(void*))
};
// --------------------------------------------------------------------------
// [Construction / Destruction]
// --------------------------------------------------------------------------
//! Create a new instance of `Zone` allocator.
//!
//! The `blockSize` parameter describes the default size of the block. If the
//! `size` parameter passed to `alloc()` is greater than the default size
//! `Zone` will allocate and use a larger block, but it will not change the
//! default `blockSize`.
//!
//! It's not required, but it's good practice to set `blockSize` to a
//! reasonable value that depends on the usage of `Zone`. Greater block sizes
//! are generally safer and performs better than unreasonably low values.
ASMJIT_API Zone(size_t blockSize) noexcept;
//! Destroy the `Zone` instance.
//!
//! This will destroy the `Zone` instance and release all blocks of memory
//! allocated by it. It performs implicit `reset(true)`.
ASMJIT_API ~Zone() noexcept;
// --------------------------------------------------------------------------
// [Reset]
// --------------------------------------------------------------------------
//! Reset the `Zone` invalidating all blocks allocated.
//!
//! If `releaseMemory` is true all buffers will be released to the system.
ASMJIT_API void reset(bool releaseMemory = false) noexcept;
// --------------------------------------------------------------------------
// [Accessors]
// --------------------------------------------------------------------------
//! Get the default block size.
ASMJIT_INLINE size_t getBlockSize() const noexcept {
return _blockSize;
}
// --------------------------------------------------------------------------
// [Alloc]
// --------------------------------------------------------------------------
//! Allocate `size` bytes of memory.
//!
//! Pointer returned is valid until the `Zone` instance is destroyed or reset
//! by calling `reset()`. If you plan to make an instance of C++ from the
//! given pointer use placement `new` and `delete` operators:
//!
//! ~~~
//! using namespace asmjit;
//!
//! class Object { ... };
//!
//! // Create Zone with default block size of approximately 65536 bytes.
//! Zone zone(65536 - Zone::kZoneOverhead);
//!
//! // Create your objects using zone object allocating, for example:
//! Object* obj = static_cast<Object*>( zone.alloc(sizeof(Object)) );
//
//! if (obj == nullptr) {
//! // Handle out of memory error.
//! }
//!
//! // Placement `new` and `delete` operators can be used to instantiate it.
//! new(obj) Object();
//!
//! // ... lifetime of your objects ...
//!
//! // To destroy the instance (if required).
//! obj->~Object();
//!
//! // Reset or destroy `Zone`.
//! zone.reset();
//! ~~~
ASMJIT_INLINE void* alloc(size_t size) noexcept {
Block* cur = _block;
uint8_t* ptr = cur->pos;
size_t remainingBytes = (size_t)(cur->end - ptr);
if (remainingBytes < size)
return _alloc(size);
cur->pos += size;
ASMJIT_ASSERT(cur->pos <= cur->end);
return (void*)ptr;
}
//! Allocate `size` bytes of zeroed memory.
//!
//! See \ref alloc() for more details.
ASMJIT_API void* allocZeroed(size_t size) noexcept;
//! Like `alloc()`, but the return pointer is casted to `T*`.
template<typename T>
ASMJIT_INLINE T* allocT(size_t size = sizeof(T)) noexcept {
return static_cast<T*>(alloc(size));
}
//! Like `allocZeroed()`, but the return pointer is casted to `T*`.
template<typename T>
ASMJIT_INLINE T* allocZeroedT(size_t size = sizeof(T)) noexcept {
return static_cast<T*>(allocZeroed(size));
}
//! \internal
ASMJIT_API void* _alloc(size_t size) noexcept;
//! Helper to duplicate data.
ASMJIT_API void* dup(const void* data, size_t size) noexcept;
//! Helper to duplicate string.
ASMJIT_API char* sdup(const char* str) noexcept;
//! Helper to duplicate formatted string, maximum length is 256 bytes.
ASMJIT_API char* sformat(const char* str, ...) noexcept;
// --------------------------------------------------------------------------
// [Members]
// --------------------------------------------------------------------------
//! The current block.
Block* _block;
//! Default block size.
size_t _blockSize;
};
//! \}
} // asmjit namespace
// [Api-End]
#include "../apiend.h"
// [Guard]
#endif // _ASMJIT_BASE_ZONE_H