@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.
- package/LICENSE.md +17 -0
- package/README.md +80 -0
- package/out/cjs/index.cjs +51 -0
- package/out/cjs/yo-cli.cjs +2158 -0
- package/out/esm/index.mjs +51 -0
- package/out/types/src/codegen/async/runtime.d.ts +2 -0
- package/out/types/src/codegen/async/state-code-gen.d.ts +10 -0
- package/out/types/src/codegen/async/state-machine.d.ts +13 -0
- package/out/types/src/codegen/c/collection.d.ts +3 -0
- package/out/types/src/codegen/codegen-c.d.ts +12 -0
- package/out/types/src/codegen/constants.d.ts +3 -0
- package/out/types/src/codegen/expressions/array.d.ts +4 -0
- package/out/types/src/codegen/expressions/generation.d.ts +11 -0
- package/out/types/src/codegen/expressions/index.d.ts +2 -0
- package/out/types/src/codegen/functions/collection.d.ts +5 -0
- package/out/types/src/codegen/functions/context.d.ts +57 -0
- package/out/types/src/codegen/functions/generation.d.ts +25 -0
- package/out/types/src/codegen/functions/index.d.ts +2 -0
- package/out/types/src/codegen/index.d.ts +20 -0
- package/out/types/src/codegen/parallelism/runtime.d.ts +2 -0
- package/out/types/src/codegen/types/collection.d.ts +8 -0
- package/out/types/src/codegen/types/generation.d.ts +13 -0
- package/out/types/src/codegen/types/index.d.ts +2 -0
- package/out/types/src/codegen/utils/fixup.d.ts +2 -0
- package/out/types/src/codegen/utils/index.d.ts +77 -0
- package/out/types/src/codegen/values/index.d.ts +1 -0
- package/out/types/src/emitter.d.ts +11 -0
- package/out/types/src/env.d.ts +85 -0
- package/out/types/src/error.d.ts +45 -0
- package/out/types/src/evaluator/async/await-analysis-types.d.ts +23 -0
- package/out/types/src/evaluator/async/await-analysis.d.ts +5 -0
- package/out/types/src/evaluator/builtins/alignof.d.ts +8 -0
- package/out/types/src/evaluator/builtins/and_or.d.ts +8 -0
- package/out/types/src/evaluator/builtins/arc_fns.d.ts +58 -0
- package/out/types/src/evaluator/builtins/array_fns.d.ts +0 -0
- package/out/types/src/evaluator/builtins/as.d.ts +8 -0
- package/out/types/src/evaluator/builtins/async_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_assert.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_boolean_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_expect_error.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_list_fns.d.ts +33 -0
- package/out/types/src/evaluator/builtins/compt_print.d.ts +8 -0
- package/out/types/src/evaluator/builtins/compt_string_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/consume.d.ts +8 -0
- package/out/types/src/evaluator/builtins/drop.d.ts +8 -0
- package/out/types/src/evaluator/builtins/dup.d.ts +8 -0
- package/out/types/src/evaluator/builtins/expr_fns.d.ts +33 -0
- package/out/types/src/evaluator/builtins/future_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/gc.d.ts +8 -0
- package/out/types/src/evaluator/builtins/gensym.d.ts +8 -0
- package/out/types/src/evaluator/builtins/impl_constraint.d.ts +8 -0
- package/out/types/src/evaluator/builtins/macro_expand.d.ts +8 -0
- package/out/types/src/evaluator/builtins/numeric_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/panic.d.ts +8 -0
- package/out/types/src/evaluator/builtins/ptr_fns.d.ts +8 -0
- package/out/types/src/evaluator/builtins/quote.d.ts +13 -0
- package/out/types/src/evaluator/builtins/rc.d.ts +8 -0
- package/out/types/src/evaluator/builtins/sizeof.d.ts +8 -0
- package/out/types/src/evaluator/builtins/the.d.ts +8 -0
- package/out/types/src/evaluator/builtins/type_fns.d.ts +28 -0
- package/out/types/src/evaluator/builtins/va_start.d.ts +8 -0
- package/out/types/src/evaluator/builtins/var_fns.d.ts +18 -0
- package/out/types/src/evaluator/calls/array.d.ts +13 -0
- package/out/types/src/evaluator/calls/array_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/closure_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/compt_function.d.ts +19 -0
- package/out/types/src/evaluator/calls/compt_list_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/function.d.ts +16 -0
- package/out/types/src/evaluator/calls/function_type.d.ts +15 -0
- package/out/types/src/evaluator/calls/helper.d.ts +42 -0
- package/out/types/src/evaluator/calls/iso.d.ts +15 -0
- package/out/types/src/evaluator/calls/module_type.d.ts +11 -0
- package/out/types/src/evaluator/calls/numeric_type.d.ts +15 -0
- package/out/types/src/evaluator/calls/pointer.d.ts +8 -0
- package/out/types/src/evaluator/calls/pointer_type.d.ts +14 -0
- package/out/types/src/evaluator/calls/type.d.ts +12 -0
- package/out/types/src/evaluator/context.d.ts +169 -0
- package/out/types/src/evaluator/exprs/_expr.d.ts +8 -0
- package/out/types/src/evaluator/exprs/assignment.d.ts +9 -0
- package/out/types/src/evaluator/exprs/begin.d.ts +10 -0
- package/out/types/src/evaluator/exprs/binding.d.ts +12 -0
- package/out/types/src/evaluator/exprs/c_include.d.ts +8 -0
- package/out/types/src/evaluator/exprs/cond.d.ts +8 -0
- package/out/types/src/evaluator/exprs/destructuring_assignment.d.ts +33 -0
- package/out/types/src/evaluator/exprs/exists.d.ts +0 -0
- package/out/types/src/evaluator/exprs/expr.d.ts +9 -0
- package/out/types/src/evaluator/exprs/extern.d.ts +8 -0
- package/out/types/src/evaluator/exprs/identifer_and_operator.d.ts +9 -0
- package/out/types/src/evaluator/exprs/import.d.ts +9 -0
- package/out/types/src/evaluator/exprs/initialization_assignment.d.ts +8 -0
- package/out/types/src/evaluator/exprs/match.d.ts +8 -0
- package/out/types/src/evaluator/exprs/open.d.ts +8 -0
- package/out/types/src/evaluator/exprs/property_access.d.ts +8 -0
- package/out/types/src/evaluator/exprs/recur.d.ts +8 -0
- package/out/types/src/evaluator/exprs/subtype_of.d.ts +21 -0
- package/out/types/src/evaluator/exprs/test.d.ts +8 -0
- package/out/types/src/evaluator/exprs/typeof.d.ts +8 -0
- package/out/types/src/evaluator/exprs/while.d.ts +8 -0
- package/out/types/src/evaluator/index.d.ts +26 -0
- package/out/types/src/evaluator/types/array.d.ts +8 -0
- package/out/types/src/evaluator/types/closure.d.ts +8 -0
- package/out/types/src/evaluator/types/compt_list.d.ts +8 -0
- package/out/types/src/evaluator/types/concrete_module.d.ts +8 -0
- package/out/types/src/evaluator/types/dyn.d.ts +8 -0
- package/out/types/src/evaluator/types/enum.d.ts +8 -0
- package/out/types/src/evaluator/types/expr_synthesizer.d.ts +14 -0
- package/out/types/src/evaluator/types/field.d.ts +14 -0
- package/out/types/src/evaluator/types/fn_module.d.ts +8 -0
- package/out/types/src/evaluator/types/function.d.ts +58 -0
- package/out/types/src/evaluator/types/future_module.d.ts +8 -0
- package/out/types/src/evaluator/types/module.d.ts +19 -0
- package/out/types/src/evaluator/types/newtype.d.ts +8 -0
- package/out/types/src/evaluator/types/object.d.ts +8 -0
- package/out/types/src/evaluator/types/proofs.d.ts +0 -0
- package/out/types/src/evaluator/types/slice.d.ts +8 -0
- package/out/types/src/evaluator/types/struct.d.ts +8 -0
- package/out/types/src/evaluator/types/synthesizer.d.ts +16 -0
- package/out/types/src/evaluator/types/tuple.d.ts +18 -0
- package/out/types/src/evaluator/types/union.d.ts +8 -0
- package/out/types/src/evaluator/types/utils.d.ts +71 -0
- package/out/types/src/evaluator/types/validation.d.ts +3 -0
- package/out/types/src/evaluator/utils/array-utils.d.ts +15 -0
- package/out/types/src/evaluator/utils/closure.d.ts +35 -0
- package/out/types/src/evaluator/utils.d.ts +4 -0
- package/out/types/src/evaluator/values/anonymous_function.d.ts +8 -0
- package/out/types/src/evaluator/values/anonymous_module.d.ts +17 -0
- package/out/types/src/evaluator/values/anonymous_struct.d.ts +8 -0
- package/out/types/src/evaluator/values/array.d.ts +8 -0
- package/out/types/src/evaluator/values/boolean.d.ts +3 -0
- package/out/types/src/evaluator/values/char.d.ts +3 -0
- package/out/types/src/evaluator/values/compt_list.d.ts +8 -0
- package/out/types/src/evaluator/values/dyn.d.ts +8 -0
- package/out/types/src/evaluator/values/float.d.ts +4 -0
- package/out/types/src/evaluator/values/integer.d.ts +4 -0
- package/out/types/src/evaluator/values/module.d.ts +58 -0
- package/out/types/src/evaluator/values/string.d.ts +3 -0
- package/out/types/src/evaluator/values/tuple.d.ts +32 -0
- package/out/types/src/expr.d.ts +456 -0
- package/out/types/src/function-value.d.ts +42 -0
- package/out/types/src/index.d.ts +4 -0
- package/out/types/src/lexer.d.ts +2 -0
- package/out/types/src/logger.d.ts +1 -0
- package/out/types/src/module-manager.d.ts +30 -0
- package/out/types/src/naming-checker.d.ts +4 -0
- package/out/types/src/parser.d.ts +33 -0
- package/out/types/src/test-runner.d.ts +30 -0
- package/out/types/src/tests/codegen.test.d.ts +1 -0
- package/out/types/src/tests/fixme.test.d.ts +1 -0
- package/out/types/src/tests/module-manager.test.d.ts +1 -0
- package/out/types/src/tests/parser.test.d.ts +1 -0
- package/out/types/src/tests/sample.test.d.ts +0 -0
- package/out/types/src/tests/std.test.d.ts +1 -0
- package/out/types/src/token.d.ts +40 -0
- package/out/types/src/type-value.d.ts +7 -0
- package/out/types/src/types/compatibility.d.ts +16 -0
- package/out/types/src/types/creators.d.ts +73 -0
- package/out/types/src/types/definitions.d.ts +218 -0
- package/out/types/src/types/guards.d.ts +70 -0
- package/out/types/src/types/hierarchy.d.ts +4 -0
- package/out/types/src/types/index.d.ts +7 -0
- package/out/types/src/types/module_field.d.ts +2 -0
- package/out/types/src/types/tags.d.ts +45 -0
- package/out/types/src/types/utils.d.ts +50 -0
- package/out/types/src/unit-value.d.ts +7 -0
- package/out/types/src/utils.d.ts +6 -0
- package/out/types/src/value-tag.d.ts +29 -0
- package/out/types/src/value.d.ts +110 -0
- package/out/types/src/yo-cli.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -0
- package/package.json +57 -0
- package/scripts/check-liburing.js +76 -0
- package/std/alg/hash.yo +50 -0
- package/std/allocator.yo +113 -0
- package/std/allocators/c_allocator.yo +118 -0
- package/std/async.yo +13 -0
- package/std/collections/array_list.yo +415 -0
- package/std/collections/hash_map.yo +482 -0
- package/std/collections/hash_set.yo +706 -0
- package/std/collections/index.yo +11 -0
- package/std/collections/linked_list.yo +439 -0
- package/std/error.yo +0 -0
- package/std/gc.yo +10 -0
- package/std/index.yo +12 -0
- package/std/io/file.yo +191 -0
- package/std/io/index.yo +5 -0
- package/std/libc/assert.yo +39 -0
- package/std/libc/ctype.yo +57 -0
- package/std/libc/errno.yo +182 -0
- package/std/libc/float.yo +87 -0
- package/std/libc/index.yo +29 -0
- package/std/libc/limits.yo +65 -0
- package/std/libc/math.yo +679 -0
- package/std/libc/signal.yo +101 -0
- package/std/libc/stdatomic.yo +213 -0
- package/std/libc/stdint.yo +214 -0
- package/std/libc/stdio.yo +225 -0
- package/std/libc/stdlib.yo +204 -0
- package/std/libc/string.yo +151 -0
- package/std/libc/time.yo +92 -0
- package/std/libc/unistd.yo +130 -0
- package/std/monad.yo +152 -0
- package/std/prelude.yo +3094 -0
- package/std/string/index.yo +8 -0
- package/std/string/rune.yo +82 -0
- package/std/string/string.yo +288 -0
- package/std/sync.yo +95 -0
- package/std/thread.yo +36 -0
- package/std/time.yo +13 -0
- package/std/worker.yo +36 -0
- package/vendor/mimalloc/.gitattributes +12 -0
- package/vendor/mimalloc/CMakeLists.txt +763 -0
- package/vendor/mimalloc/LICENSE +21 -0
- package/vendor/mimalloc/SECURITY.md +41 -0
- package/vendor/mimalloc/azure-pipelines.yml +251 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64.lib +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect-arm64ec.lib +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect.lib +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect32.dll +0 -0
- package/vendor/mimalloc/bin/mimalloc-redirect32.lib +0 -0
- package/vendor/mimalloc/bin/minject-arm64.exe +0 -0
- package/vendor/mimalloc/bin/minject.exe +0 -0
- package/vendor/mimalloc/bin/minject32.exe +0 -0
- package/vendor/mimalloc/bin/readme.md +118 -0
- package/vendor/mimalloc/cmake/JoinPaths.cmake +23 -0
- package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +19 -0
- package/vendor/mimalloc/cmake/mimalloc-config.cmake +14 -0
- package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +23 -0
- package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +28 -0
- package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +28 -0
- package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +23 -0
- package/vendor/mimalloc/contrib/docker/readme.md +10 -0
- package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +64 -0
- package/vendor/mimalloc/contrib/vcpkg/readme.md +40 -0
- package/vendor/mimalloc/contrib/vcpkg/usage +20 -0
- package/vendor/mimalloc/contrib/vcpkg/vcpkg-cmake-wrapper.cmake +20 -0
- package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +48 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-a.svg +887 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-b.svg +1185 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-a.svg +757 -0
- package/vendor/mimalloc/doc/bench-2020/bench-c5-18xlarge-2020-01-20-rss-b.svg +1028 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-1.svg +769 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-a.svg +868 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-12xlarge-2020-01-16-b.svg +1157 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-2.svg +983 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-1.svg +683 -0
- package/vendor/mimalloc/doc/bench-2020/bench-r5a-rss-2.svg +854 -0
- package/vendor/mimalloc/doc/bench-2020/bench-spec-rss.svg +713 -0
- package/vendor/mimalloc/doc/bench-2020/bench-spec.svg +713 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-1.svg +890 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-2.svg +1146 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-1.svg +796 -0
- package/vendor/mimalloc/doc/bench-2020/bench-z4-rss-2.svg +974 -0
- package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-a.svg +952 -0
- package/vendor/mimalloc/doc/bench-2021/bench-amd5950x-2021-01-30-b.svg +1255 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-a.svg +955 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-b.svg +1269 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-a.svg +836 -0
- package/vendor/mimalloc/doc/bench-2021/bench-c5-18xlarge-2021-01-30-rss-b.svg +1131 -0
- package/vendor/mimalloc/doc/bench-2021/bench-macmini-2021-01-30.svg +766 -0
- package/vendor/mimalloc/doc/doxyfile +2895 -0
- package/vendor/mimalloc/doc/ds-logo.jpg +0 -0
- package/vendor/mimalloc/doc/ds-logo.png +0 -0
- package/vendor/mimalloc/doc/mimalloc-doc.h +1452 -0
- package/vendor/mimalloc/doc/mimalloc-doxygen.css +60 -0
- package/vendor/mimalloc/doc/mimalloc-logo-100.png +0 -0
- package/vendor/mimalloc/doc/mimalloc-logo.png +0 -0
- package/vendor/mimalloc/doc/mimalloc-logo.svg +161 -0
- package/vendor/mimalloc/doc/spades-logo.png +0 -0
- package/vendor/mimalloc/doc/unreal-logo.svg +43 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +500 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj.filters +108 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj +508 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-dll.vcxproj.filters +111 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-test-dep.vcxproj +355 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-test.vcxproj +360 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-api.vcxproj +295 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-stress.vcxproj +292 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test.vcxproj +289 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc.sln +151 -0
- package/vendor/mimalloc/include/mimalloc/atomic.h +557 -0
- package/vendor/mimalloc/include/mimalloc/internal.h +1153 -0
- package/vendor/mimalloc/include/mimalloc/prim.h +421 -0
- package/vendor/mimalloc/include/mimalloc/track.h +145 -0
- package/vendor/mimalloc/include/mimalloc/types.h +685 -0
- package/vendor/mimalloc/include/mimalloc-new-delete.h +66 -0
- package/vendor/mimalloc/include/mimalloc-override.h +68 -0
- package/vendor/mimalloc/include/mimalloc-stats.h +103 -0
- package/vendor/mimalloc/include/mimalloc.h +612 -0
- package/vendor/mimalloc/mimalloc.pc.in +11 -0
- package/vendor/mimalloc/readme.md +946 -0
- package/vendor/mimalloc/src/alloc-aligned.c +360 -0
- package/vendor/mimalloc/src/alloc-override.c +316 -0
- package/vendor/mimalloc/src/alloc-posix.c +185 -0
- package/vendor/mimalloc/src/alloc.c +692 -0
- package/vendor/mimalloc/src/arena-abandon.c +346 -0
- package/vendor/mimalloc/src/arena.c +1043 -0
- package/vendor/mimalloc/src/bitmap.c +441 -0
- package/vendor/mimalloc/src/bitmap.h +119 -0
- package/vendor/mimalloc/src/free.c +572 -0
- package/vendor/mimalloc/src/heap.c +733 -0
- package/vendor/mimalloc/src/init.c +714 -0
- package/vendor/mimalloc/src/libc.c +334 -0
- package/vendor/mimalloc/src/options.c +663 -0
- package/vendor/mimalloc/src/os.c +770 -0
- package/vendor/mimalloc/src/page-queue.c +390 -0
- package/vendor/mimalloc/src/page.c +1049 -0
- package/vendor/mimalloc/src/prim/emscripten/prim.c +249 -0
- package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +461 -0
- package/vendor/mimalloc/src/prim/osx/prim.c +9 -0
- package/vendor/mimalloc/src/prim/prim.c +76 -0
- package/vendor/mimalloc/src/prim/readme.md +9 -0
- package/vendor/mimalloc/src/prim/unix/prim.c +934 -0
- package/vendor/mimalloc/src/prim/wasi/prim.c +284 -0
- package/vendor/mimalloc/src/prim/windows/etw-mimalloc.wprp +61 -0
- package/vendor/mimalloc/src/prim/windows/etw.h +905 -0
- package/vendor/mimalloc/src/prim/windows/etw.man +0 -0
- package/vendor/mimalloc/src/prim/windows/prim.c +878 -0
- package/vendor/mimalloc/src/prim/windows/readme.md +17 -0
- package/vendor/mimalloc/src/random.c +258 -0
- package/vendor/mimalloc/src/segment-map.c +142 -0
- package/vendor/mimalloc/src/segment.c +1702 -0
- package/vendor/mimalloc/src/static.c +41 -0
- package/vendor/mimalloc/src/stats.c +635 -0
- package/vendor/mimalloc/test/CMakeLists.txt +56 -0
- package/vendor/mimalloc/test/main-override-dep.cpp +51 -0
- package/vendor/mimalloc/test/main-override-dep.h +11 -0
- package/vendor/mimalloc/test/main-override-static.c +539 -0
- package/vendor/mimalloc/test/main-override.c +36 -0
- package/vendor/mimalloc/test/main-override.cpp +497 -0
- package/vendor/mimalloc/test/main.c +46 -0
- package/vendor/mimalloc/test/readme.md +16 -0
- package/vendor/mimalloc/test/test-api-fill.c +343 -0
- package/vendor/mimalloc/test/test-api.c +466 -0
- package/vendor/mimalloc/test/test-stress.c +428 -0
- package/vendor/mimalloc/test/test-wrong.c +92 -0
- package/vendor/mimalloc/test/testhelper.h +49 -0
|
@@ -0,0 +1,663 @@
|
|
|
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
|
+
#include "mimalloc.h"
|
|
8
|
+
#include "mimalloc/internal.h"
|
|
9
|
+
#include "mimalloc/atomic.h"
|
|
10
|
+
#include "mimalloc/prim.h" // mi_prim_out_stderr
|
|
11
|
+
|
|
12
|
+
#include <stdio.h> // stdin/stdout
|
|
13
|
+
#include <stdlib.h> // abort
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
static long mi_max_error_count = 16; // stop outputting errors after this (use < 0 for no limit)
|
|
18
|
+
static long mi_max_warning_count = 16; // stop outputting warnings after this (use < 0 for no limit)
|
|
19
|
+
|
|
20
|
+
static void mi_add_stderr_output(void);
|
|
21
|
+
|
|
22
|
+
int mi_version(void) mi_attr_noexcept {
|
|
23
|
+
return MI_MALLOC_VERSION;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
// --------------------------------------------------------
|
|
28
|
+
// Options
|
|
29
|
+
// These can be accessed by multiple threads and may be
|
|
30
|
+
// concurrently initialized, but an initializing data race
|
|
31
|
+
// is ok since they resolve to the same value.
|
|
32
|
+
// --------------------------------------------------------
|
|
33
|
+
typedef enum mi_init_e {
|
|
34
|
+
UNINIT, // not yet initialized
|
|
35
|
+
DEFAULTED, // not found in the environment, use default value
|
|
36
|
+
INITIALIZED // found in environment or set explicitly
|
|
37
|
+
} mi_init_t;
|
|
38
|
+
|
|
39
|
+
typedef struct mi_option_desc_s {
|
|
40
|
+
long value; // the value
|
|
41
|
+
mi_init_t init; // is it initialized yet? (from the environment)
|
|
42
|
+
mi_option_t option; // for debugging: the option index should match the option
|
|
43
|
+
const char* name; // option name without `mimalloc_` prefix
|
|
44
|
+
const char* legacy_name; // potential legacy option name
|
|
45
|
+
} mi_option_desc_t;
|
|
46
|
+
|
|
47
|
+
#define MI_OPTION(opt) mi_option_##opt, #opt, NULL
|
|
48
|
+
#define MI_OPTION_LEGACY(opt,legacy) mi_option_##opt, #opt, #legacy
|
|
49
|
+
|
|
50
|
+
// Some options can be set at build time for statically linked libraries
|
|
51
|
+
// (use `-DMI_EXTRA_CPPDEFS="opt1=val1;opt2=val2"`)
|
|
52
|
+
//
|
|
53
|
+
// This is useful if we cannot pass them as environment variables
|
|
54
|
+
// (and setting them programmatically would be too late)
|
|
55
|
+
|
|
56
|
+
#ifndef MI_DEFAULT_VERBOSE
|
|
57
|
+
#define MI_DEFAULT_VERBOSE 0
|
|
58
|
+
#endif
|
|
59
|
+
|
|
60
|
+
#ifndef MI_DEFAULT_EAGER_COMMIT
|
|
61
|
+
#define MI_DEFAULT_EAGER_COMMIT 1
|
|
62
|
+
#endif
|
|
63
|
+
|
|
64
|
+
#ifndef MI_DEFAULT_ARENA_EAGER_COMMIT
|
|
65
|
+
#define MI_DEFAULT_ARENA_EAGER_COMMIT 2
|
|
66
|
+
#endif
|
|
67
|
+
|
|
68
|
+
// in KiB
|
|
69
|
+
#ifndef MI_DEFAULT_ARENA_RESERVE
|
|
70
|
+
#if (MI_INTPTR_SIZE>4)
|
|
71
|
+
#define MI_DEFAULT_ARENA_RESERVE 1024L*1024L
|
|
72
|
+
#else
|
|
73
|
+
#define MI_DEFAULT_ARENA_RESERVE 128L*1024L
|
|
74
|
+
#endif
|
|
75
|
+
#endif
|
|
76
|
+
|
|
77
|
+
#ifndef MI_DEFAULT_DISALLOW_ARENA_ALLOC
|
|
78
|
+
#define MI_DEFAULT_DISALLOW_ARENA_ALLOC 0
|
|
79
|
+
#endif
|
|
80
|
+
|
|
81
|
+
#ifndef MI_DEFAULT_ALLOW_LARGE_OS_PAGES
|
|
82
|
+
#if defined(__linux__) && !defined(__ANDROID__)
|
|
83
|
+
#define MI_DEFAULT_ALLOW_LARGE_OS_PAGES 2 // enabled, but only use transparent huge pages through madvise
|
|
84
|
+
#else
|
|
85
|
+
#define MI_DEFAULT_ALLOW_LARGE_OS_PAGES 0
|
|
86
|
+
#endif
|
|
87
|
+
#endif
|
|
88
|
+
|
|
89
|
+
#ifndef MI_DEFAULT_RESERVE_HUGE_OS_PAGES
|
|
90
|
+
#define MI_DEFAULT_RESERVE_HUGE_OS_PAGES 0
|
|
91
|
+
#endif
|
|
92
|
+
|
|
93
|
+
#ifndef MI_DEFAULT_RESERVE_OS_MEMORY
|
|
94
|
+
#define MI_DEFAULT_RESERVE_OS_MEMORY 0
|
|
95
|
+
#endif
|
|
96
|
+
|
|
97
|
+
#ifndef MI_DEFAULT_GUARDED_SAMPLE_RATE
|
|
98
|
+
#if MI_GUARDED
|
|
99
|
+
#define MI_DEFAULT_GUARDED_SAMPLE_RATE 4000
|
|
100
|
+
#else
|
|
101
|
+
#define MI_DEFAULT_GUARDED_SAMPLE_RATE 0
|
|
102
|
+
#endif
|
|
103
|
+
#endif
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
static mi_option_desc_t options[_mi_option_last] =
|
|
107
|
+
{
|
|
108
|
+
// stable options
|
|
109
|
+
#if MI_DEBUG || defined(MI_SHOW_ERRORS)
|
|
110
|
+
{ 1, UNINIT, MI_OPTION(show_errors) },
|
|
111
|
+
#else
|
|
112
|
+
{ 0, UNINIT, MI_OPTION(show_errors) },
|
|
113
|
+
#endif
|
|
114
|
+
{ 0, UNINIT, MI_OPTION(show_stats) },
|
|
115
|
+
{ MI_DEFAULT_VERBOSE, UNINIT, MI_OPTION(verbose) },
|
|
116
|
+
|
|
117
|
+
// some of the following options are experimental and not all combinations are allowed.
|
|
118
|
+
{ MI_DEFAULT_EAGER_COMMIT,
|
|
119
|
+
UNINIT, MI_OPTION(eager_commit) }, // commit per segment directly (4MiB) (but see also `eager_commit_delay`)
|
|
120
|
+
{ MI_DEFAULT_ARENA_EAGER_COMMIT,
|
|
121
|
+
UNINIT, MI_OPTION_LEGACY(arena_eager_commit,eager_region_commit) }, // eager commit arena's? 2 is used to enable this only on an OS that has overcommit (i.e. linux)
|
|
122
|
+
{ 1, UNINIT, MI_OPTION_LEGACY(purge_decommits,reset_decommits) }, // purge decommits memory (instead of reset) (note: on linux this uses MADV_DONTNEED for decommit)
|
|
123
|
+
{ MI_DEFAULT_ALLOW_LARGE_OS_PAGES,
|
|
124
|
+
UNINIT, MI_OPTION_LEGACY(allow_large_os_pages,large_os_pages) }, // use large OS pages, use only with eager commit to prevent fragmentation of VMA's
|
|
125
|
+
{ MI_DEFAULT_RESERVE_HUGE_OS_PAGES,
|
|
126
|
+
UNINIT, MI_OPTION(reserve_huge_os_pages) }, // per 1GiB huge pages
|
|
127
|
+
{-1, UNINIT, MI_OPTION(reserve_huge_os_pages_at) }, // reserve huge pages at node N
|
|
128
|
+
{ MI_DEFAULT_RESERVE_OS_MEMORY,
|
|
129
|
+
UNINIT, MI_OPTION(reserve_os_memory) }, // reserve N KiB OS memory in advance (use `option_get_size`)
|
|
130
|
+
{ 0, UNINIT, MI_OPTION(deprecated_segment_cache) }, // cache N segments per thread
|
|
131
|
+
{ 0, UNINIT, MI_OPTION(deprecated_page_reset) }, // reset page memory on free
|
|
132
|
+
{ 0, UNINIT, MI_OPTION_LEGACY(abandoned_page_purge,abandoned_page_reset) }, // reset free page memory when a thread terminates
|
|
133
|
+
{ 0, UNINIT, MI_OPTION(deprecated_segment_reset) }, // reset segment memory on free (needs eager commit)
|
|
134
|
+
#if defined(__NetBSD__)
|
|
135
|
+
{ 0, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed
|
|
136
|
+
#else
|
|
137
|
+
{ 1, UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed (but per page in the segment on demand)
|
|
138
|
+
#endif
|
|
139
|
+
{ 10, UNINIT, MI_OPTION_LEGACY(purge_delay,reset_delay) }, // purge delay in milli-seconds
|
|
140
|
+
{ 0, UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes.
|
|
141
|
+
{ 0, UNINIT, MI_OPTION_LEGACY(disallow_os_alloc,limit_os_alloc) }, // 1 = do not use OS memory for allocation (but only reserved arenas)
|
|
142
|
+
{ 100, UNINIT, MI_OPTION(os_tag) }, // only apple specific for now but might serve more or less related purpose
|
|
143
|
+
{ 32, UNINIT, MI_OPTION(max_errors) }, // maximum errors that are output
|
|
144
|
+
{ 32, UNINIT, MI_OPTION(max_warnings) }, // maximum warnings that are output
|
|
145
|
+
{ 10, UNINIT, MI_OPTION(max_segment_reclaim)}, // max. percentage of the abandoned segments to be reclaimed per try.
|
|
146
|
+
{ 0, UNINIT, MI_OPTION(destroy_on_exit)}, // release all OS memory on process exit; careful with dangling pointer or after-exit frees!
|
|
147
|
+
{ MI_DEFAULT_ARENA_RESERVE, UNINIT, MI_OPTION(arena_reserve) }, // reserve memory N KiB at a time (=1GiB) (use `option_get_size`)
|
|
148
|
+
{ 10, UNINIT, MI_OPTION(arena_purge_mult) }, // purge delay multiplier for arena's
|
|
149
|
+
{ 1, UNINIT, MI_OPTION_LEGACY(purge_extend_delay, decommit_extend_delay) },
|
|
150
|
+
{ 0, UNINIT, MI_OPTION(abandoned_reclaim_on_free) },// reclaim an abandoned segment on a free
|
|
151
|
+
{ MI_DEFAULT_DISALLOW_ARENA_ALLOC, UNINIT, MI_OPTION(disallow_arena_alloc) }, // 1 = do not use arena's for allocation (except if using specific arena id's)
|
|
152
|
+
{ 400, UNINIT, MI_OPTION(retry_on_oom) }, // windows only: retry on out-of-memory for N milli seconds (=400), set to 0 to disable retries.
|
|
153
|
+
#if defined(MI_VISIT_ABANDONED)
|
|
154
|
+
{ 1, INITIALIZED, MI_OPTION(visit_abandoned) }, // allow visiting heap blocks in abandoned segments; requires taking locks during reclaim.
|
|
155
|
+
#else
|
|
156
|
+
{ 0, UNINIT, MI_OPTION(visit_abandoned) },
|
|
157
|
+
#endif
|
|
158
|
+
{ 0, UNINIT, MI_OPTION(guarded_min) }, // only used when building with MI_GUARDED: minimal rounded object size for guarded objects
|
|
159
|
+
{ MI_GiB, UNINIT, MI_OPTION(guarded_max) }, // only used when building with MI_GUARDED: maximal rounded object size for guarded objects
|
|
160
|
+
{ 0, UNINIT, MI_OPTION(guarded_precise) }, // disregard minimal alignment requirement to always place guarded blocks exactly in front of a guard page (=0)
|
|
161
|
+
{ MI_DEFAULT_GUARDED_SAMPLE_RATE,
|
|
162
|
+
UNINIT, MI_OPTION(guarded_sample_rate)}, // 1 out of N allocations in the min/max range will be guarded (=4000)
|
|
163
|
+
{ 0, UNINIT, MI_OPTION(guarded_sample_seed)},
|
|
164
|
+
{ 0, UNINIT, MI_OPTION(target_segments_per_thread) }, // abandon segments beyond this point, or 0 to disable.
|
|
165
|
+
{ 10000, UNINIT, MI_OPTION(generic_collect) }, // collect heaps every N (=10000) generic allocation calls
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
static void mi_option_init(mi_option_desc_t* desc);
|
|
169
|
+
|
|
170
|
+
static bool mi_option_has_size_in_kib(mi_option_t option) {
|
|
171
|
+
return (option == mi_option_reserve_os_memory || option == mi_option_arena_reserve);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
void _mi_options_init(void) {
|
|
175
|
+
// called on process load
|
|
176
|
+
mi_add_stderr_output(); // now it safe to use stderr for output
|
|
177
|
+
for(int i = 0; i < _mi_option_last; i++ ) {
|
|
178
|
+
mi_option_t option = (mi_option_t)i;
|
|
179
|
+
long l = mi_option_get(option); MI_UNUSED(l); // initialize
|
|
180
|
+
}
|
|
181
|
+
mi_max_error_count = mi_option_get(mi_option_max_errors);
|
|
182
|
+
mi_max_warning_count = mi_option_get(mi_option_max_warnings);
|
|
183
|
+
#if MI_GUARDED
|
|
184
|
+
if (mi_option_get(mi_option_guarded_sample_rate) > 0) {
|
|
185
|
+
if (mi_option_is_enabled(mi_option_allow_large_os_pages)) {
|
|
186
|
+
mi_option_disable(mi_option_allow_large_os_pages);
|
|
187
|
+
_mi_warning_message("option 'allow_large_os_pages' is disabled to allow for guarded objects\n");
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
#endif
|
|
191
|
+
if (mi_option_is_enabled(mi_option_verbose)) { mi_options_print(); }
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
#define mi_stringifyx(str) #str // and stringify
|
|
195
|
+
#define mi_stringify(str) mi_stringifyx(str) // expand
|
|
196
|
+
|
|
197
|
+
void mi_options_print(void) mi_attr_noexcept
|
|
198
|
+
{
|
|
199
|
+
// show version
|
|
200
|
+
const int vermajor = MI_MALLOC_VERSION/100;
|
|
201
|
+
const int verminor = (MI_MALLOC_VERSION%100)/10;
|
|
202
|
+
const int verpatch = (MI_MALLOC_VERSION%10);
|
|
203
|
+
_mi_message("v%i.%i.%i%s%s (built on %s, %s)\n", vermajor, verminor, verpatch,
|
|
204
|
+
#if defined(MI_CMAKE_BUILD_TYPE)
|
|
205
|
+
", " mi_stringify(MI_CMAKE_BUILD_TYPE)
|
|
206
|
+
#else
|
|
207
|
+
""
|
|
208
|
+
#endif
|
|
209
|
+
,
|
|
210
|
+
#if defined(MI_GIT_DESCRIBE)
|
|
211
|
+
", git " mi_stringify(MI_GIT_DESCRIBE)
|
|
212
|
+
#else
|
|
213
|
+
""
|
|
214
|
+
#endif
|
|
215
|
+
, __DATE__, __TIME__);
|
|
216
|
+
|
|
217
|
+
// show options
|
|
218
|
+
for (int i = 0; i < _mi_option_last; i++) {
|
|
219
|
+
mi_option_t option = (mi_option_t)i;
|
|
220
|
+
long l = mi_option_get(option); MI_UNUSED(l); // possibly initialize
|
|
221
|
+
mi_option_desc_t* desc = &options[option];
|
|
222
|
+
_mi_message("option '%s': %ld %s\n", desc->name, desc->value, (mi_option_has_size_in_kib(option) ? "KiB" : ""));
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// show build configuration
|
|
226
|
+
_mi_message("debug level : %d\n", MI_DEBUG );
|
|
227
|
+
_mi_message("secure level: %d\n", MI_SECURE );
|
|
228
|
+
_mi_message("mem tracking: %s\n", MI_TRACK_TOOL);
|
|
229
|
+
#if MI_GUARDED
|
|
230
|
+
_mi_message("guarded build: %s\n", mi_option_get(mi_option_guarded_sample_rate) != 0 ? "enabled" : "disabled");
|
|
231
|
+
#endif
|
|
232
|
+
#if MI_TSAN
|
|
233
|
+
_mi_message("thread santizer enabled\n");
|
|
234
|
+
#endif
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
long _mi_option_get_fast(mi_option_t option) {
|
|
238
|
+
mi_assert(option >= 0 && option < _mi_option_last);
|
|
239
|
+
mi_option_desc_t* desc = &options[option];
|
|
240
|
+
mi_assert(desc->option == option); // index should match the option
|
|
241
|
+
//mi_assert(desc->init != UNINIT);
|
|
242
|
+
return desc->value;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
mi_decl_nodiscard long mi_option_get(mi_option_t option) {
|
|
247
|
+
mi_assert(option >= 0 && option < _mi_option_last);
|
|
248
|
+
if (option < 0 || option >= _mi_option_last) return 0;
|
|
249
|
+
mi_option_desc_t* desc = &options[option];
|
|
250
|
+
mi_assert(desc->option == option); // index should match the option
|
|
251
|
+
if mi_unlikely(desc->init == UNINIT) {
|
|
252
|
+
mi_option_init(desc);
|
|
253
|
+
}
|
|
254
|
+
return desc->value;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
mi_decl_nodiscard long mi_option_get_clamp(mi_option_t option, long min, long max) {
|
|
258
|
+
long x = mi_option_get(option);
|
|
259
|
+
return (x < min ? min : (x > max ? max : x));
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
mi_decl_nodiscard size_t mi_option_get_size(mi_option_t option) {
|
|
263
|
+
const long x = mi_option_get(option);
|
|
264
|
+
size_t size = (x < 0 ? 0 : (size_t)x);
|
|
265
|
+
if (mi_option_has_size_in_kib(option)) {
|
|
266
|
+
size *= MI_KiB;
|
|
267
|
+
}
|
|
268
|
+
return size;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
void mi_option_set(mi_option_t option, long value) {
|
|
272
|
+
mi_assert(option >= 0 && option < _mi_option_last);
|
|
273
|
+
if (option < 0 || option >= _mi_option_last) return;
|
|
274
|
+
mi_option_desc_t* desc = &options[option];
|
|
275
|
+
mi_assert(desc->option == option); // index should match the option
|
|
276
|
+
desc->value = value;
|
|
277
|
+
desc->init = INITIALIZED;
|
|
278
|
+
// ensure min/max range; be careful to not recurse.
|
|
279
|
+
if (desc->option == mi_option_guarded_min && _mi_option_get_fast(mi_option_guarded_max) < value) {
|
|
280
|
+
mi_option_set(mi_option_guarded_max, value);
|
|
281
|
+
}
|
|
282
|
+
else if (desc->option == mi_option_guarded_max && _mi_option_get_fast(mi_option_guarded_min) > value) {
|
|
283
|
+
mi_option_set(mi_option_guarded_min, value);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
void mi_option_set_default(mi_option_t option, long value) {
|
|
288
|
+
mi_assert(option >= 0 && option < _mi_option_last);
|
|
289
|
+
if (option < 0 || option >= _mi_option_last) return;
|
|
290
|
+
mi_option_desc_t* desc = &options[option];
|
|
291
|
+
if (desc->init != INITIALIZED) {
|
|
292
|
+
desc->value = value;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
mi_decl_nodiscard bool mi_option_is_enabled(mi_option_t option) {
|
|
297
|
+
return (mi_option_get(option) != 0);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
void mi_option_set_enabled(mi_option_t option, bool enable) {
|
|
301
|
+
mi_option_set(option, (enable ? 1 : 0));
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
void mi_option_set_enabled_default(mi_option_t option, bool enable) {
|
|
305
|
+
mi_option_set_default(option, (enable ? 1 : 0));
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
void mi_option_enable(mi_option_t option) {
|
|
309
|
+
mi_option_set_enabled(option,true);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
void mi_option_disable(mi_option_t option) {
|
|
313
|
+
mi_option_set_enabled(option,false);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
static void mi_cdecl mi_out_stderr(const char* msg, void* arg) {
|
|
317
|
+
MI_UNUSED(arg);
|
|
318
|
+
if (msg != NULL && msg[0] != 0) {
|
|
319
|
+
_mi_prim_out_stderr(msg);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Since an output function can be registered earliest in the `main`
|
|
324
|
+
// function we also buffer output that happens earlier. When
|
|
325
|
+
// an output function is registered it is called immediately with
|
|
326
|
+
// the output up to that point.
|
|
327
|
+
#ifndef MI_MAX_DELAY_OUTPUT
|
|
328
|
+
#define MI_MAX_DELAY_OUTPUT ((size_t)(16*1024))
|
|
329
|
+
#endif
|
|
330
|
+
static char out_buf[MI_MAX_DELAY_OUTPUT+1];
|
|
331
|
+
static _Atomic(size_t) out_len;
|
|
332
|
+
|
|
333
|
+
static void mi_cdecl mi_out_buf(const char* msg, void* arg) {
|
|
334
|
+
MI_UNUSED(arg);
|
|
335
|
+
if (msg==NULL) return;
|
|
336
|
+
if (mi_atomic_load_relaxed(&out_len)>=MI_MAX_DELAY_OUTPUT) return;
|
|
337
|
+
size_t n = _mi_strlen(msg);
|
|
338
|
+
if (n==0) return;
|
|
339
|
+
// claim space
|
|
340
|
+
size_t start = mi_atomic_add_acq_rel(&out_len, n);
|
|
341
|
+
if (start >= MI_MAX_DELAY_OUTPUT) return;
|
|
342
|
+
// check bound
|
|
343
|
+
if (start+n >= MI_MAX_DELAY_OUTPUT) {
|
|
344
|
+
n = MI_MAX_DELAY_OUTPUT-start-1;
|
|
345
|
+
}
|
|
346
|
+
_mi_memcpy(&out_buf[start], msg, n);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) {
|
|
350
|
+
if (out==NULL) return;
|
|
351
|
+
// claim (if `no_more_buf == true`, no more output will be added after this point)
|
|
352
|
+
size_t count = mi_atomic_add_acq_rel(&out_len, (no_more_buf ? MI_MAX_DELAY_OUTPUT : 1));
|
|
353
|
+
// and output the current contents
|
|
354
|
+
if (count>MI_MAX_DELAY_OUTPUT) count = MI_MAX_DELAY_OUTPUT;
|
|
355
|
+
out_buf[count] = 0;
|
|
356
|
+
out(out_buf,arg);
|
|
357
|
+
if (!no_more_buf) {
|
|
358
|
+
out_buf[count] = '\n'; // if continue with the buffer, insert a newline
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
// Once this module is loaded, switch to this routine
|
|
364
|
+
// which outputs to stderr and the delayed output buffer.
|
|
365
|
+
static void mi_cdecl mi_out_buf_stderr(const char* msg, void* arg) {
|
|
366
|
+
mi_out_stderr(msg,arg);
|
|
367
|
+
mi_out_buf(msg,arg);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
// --------------------------------------------------------
|
|
373
|
+
// Default output handler
|
|
374
|
+
// --------------------------------------------------------
|
|
375
|
+
|
|
376
|
+
// Should be atomic but gives errors on many platforms as generally we cannot cast a function pointer to a uintptr_t.
|
|
377
|
+
// For now, don't register output from multiple threads.
|
|
378
|
+
static mi_output_fun* volatile mi_out_default; // = NULL
|
|
379
|
+
static _Atomic(void*) mi_out_arg; // = NULL
|
|
380
|
+
|
|
381
|
+
static mi_output_fun* mi_out_get_default(void** parg) {
|
|
382
|
+
if (parg != NULL) { *parg = mi_atomic_load_ptr_acquire(void,&mi_out_arg); }
|
|
383
|
+
mi_output_fun* out = mi_out_default;
|
|
384
|
+
return (out == NULL ? &mi_out_buf : out);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept {
|
|
388
|
+
mi_out_default = (out == NULL ? &mi_out_stderr : out); // stop using the delayed output buffer
|
|
389
|
+
mi_atomic_store_ptr_release(void,&mi_out_arg, arg);
|
|
390
|
+
if (out!=NULL) mi_out_buf_flush(out,true,arg); // output all the delayed output now
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// add stderr to the delayed output after the module is loaded
|
|
394
|
+
static void mi_add_stderr_output(void) {
|
|
395
|
+
mi_assert_internal(mi_out_default == NULL);
|
|
396
|
+
mi_out_buf_flush(&mi_out_stderr, false, NULL); // flush current contents to stderr
|
|
397
|
+
mi_out_default = &mi_out_buf_stderr; // and add stderr to the delayed output
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// --------------------------------------------------------
|
|
401
|
+
// Messages, all end up calling `_mi_fputs`.
|
|
402
|
+
// --------------------------------------------------------
|
|
403
|
+
static _Atomic(size_t) error_count; // = 0; // when >= max_error_count stop emitting errors
|
|
404
|
+
static _Atomic(size_t) warning_count; // = 0; // when >= max_warning_count stop emitting warnings
|
|
405
|
+
|
|
406
|
+
// When overriding malloc, we may recurse into mi_vfprintf if an allocation
|
|
407
|
+
// inside the C runtime causes another message.
|
|
408
|
+
// In some cases (like on macOS) the loader already allocates which
|
|
409
|
+
// calls into mimalloc; if we then access thread locals (like `recurse`)
|
|
410
|
+
// this may crash as the access may call _tlv_bootstrap that tries to
|
|
411
|
+
// (recursively) invoke malloc again to allocate space for the thread local
|
|
412
|
+
// variables on demand. This is why we use a _mi_preloading test on such
|
|
413
|
+
// platforms. However, C code generator may move the initial thread local address
|
|
414
|
+
// load before the `if` and we therefore split it out in a separate function.
|
|
415
|
+
static mi_decl_thread bool recurse = false;
|
|
416
|
+
|
|
417
|
+
static mi_decl_noinline bool mi_recurse_enter_prim(void) {
|
|
418
|
+
if (recurse) return false;
|
|
419
|
+
recurse = true;
|
|
420
|
+
return true;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
static mi_decl_noinline void mi_recurse_exit_prim(void) {
|
|
424
|
+
recurse = false;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
static bool mi_recurse_enter(void) {
|
|
428
|
+
#if defined(__APPLE__) || defined(__ANDROID__) || defined(MI_TLS_RECURSE_GUARD)
|
|
429
|
+
if (_mi_preloading()) return false;
|
|
430
|
+
#endif
|
|
431
|
+
return mi_recurse_enter_prim();
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
static void mi_recurse_exit(void) {
|
|
435
|
+
#if defined(__APPLE__) || defined(__ANDROID__) || defined(MI_TLS_RECURSE_GUARD)
|
|
436
|
+
if (_mi_preloading()) return;
|
|
437
|
+
#endif
|
|
438
|
+
mi_recurse_exit_prim();
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
void _mi_fputs(mi_output_fun* out, void* arg, const char* prefix, const char* message) {
|
|
442
|
+
if (out==NULL || (void*)out==(void*)stdout || (void*)out==(void*)stderr) { // TODO: use mi_out_stderr for stderr?
|
|
443
|
+
if (!mi_recurse_enter()) return;
|
|
444
|
+
out = mi_out_get_default(&arg);
|
|
445
|
+
if (prefix != NULL) out(prefix, arg);
|
|
446
|
+
out(message, arg);
|
|
447
|
+
mi_recurse_exit();
|
|
448
|
+
}
|
|
449
|
+
else {
|
|
450
|
+
if (prefix != NULL) out(prefix, arg);
|
|
451
|
+
out(message, arg);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
// Define our own limited `fprintf` that avoids memory allocation.
|
|
456
|
+
// We do this using `_mi_vsnprintf` with a limited buffer.
|
|
457
|
+
static void mi_vfprintf( mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args ) {
|
|
458
|
+
char buf[512];
|
|
459
|
+
if (fmt==NULL) return;
|
|
460
|
+
if (!mi_recurse_enter()) return;
|
|
461
|
+
_mi_vsnprintf(buf, sizeof(buf)-1, fmt, args);
|
|
462
|
+
mi_recurse_exit();
|
|
463
|
+
_mi_fputs(out,arg,prefix,buf);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
void _mi_fprintf( mi_output_fun* out, void* arg, const char* fmt, ... ) {
|
|
467
|
+
va_list args;
|
|
468
|
+
va_start(args,fmt);
|
|
469
|
+
mi_vfprintf(out,arg,NULL,fmt,args);
|
|
470
|
+
va_end(args);
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
static void mi_vfprintf_thread(mi_output_fun* out, void* arg, const char* prefix, const char* fmt, va_list args) {
|
|
474
|
+
if (prefix != NULL && _mi_strnlen(prefix,33) <= 32 && !_mi_is_main_thread()) {
|
|
475
|
+
char tprefix[64];
|
|
476
|
+
_mi_snprintf(tprefix, sizeof(tprefix), "%sthread 0x%tx: ", prefix, (uintptr_t)_mi_thread_id());
|
|
477
|
+
mi_vfprintf(out, arg, tprefix, fmt, args);
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
mi_vfprintf(out, arg, prefix, fmt, args);
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
void _mi_message(const char* fmt, ...) {
|
|
485
|
+
va_list args;
|
|
486
|
+
va_start(args, fmt);
|
|
487
|
+
mi_vfprintf_thread(NULL, NULL, "mimalloc: ", fmt, args);
|
|
488
|
+
va_end(args);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
void _mi_trace_message(const char* fmt, ...) {
|
|
492
|
+
if (mi_option_get(mi_option_verbose) <= 1) return; // only with verbose level 2 or higher
|
|
493
|
+
va_list args;
|
|
494
|
+
va_start(args, fmt);
|
|
495
|
+
mi_vfprintf_thread(NULL, NULL, "mimalloc: ", fmt, args);
|
|
496
|
+
va_end(args);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
void _mi_verbose_message(const char* fmt, ...) {
|
|
500
|
+
if (!mi_option_is_enabled(mi_option_verbose)) return;
|
|
501
|
+
va_list args;
|
|
502
|
+
va_start(args,fmt);
|
|
503
|
+
mi_vfprintf(NULL, NULL, "mimalloc: ", fmt, args);
|
|
504
|
+
va_end(args);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
static void mi_show_error_message(const char* fmt, va_list args) {
|
|
508
|
+
if (!mi_option_is_enabled(mi_option_verbose)) {
|
|
509
|
+
if (!mi_option_is_enabled(mi_option_show_errors)) return;
|
|
510
|
+
if (mi_max_error_count >= 0 && (long)mi_atomic_increment_acq_rel(&error_count) > mi_max_error_count) return;
|
|
511
|
+
}
|
|
512
|
+
mi_vfprintf_thread(NULL, NULL, "mimalloc: error: ", fmt, args);
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
void _mi_warning_message(const char* fmt, ...) {
|
|
516
|
+
if (!mi_option_is_enabled(mi_option_verbose)) {
|
|
517
|
+
if (!mi_option_is_enabled(mi_option_show_errors)) return;
|
|
518
|
+
if (mi_max_warning_count >= 0 && (long)mi_atomic_increment_acq_rel(&warning_count) > mi_max_warning_count) return;
|
|
519
|
+
}
|
|
520
|
+
va_list args;
|
|
521
|
+
va_start(args,fmt);
|
|
522
|
+
mi_vfprintf_thread(NULL, NULL, "mimalloc: warning: ", fmt, args);
|
|
523
|
+
va_end(args);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
#if MI_DEBUG
|
|
528
|
+
mi_decl_noreturn mi_decl_cold void _mi_assert_fail(const char* assertion, const char* fname, unsigned line, const char* func ) mi_attr_noexcept {
|
|
529
|
+
_mi_fprintf(NULL, NULL, "mimalloc: assertion failed: at \"%s\":%u, %s\n assertion: \"%s\"\n", fname, line, (func==NULL?"":func), assertion);
|
|
530
|
+
abort();
|
|
531
|
+
}
|
|
532
|
+
#endif
|
|
533
|
+
|
|
534
|
+
// --------------------------------------------------------
|
|
535
|
+
// Errors
|
|
536
|
+
// --------------------------------------------------------
|
|
537
|
+
|
|
538
|
+
static mi_error_fun* volatile mi_error_handler; // = NULL
|
|
539
|
+
static _Atomic(void*) mi_error_arg; // = NULL
|
|
540
|
+
|
|
541
|
+
static void mi_error_default(int err) {
|
|
542
|
+
MI_UNUSED(err);
|
|
543
|
+
#if (MI_DEBUG>0)
|
|
544
|
+
if (err==EFAULT) {
|
|
545
|
+
#ifdef _MSC_VER
|
|
546
|
+
__debugbreak();
|
|
547
|
+
#endif
|
|
548
|
+
abort();
|
|
549
|
+
}
|
|
550
|
+
#endif
|
|
551
|
+
#if (MI_SECURE>0)
|
|
552
|
+
if (err==EFAULT) { // abort on serious errors in secure mode (corrupted meta-data)
|
|
553
|
+
abort();
|
|
554
|
+
}
|
|
555
|
+
#endif
|
|
556
|
+
#if defined(MI_XMALLOC)
|
|
557
|
+
if (err==ENOMEM || err==EOVERFLOW) { // abort on memory allocation fails in xmalloc mode
|
|
558
|
+
abort();
|
|
559
|
+
}
|
|
560
|
+
#endif
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
void mi_register_error(mi_error_fun* fun, void* arg) {
|
|
564
|
+
mi_error_handler = fun; // can be NULL
|
|
565
|
+
mi_atomic_store_ptr_release(void,&mi_error_arg, arg);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
void _mi_error_message(int err, const char* fmt, ...) {
|
|
569
|
+
// show detailed error message
|
|
570
|
+
va_list args;
|
|
571
|
+
va_start(args, fmt);
|
|
572
|
+
mi_show_error_message(fmt, args);
|
|
573
|
+
va_end(args);
|
|
574
|
+
// and call the error handler which may abort (or return normally)
|
|
575
|
+
if (mi_error_handler != NULL) {
|
|
576
|
+
mi_error_handler(err, mi_atomic_load_ptr_acquire(void,&mi_error_arg));
|
|
577
|
+
}
|
|
578
|
+
else {
|
|
579
|
+
mi_error_default(err);
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// --------------------------------------------------------
|
|
584
|
+
// Initialize options by checking the environment
|
|
585
|
+
// --------------------------------------------------------
|
|
586
|
+
|
|
587
|
+
// TODO: implement ourselves to reduce dependencies on the C runtime
|
|
588
|
+
#include <stdlib.h> // strtol
|
|
589
|
+
#include <string.h> // strstr
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
static void mi_option_init(mi_option_desc_t* desc) {
|
|
593
|
+
// Read option value from the environment
|
|
594
|
+
char s[64 + 1];
|
|
595
|
+
char buf[64+1];
|
|
596
|
+
_mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
|
597
|
+
_mi_strlcat(buf, desc->name, sizeof(buf));
|
|
598
|
+
bool found = _mi_getenv(buf, s, sizeof(s));
|
|
599
|
+
if (!found && desc->legacy_name != NULL) {
|
|
600
|
+
_mi_strlcpy(buf, "mimalloc_", sizeof(buf));
|
|
601
|
+
_mi_strlcat(buf, desc->legacy_name, sizeof(buf));
|
|
602
|
+
found = _mi_getenv(buf, s, sizeof(s));
|
|
603
|
+
if (found) {
|
|
604
|
+
_mi_warning_message("environment option \"mimalloc_%s\" is deprecated -- use \"mimalloc_%s\" instead.\n", desc->legacy_name, desc->name);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
if (found) {
|
|
609
|
+
size_t len = _mi_strnlen(s, sizeof(buf) - 1);
|
|
610
|
+
for (size_t i = 0; i < len; i++) {
|
|
611
|
+
buf[i] = _mi_toupper(s[i]);
|
|
612
|
+
}
|
|
613
|
+
buf[len] = 0;
|
|
614
|
+
if (buf[0] == 0 || strstr("1;TRUE;YES;ON", buf) != NULL) {
|
|
615
|
+
desc->value = 1;
|
|
616
|
+
desc->init = INITIALIZED;
|
|
617
|
+
}
|
|
618
|
+
else if (strstr("0;FALSE;NO;OFF", buf) != NULL) {
|
|
619
|
+
desc->value = 0;
|
|
620
|
+
desc->init = INITIALIZED;
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
char* end = buf;
|
|
624
|
+
long value = strtol(buf, &end, 10);
|
|
625
|
+
if (mi_option_has_size_in_kib(desc->option)) {
|
|
626
|
+
// this option is interpreted in KiB to prevent overflow of `long` for large allocations
|
|
627
|
+
// (long is 32-bit on 64-bit windows, which allows for 4TiB max.)
|
|
628
|
+
size_t size = (value < 0 ? 0 : (size_t)value);
|
|
629
|
+
bool overflow = false;
|
|
630
|
+
if (*end == 'K') { end++; }
|
|
631
|
+
else if (*end == 'M') { overflow = mi_mul_overflow(size,MI_KiB,&size); end++; }
|
|
632
|
+
else if (*end == 'G') { overflow = mi_mul_overflow(size,MI_MiB,&size); end++; }
|
|
633
|
+
else if (*end == 'T') { overflow = mi_mul_overflow(size,MI_GiB,&size); end++; }
|
|
634
|
+
else { size = (size + MI_KiB - 1) / MI_KiB; }
|
|
635
|
+
if (end[0] == 'I' && end[1] == 'B') { end += 2; } // KiB, MiB, GiB, TiB
|
|
636
|
+
else if (*end == 'B') { end++; } // Kb, Mb, Gb, Tb
|
|
637
|
+
if (overflow || size > MI_MAX_ALLOC_SIZE) { size = (MI_MAX_ALLOC_SIZE / MI_KiB); }
|
|
638
|
+
value = (size > LONG_MAX ? LONG_MAX : (long)size);
|
|
639
|
+
}
|
|
640
|
+
if (*end == 0) {
|
|
641
|
+
mi_option_set(desc->option, value);
|
|
642
|
+
}
|
|
643
|
+
else {
|
|
644
|
+
// set `init` first to avoid recursion through _mi_warning_message on mimalloc_verbose.
|
|
645
|
+
desc->init = DEFAULTED;
|
|
646
|
+
if (desc->option == mi_option_verbose && desc->value == 0) {
|
|
647
|
+
// if the 'mimalloc_verbose' env var has a bogus value we'd never know
|
|
648
|
+
// (since the value defaults to 'off') so in that case briefly enable verbose
|
|
649
|
+
desc->value = 1;
|
|
650
|
+
_mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name);
|
|
651
|
+
desc->value = 0;
|
|
652
|
+
}
|
|
653
|
+
else {
|
|
654
|
+
_mi_warning_message("environment option mimalloc_%s has an invalid value.\n", desc->name);
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
mi_assert_internal(desc->init != UNINIT);
|
|
659
|
+
}
|
|
660
|
+
else if (!_mi_preloading()) {
|
|
661
|
+
desc->init = DEFAULTED;
|
|
662
|
+
}
|
|
663
|
+
}
|