@shd101wyy/yo 0.0.2

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.
Files changed (339) hide show
  1. package/LICENSE.md +17 -0
  2. package/README.md +80 -0
  3. package/out/cjs/index.cjs +51 -0
  4. package/out/cjs/yo-cli.cjs +2158 -0
  5. package/out/esm/index.mjs +51 -0
  6. package/out/types/src/codegen/async/runtime.d.ts +2 -0
  7. package/out/types/src/codegen/async/state-code-gen.d.ts +10 -0
  8. package/out/types/src/codegen/async/state-machine.d.ts +13 -0
  9. package/out/types/src/codegen/c/collection.d.ts +3 -0
  10. package/out/types/src/codegen/codegen-c.d.ts +12 -0
  11. package/out/types/src/codegen/constants.d.ts +3 -0
  12. package/out/types/src/codegen/expressions/array.d.ts +4 -0
  13. package/out/types/src/codegen/expressions/generation.d.ts +11 -0
  14. package/out/types/src/codegen/expressions/index.d.ts +2 -0
  15. package/out/types/src/codegen/functions/collection.d.ts +5 -0
  16. package/out/types/src/codegen/functions/context.d.ts +57 -0
  17. package/out/types/src/codegen/functions/generation.d.ts +25 -0
  18. package/out/types/src/codegen/functions/index.d.ts +2 -0
  19. package/out/types/src/codegen/index.d.ts +20 -0
  20. package/out/types/src/codegen/parallelism/runtime.d.ts +2 -0
  21. package/out/types/src/codegen/types/collection.d.ts +8 -0
  22. package/out/types/src/codegen/types/generation.d.ts +13 -0
  23. package/out/types/src/codegen/types/index.d.ts +2 -0
  24. package/out/types/src/codegen/utils/fixup.d.ts +2 -0
  25. package/out/types/src/codegen/utils/index.d.ts +77 -0
  26. package/out/types/src/codegen/values/index.d.ts +1 -0
  27. package/out/types/src/emitter.d.ts +11 -0
  28. package/out/types/src/env.d.ts +85 -0
  29. package/out/types/src/error.d.ts +45 -0
  30. package/out/types/src/evaluator/async/await-analysis-types.d.ts +23 -0
  31. package/out/types/src/evaluator/async/await-analysis.d.ts +5 -0
  32. package/out/types/src/evaluator/builtins/alignof.d.ts +8 -0
  33. package/out/types/src/evaluator/builtins/and_or.d.ts +8 -0
  34. package/out/types/src/evaluator/builtins/arc_fns.d.ts +58 -0
  35. package/out/types/src/evaluator/builtins/array_fns.d.ts +0 -0
  36. package/out/types/src/evaluator/builtins/as.d.ts +8 -0
  37. package/out/types/src/evaluator/builtins/async_fns.d.ts +8 -0
  38. package/out/types/src/evaluator/builtins/compt_assert.d.ts +8 -0
  39. package/out/types/src/evaluator/builtins/compt_boolean_fns.d.ts +8 -0
  40. package/out/types/src/evaluator/builtins/compt_expect_error.d.ts +8 -0
  41. package/out/types/src/evaluator/builtins/compt_list_fns.d.ts +33 -0
  42. package/out/types/src/evaluator/builtins/compt_print.d.ts +8 -0
  43. package/out/types/src/evaluator/builtins/compt_string_fns.d.ts +8 -0
  44. package/out/types/src/evaluator/builtins/consume.d.ts +8 -0
  45. package/out/types/src/evaluator/builtins/drop.d.ts +8 -0
  46. package/out/types/src/evaluator/builtins/dup.d.ts +8 -0
  47. package/out/types/src/evaluator/builtins/expr_fns.d.ts +33 -0
  48. package/out/types/src/evaluator/builtins/future_fns.d.ts +8 -0
  49. package/out/types/src/evaluator/builtins/gc.d.ts +8 -0
  50. package/out/types/src/evaluator/builtins/gensym.d.ts +8 -0
  51. package/out/types/src/evaluator/builtins/impl_constraint.d.ts +8 -0
  52. package/out/types/src/evaluator/builtins/macro_expand.d.ts +8 -0
  53. package/out/types/src/evaluator/builtins/numeric_fns.d.ts +8 -0
  54. package/out/types/src/evaluator/builtins/panic.d.ts +8 -0
  55. package/out/types/src/evaluator/builtins/ptr_fns.d.ts +8 -0
  56. package/out/types/src/evaluator/builtins/quote.d.ts +13 -0
  57. package/out/types/src/evaluator/builtins/rc.d.ts +8 -0
  58. package/out/types/src/evaluator/builtins/sizeof.d.ts +8 -0
  59. package/out/types/src/evaluator/builtins/the.d.ts +8 -0
  60. package/out/types/src/evaluator/builtins/type_fns.d.ts +28 -0
  61. package/out/types/src/evaluator/builtins/va_start.d.ts +8 -0
  62. package/out/types/src/evaluator/builtins/var_fns.d.ts +18 -0
  63. package/out/types/src/evaluator/calls/array.d.ts +13 -0
  64. package/out/types/src/evaluator/calls/array_type.d.ts +11 -0
  65. package/out/types/src/evaluator/calls/closure_type.d.ts +11 -0
  66. package/out/types/src/evaluator/calls/compt_function.d.ts +19 -0
  67. package/out/types/src/evaluator/calls/compt_list_type.d.ts +11 -0
  68. package/out/types/src/evaluator/calls/function.d.ts +16 -0
  69. package/out/types/src/evaluator/calls/function_type.d.ts +15 -0
  70. package/out/types/src/evaluator/calls/helper.d.ts +42 -0
  71. package/out/types/src/evaluator/calls/iso.d.ts +15 -0
  72. package/out/types/src/evaluator/calls/module_type.d.ts +11 -0
  73. package/out/types/src/evaluator/calls/numeric_type.d.ts +15 -0
  74. package/out/types/src/evaluator/calls/pointer.d.ts +8 -0
  75. package/out/types/src/evaluator/calls/pointer_type.d.ts +14 -0
  76. package/out/types/src/evaluator/calls/type.d.ts +12 -0
  77. package/out/types/src/evaluator/context.d.ts +169 -0
  78. package/out/types/src/evaluator/exprs/_expr.d.ts +8 -0
  79. package/out/types/src/evaluator/exprs/assignment.d.ts +9 -0
  80. package/out/types/src/evaluator/exprs/begin.d.ts +10 -0
  81. package/out/types/src/evaluator/exprs/binding.d.ts +12 -0
  82. package/out/types/src/evaluator/exprs/c_include.d.ts +8 -0
  83. package/out/types/src/evaluator/exprs/cond.d.ts +8 -0
  84. package/out/types/src/evaluator/exprs/destructuring_assignment.d.ts +33 -0
  85. package/out/types/src/evaluator/exprs/exists.d.ts +0 -0
  86. package/out/types/src/evaluator/exprs/expr.d.ts +9 -0
  87. package/out/types/src/evaluator/exprs/extern.d.ts +8 -0
  88. package/out/types/src/evaluator/exprs/identifer_and_operator.d.ts +9 -0
  89. package/out/types/src/evaluator/exprs/import.d.ts +9 -0
  90. package/out/types/src/evaluator/exprs/initialization_assignment.d.ts +8 -0
  91. package/out/types/src/evaluator/exprs/match.d.ts +8 -0
  92. package/out/types/src/evaluator/exprs/open.d.ts +8 -0
  93. package/out/types/src/evaluator/exprs/property_access.d.ts +8 -0
  94. package/out/types/src/evaluator/exprs/recur.d.ts +8 -0
  95. package/out/types/src/evaluator/exprs/subtype_of.d.ts +21 -0
  96. package/out/types/src/evaluator/exprs/test.d.ts +8 -0
  97. package/out/types/src/evaluator/exprs/typeof.d.ts +8 -0
  98. package/out/types/src/evaluator/exprs/while.d.ts +8 -0
  99. package/out/types/src/evaluator/index.d.ts +26 -0
  100. package/out/types/src/evaluator/types/array.d.ts +8 -0
  101. package/out/types/src/evaluator/types/closure.d.ts +8 -0
  102. package/out/types/src/evaluator/types/compt_list.d.ts +8 -0
  103. package/out/types/src/evaluator/types/concrete_module.d.ts +8 -0
  104. package/out/types/src/evaluator/types/dyn.d.ts +8 -0
  105. package/out/types/src/evaluator/types/enum.d.ts +8 -0
  106. package/out/types/src/evaluator/types/expr_synthesizer.d.ts +14 -0
  107. package/out/types/src/evaluator/types/field.d.ts +14 -0
  108. package/out/types/src/evaluator/types/fn_module.d.ts +8 -0
  109. package/out/types/src/evaluator/types/function.d.ts +58 -0
  110. package/out/types/src/evaluator/types/future_module.d.ts +8 -0
  111. package/out/types/src/evaluator/types/module.d.ts +19 -0
  112. package/out/types/src/evaluator/types/newtype.d.ts +8 -0
  113. package/out/types/src/evaluator/types/object.d.ts +8 -0
  114. package/out/types/src/evaluator/types/proofs.d.ts +0 -0
  115. package/out/types/src/evaluator/types/slice.d.ts +8 -0
  116. package/out/types/src/evaluator/types/struct.d.ts +8 -0
  117. package/out/types/src/evaluator/types/synthesizer.d.ts +16 -0
  118. package/out/types/src/evaluator/types/tuple.d.ts +18 -0
  119. package/out/types/src/evaluator/types/union.d.ts +8 -0
  120. package/out/types/src/evaluator/types/utils.d.ts +71 -0
  121. package/out/types/src/evaluator/types/validation.d.ts +3 -0
  122. package/out/types/src/evaluator/utils/array-utils.d.ts +15 -0
  123. package/out/types/src/evaluator/utils/closure.d.ts +35 -0
  124. package/out/types/src/evaluator/utils.d.ts +4 -0
  125. package/out/types/src/evaluator/values/anonymous_function.d.ts +8 -0
  126. package/out/types/src/evaluator/values/anonymous_module.d.ts +17 -0
  127. package/out/types/src/evaluator/values/anonymous_struct.d.ts +8 -0
  128. package/out/types/src/evaluator/values/array.d.ts +8 -0
  129. package/out/types/src/evaluator/values/boolean.d.ts +3 -0
  130. package/out/types/src/evaluator/values/char.d.ts +3 -0
  131. package/out/types/src/evaluator/values/compt_list.d.ts +8 -0
  132. package/out/types/src/evaluator/values/dyn.d.ts +8 -0
  133. package/out/types/src/evaluator/values/float.d.ts +4 -0
  134. package/out/types/src/evaluator/values/integer.d.ts +4 -0
  135. package/out/types/src/evaluator/values/module.d.ts +58 -0
  136. package/out/types/src/evaluator/values/string.d.ts +3 -0
  137. package/out/types/src/evaluator/values/tuple.d.ts +32 -0
  138. package/out/types/src/expr.d.ts +456 -0
  139. package/out/types/src/function-value.d.ts +42 -0
  140. package/out/types/src/index.d.ts +4 -0
  141. package/out/types/src/lexer.d.ts +2 -0
  142. package/out/types/src/logger.d.ts +1 -0
  143. package/out/types/src/module-manager.d.ts +30 -0
  144. package/out/types/src/naming-checker.d.ts +4 -0
  145. package/out/types/src/parser.d.ts +33 -0
  146. package/out/types/src/test-runner.d.ts +30 -0
  147. package/out/types/src/tests/codegen.test.d.ts +1 -0
  148. package/out/types/src/tests/fixme.test.d.ts +1 -0
  149. package/out/types/src/tests/module-manager.test.d.ts +1 -0
  150. package/out/types/src/tests/parser.test.d.ts +1 -0
  151. package/out/types/src/tests/sample.test.d.ts +0 -0
  152. package/out/types/src/tests/std.test.d.ts +1 -0
  153. package/out/types/src/token.d.ts +40 -0
  154. package/out/types/src/type-value.d.ts +7 -0
  155. package/out/types/src/types/compatibility.d.ts +16 -0
  156. package/out/types/src/types/creators.d.ts +73 -0
  157. package/out/types/src/types/definitions.d.ts +218 -0
  158. package/out/types/src/types/guards.d.ts +70 -0
  159. package/out/types/src/types/hierarchy.d.ts +4 -0
  160. package/out/types/src/types/index.d.ts +7 -0
  161. package/out/types/src/types/module_field.d.ts +2 -0
  162. package/out/types/src/types/tags.d.ts +45 -0
  163. package/out/types/src/types/utils.d.ts +50 -0
  164. package/out/types/src/unit-value.d.ts +7 -0
  165. package/out/types/src/utils.d.ts +6 -0
  166. package/out/types/src/value-tag.d.ts +29 -0
  167. package/out/types/src/value.d.ts +110 -0
  168. package/out/types/src/yo-cli.d.ts +1 -0
  169. package/out/types/tsconfig.tsbuildinfo +1 -0
  170. package/package.json +57 -0
  171. package/scripts/check-liburing.js +76 -0
  172. package/std/alg/hash.yo +50 -0
  173. package/std/allocator.yo +113 -0
  174. package/std/allocators/c_allocator.yo +118 -0
  175. package/std/async.yo +13 -0
  176. package/std/collections/array_list.yo +415 -0
  177. package/std/collections/hash_map.yo +482 -0
  178. package/std/collections/hash_set.yo +706 -0
  179. package/std/collections/index.yo +11 -0
  180. package/std/collections/linked_list.yo +439 -0
  181. package/std/error.yo +0 -0
  182. package/std/gc.yo +10 -0
  183. package/std/index.yo +12 -0
  184. package/std/io/file.yo +191 -0
  185. package/std/io/index.yo +5 -0
  186. package/std/libc/assert.yo +39 -0
  187. package/std/libc/ctype.yo +57 -0
  188. package/std/libc/errno.yo +182 -0
  189. package/std/libc/float.yo +87 -0
  190. package/std/libc/index.yo +29 -0
  191. package/std/libc/limits.yo +65 -0
  192. package/std/libc/math.yo +679 -0
  193. package/std/libc/signal.yo +101 -0
  194. package/std/libc/stdatomic.yo +213 -0
  195. package/std/libc/stdint.yo +214 -0
  196. package/std/libc/stdio.yo +225 -0
  197. package/std/libc/stdlib.yo +204 -0
  198. package/std/libc/string.yo +151 -0
  199. package/std/libc/time.yo +92 -0
  200. package/std/libc/unistd.yo +130 -0
  201. package/std/monad.yo +152 -0
  202. package/std/prelude.yo +3094 -0
  203. package/std/string/index.yo +8 -0
  204. package/std/string/rune.yo +82 -0
  205. package/std/string/string.yo +288 -0
  206. package/std/sync.yo +95 -0
  207. package/std/thread.yo +36 -0
  208. package/std/time.yo +13 -0
  209. package/std/worker.yo +36 -0
  210. package/vendor/mimalloc/.gitattributes +12 -0
  211. package/vendor/mimalloc/CMakeLists.txt +763 -0
  212. package/vendor/mimalloc/LICENSE +21 -0
  213. package/vendor/mimalloc/SECURITY.md +41 -0
  214. package/vendor/mimalloc/azure-pipelines.yml +251 -0
  215. package/vendor/mimalloc/bin/mimalloc-redirect-arm64.dll +0 -0
  216. package/vendor/mimalloc/bin/mimalloc-redirect-arm64.lib +0 -0
  217. package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.dll +0 -0
  218. package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.lib +0 -0
  219. package/vendor/mimalloc/bin/mimalloc-redirect.dll +0 -0
  220. package/vendor/mimalloc/bin/mimalloc-redirect.lib +0 -0
  221. package/vendor/mimalloc/bin/mimalloc-redirect32.dll +0 -0
  222. package/vendor/mimalloc/bin/mimalloc-redirect32.lib +0 -0
  223. package/vendor/mimalloc/bin/minject-arm64.exe +0 -0
  224. package/vendor/mimalloc/bin/minject.exe +0 -0
  225. package/vendor/mimalloc/bin/minject32.exe +0 -0
  226. package/vendor/mimalloc/bin/readme.md +118 -0
  227. package/vendor/mimalloc/cmake/JoinPaths.cmake +23 -0
  228. package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +19 -0
  229. package/vendor/mimalloc/cmake/mimalloc-config.cmake +14 -0
  230. package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +23 -0
  231. package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +28 -0
  232. package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +28 -0
  233. package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +23 -0
  234. package/vendor/mimalloc/contrib/docker/readme.md +10 -0
  235. package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +64 -0
  236. package/vendor/mimalloc/contrib/vcpkg/readme.md +40 -0
  237. package/vendor/mimalloc/contrib/vcpkg/usage +20 -0
  238. package/vendor/mimalloc/contrib/vcpkg/vcpkg-cmake-wrapper.cmake +20 -0
  239. package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +48 -0
  240. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg +887 -0
  241. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg +1185 -0
  242. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg +757 -0
  243. package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg +1028 -0
  244. package/vendor/mimalloc/doc/bench-2020/bench-r5a-1.svg +769 -0
  245. package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg +868 -0
  246. package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg +1157 -0
  247. package/vendor/mimalloc/doc/bench-2020/bench-r5a-2.svg +983 -0
  248. package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-1.svg +683 -0
  249. package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-2.svg +854 -0
  250. package/vendor/mimalloc/doc/bench-2020/bench-spec-rss.svg +713 -0
  251. package/vendor/mimalloc/doc/bench-2020/bench-spec.svg +713 -0
  252. package/vendor/mimalloc/doc/bench-2020/bench-z4-1.svg +890 -0
  253. package/vendor/mimalloc/doc/bench-2020/bench-z4-2.svg +1146 -0
  254. package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-1.svg +796 -0
  255. package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-2.svg +974 -0
  256. package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-a.svg +952 -0
  257. package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-b.svg +1255 -0
  258. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg +955 -0
  259. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg +1269 -0
  260. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg +836 -0
  261. package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg +1131 -0
  262. package/vendor/mimalloc/doc/bench-2021/bench-macmini-2021-01-30.svg +766 -0
  263. package/vendor/mimalloc/doc/doxyfile +2895 -0
  264. package/vendor/mimalloc/doc/ds-logo.jpg +0 -0
  265. package/vendor/mimalloc/doc/ds-logo.png +0 -0
  266. package/vendor/mimalloc/doc/mimalloc-doc.h +1452 -0
  267. package/vendor/mimalloc/doc/mimalloc-doxygen.css +60 -0
  268. package/vendor/mimalloc/doc/mimalloc-logo-100.png +0 -0
  269. package/vendor/mimalloc/doc/mimalloc-logo.png +0 -0
  270. package/vendor/mimalloc/doc/mimalloc-logo.svg +161 -0
  271. package/vendor/mimalloc/doc/spades-logo.png +0 -0
  272. package/vendor/mimalloc/doc/unreal-logo.svg +43 -0
  273. package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +500 -0
  274. package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj.filters +108 -0
  275. package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj +508 -0
  276. package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj.filters +111 -0
  277. package/vendor/mimalloc/ide/vs2022/mimalloc-override-test-dep.vcxproj +355 -0
  278. package/vendor/mimalloc/ide/vs2022/mimalloc-override-test.vcxproj +360 -0
  279. package/vendor/mimalloc/ide/vs2022/mimalloc-test-api.vcxproj +295 -0
  280. package/vendor/mimalloc/ide/vs2022/mimalloc-test-stress.vcxproj +292 -0
  281. package/vendor/mimalloc/ide/vs2022/mimalloc-test.vcxproj +289 -0
  282. package/vendor/mimalloc/ide/vs2022/mimalloc.sln +151 -0
  283. package/vendor/mimalloc/include/mimalloc/atomic.h +557 -0
  284. package/vendor/mimalloc/include/mimalloc/internal.h +1153 -0
  285. package/vendor/mimalloc/include/mimalloc/prim.h +421 -0
  286. package/vendor/mimalloc/include/mimalloc/track.h +145 -0
  287. package/vendor/mimalloc/include/mimalloc/types.h +685 -0
  288. package/vendor/mimalloc/include/mimalloc-new-delete.h +66 -0
  289. package/vendor/mimalloc/include/mimalloc-override.h +68 -0
  290. package/vendor/mimalloc/include/mimalloc-stats.h +103 -0
  291. package/vendor/mimalloc/include/mimalloc.h +612 -0
  292. package/vendor/mimalloc/mimalloc.pc.in +11 -0
  293. package/vendor/mimalloc/readme.md +946 -0
  294. package/vendor/mimalloc/src/alloc-aligned.c +360 -0
  295. package/vendor/mimalloc/src/alloc-override.c +316 -0
  296. package/vendor/mimalloc/src/alloc-posix.c +185 -0
  297. package/vendor/mimalloc/src/alloc.c +692 -0
  298. package/vendor/mimalloc/src/arena-abandon.c +346 -0
  299. package/vendor/mimalloc/src/arena.c +1043 -0
  300. package/vendor/mimalloc/src/bitmap.c +441 -0
  301. package/vendor/mimalloc/src/bitmap.h +119 -0
  302. package/vendor/mimalloc/src/free.c +572 -0
  303. package/vendor/mimalloc/src/heap.c +733 -0
  304. package/vendor/mimalloc/src/init.c +714 -0
  305. package/vendor/mimalloc/src/libc.c +334 -0
  306. package/vendor/mimalloc/src/options.c +663 -0
  307. package/vendor/mimalloc/src/os.c +770 -0
  308. package/vendor/mimalloc/src/page-queue.c +390 -0
  309. package/vendor/mimalloc/src/page.c +1049 -0
  310. package/vendor/mimalloc/src/prim/emscripten/prim.c +249 -0
  311. package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +461 -0
  312. package/vendor/mimalloc/src/prim/osx/prim.c +9 -0
  313. package/vendor/mimalloc/src/prim/prim.c +76 -0
  314. package/vendor/mimalloc/src/prim/readme.md +9 -0
  315. package/vendor/mimalloc/src/prim/unix/prim.c +934 -0
  316. package/vendor/mimalloc/src/prim/wasi/prim.c +284 -0
  317. package/vendor/mimalloc/src/prim/windows/etw-mimalloc.wprp +61 -0
  318. package/vendor/mimalloc/src/prim/windows/etw.h +905 -0
  319. package/vendor/mimalloc/src/prim/windows/etw.man +0 -0
  320. package/vendor/mimalloc/src/prim/windows/prim.c +878 -0
  321. package/vendor/mimalloc/src/prim/windows/readme.md +17 -0
  322. package/vendor/mimalloc/src/random.c +258 -0
  323. package/vendor/mimalloc/src/segment-map.c +142 -0
  324. package/vendor/mimalloc/src/segment.c +1702 -0
  325. package/vendor/mimalloc/src/static.c +41 -0
  326. package/vendor/mimalloc/src/stats.c +635 -0
  327. package/vendor/mimalloc/test/CMakeLists.txt +56 -0
  328. package/vendor/mimalloc/test/main-override-dep.cpp +51 -0
  329. package/vendor/mimalloc/test/main-override-dep.h +11 -0
  330. package/vendor/mimalloc/test/main-override-static.c +539 -0
  331. package/vendor/mimalloc/test/main-override.c +36 -0
  332. package/vendor/mimalloc/test/main-override.cpp +497 -0
  333. package/vendor/mimalloc/test/main.c +46 -0
  334. package/vendor/mimalloc/test/readme.md +16 -0
  335. package/vendor/mimalloc/test/test-api-fill.c +343 -0
  336. package/vendor/mimalloc/test/test-api.c +466 -0
  337. package/vendor/mimalloc/test/test-stress.c +428 -0
  338. package/vendor/mimalloc/test/test-wrong.c +92 -0
  339. package/vendor/mimalloc/test/testhelper.h +49 -0
