asmjit 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/asmjit.gemspec +1 -1
- data/ext/asmjit/asmjit/.editorconfig +10 -0
- data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
- data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
- data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
- data/ext/asmjit/asmjit/.gitignore +6 -0
- data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
- data/ext/asmjit/asmjit/LICENSE.md +17 -0
- data/ext/asmjit/asmjit/README.md +69 -0
- data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
- data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
- data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
- data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
- data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
- data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
- data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
- data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
- data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
- data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
- data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
- data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
- data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
- data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
- data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
- data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
- data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
- data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
- data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
- data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
- data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
- data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
- data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
- data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
- data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
- data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
- data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
- data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
- data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
- data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
- data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
- data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
- data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
- data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
- data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
- data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
- data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
- data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
- data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
- data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
- data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
- data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
- data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
- data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
- data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
- data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
- data/ext/asmjit/asmjit/test/broken.cpp +312 -0
- data/ext/asmjit/asmjit/test/broken.h +148 -0
- data/ext/asmjit/asmjit/test/cmdline.h +61 -0
- data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
- data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
- data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
- data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
- data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
- data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
- data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
- data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
- data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
- data/ext/asmjit/asmjit.cc +18 -0
- data/lib/asmjit/version.rb +1 -1
- metadata +197 -2
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
// This file is part of AsmJit project <https://asmjit.com>
|
|
2
|
+
//
|
|
3
|
+
// See asmjit.h or LICENSE.md for license and copyright information
|
|
4
|
+
// SPDX-License-Identifier: Zlib
|
|
5
|
+
|
|
6
|
+
#ifndef ASMJIT_CORE_ZONE_H_INCLUDED
|
|
7
|
+
#define ASMJIT_CORE_ZONE_H_INCLUDED
|
|
8
|
+
|
|
9
|
+
#include "../core/support.h"
|
|
10
|
+
|
|
11
|
+
ASMJIT_BEGIN_NAMESPACE
|
|
12
|
+
|
|
13
|
+
//! \addtogroup asmjit_zone
|
|
14
|
+
//! \{
|
|
15
|
+
|
|
16
|
+
//! Zone memory.
|
|
17
|
+
//!
|
|
18
|
+
//! Zone is an incremental memory allocator that allocates memory by simply incrementing a pointer. It allocates
|
|
19
|
+
//! blocks of memory by using C's `malloc()`, but divides these blocks into smaller segments requested by calling
|
|
20
|
+
//! `Zone::alloc()` and friends.
|
|
21
|
+
//!
|
|
22
|
+
//! Zone has no function to release the allocated memory. It has to be released all at once by calling `reset()`.
|
|
23
|
+
//! If you need a more friendly allocator that also supports `release()`, consider using `Zone` with `ZoneAllocator`.
|
|
24
|
+
class Zone {
|
|
25
|
+
public:
|
|
26
|
+
ASMJIT_NONCOPYABLE(Zone)
|
|
27
|
+
|
|
28
|
+
//! \cond INTERNAL
|
|
29
|
+
|
|
30
|
+
//! A single block of memory managed by `Zone`.
|
|
31
|
+
struct Block {
|
|
32
|
+
inline uint8_t* data() const noexcept {
|
|
33
|
+
return const_cast<uint8_t*>(reinterpret_cast<const uint8_t*>(this) + sizeof(*this));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//! Link to the previous block.
|
|
37
|
+
Block* prev;
|
|
38
|
+
//! Link to the next block.
|
|
39
|
+
Block* next;
|
|
40
|
+
//! Size of the block.
|
|
41
|
+
size_t size;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
enum Limits : size_t {
|
|
45
|
+
kBlockSize = sizeof(Block),
|
|
46
|
+
kBlockOverhead = Globals::kAllocOverhead + kBlockSize,
|
|
47
|
+
|
|
48
|
+
kMinBlockSize = 64, // The number is ridiculously small, but still possible.
|
|
49
|
+
kMaxBlockSize = size_t(1) << (sizeof(size_t) * 8 - 4 - 1),
|
|
50
|
+
kMinAlignment = 1,
|
|
51
|
+
kMaxAlignment = 64
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
//! Pointer in the current block.
|
|
55
|
+
uint8_t* _ptr;
|
|
56
|
+
//! End of the current block.
|
|
57
|
+
uint8_t* _end;
|
|
58
|
+
//! Current block.
|
|
59
|
+
Block* _block;
|
|
60
|
+
|
|
61
|
+
union {
|
|
62
|
+
struct {
|
|
63
|
+
//! Default block size.
|
|
64
|
+
size_t _blockSize : Support::bitSizeOf<size_t>() - 4;
|
|
65
|
+
//! First block is temporary (ZoneTmp).
|
|
66
|
+
size_t _isTemporary : 1;
|
|
67
|
+
//! Block alignment (1 << alignment).
|
|
68
|
+
size_t _blockAlignmentShift : 3;
|
|
69
|
+
};
|
|
70
|
+
size_t _packedData;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
static ASMJIT_API const Block _zeroBlock;
|
|
74
|
+
|
|
75
|
+
//! \endcond
|
|
76
|
+
|
|
77
|
+
//! \name Construction & Destruction
|
|
78
|
+
//! \{
|
|
79
|
+
|
|
80
|
+
//! Creates a new Zone.
|
|
81
|
+
//!
|
|
82
|
+
//! The `blockSize` parameter describes the default size of the block. If the `size` parameter passed to `alloc()`
|
|
83
|
+
//! is greater than the default size `Zone` will allocate and use a larger block, but it will not change the
|
|
84
|
+
//! default `blockSize`.
|
|
85
|
+
//!
|
|
86
|
+
//! It's not required, but it's good practice to set `blockSize` to a reasonable value that depends on the usage
|
|
87
|
+
//! of `Zone`. Greater block sizes are generally safer and perform better than unreasonably low block sizes.
|
|
88
|
+
inline explicit Zone(size_t blockSize, size_t blockAlignment = 1) noexcept {
|
|
89
|
+
_init(blockSize, blockAlignment, nullptr);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
//! Creates a new Zone with a first block pointing to a `temporary` memory.
|
|
93
|
+
inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary& temporary) noexcept {
|
|
94
|
+
_init(blockSize, blockAlignment, &temporary);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//! \overload
|
|
98
|
+
inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept {
|
|
99
|
+
_init(blockSize, blockAlignment, temporary);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
//! Moves an existing `Zone`.
|
|
103
|
+
//!
|
|
104
|
+
//! \note You cannot move an existing `ZoneTmp` as it uses embedded storage. Attempting to move `ZoneTmp` would
|
|
105
|
+
//! result in assertion failure in debug mode and undefined behavior in release mode.
|
|
106
|
+
inline Zone(Zone&& other) noexcept
|
|
107
|
+
: _ptr(other._ptr),
|
|
108
|
+
_end(other._end),
|
|
109
|
+
_block(other._block),
|
|
110
|
+
_packedData(other._packedData) {
|
|
111
|
+
ASMJIT_ASSERT(!other.isTemporary());
|
|
112
|
+
other._block = const_cast<Block*>(&_zeroBlock);
|
|
113
|
+
other._ptr = other._block->data();
|
|
114
|
+
other._end = other._block->data();
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//! Destroys the `Zone` instance.
|
|
118
|
+
//!
|
|
119
|
+
//! This will destroy the `Zone` instance and release all blocks of memory allocated by it. It performs implicit
|
|
120
|
+
//! `reset(ResetPolicy::kHard)`.
|
|
121
|
+
inline ~Zone() noexcept { reset(ResetPolicy::kHard); }
|
|
122
|
+
|
|
123
|
+
ASMJIT_API void _init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept;
|
|
124
|
+
|
|
125
|
+
//! Resets the `Zone` invalidating all blocks allocated.
|
|
126
|
+
//!
|
|
127
|
+
//! See `Globals::ResetPolicy` for more details.
|
|
128
|
+
ASMJIT_API void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept;
|
|
129
|
+
|
|
130
|
+
//! \}
|
|
131
|
+
|
|
132
|
+
//! \name Accessors
|
|
133
|
+
//! \{
|
|
134
|
+
|
|
135
|
+
//! Tests whether this `Zone` is actually a `ZoneTmp` that uses temporary memory.
|
|
136
|
+
inline bool isTemporary() const noexcept { return _isTemporary != 0; }
|
|
137
|
+
|
|
138
|
+
//! Returns the default block size.
|
|
139
|
+
inline size_t blockSize() const noexcept { return _blockSize; }
|
|
140
|
+
//! Returns the default block alignment.
|
|
141
|
+
inline size_t blockAlignment() const noexcept { return size_t(1) << _blockAlignmentShift; }
|
|
142
|
+
//! Returns remaining size of the current block.
|
|
143
|
+
inline size_t remainingSize() const noexcept { return (size_t)(_end - _ptr); }
|
|
144
|
+
|
|
145
|
+
//! Returns the current zone cursor (dangerous).
|
|
146
|
+
//!
|
|
147
|
+
//! This is a function that can be used to get exclusive access to the current block's memory buffer.
|
|
148
|
+
template<typename T = uint8_t>
|
|
149
|
+
inline T* ptr() noexcept { return reinterpret_cast<T*>(_ptr); }
|
|
150
|
+
|
|
151
|
+
//! Returns the end of the current zone block, only useful if you use `ptr()`.
|
|
152
|
+
template<typename T = uint8_t>
|
|
153
|
+
inline T* end() noexcept { return reinterpret_cast<T*>(_end); }
|
|
154
|
+
|
|
155
|
+
//! Sets the current zone pointer to `ptr` (must be within the current block).
|
|
156
|
+
template<typename T>
|
|
157
|
+
inline void setPtr(T* ptr) noexcept {
|
|
158
|
+
uint8_t* p = reinterpret_cast<uint8_t*>(ptr);
|
|
159
|
+
ASMJIT_ASSERT(p >= _ptr && p <= _end);
|
|
160
|
+
_ptr = p;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
//! Sets the end zone pointer to `end` (must be within the current block).
|
|
164
|
+
template<typename T>
|
|
165
|
+
inline void setEnd(T* end) noexcept {
|
|
166
|
+
uint8_t* p = reinterpret_cast<uint8_t*>(end);
|
|
167
|
+
ASMJIT_ASSERT(p >= _ptr && p <= _end);
|
|
168
|
+
_end = p;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
//! \}
|
|
172
|
+
|
|
173
|
+
//! \name Utilities
|
|
174
|
+
//! \{
|
|
175
|
+
|
|
176
|
+
inline void swap(Zone& other) noexcept {
|
|
177
|
+
// This could lead to a disaster.
|
|
178
|
+
ASMJIT_ASSERT(!this->isTemporary());
|
|
179
|
+
ASMJIT_ASSERT(!other.isTemporary());
|
|
180
|
+
|
|
181
|
+
std::swap(_ptr, other._ptr);
|
|
182
|
+
std::swap(_end, other._end);
|
|
183
|
+
std::swap(_block, other._block);
|
|
184
|
+
std::swap(_packedData, other._packedData);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
//! Aligns the current pointer to `alignment`.
|
|
188
|
+
inline void align(size_t alignment) noexcept {
|
|
189
|
+
_ptr = Support::min(Support::alignUp(_ptr, alignment), _end);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
//! Ensures the remaining size is at least equal or greater than `size`.
|
|
193
|
+
//!
|
|
194
|
+
//! \note This function doesn't respect any alignment. If you need to ensure there is enough room for an aligned
|
|
195
|
+
//! allocation you need to call `align()` before calling `ensure()`.
|
|
196
|
+
inline Error ensure(size_t size) noexcept {
|
|
197
|
+
if (size <= remainingSize())
|
|
198
|
+
return kErrorOk;
|
|
199
|
+
else
|
|
200
|
+
return _alloc(0, 1) ? kErrorOk : DebugUtils::errored(kErrorOutOfMemory);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
inline void _assignBlock(Block* block) noexcept {
|
|
204
|
+
size_t alignment = blockAlignment();
|
|
205
|
+
_ptr = Support::alignUp(block->data(), alignment);
|
|
206
|
+
_end = Support::alignDown(block->data() + block->size, alignment);
|
|
207
|
+
_block = block;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
inline void _assignZeroBlock() noexcept {
|
|
211
|
+
Block* block = const_cast<Block*>(&_zeroBlock);
|
|
212
|
+
_ptr = block->data();
|
|
213
|
+
_end = block->data();
|
|
214
|
+
_block = block;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
//! \}
|
|
218
|
+
|
|
219
|
+
//! \name Allocation
|
|
220
|
+
//! \{
|
|
221
|
+
|
|
222
|
+
//! Allocates the requested memory specified by `size`.
|
|
223
|
+
//!
|
|
224
|
+
//! Pointer returned is valid until the `Zone` instance is destroyed or reset by calling `reset()`. If you plan to
|
|
225
|
+
//! make an instance of C++ from the given pointer use placement `new` and `delete` operators:
|
|
226
|
+
//!
|
|
227
|
+
//! ```
|
|
228
|
+
//! using namespace asmjit;
|
|
229
|
+
//!
|
|
230
|
+
//! class Object { ... };
|
|
231
|
+
//!
|
|
232
|
+
//! // Create Zone with default block size of approximately 65536 bytes.
|
|
233
|
+
//! Zone zone(65536 - Zone::kBlockOverhead);
|
|
234
|
+
//!
|
|
235
|
+
//! // Create your objects using zone object allocating, for example:
|
|
236
|
+
//! Object* obj = static_cast<Object*>( zone.alloc(sizeof(Object)) );
|
|
237
|
+
//!
|
|
238
|
+
//! if (!obj) {
|
|
239
|
+
//! // Handle out of memory error.
|
|
240
|
+
//! }
|
|
241
|
+
//!
|
|
242
|
+
//! // Placement `new` and `delete` operators can be used to instantiate it.
|
|
243
|
+
//! new(obj) Object();
|
|
244
|
+
//!
|
|
245
|
+
//! // ... lifetime of your objects ...
|
|
246
|
+
//!
|
|
247
|
+
//! // To destroy the instance (if required).
|
|
248
|
+
//! obj->~Object();
|
|
249
|
+
//!
|
|
250
|
+
//! // Reset or destroy `Zone`.
|
|
251
|
+
//! zone.reset();
|
|
252
|
+
//! ```
|
|
253
|
+
inline void* alloc(size_t size) noexcept {
|
|
254
|
+
if (ASMJIT_UNLIKELY(size > remainingSize()))
|
|
255
|
+
return _alloc(size, 1);
|
|
256
|
+
|
|
257
|
+
uint8_t* ptr = _ptr;
|
|
258
|
+
_ptr += size;
|
|
259
|
+
return static_cast<void*>(ptr);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
//! Allocates the requested memory specified by `size` and `alignment`.
|
|
263
|
+
inline void* alloc(size_t size, size_t alignment) noexcept {
|
|
264
|
+
ASMJIT_ASSERT(Support::isPowerOf2(alignment));
|
|
265
|
+
uint8_t* ptr = Support::alignUp(_ptr, alignment);
|
|
266
|
+
|
|
267
|
+
if (ptr >= _end || size > (size_t)(_end - ptr))
|
|
268
|
+
return _alloc(size, alignment);
|
|
269
|
+
|
|
270
|
+
_ptr = ptr + size;
|
|
271
|
+
return static_cast<void*>(ptr);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
//! Allocates the requested memory specified by `size` without doing any checks.
|
|
275
|
+
//!
|
|
276
|
+
//! Can only be called if `remainingSize()` returns size at least equal to `size`.
|
|
277
|
+
inline void* allocNoCheck(size_t size) noexcept {
|
|
278
|
+
ASMJIT_ASSERT(remainingSize() >= size);
|
|
279
|
+
|
|
280
|
+
uint8_t* ptr = _ptr;
|
|
281
|
+
_ptr += size;
|
|
282
|
+
return static_cast<void*>(ptr);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
//! Allocates the requested memory specified by `size` and `alignment` without doing any checks.
|
|
286
|
+
//!
|
|
287
|
+
//! Performs the same operation as `Zone::allocNoCheck(size)` with `alignment` applied.
|
|
288
|
+
inline void* allocNoCheck(size_t size, size_t alignment) noexcept {
|
|
289
|
+
ASMJIT_ASSERT(Support::isPowerOf2(alignment));
|
|
290
|
+
|
|
291
|
+
uint8_t* ptr = Support::alignUp(_ptr, alignment);
|
|
292
|
+
ASMJIT_ASSERT(size <= (size_t)(_end - ptr));
|
|
293
|
+
|
|
294
|
+
_ptr = ptr + size;
|
|
295
|
+
return static_cast<void*>(ptr);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
//! Allocates `size` bytes of zeroed memory. See `alloc()` for more details.
|
|
299
|
+
ASMJIT_API void* allocZeroed(size_t size, size_t alignment = 1) noexcept;
|
|
300
|
+
|
|
301
|
+
//! Like `alloc()`, but the return pointer is casted to `T*`.
|
|
302
|
+
template<typename T>
|
|
303
|
+
inline T* allocT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept {
|
|
304
|
+
return static_cast<T*>(alloc(size, alignment));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
//! Like `allocNoCheck()`, but the return pointer is casted to `T*`.
|
|
308
|
+
template<typename T>
|
|
309
|
+
inline T* allocNoCheckT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept {
|
|
310
|
+
return static_cast<T*>(allocNoCheck(size, alignment));
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
//! Like `allocZeroed()`, but the return pointer is casted to `T*`.
|
|
314
|
+
template<typename T>
|
|
315
|
+
inline T* allocZeroedT(size_t size = sizeof(T), size_t alignment = alignof(T)) noexcept {
|
|
316
|
+
return static_cast<T*>(allocZeroed(size, alignment));
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
//! Like `new(std::nothrow) T(...)`, but allocated by `Zone`.
|
|
320
|
+
template<typename T>
|
|
321
|
+
inline T* newT() noexcept {
|
|
322
|
+
void* p = alloc(sizeof(T), alignof(T));
|
|
323
|
+
if (ASMJIT_UNLIKELY(!p))
|
|
324
|
+
return nullptr;
|
|
325
|
+
return new(p) T();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
//! Like `new(std::nothrow) T(...)`, but allocated by `Zone`.
|
|
329
|
+
template<typename T, typename... Args>
|
|
330
|
+
inline T* newT(Args&&... args) noexcept {
|
|
331
|
+
void* p = alloc(sizeof(T), alignof(T));
|
|
332
|
+
if (ASMJIT_UNLIKELY(!p))
|
|
333
|
+
return nullptr;
|
|
334
|
+
return new(p) T(std::forward<Args>(args)...);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
//! \cond INTERNAL
|
|
338
|
+
//!
|
|
339
|
+
//! Internal alloc function used by other inlines.
|
|
340
|
+
ASMJIT_API void* _alloc(size_t size, size_t alignment) noexcept;
|
|
341
|
+
//! \endcond
|
|
342
|
+
|
|
343
|
+
//! Helper to duplicate data.
|
|
344
|
+
ASMJIT_API void* dup(const void* data, size_t size, bool nullTerminate = false) noexcept;
|
|
345
|
+
|
|
346
|
+
//! Helper to duplicate data.
|
|
347
|
+
inline void* dupAligned(const void* data, size_t size, size_t alignment, bool nullTerminate = false) noexcept {
|
|
348
|
+
align(alignment);
|
|
349
|
+
return dup(data, size, nullTerminate);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
//! Helper to duplicate a formatted string, maximum size is 256 bytes.
|
|
353
|
+
ASMJIT_API char* sformat(const char* str, ...) noexcept;
|
|
354
|
+
|
|
355
|
+
//! \}
|
|
356
|
+
};
|
|
357
|
+
|
|
358
|
+
//! \ref Zone with `N` bytes of a static storage, used for the initial block.
|
|
359
|
+
//!
|
|
360
|
+
//! Temporary zones are used in cases where it's known that some memory will be required, but in many cases it won't
|
|
361
|
+
//! exceed N bytes, so the whole operation can be performed without a dynamic memory allocation.
|
|
362
|
+
template<size_t N>
|
|
363
|
+
class ZoneTmp : public Zone {
|
|
364
|
+
public:
|
|
365
|
+
ASMJIT_NONCOPYABLE(ZoneTmp)
|
|
366
|
+
|
|
367
|
+
//! Temporary storage, embedded after \ref Zone.
|
|
368
|
+
struct Storage {
|
|
369
|
+
char data[N];
|
|
370
|
+
} _storage;
|
|
371
|
+
|
|
372
|
+
//! Creates a temporary zone. Dynamic block size is specified by `blockSize`.
|
|
373
|
+
inline explicit ZoneTmp(size_t blockSize, size_t blockAlignment = 1) noexcept
|
|
374
|
+
: Zone(blockSize, blockAlignment, Support::Temporary(_storage.data, N)) {}
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
//! Zone-based memory allocator that uses an existing `Zone` and provides a `release()` functionality on top of it.
|
|
378
|
+
//! It uses `Zone` only for chunks that can be pooled, and uses libc `malloc()` for chunks that are large.
|
|
379
|
+
//!
|
|
380
|
+
//! The advantage of ZoneAllocator is that it can allocate small chunks of memory really fast, and these chunks,
|
|
381
|
+
//! when released, will be reused by consecutive calls to `alloc()`. Also, since ZoneAllocator uses `Zone`, you can
|
|
382
|
+
//! turn any `Zone` into a `ZoneAllocator`, and use it in your `Pass` when necessary.
|
|
383
|
+
//!
|
|
384
|
+
//! ZoneAllocator is used by AsmJit containers to make containers having only few elements fast (and lightweight)
|
|
385
|
+
//! and to allow them to grow and use dynamic blocks when require more storage.
|
|
386
|
+
class ZoneAllocator {
|
|
387
|
+
public:
|
|
388
|
+
ASMJIT_NONCOPYABLE(ZoneAllocator)
|
|
389
|
+
|
|
390
|
+
//! \cond INTERNAL
|
|
391
|
+
|
|
392
|
+
// In short, we pool chunks of these sizes:
|
|
393
|
+
// [32, 64, 96, 128, 192, 256, 320, 384, 448, 512]
|
|
394
|
+
|
|
395
|
+
enum : uint32_t {
|
|
396
|
+
//! How many bytes per a low granularity pool (has to be at least 16).
|
|
397
|
+
kLoGranularity = 32,
|
|
398
|
+
//! Number of slots of a low granularity pool.
|
|
399
|
+
kLoCount = 4,
|
|
400
|
+
//! Maximum size of a block that can be allocated in a low granularity pool.
|
|
401
|
+
kLoMaxSize = kLoGranularity * kLoCount,
|
|
402
|
+
|
|
403
|
+
//! How many bytes per a high granularity pool.
|
|
404
|
+
kHiGranularity = 64,
|
|
405
|
+
//! Number of slots of a high granularity pool.
|
|
406
|
+
kHiCount = 6,
|
|
407
|
+
//! Maximum size of a block that can be allocated in a high granularity pool.
|
|
408
|
+
kHiMaxSize = kLoMaxSize + kHiGranularity * kHiCount,
|
|
409
|
+
|
|
410
|
+
//! Alignment of every pointer returned by `alloc()`.
|
|
411
|
+
kBlockAlignment = kLoGranularity
|
|
412
|
+
};
|
|
413
|
+
|
|
414
|
+
//! Single-linked list used to store unused chunks.
|
|
415
|
+
struct Slot {
|
|
416
|
+
//! Link to a next slot in a single-linked list.
|
|
417
|
+
Slot* next;
|
|
418
|
+
};
|
|
419
|
+
|
|
420
|
+
//! A block of memory that has been allocated dynamically and is not part of block-list used by the allocator.
|
|
421
|
+
//! This is used to keep track of all these blocks so they can be freed by `reset()` if not freed explicitly.
|
|
422
|
+
struct DynamicBlock {
|
|
423
|
+
DynamicBlock* prev;
|
|
424
|
+
DynamicBlock* next;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
//! \endcond
|
|
428
|
+
|
|
429
|
+
//! \name Members
|
|
430
|
+
//! \{
|
|
431
|
+
|
|
432
|
+
//! Zone used to allocate memory that fits into slots.
|
|
433
|
+
Zone* _zone;
|
|
434
|
+
//! Indexed slots containing released memory.
|
|
435
|
+
Slot* _slots[kLoCount + kHiCount];
|
|
436
|
+
//! Dynamic blocks for larger allocations (no slots).
|
|
437
|
+
DynamicBlock* _dynamicBlocks;
|
|
438
|
+
|
|
439
|
+
//! \}
|
|
440
|
+
|
|
441
|
+
//! \name Construction & Destruction
|
|
442
|
+
//! \{
|
|
443
|
+
|
|
444
|
+
//! Creates a new `ZoneAllocator`.
|
|
445
|
+
//!
|
|
446
|
+
//! \note To use it, you must first `init()` it.
|
|
447
|
+
inline ZoneAllocator() noexcept {
|
|
448
|
+
memset(this, 0, sizeof(*this));
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
//! Creates a new `ZoneAllocator` initialized to use `zone`.
|
|
452
|
+
inline explicit ZoneAllocator(Zone* zone) noexcept {
|
|
453
|
+
memset(this, 0, sizeof(*this));
|
|
454
|
+
_zone = zone;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
//! Destroys the `ZoneAllocator`.
|
|
458
|
+
inline ~ZoneAllocator() noexcept { reset(); }
|
|
459
|
+
|
|
460
|
+
//! Tests whether the `ZoneAllocator` is initialized (i.e. has `Zone`).
|
|
461
|
+
inline bool isInitialized() const noexcept { return _zone != nullptr; }
|
|
462
|
+
|
|
463
|
+
//! Convenience function to initialize the `ZoneAllocator` with `zone`.
|
|
464
|
+
//!
|
|
465
|
+
//! It's the same as calling `reset(zone)`.
|
|
466
|
+
inline void init(Zone* zone) noexcept { reset(zone); }
|
|
467
|
+
|
|
468
|
+
//! Resets this `ZoneAllocator` and also forget about the current `Zone` which is attached (if any). Reset
|
|
469
|
+
//! optionally attaches a new `zone` passed, or keeps the `ZoneAllocator` in an uninitialized state, if
|
|
470
|
+
//! `zone` is null.
|
|
471
|
+
ASMJIT_API void reset(Zone* zone = nullptr) noexcept;
|
|
472
|
+
|
|
473
|
+
//! \}
|
|
474
|
+
|
|
475
|
+
//! \name Accessors
|
|
476
|
+
//! \{
|
|
477
|
+
|
|
478
|
+
//! Returns the assigned `Zone` of this allocator or null if this `ZoneAllocator` is not initialized.
|
|
479
|
+
inline Zone* zone() const noexcept { return _zone; }
|
|
480
|
+
|
|
481
|
+
//! \}
|
|
482
|
+
|
|
483
|
+
//! \cond
|
|
484
|
+
//! \name Internals
|
|
485
|
+
//! \{
|
|
486
|
+
|
|
487
|
+
//! Returns the slot index to be used for `size`. Returns `true` if a valid slot has been written to `slot` and
|
|
488
|
+
//! `allocatedSize` has been filled with slot exact size (`allocatedSize` can be equal or slightly greater than
|
|
489
|
+
//! `size`).
|
|
490
|
+
static inline bool _getSlotIndex(size_t size, uint32_t& slot) noexcept {
|
|
491
|
+
ASMJIT_ASSERT(size > 0);
|
|
492
|
+
if (size > kHiMaxSize)
|
|
493
|
+
return false;
|
|
494
|
+
|
|
495
|
+
if (size <= kLoMaxSize)
|
|
496
|
+
slot = uint32_t((size - 1) / kLoGranularity);
|
|
497
|
+
else
|
|
498
|
+
slot = uint32_t((size - kLoMaxSize - 1) / kHiGranularity) + kLoCount;
|
|
499
|
+
|
|
500
|
+
return true;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
//! \overload
|
|
504
|
+
static inline bool _getSlotIndex(size_t size, uint32_t& slot, size_t& allocatedSize) noexcept {
|
|
505
|
+
ASMJIT_ASSERT(size > 0);
|
|
506
|
+
if (size > kHiMaxSize)
|
|
507
|
+
return false;
|
|
508
|
+
|
|
509
|
+
if (size <= kLoMaxSize) {
|
|
510
|
+
slot = uint32_t((size - 1) / kLoGranularity);
|
|
511
|
+
allocatedSize = Support::alignUp(size, kLoGranularity);
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
slot = uint32_t((size - kLoMaxSize - 1) / kHiGranularity) + kLoCount;
|
|
515
|
+
allocatedSize = Support::alignUp(size, kHiGranularity);
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return true;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
//! \}
|
|
522
|
+
//! \endcond
|
|
523
|
+
|
|
524
|
+
//! \name Allocation
|
|
525
|
+
//! \{
|
|
526
|
+
|
|
527
|
+
//! \cond INTERNAL
|
|
528
|
+
ASMJIT_API void* _alloc(size_t size, size_t& allocatedSize) noexcept;
|
|
529
|
+
ASMJIT_API void* _allocZeroed(size_t size, size_t& allocatedSize) noexcept;
|
|
530
|
+
ASMJIT_API void _releaseDynamic(void* p, size_t size) noexcept;
|
|
531
|
+
//! \endcond
|
|
532
|
+
|
|
533
|
+
//! Allocates `size` bytes of memory, ideally from an available pool.
|
|
534
|
+
//!
|
|
535
|
+
//! \note `size` can't be zero, it will assert in debug mode in such case.
|
|
536
|
+
inline void* alloc(size_t size) noexcept {
|
|
537
|
+
ASMJIT_ASSERT(isInitialized());
|
|
538
|
+
size_t allocatedSize;
|
|
539
|
+
return _alloc(size, allocatedSize);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
//! Like `alloc(size)`, but provides a second argument `allocatedSize` that provides a way to know how big
|
|
543
|
+
//! the block returned actually is. This is useful for containers to prevent growing too early.
|
|
544
|
+
inline void* alloc(size_t size, size_t& allocatedSize) noexcept {
|
|
545
|
+
ASMJIT_ASSERT(isInitialized());
|
|
546
|
+
return _alloc(size, allocatedSize);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
//! Like `alloc()`, but the return pointer is casted to `T*`.
|
|
550
|
+
template<typename T>
|
|
551
|
+
inline T* allocT(size_t size = sizeof(T)) noexcept {
|
|
552
|
+
return static_cast<T*>(alloc(size));
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
//! Like `alloc(size)`, but returns zeroed memory.
|
|
556
|
+
inline void* allocZeroed(size_t size) noexcept {
|
|
557
|
+
ASMJIT_ASSERT(isInitialized());
|
|
558
|
+
size_t allocatedSize;
|
|
559
|
+
return _allocZeroed(size, allocatedSize);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
//! Like `alloc(size, allocatedSize)`, but returns zeroed memory.
|
|
563
|
+
inline void* allocZeroed(size_t size, size_t& allocatedSize) noexcept {
|
|
564
|
+
ASMJIT_ASSERT(isInitialized());
|
|
565
|
+
return _allocZeroed(size, allocatedSize);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
//! Like `allocZeroed()`, but the return pointer is casted to `T*`.
|
|
569
|
+
template<typename T>
|
|
570
|
+
inline T* allocZeroedT(size_t size = sizeof(T)) noexcept {
|
|
571
|
+
return static_cast<T*>(allocZeroed(size));
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
//! Like `new(std::nothrow) T(...)`, but allocated by `Zone`.
|
|
575
|
+
template<typename T>
|
|
576
|
+
inline T* newT() noexcept {
|
|
577
|
+
void* p = allocT<T>();
|
|
578
|
+
if (ASMJIT_UNLIKELY(!p))
|
|
579
|
+
return nullptr;
|
|
580
|
+
return new(p) T();
|
|
581
|
+
}
|
|
582
|
+
//! Like `new(std::nothrow) T(...)`, but allocated by `Zone`.
|
|
583
|
+
template<typename T, typename... Args>
|
|
584
|
+
inline T* newT(Args&&... args) noexcept {
|
|
585
|
+
void* p = allocT<T>();
|
|
586
|
+
if (ASMJIT_UNLIKELY(!p))
|
|
587
|
+
return nullptr;
|
|
588
|
+
return new(p) T(std::forward<Args>(args)...);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
//! Releases the memory previously allocated by `alloc()`. The `size` argument has to be the same as used to call
|
|
592
|
+
//! `alloc()` or `allocatedSize` returned by `alloc()`.
|
|
593
|
+
inline void release(void* p, size_t size) noexcept {
|
|
594
|
+
ASMJIT_ASSERT(isInitialized());
|
|
595
|
+
ASMJIT_ASSERT(p != nullptr);
|
|
596
|
+
ASMJIT_ASSERT(size != 0);
|
|
597
|
+
|
|
598
|
+
uint32_t slot;
|
|
599
|
+
if (_getSlotIndex(size, slot)) {
|
|
600
|
+
static_cast<Slot*>(p)->next = static_cast<Slot*>(_slots[slot]);
|
|
601
|
+
_slots[slot] = static_cast<Slot*>(p);
|
|
602
|
+
}
|
|
603
|
+
else {
|
|
604
|
+
_releaseDynamic(p, size);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
//! \}
|
|
609
|
+
};
|
|
610
|
+
|
|
611
|
+
//! \}
|
|
612
|
+
|
|
613
|
+
ASMJIT_END_NAMESPACE
|
|
614
|
+
|
|
615
|
+
#endif // ASMJIT_CORE_ZONE_H_INCLUDED
|