asmjit 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/asmjit.gemspec +1 -1
  4. data/ext/asmjit/asmjit/.editorconfig +10 -0
  5. data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
  6. data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
  7. data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
  8. data/ext/asmjit/asmjit/.gitignore +6 -0
  9. data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
  10. data/ext/asmjit/asmjit/LICENSE.md +17 -0
  11. data/ext/asmjit/asmjit/README.md +69 -0
  12. data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
  13. data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
  14. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
  15. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
  16. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
  17. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
  18. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
  19. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
  20. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
  21. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
  22. data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
  23. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
  24. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
  25. data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
  26. data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
  27. data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
  28. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
  29. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
  30. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
  31. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
  32. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
  33. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
  34. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
  35. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
  36. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
  37. data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
  38. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
  39. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
  40. data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
  41. data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
  42. data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
  43. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
  44. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
  45. data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
  46. data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
  47. data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
  48. data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
  49. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
  50. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
  51. data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
  52. data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
  53. data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
  54. data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
  55. data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
  56. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
  57. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
  58. data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
  59. data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
  60. data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
  61. data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
  62. data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
  63. data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
  64. data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
  65. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
  66. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
  67. data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
  68. data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
  69. data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
  70. data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
  71. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
  72. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
  73. data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
  74. data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
  75. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
  76. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
  77. data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
  78. data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
  79. data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
  80. data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
  81. data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
  82. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
  83. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
  84. data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
  85. data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
  86. data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
  87. data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
  88. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
  89. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
  90. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
  91. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
  92. data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
  93. data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
  94. data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
  95. data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
  96. data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
  97. data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
  98. data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
  99. data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
  100. data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
  101. data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
  102. data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
  103. data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
  104. data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
  105. data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
  106. data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
  107. data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
  108. data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
  109. data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
  110. data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
  111. data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
  112. data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
  113. data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
  114. data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
  115. data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
  116. data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
  117. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
  118. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
  119. data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
  120. data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
  121. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
  122. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
  123. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
  124. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
  125. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
  126. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
  127. data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
  128. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
  129. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
  130. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
  131. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
  132. data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
  133. data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
  134. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
  135. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
  136. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
  137. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
  138. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
  139. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
  140. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
  141. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
  142. data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
  143. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
  144. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
  145. data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
  146. data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
  147. data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
  148. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
  149. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
  150. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
  151. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
  152. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
  153. data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
  154. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
  155. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
  156. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
  157. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
  158. data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
  159. data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
  160. data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
  161. data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
  162. data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
  163. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
  164. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
  165. data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
  166. data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
  167. data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
  168. data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
  169. data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
  170. data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
  171. data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
  172. data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
  173. data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
  174. data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
  175. data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
  176. data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
  177. data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
  178. data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
  179. data/ext/asmjit/asmjit/test/broken.cpp +312 -0
  180. data/ext/asmjit/asmjit/test/broken.h +148 -0
  181. data/ext/asmjit/asmjit/test/cmdline.h +61 -0
  182. data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
  183. data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
  184. data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
  185. data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
  186. data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
  187. data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
  188. data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
  189. data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
  190. data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
  191. data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
  192. data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
  193. data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
  194. data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
  195. data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
  196. data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
  197. data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
  198. data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
  199. data/ext/asmjit/asmjit.cc +18 -0
  200. data/lib/asmjit/version.rb +1 -1
  201. 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