@@ -0,0 +1,770 @@
1
+ /* ----------------------------------------------------------------------------
2
+ Copyright (c) 2018-2025, Microsoft Research, Daan Leijen
3
+ This is free software; you can redistribute it and/or modify it under the
4
+ terms of the MIT license. A copy of the license can be found in the file
5
+ "LICENSE" at the root of this distribution.
6
+ -----------------------------------------------------------------------------*/
7
+ #include "mimalloc.h"
8
+ #include "mimalloc/internal.h"
9
+ #include "mimalloc/atomic.h"
10
+ #include "mimalloc/prim.h"
11
+
12
+ #define mi_os_stat_increase(stat,amount) _mi_stat_increase(&_mi_stats_main.stat, amount)
13
+ #define mi_os_stat_decrease(stat,amount) _mi_stat_decrease(&_mi_stats_main.stat, amount)
14
+ #define mi_os_stat_counter_increase(stat,inc) _mi_stat_counter_increase(&_mi_stats_main.stat, inc)
15
+
16
+ /* -----------------------------------------------------------
17
+ Initialization.
18
+ ----------------------------------------------------------- */
19
+ #ifndef MI_DEFAULT_VIRTUAL_ADDRESS_BITS
20
+ #if MI_INTPTR_SIZE < 8
21
+ #define MI_DEFAULT_VIRTUAL_ADDRESS_BITS 32
22
+ #else
23
+ #define MI_DEFAULT_VIRTUAL_ADDRESS_BITS 48
24
+ #endif
25
+ #endif
26
+
27
+ #ifndef MI_DEFAULT_PHYSICAL_MEMORY_IN_KIB
28
+ #if MI_INTPTR_SIZE < 8
29
+ #define MI_DEFAULT_PHYSICAL_MEMORY_IN_KIB 4*MI_MiB // 4 GiB
30
+ #else
31
+ #define MI_DEFAULT_PHYSICAL_MEMORY_IN_KIB 32*MI_MiB // 32 GiB
32
+ #endif
33
+ #endif
34
+
35
+ static mi_os_mem_config_t mi_os_mem_config = {
36
+ 4096, // page size
37
+ 0, // large page size (usually 2MiB)
38
+ 4096, // allocation granularity
39
+ MI_DEFAULT_PHYSICAL_MEMORY_IN_KIB,
40
+ MI_DEFAULT_VIRTUAL_ADDRESS_BITS,
41
+ true, // has overcommit? (if true we use MAP_NORESERVE on mmap systems)
42
+ false, // can we partially free allocated blocks? (on mmap systems we can free anywhere in a mapped range, but on Windows we must free the entire span)
43
+ true // has virtual reserve? (if true we can reserve virtual address space without using commit or physical memory)
44
+ };
45
+
46
+ bool _mi_os_has_overcommit(void) {
47
+ return mi_os_mem_config.has_overcommit;
48
+ }
49
+
50
+ bool _mi_os_has_virtual_reserve(void) {
51
+ return mi_os_mem_config.has_virtual_reserve;
52
+ }
53
+
54
+
55
+ // OS (small) page size
56
+ size_t _mi_os_page_size(void) {
57
+ return mi_os_mem_config.page_size;
58
+ }
59
+
60
+ // if large OS pages are supported (2 or 4MiB), then return the size, otherwise return the small page size (4KiB)
61
+ size_t _mi_os_large_page_size(void) {
62
+ return (mi_os_mem_config.large_page_size != 0 ? mi_os_mem_config.large_page_size : _mi_os_page_size());
63
+ }
64
+
65
+ bool _mi_os_use_large_page(size_t size, size_t alignment) {
66
+ // if we have access, check the size and alignment requirements
67
+ if (mi_os_mem_config.large_page_size == 0 || !mi_option_is_enabled(mi_option_allow_large_os_pages)) return false;
68
+ return ((size % mi_os_mem_config.large_page_size) == 0 && (alignment % mi_os_mem_config.large_page_size) == 0);
69
+ }
70
+
71
+ // round to a good OS allocation size (bounded by max 12.5% waste)
72
+ size_t _mi_os_good_alloc_size(size_t size) {
73
+ size_t align_size;
74
+ if (size < 512*MI_KiB) align_size = _mi_os_page_size();
75
+ else if (size < 2*MI_MiB) align_size = 64*MI_KiB;
76
+ else if (size < 8*MI_MiB) align_size = 256*MI_KiB;
77
+ else if (size < 32*MI_MiB) align_size = 1*MI_MiB;
78
+ else align_size = 4*MI_MiB;
79
+ if mi_unlikely(size >= (SIZE_MAX - align_size)) return size; // possible overflow?
80
+ return _mi_align_up(size, align_size);
81
+ }
82
+
83
+ void _mi_os_init(void) {
84
+ _mi_prim_mem_init(&mi_os_mem_config);
85
+ }
86
+
87
+
88
+ /* -----------------------------------------------------------
89
+ Util
90
+ -------------------------------------------------------------- */
91
+ bool _mi_os_decommit(void* addr, size_t size);
92
+ bool _mi_os_commit(void* addr, size_t size, bool* is_zero);
93
+
94
+
95
+ /* -----------------------------------------------------------
96
+ aligned hinting
97
+ -------------------------------------------------------------- */
98
+
99
+ // On systems with enough virtual address bits, we can do efficient aligned allocation by using
100
+ // the 2TiB to 30TiB area to allocate those. If we have at least 46 bits of virtual address
101
+ // space (64TiB) we use this technique. (but see issue #939)
102
+ #if (MI_INTPTR_SIZE >= 8) && !defined(MI_NO_ALIGNED_HINT)
103
+ static mi_decl_cache_align _Atomic(uintptr_t)aligned_base;
104
+
105
+ // Return a MI_SEGMENT_SIZE aligned address that is probably available.
106
+ // If this returns NULL, the OS will determine the address but on some OS's that may not be
107
+ // properly aligned which can be more costly as it needs to be adjusted afterwards.
108
+ // For a size > 1GiB this always returns NULL in order to guarantee good ASLR randomization;
109
+ // (otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses
110
+ // in the middle of the 2TiB - 6TiB address range (see issue #372))
111
+
112
+ #define MI_HINT_BASE ((uintptr_t)2 << 40) // 2TiB start
113
+ #define MI_HINT_AREA ((uintptr_t)4 << 40) // upto 6TiB (since before win8 there is "only" 8TiB available to processes)
114
+ #define MI_HINT_MAX ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages)
115
+
116
+ void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size)
117
+ {
118
+ if (try_alignment <= 1 || try_alignment > MI_SEGMENT_SIZE) return NULL;
119
+ if (mi_os_mem_config.virtual_address_bits < 46) return NULL; // < 64TiB virtual address space
120
+ size = _mi_align_up(size, MI_SEGMENT_SIZE);
121
+ if (size > 1*MI_GiB) return NULL; // guarantee the chance of fixed valid address is at most 1/(MI_HINT_AREA / 1<<30) = 1/4096.
122
+ #if (MI_SECURE>0)
123
+ size += MI_SEGMENT_SIZE; // put in `MI_SEGMENT_SIZE` virtual gaps between hinted blocks; this splits VLA's but increases guarded areas.
124
+ #endif
125
+
126
+ uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size);
127
+ if (hint == 0 || hint > MI_HINT_MAX) { // wrap or initialize
128
+ uintptr_t init = MI_HINT_BASE;
129
+ #if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of aligned allocations unless in debug mode
130
+ uintptr_t r = _mi_heap_random_next(mi_prim_get_default_heap());
131
+ init = init + ((MI_SEGMENT_SIZE * ((r>>17) & 0xFFFFF)) % MI_HINT_AREA); // (randomly 20 bits)*4MiB == 0 to 4TiB
132
+ #endif
133
+ uintptr_t expected = hint + size;
134
+ mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init);
135
+ hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > MI_HINT_MAX but that is ok, it is a hint after all
136
+ }
137
+ if (hint%try_alignment != 0) return NULL;
138
+ return (void*)hint;
139
+ }
140
+ #else
141
+ void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
142
+ MI_UNUSED(try_alignment); MI_UNUSED(size);
143
+ return NULL;
144
+ }
145
+ #endif
146
+
147
+ /* -----------------------------------------------------------
148
+ Free memory
149
+ -------------------------------------------------------------- */
150
+
151
+ static void mi_os_free_huge_os_pages(void* p, size_t size);
152
+
153
+ static void mi_os_prim_free(void* addr, size_t size, size_t commit_size) {
154
+ mi_assert_internal((size % _mi_os_page_size()) == 0);
155
+ if (addr == NULL) return; // || _mi_os_is_huge_reserved(addr)
156
+ int err = _mi_prim_free(addr, size); // allow size==0 (issue #1041)
157
+ if (err != 0) {
158
+ _mi_warning_message("unable to free OS memory (error: %d (0x%x), size: 0x%zx bytes, address: %p)\n", err, err, size, addr);
159
+ }
160
+ if (commit_size > 0) {
161
+ mi_os_stat_decrease(committed, commit_size);
162
+ }
163
+ mi_os_stat_decrease(reserved, size);
164
+ }
165
+
166
+ void _mi_os_free_ex(void* addr, size_t size, bool still_committed, mi_memid_t memid) {
167
+ if (mi_memkind_is_os(memid.memkind)) {
168
+ size_t csize = memid.mem.os.size;
169
+ if (csize==0) { csize = _mi_os_good_alloc_size(size); }
170
+ mi_assert_internal(csize >= size);
171
+ size_t commit_size = (still_committed ? csize : 0);
172
+ void* base = addr;
173
+ // different base? (due to alignment)
174
+ if (memid.mem.os.base != base) {
175
+ mi_assert(memid.mem.os.base <= addr);
176
+ base = memid.mem.os.base;
177
+ const size_t diff = (uint8_t*)addr - (uint8_t*)memid.mem.os.base;
178
+ if (memid.mem.os.size==0) {
179
+ csize += diff;
180
+ }
181
+ if (still_committed) {
182
+ commit_size -= diff; // the (addr-base) part was already un-committed
183
+ }
184
+ }
185
+ // free it
186
+ if (memid.memkind == MI_MEM_OS_HUGE) {
187
+ mi_assert(memid.is_pinned);
188
+ mi_os_free_huge_os_pages(base, csize);
189
+ }
190
+ else {
191
+ mi_os_prim_free(base, csize, (still_committed ? commit_size : 0));
192
+ }
193
+ }
194
+ else {
195
+ // nothing to do
196
+ mi_assert(memid.memkind < MI_MEM_OS);
197
+ }
198
+ }
199
+
200
+ void _mi_os_free(void* p, size_t size, mi_memid_t memid) {
201
+ _mi_os_free_ex(p, size, true, memid);
202
+ }
203
+
204
+
205
+ /* -----------------------------------------------------------
206
+ Primitive allocation from the OS.
207
+ -------------------------------------------------------------- */
208
+
209
+ // Note: the `try_alignment` is just a hint and the returned pointer is not guaranteed to be aligned.
210
+ // Also `hint_addr` is a hint and may be ignored.
211
+ static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero) {
212
+ mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
213
+ mi_assert_internal(is_zero != NULL);
214
+ mi_assert_internal(is_large != NULL);
215
+ if (size == 0) return NULL;
216
+ if (!commit) { allow_large = false; }
217
+ if (try_alignment == 0) { try_alignment = 1; } // avoid 0 to ensure there will be no divide by zero when aligning
218
+ *is_zero = false;
219
+ void* p = NULL;
220
+ int err = _mi_prim_alloc(hint_addr, size, try_alignment, commit, allow_large, is_large, is_zero, &p);
221
+ if (err != 0) {
222
+ _mi_warning_message("unable to allocate OS memory (error: %d (0x%x), addr: %p, size: 0x%zx bytes, align: 0x%zx, commit: %d, allow large: %d)\n", err, err, hint_addr, size, try_alignment, commit, allow_large);
223
+ }
224
+
225
+
226
+
227
+ mi_os_stat_counter_increase(mmap_calls, 1);
228
+ if (p != NULL) {
229
+ mi_os_stat_increase(reserved, size);
230
+ if (commit) {
231
+ mi_os_stat_increase(committed, size);
232
+ // seems needed for asan (or `mimalloc-test-api` fails)
233
+ #ifdef MI_TRACK_ASAN
234
+ if (*is_zero) { mi_track_mem_defined(p,size); }
235
+ else { mi_track_mem_undefined(p,size); }
236
+ #endif
237
+ }
238
+ }
239
+ return p;
240
+ }
241
+
242
+ static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero) {
243
+ return mi_os_prim_alloc_at(NULL, size, try_alignment, commit, allow_large, is_large, is_zero);
244
+ }
245
+
246
+
247
+ // Primitive aligned allocation from the OS.
248
+ // This function guarantees the allocated memory is aligned.
249
+ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, bool* is_large, bool* is_zero, void** base) {
250
+ mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0));
251
+ mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
252
+ mi_assert_internal(is_large != NULL);
253
+ mi_assert_internal(is_zero != NULL);
254
+ mi_assert_internal(base != NULL);
255
+ if (!commit) allow_large = false;
256
+ if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL;
257
+ size = _mi_align_up(size, _mi_os_page_size());
258
+
259
+ // try first with a requested alignment hint (this will usually be aligned directly on Win 10+ or BSD)
260
+ void* p = mi_os_prim_alloc(size, alignment, commit, allow_large, is_large, is_zero);
261
+ if (p == NULL) return NULL;
262
+
263
+ // aligned already?
264
+ if (((uintptr_t)p % alignment) == 0) {
265
+ *base = p;
266
+ }
267
+ else {
268
+ // if not aligned, free it, overallocate, and unmap around it
269
+ #if !MI_TRACK_ASAN
270
+ _mi_warning_message("unable to allocate aligned OS memory directly, fall back to over-allocation (size: 0x%zx bytes, address: %p, alignment: 0x%zx, commit: %d)\n", size, p, alignment, commit);
271
+ #endif
272
+ if (p != NULL) { mi_os_prim_free(p, size, (commit ? size : 0)); }
273
+ if (size >= (SIZE_MAX - alignment)) return NULL; // overflow
274
+ const size_t over_size = size + alignment;
275
+
276
+ if (!mi_os_mem_config.has_partial_free) { // win32 virtualAlloc cannot free parts of an allocated block
277
+ // over-allocate uncommitted (virtual) memory
278
+ p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */, is_large, is_zero);
279
+ if (p == NULL) return NULL;
280
+
281
+ // set p to the aligned part in the full region
282
+ // note: this is dangerous on Windows as VirtualFree needs the actual base pointer
283
+ // this is handled though by having the `base` field in the memid's
284
+ *base = p; // remember the base
285
+ p = mi_align_up_ptr(p, alignment);
286
+
287
+ // explicitly commit only the aligned part
288
+ if (commit) {
289
+ if (!_mi_os_commit(p, size, NULL)) {
290
+ mi_os_prim_free(*base, over_size, 0);
291
+ return NULL;
292
+ }
293
+ }
294
+ }
295
+ else { // mmap can free inside an allocation
296
+ // overallocate...
297
+ p = mi_os_prim_alloc(over_size, 1, commit, false, is_large, is_zero);
298
+ if (p == NULL) return NULL;
299
+
300
+ // and selectively unmap parts around the over-allocated area.
301
+ void* aligned_p = mi_align_up_ptr(p, alignment);
302
+ size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p;
303
+ size_t mid_size = _mi_align_up(size, _mi_os_page_size());
304
+ size_t post_size = over_size - pre_size - mid_size;
305
+ mi_assert_internal(pre_size < over_size&& post_size < over_size&& mid_size >= size);
306
+ if (pre_size > 0) { mi_os_prim_free(p, pre_size, (commit ? pre_size : 0)); }
307
+ if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, (commit ? post_size : 0)); }
308
+ // we can return the aligned pointer on `mmap` systems
309
+ p = aligned_p;
310
+ *base = aligned_p; // since we freed the pre part, `*base == p`.
311
+ }
312
+ }
313
+
314
+ mi_assert_internal(p == NULL || (p != NULL && *base != NULL && ((uintptr_t)p % alignment) == 0));
315
+ return p;
316
+ }
317
+
318
+
319
+ /* -----------------------------------------------------------
320
+ OS API: alloc and alloc_aligned
321
+ ----------------------------------------------------------- */
322
+
323
+ void* _mi_os_alloc(size_t size, mi_memid_t* memid) {
324
+ *memid = _mi_memid_none();
325
+ if (size == 0) return NULL;
326
+ size = _mi_os_good_alloc_size(size);
327
+ bool os_is_large = false;
328
+ bool os_is_zero = false;
329
+ void* p = mi_os_prim_alloc(size, 0, true, false, &os_is_large, &os_is_zero);
330
+ if (p == NULL) return NULL;
331
+
332
+ *memid = _mi_memid_create_os(p, size, true, os_is_zero, os_is_large);
333
+ mi_assert_internal(memid->mem.os.size >= size);
334
+ mi_assert_internal(memid->initially_committed);
335
+ return p;
336
+ }
337
+
338
+ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid)
339
+ {
340
+ MI_UNUSED(&_mi_os_get_aligned_hint); // suppress unused warnings
341
+ *memid = _mi_memid_none();
342
+ if (size == 0) return NULL;
343
+ size = _mi_os_good_alloc_size(size);
344
+ alignment = _mi_align_up(alignment, _mi_os_page_size());
345
+
346
+ bool os_is_large = false;
347
+ bool os_is_zero = false;
348
+ void* os_base = NULL;
349
+ void* p = mi_os_prim_alloc_aligned(size, alignment, commit, allow_large, &os_is_large, &os_is_zero, &os_base );
350
+ if (p == NULL) return NULL;
351
+
352
+ *memid = _mi_memid_create_os(p, size, commit, os_is_zero, os_is_large);
353
+ memid->mem.os.base = os_base;
354
+ memid->mem.os.size += ((uint8_t*)p - (uint8_t*)os_base); // todo: return from prim_alloc_aligned?
355
+
356
+ mi_assert_internal(memid->mem.os.size >= size);
357
+ mi_assert_internal(_mi_is_aligned(p,alignment));
358
+ if (commit) { mi_assert_internal(memid->initially_committed); }
359
+ return p;
360
+ }
361
+
362
+
363
+ mi_decl_nodiscard static void* mi_os_ensure_zero(void* p, size_t size, mi_memid_t* memid) {
364
+ if (p==NULL || size==0) return p;
365
+ // ensure committed
366
+ if (!memid->initially_committed) {
367
+ bool is_zero = false;
368
+ if (!_mi_os_commit(p, size, &is_zero)) {
369
+ _mi_os_free(p, size, *memid);
370
+ return NULL;
371
+ }
372
+ memid->initially_committed = true;
373
+ }
374
+ // ensure zero'd
375
+ if (memid->initially_zero) return p;
376
+ _mi_memzero_aligned(p,size);
377
+ memid->initially_zero = true;
378
+ return p;
379
+ }
380
+
381
+ void* _mi_os_zalloc(size_t size, mi_memid_t* memid) {
382
+ void* p = _mi_os_alloc(size,memid);
383
+ return mi_os_ensure_zero(p, size, memid);
384
+ }
385
+
386
+ /* -----------------------------------------------------------
387
+ OS aligned allocation with an offset. This is used
388
+ for large alignments > MI_BLOCK_ALIGNMENT_MAX. We use a large mimalloc
389
+ page where the object can be aligned at an offset from the start of the segment.
390
+ As we may need to overallocate, we need to free such pointers using `mi_free_aligned`
391
+ to use the actual start of the memory region.
392
+ ----------------------------------------------------------- */
393
+
394
+ void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t offset, bool commit, bool allow_large, mi_memid_t* memid) {
395
+ mi_assert(offset <= MI_SEGMENT_SIZE);
396
+ mi_assert(offset <= size);
397
+ mi_assert((alignment % _mi_os_page_size()) == 0);
398
+ *memid = _mi_memid_none();
399
+ if (offset > MI_SEGMENT_SIZE) return NULL;
400
+ if (offset == 0) {
401
+ // regular aligned allocation
402
+ return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid);
403
+ }
404
+ else {
405
+ // overallocate to align at an offset
406
+ const size_t extra = _mi_align_up(offset, alignment) - offset;
407
+ const size_t oversize = size + extra;
408
+ void* const start = _mi_os_alloc_aligned(oversize, alignment, commit, allow_large, memid);
409
+ if (start == NULL) return NULL;
410
+
411
+ void* const p = (uint8_t*)start + extra;
412
+ mi_assert(_mi_is_aligned((uint8_t*)p + offset, alignment));
413
+ // decommit the overallocation at the start
414
+ if (commit && extra > _mi_os_page_size()) {
415
+ _mi_os_decommit(start, extra);
416
+ }
417
+ return p;
418
+ }
419
+ }
420
+
421
+ /* -----------------------------------------------------------
422
+ OS memory API: reset, commit, decommit, protect, unprotect.
423
+ ----------------------------------------------------------- */
424
+
425
+ // OS page align within a given area, either conservative (pages inside the area only),
426
+ // or not (straddling pages outside the area is possible)
427
+ static void* mi_os_page_align_areax(bool conservative, void* addr, size_t size, size_t* newsize) {
428
+ mi_assert(addr != NULL && size > 0);
429
+ if (newsize != NULL) *newsize = 0;
430
+ if (size == 0 || addr == NULL) return NULL;
431
+
432
+ // page align conservatively within the range
433
+ void* start = (conservative ? mi_align_up_ptr(addr, _mi_os_page_size())
434
+ : mi_align_down_ptr(addr, _mi_os_page_size()));
435
+ void* end = (conservative ? mi_align_down_ptr((uint8_t*)addr + size, _mi_os_page_size())
436
+ : mi_align_up_ptr((uint8_t*)addr + size, _mi_os_page_size()));
437
+ ptrdiff_t diff = (uint8_t*)end - (uint8_t*)start;
438
+ if (diff <= 0) return NULL;
439
+
440
+ mi_assert_internal((conservative && (size_t)diff <= size) || (!conservative && (size_t)diff >= size));
441
+ if (newsize != NULL) *newsize = (size_t)diff;
442
+ return start;
443
+ }
444
+
445
+ static void* mi_os_page_align_area_conservative(void* addr, size_t size, size_t* newsize) {
446
+ return mi_os_page_align_areax(true, addr, size, newsize);
447
+ }
448
+
449
+ bool _mi_os_commit_ex(void* addr, size_t size, bool* is_zero, size_t stat_size) {
450
+ if (is_zero != NULL) { *is_zero = false; }
451
+ mi_os_stat_increase(committed, stat_size); // use size for precise commit vs. decommit
452
+ mi_os_stat_counter_increase(commit_calls, 1);
453
+
454
+ // page align range
455
+ size_t csize;
456
+ void* start = mi_os_page_align_areax(false /* conservative? */, addr, size, &csize);
457
+ if (csize == 0) return true;
458
+
459
+ // commit
460
+ bool os_is_zero = false;
461
+ int err = _mi_prim_commit(start, csize, &os_is_zero);
462
+ if (err != 0) {
463
+ _mi_warning_message("cannot commit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
464
+ return false;
465
+ }
466
+ if (os_is_zero && is_zero != NULL) {
467
+ *is_zero = true;
468
+ mi_assert_expensive(mi_mem_is_zero(start, csize));
469
+ }
470
+ // note: the following seems required for asan (otherwise `mimalloc-test-stress` fails)
471
+ #ifdef MI_TRACK_ASAN
472
+ if (os_is_zero) { mi_track_mem_defined(start,csize); }
473
+ else { mi_track_mem_undefined(start,csize); }
474
+ #endif
475
+ return true;
476
+ }
477
+
478
+ bool _mi_os_commit(void* addr, size_t size, bool* is_zero) {
479
+ return _mi_os_commit_ex(addr, size, is_zero, size);
480
+ }
481
+
482
+ static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, size_t stat_size) {
483
+ mi_assert_internal(needs_recommit!=NULL);
484
+ mi_os_stat_decrease(committed, stat_size);
485
+
486
+ // page align
487
+ size_t csize;
488
+ void* start = mi_os_page_align_area_conservative(addr, size, &csize);
489
+ if (csize == 0) return true;
490
+
491
+ // decommit
492
+ *needs_recommit = true;
493
+ int err = _mi_prim_decommit(start,csize,needs_recommit);
494
+ if (err != 0) {
495
+ _mi_warning_message("cannot decommit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
496
+ }
497
+ mi_assert_internal(err == 0);
498
+ return (err == 0);
499
+ }
500
+
501
+ bool _mi_os_decommit(void* addr, size_t size) {
502
+ bool needs_recommit;
503
+ return mi_os_decommit_ex(addr, size, &needs_recommit, size);
504
+ }
505
+
506
+
507
+ // Signal to the OS that the address range is no longer in use
508
+ // but may be used later again. This will release physical memory
509
+ // pages and reduce swapping while keeping the memory committed.
510
+ // We page align to a conservative area inside the range to reset.
511
+ bool _mi_os_reset(void* addr, size_t size) {
512
+ // page align conservatively within the range
513
+ size_t csize;
514
+ void* start = mi_os_page_align_area_conservative(addr, size, &csize);
515
+ if (csize == 0) return true; // || _mi_os_is_huge_reserved(addr)
516
+ mi_os_stat_increase(reset, csize);
517
+ mi_os_stat_counter_increase(reset_calls, 1);
518
+
519
+ #if (MI_DEBUG>1) && !MI_SECURE && !MI_TRACK_ENABLED // && !MI_TSAN
520
+ memset(start, 0, csize); // pretend it is eagerly reset
521
+ #endif
522
+
523
+ int err = _mi_prim_reset(start, csize);
524
+ if (err != 0) {
525
+ _mi_warning_message("cannot reset OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
526
+ }
527
+ return (err == 0);
528
+ }
529
+
530
+
531
+ void _mi_os_reuse( void* addr, size_t size ) {
532
+ // page align conservatively within the range
533
+ size_t csize = 0;
534
+ void* const start = mi_os_page_align_area_conservative(addr, size, &csize);
535
+ if (csize == 0) return;
536
+ const int err = _mi_prim_reuse(start, csize);
537
+ if (err != 0) {
538
+ _mi_warning_message("cannot reuse OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
539
+ }
540
+ }
541
+
542
+ // either resets or decommits memory, returns true if the memory needs
543
+ // to be recommitted if it is to be re-used later on.
544
+ bool _mi_os_purge_ex(void* p, size_t size, bool allow_reset, size_t stat_size)
545
+ {
546
+ if (mi_option_get(mi_option_purge_delay) < 0) return false; // is purging allowed?
547
+ mi_os_stat_counter_increase(purge_calls, 1);
548
+ mi_os_stat_increase(purged, size);
549
+
550
+ if (mi_option_is_enabled(mi_option_purge_decommits) && // should decommit?
551
+ !_mi_preloading()) // don't decommit during preloading (unsafe)
552
+ {
553
+ bool needs_recommit = true;
554
+ mi_os_decommit_ex(p, size, &needs_recommit, stat_size);
555
+ return needs_recommit;
556
+ }
557
+ else {
558
+ if (allow_reset) { // this can sometimes be not allowed if the range is not fully committed
559
+ _mi_os_reset(p, size);
560
+ }
561
+ return false; // needs no recommit
562
+ }
563
+ }
564
+
565
+ // either resets or decommits memory, returns true if the memory needs
566
+ // to be recommitted if it is to be re-used later on.
567
+ bool _mi_os_purge(void* p, size_t size) {
568
+ return _mi_os_purge_ex(p, size, true, size);
569
+ }
570
+
571
+ // Protect a region in memory to be not accessible.
572
+ static bool mi_os_protectx(void* addr, size_t size, bool protect) {
573
+ // page align conservatively within the range
574
+ size_t csize = 0;
575
+ void* start = mi_os_page_align_area_conservative(addr, size, &csize);
576
+ if (csize == 0) return false;
577
+ /*
578
+ if (_mi_os_is_huge_reserved(addr)) {
579
+ _mi_warning_message("cannot mprotect memory allocated in huge OS pages\n");
580
+ }
581
+ */
582
+ int err = _mi_prim_protect(start,csize,protect);
583
+ if (err != 0) {
584
+ _mi_warning_message("cannot %s OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", (protect ? "protect" : "unprotect"), err, err, start, csize);
585
+ }
586
+ return (err == 0);
587
+ }
588
+
589
+ bool _mi_os_protect(void* addr, size_t size) {
590
+ return mi_os_protectx(addr, size, true);
591
+ }
592
+
593
+ bool _mi_os_unprotect(void* addr, size_t size) {
594
+ return mi_os_protectx(addr, size, false);
595
+ }
596
+
597
+
598
+
599
+ /* ----------------------------------------------------------------------------
600
+ Support for allocating huge OS pages (1Gib) that are reserved up-front
601
+ and possibly associated with a specific NUMA node. (use `numa_node>=0`)
602
+ -----------------------------------------------------------------------------*/
603
+ #define MI_HUGE_OS_PAGE_SIZE (MI_GiB)
604
+
605
+
606
+ #if (MI_INTPTR_SIZE >= 8)
607
+ // To ensure proper alignment, use our own area for huge OS pages
608
+ static mi_decl_cache_align _Atomic(uintptr_t) mi_huge_start; // = 0
609
+
610
+ // Claim an aligned address range for huge pages
611
+ static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
612
+ if (total_size != NULL) *total_size = 0;
613
+ const size_t size = pages * MI_HUGE_OS_PAGE_SIZE;
614
+
615
+ uintptr_t start = 0;
616
+ uintptr_t end = 0;
617
+ uintptr_t huge_start = mi_atomic_load_relaxed(&mi_huge_start);
618
+ do {
619
+ start = huge_start;
620
+ if (start == 0) {
621
+ // Initialize the start address after the 32TiB area
622
+ start = ((uintptr_t)32 << 40); // 32TiB virtual start address
623
+ #if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of huge pages unless in debug mode
624
+ uintptr_t r = _mi_heap_random_next(mi_prim_get_default_heap());
625
+ start = start + ((uintptr_t)MI_HUGE_OS_PAGE_SIZE * ((r>>17) & 0x0FFF)); // (randomly 12bits)*1GiB == between 0 to 4TiB
626
+ #endif
627
+ }
628
+ end = start + size;
629
+ mi_assert_internal(end % MI_SEGMENT_SIZE == 0);
630
+ } while (!mi_atomic_cas_strong_acq_rel(&mi_huge_start, &huge_start, end));
631
+
632
+ if (total_size != NULL) *total_size = size;
633
+ return (uint8_t*)start;
634
+ }
635
+ #else
636
+ static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
637
+ MI_UNUSED(pages);
638
+ if (total_size != NULL) *total_size = 0;
639
+ return NULL;
640
+ }
641
+ #endif
642
+
643
+ // Allocate MI_SEGMENT_SIZE aligned huge pages
644
+ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_msecs, size_t* pages_reserved, size_t* psize, mi_memid_t* memid) {
645
+ *memid = _mi_memid_none();
646
+ if (psize != NULL) *psize = 0;
647
+ if (pages_reserved != NULL) *pages_reserved = 0;
648
+ size_t size = 0;
649
+ uint8_t* const start = mi_os_claim_huge_pages(pages, &size);
650
+ if (start == NULL) return NULL; // or 32-bit systems
651
+
652
+ // Allocate one page at the time but try to place them contiguously
653
+ // We allocate one page at the time to be able to abort if it takes too long
654
+ // or to at least allocate as many as available on the system.
655
+ mi_msecs_t start_t = _mi_clock_start();
656
+ size_t page = 0;
657
+ bool all_zero = true;
658
+ while (page < pages) {
659
+ // allocate a page
660
+ bool is_zero = false;
661
+ void* addr = start + (page * MI_HUGE_OS_PAGE_SIZE);
662
+ void* p = NULL;
663
+ int err = _mi_prim_alloc_huge_os_pages(addr, MI_HUGE_OS_PAGE_SIZE, numa_node, &is_zero, &p);
664
+ if (!is_zero) { all_zero = false; }
665
+ if (err != 0) {
666
+ _mi_warning_message("unable to allocate huge OS page (error: %d (0x%x), address: %p, size: %zx bytes)\n", err, err, addr, MI_HUGE_OS_PAGE_SIZE);
667
+ break;
668
+ }
669
+
670
+ // Did we succeed at a contiguous address?
671
+ if (p != addr) {
672
+ // no success, issue a warning and break
673
+ if (p != NULL) {
674
+ _mi_warning_message("could not allocate contiguous huge OS page %zu at %p\n", page, addr);
675
+ mi_os_prim_free(p, MI_HUGE_OS_PAGE_SIZE, MI_HUGE_OS_PAGE_SIZE);
676
+ }
677
+ break;
678
+ }
679
+
680
+ // success, record it
681
+ page++; // increase before timeout check (see issue #711)
682
+ mi_os_stat_increase(committed, MI_HUGE_OS_PAGE_SIZE);
683
+ mi_os_stat_increase(reserved, MI_HUGE_OS_PAGE_SIZE);
684
+
685
+ // check for timeout
686
+ if (max_msecs > 0) {
687
+ mi_msecs_t elapsed = _mi_clock_end(start_t);
688
+ if (page >= 1) {
689
+ mi_msecs_t estimate = ((elapsed / (page+1)) * pages);
690
+ if (estimate > 2*max_msecs) { // seems like we are going to timeout, break
691
+ elapsed = max_msecs + 1;
692
+ }
693
+ }
694
+ if (elapsed > max_msecs) {
695
+ _mi_warning_message("huge OS page allocation timed out (after allocating %zu page(s))\n", page);
696
+ break;
697
+ }
698
+ }
699
+ }
700
+ mi_assert_internal(page*MI_HUGE_OS_PAGE_SIZE <= size);
701
+ if (pages_reserved != NULL) { *pages_reserved = page; }
702
+ if (psize != NULL) { *psize = page * MI_HUGE_OS_PAGE_SIZE; }
703
+ if (page != 0) {
704
+ mi_assert(start != NULL);
705
+ *memid = _mi_memid_create_os(start, size, true /* is committed */, all_zero, true /* is_large */);
706
+ memid->memkind = MI_MEM_OS_HUGE;
707
+ mi_assert(memid->is_pinned);
708
+ #ifdef MI_TRACK_ASAN
709
+ if (all_zero) { mi_track_mem_defined(start,size); }
710
+ #endif
711
+ }
712
+ return (page == 0 ? NULL : start);
713
+ }
714
+
715
+ // free every huge page in a range individually (as we allocated per page)
716
+ // note: needed with VirtualAlloc but could potentially be done in one go on mmap'd systems.
717
+ static void mi_os_free_huge_os_pages(void* p, size_t size) {
718
+ if (p==NULL || size==0) return;
719
+ uint8_t* base = (uint8_t*)p;
720
+ while (size >= MI_HUGE_OS_PAGE_SIZE) {
721
+ mi_os_prim_free(base, MI_HUGE_OS_PAGE_SIZE, MI_HUGE_OS_PAGE_SIZE);
722
+ size -= MI_HUGE_OS_PAGE_SIZE;
723
+ base += MI_HUGE_OS_PAGE_SIZE;
724
+ }
725
+ }
726
+
727
+
728
+ /* ----------------------------------------------------------------------------
729
+ Support NUMA aware allocation
730
+ -----------------------------------------------------------------------------*/
731
+
732
+ static _Atomic(size_t) mi_numa_node_count; // = 0 // cache the node count
733
+
734
+ int _mi_os_numa_node_count(void) {
735
+ size_t count = mi_atomic_load_acquire(&mi_numa_node_count);
736
+ if mi_unlikely(count == 0) {
737
+ long ncount = mi_option_get(mi_option_use_numa_nodes); // given explicitly?
738
+ if (ncount > 0 && ncount < INT_MAX) {
739
+ count = (size_t)ncount;
740
+ }
741
+ else {
742
+ const size_t n = _mi_prim_numa_node_count(); // or detect dynamically
743
+ if (n == 0 || n > INT_MAX) { count = 1; }
744
+ else { count = n; }
745
+ }
746
+ mi_atomic_store_release(&mi_numa_node_count, count); // save it
747
+ _mi_verbose_message("using %zd numa regions\n", count);
748
+ }
749
+ mi_assert_internal(count > 0 && count <= INT_MAX);
750
+ return (int)count;
751
+ }
752
+
753
+ static int mi_os_numa_node_get(void) {
754
+ int numa_count = _mi_os_numa_node_count();
755
+ if (numa_count<=1) return 0; // optimize on single numa node systems: always node 0
756
+ // never more than the node count and >= 0
757
+ const size_t n = _mi_prim_numa_node();
758
+ int numa_node = (n < INT_MAX ? (int)n : 0);
759
+ if (numa_node >= numa_count) { numa_node = numa_node % numa_count; }
760
+ return numa_node;
761
+ }
762
+
763
+ int _mi_os_numa_node(void) {
764
+ if mi_likely(mi_atomic_load_relaxed(&mi_numa_node_count) == 1) {
765
+ return 0;
766
+ }
767
+ else {
768
+ return mi_os_numa_node_get();
769
+ }
770
+ }