@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,733 @@
1
+ /*----------------------------------------------------------------------------
2
+ Copyright (c) 2018-2021, 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
+
8
+ #include "mimalloc.h"
9
+ #include "mimalloc/internal.h"
10
+ #include "mimalloc/atomic.h"
11
+ #include "mimalloc/prim.h" // mi_prim_get_default_heap
12
+
13
+ #include <string.h> // memset, memcpy
14
+
15
+ #if defined(_MSC_VER) && (_MSC_VER < 1920)
16
+ #pragma warning(disable:4204) // non-constant aggregate initializer
17
+ #endif
18
+
19
+ /* -----------------------------------------------------------
20
+ Helpers
21
+ ----------------------------------------------------------- */
22
+
23
+ // return `true` if ok, `false` to break
24
+ typedef bool (heap_page_visitor_fun)(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2);
25
+
26
+ // Visit all pages in a heap; returns `false` if break was called.
27
+ static bool mi_heap_visit_pages(mi_heap_t* heap, heap_page_visitor_fun* fn, void* arg1, void* arg2)
28
+ {
29
+ if (heap==NULL || heap->page_count==0) return 0;
30
+
31
+ // visit all pages
32
+ #if MI_DEBUG>1
33
+ size_t total = heap->page_count;
34
+ size_t count = 0;
35
+ #endif
36
+
37
+ for (size_t i = 0; i <= MI_BIN_FULL; i++) {
38
+ mi_page_queue_t* pq = &heap->pages[i];
39
+ mi_page_t* page = pq->first;
40
+ while(page != NULL) {
41
+ mi_page_t* next = page->next; // save next in case the page gets removed from the queue
42
+ mi_assert_internal(mi_page_heap(page) == heap);
43
+ #if MI_DEBUG>1
44
+ count++;
45
+ #endif
46
+ if (!fn(heap, pq, page, arg1, arg2)) return false;
47
+ page = next; // and continue
48
+ }
49
+ }
50
+ mi_assert_internal(count == total);
51
+ return true;
52
+ }
53
+
54
+
55
+ #if MI_DEBUG>=2
56
+ static bool mi_heap_page_is_valid(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) {
57
+ MI_UNUSED(arg1);
58
+ MI_UNUSED(arg2);
59
+ MI_UNUSED(pq);
60
+ mi_assert_internal(mi_page_heap(page) == heap);
61
+ mi_segment_t* segment = _mi_page_segment(page);
62
+ mi_assert_internal(mi_atomic_load_relaxed(&segment->thread_id) == heap->thread_id);
63
+ mi_assert_expensive(_mi_page_is_valid(page));
64
+ return true;
65
+ }
66
+ #endif
67
+ #if MI_DEBUG>=3
68
+ static bool mi_heap_is_valid(mi_heap_t* heap) {
69
+ mi_assert_internal(heap!=NULL);
70
+ mi_heap_visit_pages(heap, &mi_heap_page_is_valid, NULL, NULL);
71
+ return true;
72
+ }
73
+ #endif
74
+
75
+
76
+
77
+
78
+ /* -----------------------------------------------------------
79
+ "Collect" pages by migrating `local_free` and `thread_free`
80
+ lists and freeing empty pages. This is done when a thread
81
+ stops (and in that case abandons pages if there are still
82
+ blocks alive)
83
+ ----------------------------------------------------------- */
84
+
85
+ typedef enum mi_collect_e {
86
+ MI_NORMAL,
87
+ MI_FORCE,
88
+ MI_ABANDON
89
+ } mi_collect_t;
90
+
91
+
92
+ static bool mi_heap_page_collect(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg_collect, void* arg2 ) {
93
+ MI_UNUSED(arg2);
94
+ MI_UNUSED(heap);
95
+ mi_assert_internal(mi_heap_page_is_valid(heap, pq, page, NULL, NULL));
96
+ mi_collect_t collect = *((mi_collect_t*)arg_collect);
97
+ _mi_page_free_collect(page, collect >= MI_FORCE);
98
+ if (collect == MI_FORCE) {
99
+ // note: call before a potential `_mi_page_free` as the segment may be freed if this was the last used page in that segment.
100
+ mi_segment_t* segment = _mi_page_segment(page);
101
+ _mi_segment_collect(segment, true /* force? */);
102
+ }
103
+ if (mi_page_all_free(page)) {
104
+ // no more used blocks, free the page.
105
+ // note: this will free retired pages as well.
106
+ _mi_page_free(page, pq, collect >= MI_FORCE);
107
+ }
108
+ else if (collect == MI_ABANDON) {
109
+ // still used blocks but the thread is done; abandon the page
110
+ _mi_page_abandon(page, pq);
111
+ }
112
+ return true; // don't break
113
+ }
114
+
115
+ static bool mi_heap_page_never_delayed_free(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) {
116
+ MI_UNUSED(arg1);
117
+ MI_UNUSED(arg2);
118
+ MI_UNUSED(heap);
119
+ MI_UNUSED(pq);
120
+ _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false);
121
+ return true; // don't break
122
+ }
123
+
124
+ static void mi_heap_collect_ex(mi_heap_t* heap, mi_collect_t collect)
125
+ {
126
+ if (heap==NULL || !mi_heap_is_initialized(heap)) return;
127
+
128
+ const bool force = (collect >= MI_FORCE);
129
+ _mi_deferred_free(heap, force);
130
+
131
+ // python/cpython#112532: we may be called from a thread that is not the owner of the heap
132
+ const bool is_main_thread = (_mi_is_main_thread() && heap->thread_id == _mi_thread_id());
133
+
134
+ // note: never reclaim on collect but leave it to threads that need storage to reclaim
135
+ const bool force_main =
136
+ #ifdef NDEBUG
137
+ collect == MI_FORCE
138
+ #else
139
+ collect >= MI_FORCE
140
+ #endif
141
+ && is_main_thread && mi_heap_is_backing(heap) && !heap->no_reclaim;
142
+
143
+ if (force_main) {
144
+ // the main thread is abandoned (end-of-program), try to reclaim all abandoned segments.
145
+ // if all memory is freed by now, all segments should be freed.
146
+ // note: this only collects in the current subprocess
147
+ _mi_abandoned_reclaim_all(heap, &heap->tld->segments);
148
+ }
149
+
150
+ // if abandoning, mark all pages to no longer add to delayed_free
151
+ if (collect == MI_ABANDON) {
152
+ mi_heap_visit_pages(heap, &mi_heap_page_never_delayed_free, NULL, NULL);
153
+ }
154
+
155
+ // free all current thread delayed blocks.
156
+ // (if abandoning, after this there are no more thread-delayed references into the pages.)
157
+ _mi_heap_delayed_free_all(heap);
158
+
159
+ // collect retired pages
160
+ _mi_heap_collect_retired(heap, force);
161
+
162
+ // collect all pages owned by this thread
163
+ mi_heap_visit_pages(heap, &mi_heap_page_collect, &collect, NULL);
164
+ mi_assert_internal( collect != MI_ABANDON || mi_atomic_load_ptr_acquire(mi_block_t,&heap->thread_delayed_free) == NULL );
165
+
166
+ // collect abandoned segments (in particular, purge expired parts of segments in the abandoned segment list)
167
+ // note: forced purge can be quite expensive if many threads are created/destroyed so we do not force on abandonment
168
+ _mi_abandoned_collect(heap, collect == MI_FORCE /* force? */, &heap->tld->segments);
169
+
170
+ // if forced, collect thread data cache on program-exit (or shared library unload)
171
+ if (force && is_main_thread && mi_heap_is_backing(heap)) {
172
+ _mi_thread_data_collect(); // collect thread data cache
173
+ }
174
+
175
+ // collect arenas (this is program wide so don't force purges on abandonment of threads)
176
+ _mi_arenas_collect(collect == MI_FORCE /* force purge? */);
177
+
178
+ // merge statistics
179
+ if (collect <= MI_FORCE) { _mi_stats_merge_thread(heap->tld); }
180
+ }
181
+
182
+ void _mi_heap_collect_abandon(mi_heap_t* heap) {
183
+ mi_heap_collect_ex(heap, MI_ABANDON);
184
+ }
185
+
186
+ void mi_heap_collect(mi_heap_t* heap, bool force) mi_attr_noexcept {
187
+ mi_heap_collect_ex(heap, (force ? MI_FORCE : MI_NORMAL));
188
+ }
189
+
190
+ void mi_collect(bool force) mi_attr_noexcept {
191
+ mi_heap_collect(mi_prim_get_default_heap(), force);
192
+ }
193
+
194
+
195
+ /* -----------------------------------------------------------
196
+ Heap new
197
+ ----------------------------------------------------------- */
198
+
199
+ mi_heap_t* mi_heap_get_default(void) {
200
+ mi_thread_init();
201
+ return mi_prim_get_default_heap();
202
+ }
203
+
204
+ static bool mi_heap_is_default(const mi_heap_t* heap) {
205
+ return (heap == mi_prim_get_default_heap());
206
+ }
207
+
208
+
209
+ mi_heap_t* mi_heap_get_backing(void) {
210
+ mi_heap_t* heap = mi_heap_get_default();
211
+ mi_assert_internal(heap!=NULL);
212
+ mi_heap_t* bheap = heap->tld->heap_backing;
213
+ mi_assert_internal(bheap!=NULL);
214
+ mi_assert_internal(bheap->thread_id == _mi_thread_id());
215
+ return bheap;
216
+ }
217
+
218
+ void _mi_heap_init(mi_heap_t* heap, mi_tld_t* tld, mi_arena_id_t arena_id, bool noreclaim, uint8_t tag) {
219
+ _mi_memcpy_aligned(heap, &_mi_heap_empty, sizeof(mi_heap_t));
220
+ heap->tld = tld;
221
+ heap->thread_id = _mi_thread_id();
222
+ heap->arena_id = arena_id;
223
+ heap->no_reclaim = noreclaim;
224
+ heap->tag = tag;
225
+ if (heap == tld->heap_backing) {
226
+ _mi_random_init(&heap->random);
227
+ }
228
+ else {
229
+ _mi_random_split(&tld->heap_backing->random, &heap->random);
230
+ }
231
+ heap->cookie = _mi_heap_random_next(heap) | 1;
232
+ heap->keys[0] = _mi_heap_random_next(heap);
233
+ heap->keys[1] = _mi_heap_random_next(heap);
234
+ _mi_heap_guarded_init(heap);
235
+ // push on the thread local heaps list
236
+ heap->next = heap->tld->heaps;
237
+ heap->tld->heaps = heap;
238
+ }
239
+
240
+ mi_decl_nodiscard mi_heap_t* mi_heap_new_ex(int heap_tag, bool allow_destroy, mi_arena_id_t arena_id) {
241
+ mi_heap_t* bheap = mi_heap_get_backing();
242
+ mi_heap_t* heap = mi_heap_malloc_tp(bheap, mi_heap_t); // todo: OS allocate in secure mode?
243
+ if (heap == NULL) return NULL;
244
+ mi_assert(heap_tag >= 0 && heap_tag < 256);
245
+ _mi_heap_init(heap, bheap->tld, arena_id, allow_destroy /* no reclaim? */, (uint8_t)heap_tag /* heap tag */);
246
+ return heap;
247
+ }
248
+
249
+ mi_decl_nodiscard mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t arena_id) {
250
+ return mi_heap_new_ex(0 /* default heap tag */, false /* don't allow `mi_heap_destroy` */, arena_id);
251
+ }
252
+
253
+ mi_decl_nodiscard mi_heap_t* mi_heap_new(void) {
254
+ // don't reclaim abandoned memory or otherwise destroy is unsafe
255
+ return mi_heap_new_ex(0 /* default heap tag */, true /* no reclaim */, _mi_arena_id_none());
256
+ }
257
+
258
+ bool _mi_heap_memid_is_suitable(mi_heap_t* heap, mi_memid_t memid) {
259
+ return _mi_arena_memid_is_suitable(memid, heap->arena_id);
260
+ }
261
+
262
+ uintptr_t _mi_heap_random_next(mi_heap_t* heap) {
263
+ return _mi_random_next(&heap->random);
264
+ }
265
+
266
+ // zero out the page queues
267
+ static void mi_heap_reset_pages(mi_heap_t* heap) {
268
+ mi_assert_internal(heap != NULL);
269
+ mi_assert_internal(mi_heap_is_initialized(heap));
270
+ // TODO: copy full empty heap instead?
271
+ memset(&heap->pages_free_direct, 0, sizeof(heap->pages_free_direct));
272
+ _mi_memcpy_aligned(&heap->pages, &_mi_heap_empty.pages, sizeof(heap->pages));
273
+ heap->thread_delayed_free = NULL;
274
+ heap->page_count = 0;
275
+ }
276
+
277
+ // called from `mi_heap_destroy` and `mi_heap_delete` to free the internal heap resources.
278
+ static void mi_heap_free(mi_heap_t* heap) {
279
+ mi_assert(heap != NULL);
280
+ mi_assert_internal(mi_heap_is_initialized(heap));
281
+ if (heap==NULL || !mi_heap_is_initialized(heap)) return;
282
+ if (mi_heap_is_backing(heap)) return; // dont free the backing heap
283
+
284
+ // reset default
285
+ if (mi_heap_is_default(heap)) {
286
+ _mi_heap_set_default_direct(heap->tld->heap_backing);
287
+ }
288
+
289
+ // remove ourselves from the thread local heaps list
290
+ // linear search but we expect the number of heaps to be relatively small
291
+ mi_heap_t* prev = NULL;
292
+ mi_heap_t* curr = heap->tld->heaps;
293
+ while (curr != heap && curr != NULL) {
294
+ prev = curr;
295
+ curr = curr->next;
296
+ }
297
+ mi_assert_internal(curr == heap);
298
+ if (curr == heap) {
299
+ if (prev != NULL) { prev->next = heap->next; }
300
+ else { heap->tld->heaps = heap->next; }
301
+ }
302
+ mi_assert_internal(heap->tld->heaps != NULL);
303
+
304
+ // and free the used memory
305
+ mi_free(heap);
306
+ }
307
+
308
+ // return a heap on the same thread as `heap` specialized for the specified tag (if it exists)
309
+ mi_heap_t* _mi_heap_by_tag(mi_heap_t* heap, uint8_t tag) {
310
+ if (heap->tag == tag) {
311
+ return heap;
312
+ }
313
+ for (mi_heap_t *curr = heap->tld->heaps; curr != NULL; curr = curr->next) {
314
+ if (curr->tag == tag) {
315
+ return curr;
316
+ }
317
+ }
318
+ return NULL;
319
+ }
320
+
321
+ /* -----------------------------------------------------------
322
+ Heap destroy
323
+ ----------------------------------------------------------- */
324
+
325
+ static bool _mi_heap_page_destroy(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2) {
326
+ MI_UNUSED(arg1);
327
+ MI_UNUSED(arg2);
328
+ MI_UNUSED(heap);
329
+ MI_UNUSED(pq);
330
+
331
+ // ensure no more thread_delayed_free will be added
332
+ _mi_page_use_delayed_free(page, MI_NEVER_DELAYED_FREE, false);
333
+
334
+ // stats
335
+ const size_t bsize = mi_page_block_size(page);
336
+ if (bsize > MI_MEDIUM_OBJ_SIZE_MAX) {
337
+ //if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
338
+ // mi_heap_stat_decrease(heap, malloc_large, bsize);
339
+ //}
340
+ //else
341
+ {
342
+ mi_heap_stat_decrease(heap, malloc_huge, bsize);
343
+ }
344
+ }
345
+ #if (MI_STAT>0)
346
+ _mi_page_free_collect(page, false); // update used count
347
+ const size_t inuse = page->used;
348
+ if (bsize <= MI_LARGE_OBJ_SIZE_MAX) {
349
+ mi_heap_stat_decrease(heap, malloc_normal, bsize * inuse);
350
+ #if (MI_STAT>1)
351
+ mi_heap_stat_decrease(heap, malloc_bins[_mi_bin(bsize)], inuse);
352
+ #endif
353
+ }
354
+ // mi_heap_stat_decrease(heap, malloc_requested, bsize * inuse); // todo: off for aligned blocks...
355
+ #endif
356
+
357
+ /// pretend it is all free now
358
+ mi_assert_internal(mi_page_thread_free(page) == NULL);
359
+ page->used = 0;
360
+
361
+ // and free the page
362
+ // mi_page_free(page,false);
363
+ page->next = NULL;
364
+ page->prev = NULL;
365
+ _mi_segment_page_free(page,false /* no force? */, &heap->tld->segments);
366
+
367
+ return true; // keep going
368
+ }
369
+
370
+ void _mi_heap_destroy_pages(mi_heap_t* heap) {
371
+ mi_heap_visit_pages(heap, &_mi_heap_page_destroy, NULL, NULL);
372
+ mi_heap_reset_pages(heap);
373
+ }
374
+
375
+ #if MI_TRACK_HEAP_DESTROY
376
+ static bool mi_cdecl mi_heap_track_block_free(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg) {
377
+ MI_UNUSED(heap); MI_UNUSED(area); MI_UNUSED(arg); MI_UNUSED(block_size);
378
+ mi_track_free_size(block,mi_usable_size(block));
379
+ return true;
380
+ }
381
+ #endif
382
+
383
+ void mi_heap_destroy(mi_heap_t* heap) {
384
+ mi_assert(heap != NULL);
385
+ mi_assert(mi_heap_is_initialized(heap));
386
+ mi_assert(heap->no_reclaim);
387
+ mi_assert_expensive(mi_heap_is_valid(heap));
388
+ if (heap==NULL || !mi_heap_is_initialized(heap)) return;
389
+ #if MI_GUARDED
390
+ // _mi_warning_message("'mi_heap_destroy' called but MI_GUARDED is enabled -- using `mi_heap_delete` instead (heap at %p)\n", heap);
391
+ mi_heap_delete(heap);
392
+ return;
393
+ #else
394
+ if (!heap->no_reclaim) {
395
+ _mi_warning_message("'mi_heap_destroy' called but ignored as the heap was not created with 'allow_destroy' (heap at %p)\n", heap);
396
+ // don't free in case it may contain reclaimed pages
397
+ mi_heap_delete(heap);
398
+ }
399
+ else {
400
+ // track all blocks as freed
401
+ #if MI_TRACK_HEAP_DESTROY
402
+ mi_heap_visit_blocks(heap, true, mi_heap_track_block_free, NULL);
403
+ #endif
404
+ // free all pages
405
+ _mi_heap_destroy_pages(heap);
406
+ mi_heap_free(heap);
407
+ }
408
+ #endif
409
+ }
410
+
411
+ // forcefully destroy all heaps in the current thread
412
+ void _mi_heap_unsafe_destroy_all(mi_heap_t* heap) {
413
+ mi_assert_internal(heap != NULL);
414
+ if (heap == NULL) return;
415
+ mi_heap_t* curr = heap->tld->heaps;
416
+ while (curr != NULL) {
417
+ mi_heap_t* next = curr->next;
418
+ if (curr->no_reclaim) {
419
+ mi_heap_destroy(curr);
420
+ }
421
+ else {
422
+ _mi_heap_destroy_pages(curr);
423
+ }
424
+ curr = next;
425
+ }
426
+ }
427
+
428
+ /* -----------------------------------------------------------
429
+ Safe Heap delete
430
+ ----------------------------------------------------------- */
431
+
432
+ // Transfer the pages from one heap to the other
433
+ static void mi_heap_absorb(mi_heap_t* heap, mi_heap_t* from) {
434
+ mi_assert_internal(heap!=NULL);
435
+ if (from==NULL || from->page_count == 0) return;
436
+
437
+ // reduce the size of the delayed frees
438
+ _mi_heap_delayed_free_partial(from);
439
+
440
+ // transfer all pages by appending the queues; this will set a new heap field
441
+ // so threads may do delayed frees in either heap for a while.
442
+ // note: appending waits for each page to not be in the `MI_DELAYED_FREEING` state
443
+ // so after this only the new heap will get delayed frees
444
+ for (size_t i = 0; i <= MI_BIN_FULL; i++) {
445
+ mi_page_queue_t* pq = &heap->pages[i];
446
+ mi_page_queue_t* append = &from->pages[i];
447
+ size_t pcount = _mi_page_queue_append(heap, pq, append);
448
+ heap->page_count += pcount;
449
+ from->page_count -= pcount;
450
+ }
451
+ mi_assert_internal(from->page_count == 0);
452
+
453
+ // and do outstanding delayed frees in the `from` heap
454
+ // note: be careful here as the `heap` field in all those pages no longer point to `from`,
455
+ // turns out to be ok as `_mi_heap_delayed_free` only visits the list and calls a
456
+ // the regular `_mi_free_delayed_block` which is safe.
457
+ _mi_heap_delayed_free_all(from);
458
+ #if !defined(_MSC_VER) || (_MSC_VER > 1900) // somehow the following line gives an error in VS2015, issue #353
459
+ mi_assert_internal(mi_atomic_load_ptr_relaxed(mi_block_t,&from->thread_delayed_free) == NULL);
460
+ #endif
461
+
462
+ // and reset the `from` heap
463
+ mi_heap_reset_pages(from);
464
+ }
465
+
466
+ // are two heaps compatible with respect to heap-tag, exclusive arena etc.
467
+ static bool mi_heaps_are_compatible(mi_heap_t* heap1, mi_heap_t* heap2) {
468
+ return (heap1->tag == heap2->tag && // store same kind of objects
469
+ heap1->arena_id == heap2->arena_id); // same arena preference
470
+ }
471
+
472
+ // Safe delete a heap without freeing any still allocated blocks in that heap.
473
+ void mi_heap_delete(mi_heap_t* heap)
474
+ {
475
+ mi_assert(heap != NULL);
476
+ mi_assert(mi_heap_is_initialized(heap));
477
+ mi_assert_expensive(mi_heap_is_valid(heap));
478
+ if (heap==NULL || !mi_heap_is_initialized(heap)) return;
479
+
480
+ mi_heap_t* bheap = heap->tld->heap_backing;
481
+ if (bheap != heap && mi_heaps_are_compatible(bheap,heap)) {
482
+ // transfer still used pages to the backing heap
483
+ mi_heap_absorb(bheap, heap);
484
+ }
485
+ else {
486
+ // the backing heap abandons its pages
487
+ _mi_heap_collect_abandon(heap);
488
+ }
489
+ mi_assert_internal(heap->page_count==0);
490
+ mi_heap_free(heap);
491
+ }
492
+
493
+ mi_heap_t* mi_heap_set_default(mi_heap_t* heap) {
494
+ mi_assert(heap != NULL);
495
+ mi_assert(mi_heap_is_initialized(heap));
496
+ if (heap==NULL || !mi_heap_is_initialized(heap)) return NULL;
497
+ mi_assert_expensive(mi_heap_is_valid(heap));
498
+ mi_heap_t* old = mi_prim_get_default_heap();
499
+ _mi_heap_set_default_direct(heap);
500
+ return old;
501
+ }
502
+
503
+
504
+
505
+
506
+ /* -----------------------------------------------------------
507
+ Analysis
508
+ ----------------------------------------------------------- */
509
+
510
+ // static since it is not thread safe to access heaps from other threads.
511
+ static mi_heap_t* mi_heap_of_block(const void* p) {
512
+ if (p == NULL) return NULL;
513
+ mi_segment_t* segment = _mi_ptr_segment(p);
514
+ bool valid = (_mi_ptr_cookie(segment) == segment->cookie);
515
+ mi_assert_internal(valid);
516
+ if mi_unlikely(!valid) return NULL;
517
+ return mi_page_heap(_mi_segment_page_of(segment,p));
518
+ }
519
+
520
+ bool mi_heap_contains_block(mi_heap_t* heap, const void* p) {
521
+ mi_assert(heap != NULL);
522
+ if (heap==NULL || !mi_heap_is_initialized(heap)) return false;
523
+ return (heap == mi_heap_of_block(p));
524
+ }
525
+
526
+
527
+ static bool mi_heap_page_check_owned(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* p, void* vfound) {
528
+ MI_UNUSED(heap);
529
+ MI_UNUSED(pq);
530
+ bool* found = (bool*)vfound;
531
+ void* start = mi_page_start(page);
532
+ void* end = (uint8_t*)start + (page->capacity * mi_page_block_size(page));
533
+ *found = (p >= start && p < end);
534
+ return (!*found); // continue if not found
535
+ }
536
+
537
+ bool mi_heap_check_owned(mi_heap_t* heap, const void* p) {
538
+ mi_assert(heap != NULL);
539
+ if (heap==NULL || !mi_heap_is_initialized(heap)) return false;
540
+ if (((uintptr_t)p & (MI_INTPTR_SIZE - 1)) != 0) return false; // only aligned pointers
541
+ bool found = false;
542
+ mi_heap_visit_pages(heap, &mi_heap_page_check_owned, (void*)p, &found);
543
+ return found;
544
+ }
545
+
546
+ bool mi_check_owned(const void* p) {
547
+ return mi_heap_check_owned(mi_prim_get_default_heap(), p);
548
+ }
549
+
550
+ /* -----------------------------------------------------------
551
+ Visit all heap blocks and areas
552
+ Todo: enable visiting abandoned pages, and
553
+ enable visiting all blocks of all heaps across threads
554
+ ----------------------------------------------------------- */
555
+
556
+ void _mi_heap_area_init(mi_heap_area_t* area, mi_page_t* page) {
557
+ const size_t bsize = mi_page_block_size(page);
558
+ const size_t ubsize = mi_page_usable_block_size(page);
559
+ area->reserved = page->reserved * bsize;
560
+ area->committed = page->capacity * bsize;
561
+ area->blocks = mi_page_start(page);
562
+ area->used = page->used; // number of blocks in use (#553)
563
+ area->block_size = ubsize;
564
+ area->full_block_size = bsize;
565
+ area->heap_tag = page->heap_tag;
566
+ }
567
+
568
+
569
+ static void mi_get_fast_divisor(size_t divisor, uint64_t* magic, size_t* shift) {
570
+ mi_assert_internal(divisor > 0 && divisor <= UINT32_MAX);
571
+ *shift = MI_SIZE_BITS - mi_clz(divisor - 1);
572
+ *magic = ((((uint64_t)1 << 32) * (((uint64_t)1 << *shift) - divisor)) / divisor + 1);
573
+ }
574
+
575
+ static size_t mi_fast_divide(size_t n, uint64_t magic, size_t shift) {
576
+ mi_assert_internal(n <= UINT32_MAX);
577
+ const uint64_t hi = ((uint64_t)n * magic) >> 32;
578
+ return (size_t)((hi + n) >> shift);
579
+ }
580
+
581
+ bool _mi_heap_area_visit_blocks(const mi_heap_area_t* area, mi_page_t* page, mi_block_visit_fun* visitor, void* arg) {
582
+ mi_assert(area != NULL);
583
+ if (area==NULL) return true;
584
+ mi_assert(page != NULL);
585
+ if (page == NULL) return true;
586
+
587
+ _mi_page_free_collect(page,true); // collect both thread_delayed and local_free
588
+ mi_assert_internal(page->local_free == NULL);
589
+ if (page->used == 0) return true;
590
+
591
+ size_t psize;
592
+ uint8_t* const pstart = _mi_segment_page_start(_mi_page_segment(page), page, &psize);
593
+ mi_heap_t* const heap = mi_page_heap(page);
594
+ const size_t bsize = mi_page_block_size(page);
595
+ const size_t ubsize = mi_page_usable_block_size(page); // without padding
596
+
597
+ // optimize page with one block
598
+ if (page->capacity == 1) {
599
+ mi_assert_internal(page->used == 1 && page->free == NULL);
600
+ return visitor(mi_page_heap(page), area, pstart, ubsize, arg);
601
+ }
602
+ mi_assert(bsize <= UINT32_MAX);
603
+
604
+ // optimize full pages
605
+ if (page->used == page->capacity) {
606
+ uint8_t* block = pstart;
607
+ for (size_t i = 0; i < page->capacity; i++) {
608
+ if (!visitor(heap, area, block, ubsize, arg)) return false;
609
+ block += bsize;
610
+ }
611
+ return true;
612
+ }
613
+
614
+ // create a bitmap of free blocks.
615
+ #define MI_MAX_BLOCKS (MI_SMALL_PAGE_SIZE / sizeof(void*))
616
+ uintptr_t free_map[MI_MAX_BLOCKS / MI_INTPTR_BITS];
617
+ const uintptr_t bmapsize = _mi_divide_up(page->capacity, MI_INTPTR_BITS);
618
+ memset(free_map, 0, bmapsize * sizeof(intptr_t));
619
+ if (page->capacity % MI_INTPTR_BITS != 0) {
620
+ // mark left-over bits at the end as free
621
+ size_t shift = (page->capacity % MI_INTPTR_BITS);
622
+ uintptr_t mask = (UINTPTR_MAX << shift);
623
+ free_map[bmapsize - 1] = mask;
624
+ }
625
+
626
+ // fast repeated division by the block size
627
+ uint64_t magic;
628
+ size_t shift;
629
+ mi_get_fast_divisor(bsize, &magic, &shift);
630
+
631
+ #if MI_DEBUG>1
632
+ size_t free_count = 0;
633
+ #endif
634
+ for (mi_block_t* block = page->free; block != NULL; block = mi_block_next(page, block)) {
635
+ #if MI_DEBUG>1
636
+ free_count++;
637
+ #endif
638
+ mi_assert_internal((uint8_t*)block >= pstart && (uint8_t*)block < (pstart + psize));
639
+ size_t offset = (uint8_t*)block - pstart;
640
+ mi_assert_internal(offset % bsize == 0);
641
+ mi_assert_internal(offset <= UINT32_MAX);
642
+ size_t blockidx = mi_fast_divide(offset, magic, shift);
643
+ mi_assert_internal(blockidx == offset / bsize);
644
+ mi_assert_internal(blockidx < MI_MAX_BLOCKS);
645
+ size_t bitidx = (blockidx / MI_INTPTR_BITS);
646
+ size_t bit = blockidx - (bitidx * MI_INTPTR_BITS);
647
+ free_map[bitidx] |= ((uintptr_t)1 << bit);
648
+ }
649
+ mi_assert_internal(page->capacity == (free_count + page->used));
650
+
651
+ // walk through all blocks skipping the free ones
652
+ #if MI_DEBUG>1
653
+ size_t used_count = 0;
654
+ #endif
655
+ uint8_t* block = pstart;
656
+ for (size_t i = 0; i < bmapsize; i++) {
657
+ if (free_map[i] == 0) {
658
+ // every block is in use
659
+ for (size_t j = 0; j < MI_INTPTR_BITS; j++) {
660
+ #if MI_DEBUG>1
661
+ used_count++;
662
+ #endif
663
+ if (!visitor(heap, area, block, ubsize, arg)) return false;
664
+ block += bsize;
665
+ }
666
+ }
667
+ else {
668
+ // visit the used blocks in the mask
669
+ uintptr_t m = ~free_map[i];
670
+ while (m != 0) {
671
+ #if MI_DEBUG>1
672
+ used_count++;
673
+ #endif
674
+ size_t bitidx = mi_ctz(m);
675
+ if (!visitor(heap, area, block + (bitidx * bsize), ubsize, arg)) return false;
676
+ m &= m - 1; // clear least significant bit
677
+ }
678
+ block += bsize * MI_INTPTR_BITS;
679
+ }
680
+ }
681
+ mi_assert_internal(page->used == used_count);
682
+ return true;
683
+ }
684
+
685
+
686
+
687
+ // Separate struct to keep `mi_page_t` out of the public interface
688
+ typedef struct mi_heap_area_ex_s {
689
+ mi_heap_area_t area;
690
+ mi_page_t* page;
691
+ } mi_heap_area_ex_t;
692
+
693
+ typedef bool (mi_heap_area_visit_fun)(const mi_heap_t* heap, const mi_heap_area_ex_t* area, void* arg);
694
+
695
+ static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_page_t* page, void* vfun, void* arg) {
696
+ MI_UNUSED(heap);
697
+ MI_UNUSED(pq);
698
+ mi_heap_area_visit_fun* fun = (mi_heap_area_visit_fun*)vfun;
699
+ mi_heap_area_ex_t xarea;
700
+ xarea.page = page;
701
+ _mi_heap_area_init(&xarea.area, page);
702
+ return fun(heap, &xarea, arg);
703
+ }
704
+
705
+ // Visit all heap pages as areas
706
+ static bool mi_heap_visit_areas(const mi_heap_t* heap, mi_heap_area_visit_fun* visitor, void* arg) {
707
+ if (visitor == NULL) return false;
708
+ return mi_heap_visit_pages((mi_heap_t*)heap, &mi_heap_visit_areas_page, (void*)(visitor), arg); // note: function pointer to void* :-{
709
+ }
710
+
711
+ // Just to pass arguments
712
+ typedef struct mi_visit_blocks_args_s {
713
+ bool visit_blocks;
714
+ mi_block_visit_fun* visitor;
715
+ void* arg;
716
+ } mi_visit_blocks_args_t;
717
+
718
+ static bool mi_heap_area_visitor(const mi_heap_t* heap, const mi_heap_area_ex_t* xarea, void* arg) {
719
+ mi_visit_blocks_args_t* args = (mi_visit_blocks_args_t*)arg;
720
+ if (!args->visitor(heap, &xarea->area, NULL, xarea->area.block_size, args->arg)) return false;
721
+ if (args->visit_blocks) {
722
+ return _mi_heap_area_visit_blocks(&xarea->area, xarea->page, args->visitor, args->arg);
723
+ }
724
+ else {
725
+ return true;
726
+ }
727
+ }
728
+
729
+ // Visit all blocks in a heap
730
+ bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_blocks, mi_block_visit_fun* visitor, void* arg) {
731
+ mi_visit_blocks_args_t args = { visit_blocks, visitor, arg };
732
+ return mi_heap_visit_areas(heap, &mi_heap_area_visitor, &args);
733
+ }