@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,692 @@
|
|
|
1
|
+
/* ----------------------------------------------------------------------------
|
|
2
|
+
Copyright (c) 2018-2024, 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
|
+
#ifndef _DEFAULT_SOURCE
|
|
8
|
+
#define _DEFAULT_SOURCE // for realpath() on Linux
|
|
9
|
+
#endif
|
|
10
|
+
|
|
11
|
+
#include "mimalloc.h"
|
|
12
|
+
#include "mimalloc/internal.h"
|
|
13
|
+
#include "mimalloc/atomic.h"
|
|
14
|
+
#include "mimalloc/prim.h" // _mi_prim_thread_id()
|
|
15
|
+
|
|
16
|
+
#include <string.h> // memset, strlen (for mi_strdup)
|
|
17
|
+
#include <stdlib.h> // malloc, abort
|
|
18
|
+
|
|
19
|
+
#define MI_IN_ALLOC_C
|
|
20
|
+
#include "alloc-override.c"
|
|
21
|
+
#include "free.c"
|
|
22
|
+
#undef MI_IN_ALLOC_C
|
|
23
|
+
|
|
24
|
+
// ------------------------------------------------------
|
|
25
|
+
// Allocation
|
|
26
|
+
// ------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
// Fast allocation in a page: just pop from the free list.
|
|
29
|
+
// Fall back to generic allocation only if the list is empty.
|
|
30
|
+
// Note: in release mode the (inlined) routine is about 7 instructions with a single test.
|
|
31
|
+
extern inline void* _mi_page_malloc_zero(mi_heap_t* heap, mi_page_t* page, size_t size, bool zero) mi_attr_noexcept
|
|
32
|
+
{
|
|
33
|
+
mi_assert_internal(size >= MI_PADDING_SIZE);
|
|
34
|
+
mi_assert_internal(page->block_size == 0 /* empty heap */ || mi_page_block_size(page) >= size);
|
|
35
|
+
|
|
36
|
+
// check the free list
|
|
37
|
+
mi_block_t* const block = page->free;
|
|
38
|
+
if mi_unlikely(block == NULL) {
|
|
39
|
+
return _mi_malloc_generic(heap, size, zero, 0);
|
|
40
|
+
}
|
|
41
|
+
mi_assert_internal(block != NULL && _mi_ptr_page(block) == page);
|
|
42
|
+
|
|
43
|
+
// pop from the free list
|
|
44
|
+
page->free = mi_block_next(page, block);
|
|
45
|
+
page->used++;
|
|
46
|
+
mi_assert_internal(page->free == NULL || _mi_ptr_page(page->free) == page);
|
|
47
|
+
mi_assert_internal(page->block_size < MI_MAX_ALIGN_SIZE || _mi_is_aligned(block, MI_MAX_ALIGN_SIZE));
|
|
48
|
+
|
|
49
|
+
#if MI_DEBUG>3
|
|
50
|
+
if (page->free_is_zero && size > sizeof(*block)) {
|
|
51
|
+
mi_assert_expensive(mi_mem_is_zero(block+1,size - sizeof(*block)));
|
|
52
|
+
}
|
|
53
|
+
#endif
|
|
54
|
+
|
|
55
|
+
// allow use of the block internally
|
|
56
|
+
// note: when tracking we need to avoid ever touching the MI_PADDING since
|
|
57
|
+
// that is tracked by valgrind etc. as non-accessible (through the red-zone, see `mimalloc/track.h`)
|
|
58
|
+
mi_track_mem_undefined(block, mi_page_usable_block_size(page));
|
|
59
|
+
|
|
60
|
+
// zero the block? note: we need to zero the full block size (issue #63)
|
|
61
|
+
if mi_unlikely(zero) {
|
|
62
|
+
mi_assert_internal(page->block_size != 0); // do not call with zero'ing for huge blocks (see _mi_malloc_generic)
|
|
63
|
+
mi_assert_internal(!mi_page_is_huge(page));
|
|
64
|
+
#if MI_PADDING
|
|
65
|
+
mi_assert_internal(page->block_size >= MI_PADDING_SIZE);
|
|
66
|
+
#endif
|
|
67
|
+
if (page->free_is_zero) {
|
|
68
|
+
block->next = 0;
|
|
69
|
+
mi_track_mem_defined(block, page->block_size - MI_PADDING_SIZE);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
_mi_memzero_aligned(block, page->block_size - MI_PADDING_SIZE);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
#if (MI_DEBUG>0) && !MI_TRACK_ENABLED && !MI_TSAN
|
|
77
|
+
if (!zero && !mi_page_is_huge(page)) {
|
|
78
|
+
memset(block, MI_DEBUG_UNINIT, mi_page_usable_block_size(page));
|
|
79
|
+
}
|
|
80
|
+
#elif (MI_SECURE!=0)
|
|
81
|
+
if (!zero) { block->next = 0; } // don't leak internal data
|
|
82
|
+
#endif
|
|
83
|
+
|
|
84
|
+
#if (MI_STAT>0)
|
|
85
|
+
const size_t bsize = mi_page_usable_block_size(page);
|
|
86
|
+
if (bsize <= MI_MEDIUM_OBJ_SIZE_MAX) {
|
|
87
|
+
mi_heap_stat_increase(heap, malloc_normal, bsize);
|
|
88
|
+
mi_heap_stat_counter_increase(heap, malloc_normal_count, 1);
|
|
89
|
+
#if (MI_STAT>1)
|
|
90
|
+
const size_t bin = _mi_bin(bsize);
|
|
91
|
+
mi_heap_stat_increase(heap, malloc_bins[bin], 1);
|
|
92
|
+
mi_heap_stat_increase(heap, malloc_requested, size - MI_PADDING_SIZE);
|
|
93
|
+
#endif
|
|
94
|
+
}
|
|
95
|
+
#endif
|
|
96
|
+
|
|
97
|
+
#if MI_PADDING // && !MI_TRACK_ENABLED
|
|
98
|
+
mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + mi_page_usable_block_size(page));
|
|
99
|
+
ptrdiff_t delta = ((uint8_t*)padding - (uint8_t*)block - (size - MI_PADDING_SIZE));
|
|
100
|
+
#if (MI_DEBUG>=2)
|
|
101
|
+
mi_assert_internal(delta >= 0 && mi_page_usable_block_size(page) >= (size - MI_PADDING_SIZE + delta));
|
|
102
|
+
#endif
|
|
103
|
+
mi_track_mem_defined(padding,sizeof(mi_padding_t)); // note: re-enable since mi_page_usable_block_size may set noaccess
|
|
104
|
+
padding->canary = mi_ptr_encode_canary(page,block,page->keys);
|
|
105
|
+
padding->delta = (uint32_t)(delta);
|
|
106
|
+
#if MI_PADDING_CHECK
|
|
107
|
+
if (!mi_page_is_huge(page)) {
|
|
108
|
+
uint8_t* fill = (uint8_t*)padding - delta;
|
|
109
|
+
const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // set at most N initial padding bytes
|
|
110
|
+
for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; }
|
|
111
|
+
}
|
|
112
|
+
#endif
|
|
113
|
+
#endif
|
|
114
|
+
|
|
115
|
+
return block;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// extra entries for improved efficiency in `alloc-aligned.c`.
|
|
119
|
+
extern void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept {
|
|
120
|
+
return _mi_page_malloc_zero(heap,page,size,false);
|
|
121
|
+
}
|
|
122
|
+
extern void* _mi_page_malloc_zeroed(mi_heap_t* heap, mi_page_t* page, size_t size) mi_attr_noexcept {
|
|
123
|
+
return _mi_page_malloc_zero(heap,page,size,true);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
#if MI_GUARDED
|
|
127
|
+
mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept;
|
|
128
|
+
#endif
|
|
129
|
+
|
|
130
|
+
static inline mi_decl_restrict void* mi_heap_malloc_small_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept {
|
|
131
|
+
mi_assert(heap != NULL);
|
|
132
|
+
mi_assert(size <= MI_SMALL_SIZE_MAX);
|
|
133
|
+
#if MI_DEBUG
|
|
134
|
+
const uintptr_t tid = _mi_thread_id();
|
|
135
|
+
mi_assert(heap->thread_id == 0 || heap->thread_id == tid); // heaps are thread local
|
|
136
|
+
#endif
|
|
137
|
+
#if (MI_PADDING || MI_GUARDED)
|
|
138
|
+
if (size == 0) { size = sizeof(void*); }
|
|
139
|
+
#endif
|
|
140
|
+
#if MI_GUARDED
|
|
141
|
+
if (mi_heap_malloc_use_guarded(heap,size)) {
|
|
142
|
+
return _mi_heap_malloc_guarded(heap, size, zero);
|
|
143
|
+
}
|
|
144
|
+
#endif
|
|
145
|
+
|
|
146
|
+
// get page in constant time, and allocate from it
|
|
147
|
+
mi_page_t* page = _mi_heap_get_free_small_page(heap, size + MI_PADDING_SIZE);
|
|
148
|
+
void* const p = _mi_page_malloc_zero(heap, page, size + MI_PADDING_SIZE, zero);
|
|
149
|
+
mi_track_malloc(p,size,zero);
|
|
150
|
+
|
|
151
|
+
#if MI_DEBUG>3
|
|
152
|
+
if (p != NULL && zero) {
|
|
153
|
+
mi_assert_expensive(mi_mem_is_zero(p, size));
|
|
154
|
+
}
|
|
155
|
+
#endif
|
|
156
|
+
return p;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// allocate a small block
|
|
160
|
+
mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_malloc_small(mi_heap_t* heap, size_t size) mi_attr_noexcept {
|
|
161
|
+
return mi_heap_malloc_small_zero(heap, size, false);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
mi_decl_nodiscard extern inline mi_decl_restrict void* mi_malloc_small(size_t size) mi_attr_noexcept {
|
|
165
|
+
return mi_heap_malloc_small(mi_prim_get_default_heap(), size);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// The main allocation function
|
|
169
|
+
extern inline void* _mi_heap_malloc_zero_ex(mi_heap_t* heap, size_t size, bool zero, size_t huge_alignment) mi_attr_noexcept {
|
|
170
|
+
// fast path for small objects
|
|
171
|
+
if mi_likely(size <= MI_SMALL_SIZE_MAX) {
|
|
172
|
+
mi_assert_internal(huge_alignment == 0);
|
|
173
|
+
return mi_heap_malloc_small_zero(heap, size, zero);
|
|
174
|
+
}
|
|
175
|
+
#if MI_GUARDED
|
|
176
|
+
else if (huge_alignment==0 && mi_heap_malloc_use_guarded(heap,size)) {
|
|
177
|
+
return _mi_heap_malloc_guarded(heap, size, zero);
|
|
178
|
+
}
|
|
179
|
+
#endif
|
|
180
|
+
else {
|
|
181
|
+
// regular allocation
|
|
182
|
+
mi_assert(heap!=NULL);
|
|
183
|
+
mi_assert(heap->thread_id == 0 || heap->thread_id == _mi_thread_id()); // heaps are thread local
|
|
184
|
+
void* const p = _mi_malloc_generic(heap, size + MI_PADDING_SIZE, zero, huge_alignment); // note: size can overflow but it is detected in malloc_generic
|
|
185
|
+
mi_track_malloc(p,size,zero);
|
|
186
|
+
|
|
187
|
+
#if MI_DEBUG>3
|
|
188
|
+
if (p != NULL && zero) {
|
|
189
|
+
mi_assert_expensive(mi_mem_is_zero(p, size));
|
|
190
|
+
}
|
|
191
|
+
#endif
|
|
192
|
+
return p;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
extern inline void* _mi_heap_malloc_zero(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept {
|
|
197
|
+
return _mi_heap_malloc_zero_ex(heap, size, zero, 0);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_malloc(mi_heap_t* heap, size_t size) mi_attr_noexcept {
|
|
201
|
+
return _mi_heap_malloc_zero(heap, size, false);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
mi_decl_nodiscard extern inline mi_decl_restrict void* mi_malloc(size_t size) mi_attr_noexcept {
|
|
205
|
+
return mi_heap_malloc(mi_prim_get_default_heap(), size);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// zero initialized small block
|
|
209
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_zalloc_small(size_t size) mi_attr_noexcept {
|
|
210
|
+
return mi_heap_malloc_small_zero(mi_prim_get_default_heap(), size, true);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_zalloc(mi_heap_t* heap, size_t size) mi_attr_noexcept {
|
|
214
|
+
return _mi_heap_malloc_zero(heap, size, true);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_zalloc(size_t size) mi_attr_noexcept {
|
|
218
|
+
return mi_heap_zalloc(mi_prim_get_default_heap(),size);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
mi_decl_nodiscard extern inline mi_decl_restrict void* mi_heap_calloc(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept {
|
|
223
|
+
size_t total;
|
|
224
|
+
if (mi_count_size_overflow(count,size,&total)) return NULL;
|
|
225
|
+
return mi_heap_zalloc(heap,total);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_calloc(size_t count, size_t size) mi_attr_noexcept {
|
|
229
|
+
return mi_heap_calloc(mi_prim_get_default_heap(),count,size);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Uninitialized `calloc`
|
|
233
|
+
mi_decl_nodiscard extern mi_decl_restrict void* mi_heap_mallocn(mi_heap_t* heap, size_t count, size_t size) mi_attr_noexcept {
|
|
234
|
+
size_t total;
|
|
235
|
+
if (mi_count_size_overflow(count, size, &total)) return NULL;
|
|
236
|
+
return mi_heap_malloc(heap, total);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_mallocn(size_t count, size_t size) mi_attr_noexcept {
|
|
240
|
+
return mi_heap_mallocn(mi_prim_get_default_heap(),count,size);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Expand (or shrink) in place (or fail)
|
|
244
|
+
void* mi_expand(void* p, size_t newsize) mi_attr_noexcept {
|
|
245
|
+
#if MI_PADDING
|
|
246
|
+
// we do not shrink/expand with padding enabled
|
|
247
|
+
MI_UNUSED(p); MI_UNUSED(newsize);
|
|
248
|
+
return NULL;
|
|
249
|
+
#else
|
|
250
|
+
if (p == NULL) return NULL;
|
|
251
|
+
const size_t size = _mi_usable_size(p,"mi_expand");
|
|
252
|
+
if (newsize > size) return NULL;
|
|
253
|
+
return p; // it fits
|
|
254
|
+
#endif
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
void* _mi_heap_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero) mi_attr_noexcept {
|
|
258
|
+
// if p == NULL then behave as malloc.
|
|
259
|
+
// else if size == 0 then reallocate to a zero-sized block (and don't return NULL, just as mi_malloc(0)).
|
|
260
|
+
// (this means that returning NULL always indicates an error, and `p` will not have been freed in that case.)
|
|
261
|
+
const size_t size = _mi_usable_size(p,"mi_realloc"); // also works if p == NULL (with size 0)
|
|
262
|
+
if mi_unlikely(newsize <= size && newsize >= (size / 2) && newsize > 0) { // note: newsize must be > 0 or otherwise we return NULL for realloc(NULL,0)
|
|
263
|
+
mi_assert_internal(p!=NULL);
|
|
264
|
+
// todo: do not track as the usable size is still the same in the free; adjust potential padding?
|
|
265
|
+
// mi_track_resize(p,size,newsize)
|
|
266
|
+
// if (newsize < size) { mi_track_mem_noaccess((uint8_t*)p + newsize, size - newsize); }
|
|
267
|
+
return p; // reallocation still fits and not more than 50% waste
|
|
268
|
+
}
|
|
269
|
+
void* newp = mi_heap_malloc(heap,newsize);
|
|
270
|
+
if mi_likely(newp != NULL) {
|
|
271
|
+
if (zero && newsize > size) {
|
|
272
|
+
// also set last word in the previous allocation to zero to ensure any padding is zero-initialized
|
|
273
|
+
const size_t start = (size >= sizeof(intptr_t) ? size - sizeof(intptr_t) : 0);
|
|
274
|
+
_mi_memzero((uint8_t*)newp + start, newsize - start);
|
|
275
|
+
}
|
|
276
|
+
else if (newsize == 0) {
|
|
277
|
+
((uint8_t*)newp)[0] = 0; // work around for applications that expect zero-reallocation to be zero initialized (issue #725)
|
|
278
|
+
}
|
|
279
|
+
if mi_likely(p != NULL) {
|
|
280
|
+
const size_t copysize = (newsize > size ? size : newsize);
|
|
281
|
+
mi_track_mem_defined(p,copysize); // _mi_useable_size may be too large for byte precise memory tracking..
|
|
282
|
+
_mi_memcpy(newp, p, copysize);
|
|
283
|
+
mi_free(p); // only free the original pointer if successful
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return newp;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
mi_decl_nodiscard void* mi_heap_realloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept {
|
|
290
|
+
return _mi_heap_realloc_zero(heap, p, newsize, false);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
mi_decl_nodiscard void* mi_heap_reallocn(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept {
|
|
294
|
+
size_t total;
|
|
295
|
+
if (mi_count_size_overflow(count, size, &total)) return NULL;
|
|
296
|
+
return mi_heap_realloc(heap, p, total);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
// Reallocate but free `p` on errors
|
|
301
|
+
mi_decl_nodiscard void* mi_heap_reallocf(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept {
|
|
302
|
+
void* newp = mi_heap_realloc(heap, p, newsize);
|
|
303
|
+
if (newp==NULL && p!=NULL) mi_free(p);
|
|
304
|
+
return newp;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
mi_decl_nodiscard void* mi_heap_rezalloc(mi_heap_t* heap, void* p, size_t newsize) mi_attr_noexcept {
|
|
308
|
+
return _mi_heap_realloc_zero(heap, p, newsize, true);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
mi_decl_nodiscard void* mi_heap_recalloc(mi_heap_t* heap, void* p, size_t count, size_t size) mi_attr_noexcept {
|
|
312
|
+
size_t total;
|
|
313
|
+
if (mi_count_size_overflow(count, size, &total)) return NULL;
|
|
314
|
+
return mi_heap_rezalloc(heap, p, total);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
mi_decl_nodiscard void* mi_realloc(void* p, size_t newsize) mi_attr_noexcept {
|
|
319
|
+
return mi_heap_realloc(mi_prim_get_default_heap(),p,newsize);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
mi_decl_nodiscard void* mi_reallocn(void* p, size_t count, size_t size) mi_attr_noexcept {
|
|
323
|
+
return mi_heap_reallocn(mi_prim_get_default_heap(),p,count,size);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Reallocate but free `p` on errors
|
|
327
|
+
mi_decl_nodiscard void* mi_reallocf(void* p, size_t newsize) mi_attr_noexcept {
|
|
328
|
+
return mi_heap_reallocf(mi_prim_get_default_heap(),p,newsize);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
mi_decl_nodiscard void* mi_rezalloc(void* p, size_t newsize) mi_attr_noexcept {
|
|
332
|
+
return mi_heap_rezalloc(mi_prim_get_default_heap(), p, newsize);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
mi_decl_nodiscard void* mi_recalloc(void* p, size_t count, size_t size) mi_attr_noexcept {
|
|
336
|
+
return mi_heap_recalloc(mi_prim_get_default_heap(), p, count, size);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
|
|
341
|
+
// ------------------------------------------------------
|
|
342
|
+
// strdup, strndup, and realpath
|
|
343
|
+
// ------------------------------------------------------
|
|
344
|
+
|
|
345
|
+
// `strdup` using mi_malloc
|
|
346
|
+
mi_decl_nodiscard mi_decl_restrict char* mi_heap_strdup(mi_heap_t* heap, const char* s) mi_attr_noexcept {
|
|
347
|
+
if (s == NULL) return NULL;
|
|
348
|
+
size_t len = _mi_strlen(s);
|
|
349
|
+
char* t = (char*)mi_heap_malloc(heap,len+1);
|
|
350
|
+
if (t == NULL) return NULL;
|
|
351
|
+
_mi_memcpy(t, s, len);
|
|
352
|
+
t[len] = 0;
|
|
353
|
+
return t;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
mi_decl_nodiscard mi_decl_restrict char* mi_strdup(const char* s) mi_attr_noexcept {
|
|
357
|
+
return mi_heap_strdup(mi_prim_get_default_heap(), s);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// `strndup` using mi_malloc
|
|
361
|
+
mi_decl_nodiscard mi_decl_restrict char* mi_heap_strndup(mi_heap_t* heap, const char* s, size_t n) mi_attr_noexcept {
|
|
362
|
+
if (s == NULL) return NULL;
|
|
363
|
+
const size_t len = _mi_strnlen(s,n); // len <= n
|
|
364
|
+
char* t = (char*)mi_heap_malloc(heap, len+1);
|
|
365
|
+
if (t == NULL) return NULL;
|
|
366
|
+
_mi_memcpy(t, s, len);
|
|
367
|
+
t[len] = 0;
|
|
368
|
+
return t;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
mi_decl_nodiscard mi_decl_restrict char* mi_strndup(const char* s, size_t n) mi_attr_noexcept {
|
|
372
|
+
return mi_heap_strndup(mi_prim_get_default_heap(),s,n);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
#ifndef __wasi__
|
|
376
|
+
// `realpath` using mi_malloc
|
|
377
|
+
#ifdef _WIN32
|
|
378
|
+
#ifndef PATH_MAX
|
|
379
|
+
#define PATH_MAX MAX_PATH
|
|
380
|
+
#endif
|
|
381
|
+
|
|
382
|
+
mi_decl_nodiscard mi_decl_restrict char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept {
|
|
383
|
+
// todo: use GetFullPathNameW to allow longer file names
|
|
384
|
+
char buf[PATH_MAX];
|
|
385
|
+
DWORD res = GetFullPathNameA(fname, PATH_MAX, (resolved_name == NULL ? buf : resolved_name), NULL);
|
|
386
|
+
if (res == 0) {
|
|
387
|
+
errno = GetLastError(); return NULL;
|
|
388
|
+
}
|
|
389
|
+
else if (res > PATH_MAX) {
|
|
390
|
+
errno = EINVAL; return NULL;
|
|
391
|
+
}
|
|
392
|
+
else if (resolved_name != NULL) {
|
|
393
|
+
return resolved_name;
|
|
394
|
+
}
|
|
395
|
+
else {
|
|
396
|
+
return mi_heap_strndup(heap, buf, PATH_MAX);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
#else
|
|
400
|
+
/*
|
|
401
|
+
#include <unistd.h> // pathconf
|
|
402
|
+
static size_t mi_path_max(void) {
|
|
403
|
+
static size_t path_max = 0;
|
|
404
|
+
if (path_max <= 0) {
|
|
405
|
+
long m = pathconf("/",_PC_PATH_MAX);
|
|
406
|
+
if (m <= 0) path_max = 4096; // guess
|
|
407
|
+
else if (m < 256) path_max = 256; // at least 256
|
|
408
|
+
else path_max = m;
|
|
409
|
+
}
|
|
410
|
+
return path_max;
|
|
411
|
+
}
|
|
412
|
+
*/
|
|
413
|
+
char* mi_heap_realpath(mi_heap_t* heap, const char* fname, char* resolved_name) mi_attr_noexcept {
|
|
414
|
+
if (resolved_name != NULL) {
|
|
415
|
+
return realpath(fname,resolved_name);
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
char* rname = realpath(fname, NULL);
|
|
419
|
+
if (rname == NULL) return NULL;
|
|
420
|
+
char* result = mi_heap_strdup(heap, rname);
|
|
421
|
+
mi_cfree(rname); // use checked free (which may be redirected to our free but that's ok)
|
|
422
|
+
// note: with ASAN realpath is intercepted and mi_cfree may leak the returned pointer :-(
|
|
423
|
+
return result;
|
|
424
|
+
}
|
|
425
|
+
/*
|
|
426
|
+
const size_t n = mi_path_max();
|
|
427
|
+
char* buf = (char*)mi_malloc(n+1);
|
|
428
|
+
if (buf == NULL) {
|
|
429
|
+
errno = ENOMEM;
|
|
430
|
+
return NULL;
|
|
431
|
+
}
|
|
432
|
+
char* rname = realpath(fname,buf);
|
|
433
|
+
char* result = mi_heap_strndup(heap,rname,n); // ok if `rname==NULL`
|
|
434
|
+
mi_free(buf);
|
|
435
|
+
return result;
|
|
436
|
+
}
|
|
437
|
+
*/
|
|
438
|
+
}
|
|
439
|
+
#endif
|
|
440
|
+
|
|
441
|
+
mi_decl_nodiscard mi_decl_restrict char* mi_realpath(const char* fname, char* resolved_name) mi_attr_noexcept {
|
|
442
|
+
return mi_heap_realpath(mi_prim_get_default_heap(),fname,resolved_name);
|
|
443
|
+
}
|
|
444
|
+
#endif
|
|
445
|
+
|
|
446
|
+
/*-------------------------------------------------------
|
|
447
|
+
C++ new and new_aligned
|
|
448
|
+
The standard requires calling into `get_new_handler` and
|
|
449
|
+
throwing the bad_alloc exception on failure. If we compile
|
|
450
|
+
with a C++ compiler we can implement this precisely. If we
|
|
451
|
+
use a C compiler we cannot throw a `bad_alloc` exception
|
|
452
|
+
but we call `exit` instead (i.e. not returning).
|
|
453
|
+
-------------------------------------------------------*/
|
|
454
|
+
|
|
455
|
+
#ifdef __cplusplus
|
|
456
|
+
#include <new>
|
|
457
|
+
static bool mi_try_new_handler(bool nothrow) {
|
|
458
|
+
#if defined(_MSC_VER) || (__cplusplus >= 201103L)
|
|
459
|
+
std::new_handler h = std::get_new_handler();
|
|
460
|
+
#else
|
|
461
|
+
std::new_handler h = std::set_new_handler();
|
|
462
|
+
std::set_new_handler(h);
|
|
463
|
+
#endif
|
|
464
|
+
if (h==NULL) {
|
|
465
|
+
_mi_error_message(ENOMEM, "out of memory in 'new'");
|
|
466
|
+
#if defined(_CPPUNWIND) || defined(__cpp_exceptions) // exceptions are not always enabled
|
|
467
|
+
if (!nothrow) {
|
|
468
|
+
throw std::bad_alloc();
|
|
469
|
+
}
|
|
470
|
+
#else
|
|
471
|
+
MI_UNUSED(nothrow);
|
|
472
|
+
#endif
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
else {
|
|
476
|
+
h();
|
|
477
|
+
return true;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
#else
|
|
481
|
+
typedef void (*std_new_handler_t)(void);
|
|
482
|
+
|
|
483
|
+
#if (defined(__GNUC__) || (defined(__clang__) && !defined(_MSC_VER))) // exclude clang-cl, see issue #631
|
|
484
|
+
std_new_handler_t __attribute__((weak)) _ZSt15get_new_handlerv(void) {
|
|
485
|
+
return NULL;
|
|
486
|
+
}
|
|
487
|
+
static std_new_handler_t mi_get_new_handler(void) {
|
|
488
|
+
return _ZSt15get_new_handlerv();
|
|
489
|
+
}
|
|
490
|
+
#else
|
|
491
|
+
// note: on windows we could dynamically link to `?get_new_handler@std@@YAP6AXXZXZ`.
|
|
492
|
+
static std_new_handler_t mi_get_new_handler() {
|
|
493
|
+
return NULL;
|
|
494
|
+
}
|
|
495
|
+
#endif
|
|
496
|
+
|
|
497
|
+
static bool mi_try_new_handler(bool nothrow) {
|
|
498
|
+
std_new_handler_t h = mi_get_new_handler();
|
|
499
|
+
if (h==NULL) {
|
|
500
|
+
_mi_error_message(ENOMEM, "out of memory in 'new'");
|
|
501
|
+
if (!nothrow) {
|
|
502
|
+
abort(); // cannot throw in plain C, use abort
|
|
503
|
+
}
|
|
504
|
+
return false;
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
h();
|
|
508
|
+
return true;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
#endif
|
|
512
|
+
|
|
513
|
+
mi_decl_export mi_decl_noinline void* mi_heap_try_new(mi_heap_t* heap, size_t size, bool nothrow ) {
|
|
514
|
+
void* p = NULL;
|
|
515
|
+
while(p == NULL && mi_try_new_handler(nothrow)) {
|
|
516
|
+
p = mi_heap_malloc(heap,size);
|
|
517
|
+
}
|
|
518
|
+
return p;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
static mi_decl_noinline void* mi_try_new(size_t size, bool nothrow) {
|
|
522
|
+
return mi_heap_try_new(mi_prim_get_default_heap(), size, nothrow);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
|
|
526
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_heap_alloc_new(mi_heap_t* heap, size_t size) {
|
|
527
|
+
void* p = mi_heap_malloc(heap,size);
|
|
528
|
+
if mi_unlikely(p == NULL) return mi_heap_try_new(heap, size, false);
|
|
529
|
+
return p;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_new(size_t size) {
|
|
533
|
+
return mi_heap_alloc_new(mi_prim_get_default_heap(), size);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_heap_alloc_new_n(mi_heap_t* heap, size_t count, size_t size) {
|
|
538
|
+
size_t total;
|
|
539
|
+
if mi_unlikely(mi_count_size_overflow(count, size, &total)) {
|
|
540
|
+
mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc
|
|
541
|
+
return NULL;
|
|
542
|
+
}
|
|
543
|
+
else {
|
|
544
|
+
return mi_heap_alloc_new(heap,total);
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_new_n(size_t count, size_t size) {
|
|
549
|
+
return mi_heap_alloc_new_n(mi_prim_get_default_heap(), count, size);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
|
|
553
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_new_nothrow(size_t size) mi_attr_noexcept {
|
|
554
|
+
void* p = mi_malloc(size);
|
|
555
|
+
if mi_unlikely(p == NULL) return mi_try_new(size, true);
|
|
556
|
+
return p;
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_new_aligned(size_t size, size_t alignment) {
|
|
560
|
+
void* p;
|
|
561
|
+
do {
|
|
562
|
+
p = mi_malloc_aligned(size, alignment);
|
|
563
|
+
}
|
|
564
|
+
while(p == NULL && mi_try_new_handler(false));
|
|
565
|
+
return p;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
mi_decl_nodiscard mi_decl_restrict void* mi_new_aligned_nothrow(size_t size, size_t alignment) mi_attr_noexcept {
|
|
569
|
+
void* p;
|
|
570
|
+
do {
|
|
571
|
+
p = mi_malloc_aligned(size, alignment);
|
|
572
|
+
}
|
|
573
|
+
while(p == NULL && mi_try_new_handler(true));
|
|
574
|
+
return p;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
mi_decl_nodiscard void* mi_new_realloc(void* p, size_t newsize) {
|
|
578
|
+
void* q;
|
|
579
|
+
do {
|
|
580
|
+
q = mi_realloc(p, newsize);
|
|
581
|
+
} while (q == NULL && mi_try_new_handler(false));
|
|
582
|
+
return q;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
mi_decl_nodiscard void* mi_new_reallocn(void* p, size_t newcount, size_t size) {
|
|
586
|
+
size_t total;
|
|
587
|
+
if mi_unlikely(mi_count_size_overflow(newcount, size, &total)) {
|
|
588
|
+
mi_try_new_handler(false); // on overflow we invoke the try_new_handler once to potentially throw std::bad_alloc
|
|
589
|
+
return NULL;
|
|
590
|
+
}
|
|
591
|
+
else {
|
|
592
|
+
return mi_new_realloc(p, total);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
#if MI_GUARDED
|
|
597
|
+
// We always allocate a guarded allocation at an offset (`mi_page_has_aligned` will be true).
|
|
598
|
+
// We then set the first word of the block to `0` for regular offset aligned allocations (in `alloc-aligned.c`)
|
|
599
|
+
// and the first word to `~0` for guarded allocations to have a correct `mi_usable_size`
|
|
600
|
+
|
|
601
|
+
static void* mi_block_ptr_set_guarded(mi_block_t* block, size_t obj_size) {
|
|
602
|
+
// TODO: we can still make padding work by moving it out of the guard page area
|
|
603
|
+
mi_page_t* const page = _mi_ptr_page(block);
|
|
604
|
+
mi_page_set_has_aligned(page, true);
|
|
605
|
+
block->next = MI_BLOCK_TAG_GUARDED;
|
|
606
|
+
|
|
607
|
+
// set guard page at the end of the block
|
|
608
|
+
mi_segment_t* const segment = _mi_page_segment(page);
|
|
609
|
+
const size_t block_size = mi_page_block_size(page); // must use `block_size` to match `mi_free_local`
|
|
610
|
+
const size_t os_page_size = _mi_os_page_size();
|
|
611
|
+
mi_assert_internal(block_size >= obj_size + os_page_size + sizeof(mi_block_t));
|
|
612
|
+
if (block_size < obj_size + os_page_size + sizeof(mi_block_t)) {
|
|
613
|
+
// should never happen
|
|
614
|
+
mi_free(block);
|
|
615
|
+
return NULL;
|
|
616
|
+
}
|
|
617
|
+
uint8_t* guard_page = (uint8_t*)block + block_size - os_page_size;
|
|
618
|
+
mi_assert_internal(_mi_is_aligned(guard_page, os_page_size));
|
|
619
|
+
if (segment->allow_decommit && _mi_is_aligned(guard_page, os_page_size)) {
|
|
620
|
+
_mi_os_protect(guard_page, os_page_size);
|
|
621
|
+
}
|
|
622
|
+
else {
|
|
623
|
+
_mi_warning_message("unable to set a guard page behind an object due to pinned memory (large OS pages?) (object %p of size %zu)\n", block, block_size);
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
// align pointer just in front of the guard page
|
|
627
|
+
size_t offset = block_size - os_page_size - obj_size;
|
|
628
|
+
mi_assert_internal(offset > sizeof(mi_block_t));
|
|
629
|
+
if (offset > MI_BLOCK_ALIGNMENT_MAX) {
|
|
630
|
+
// give up to place it right in front of the guard page if the offset is too large for unalignment
|
|
631
|
+
offset = MI_BLOCK_ALIGNMENT_MAX;
|
|
632
|
+
}
|
|
633
|
+
void* p = (uint8_t*)block + offset;
|
|
634
|
+
mi_track_align(block, p, offset, obj_size);
|
|
635
|
+
mi_track_mem_defined(block, sizeof(mi_block_t));
|
|
636
|
+
return p;
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
mi_decl_restrict void* _mi_heap_malloc_guarded(mi_heap_t* heap, size_t size, bool zero) mi_attr_noexcept
|
|
640
|
+
{
|
|
641
|
+
#if defined(MI_PADDING_SIZE)
|
|
642
|
+
mi_assert(MI_PADDING_SIZE==0);
|
|
643
|
+
#endif
|
|
644
|
+
// allocate multiple of page size ending in a guard page
|
|
645
|
+
// ensure minimal alignment requirement?
|
|
646
|
+
const size_t os_page_size = _mi_os_page_size();
|
|
647
|
+
const size_t obj_size = (mi_option_is_enabled(mi_option_guarded_precise) ? size : _mi_align_up(size, MI_MAX_ALIGN_SIZE));
|
|
648
|
+
const size_t bsize = _mi_align_up(_mi_align_up(obj_size, MI_MAX_ALIGN_SIZE) + sizeof(mi_block_t), MI_MAX_ALIGN_SIZE);
|
|
649
|
+
const size_t req_size = _mi_align_up(bsize + os_page_size, os_page_size);
|
|
650
|
+
mi_block_t* const block = (mi_block_t*)_mi_malloc_generic(heap, req_size, zero, 0 /* huge_alignment */);
|
|
651
|
+
if (block==NULL) return NULL;
|
|
652
|
+
void* const p = mi_block_ptr_set_guarded(block, obj_size);
|
|
653
|
+
|
|
654
|
+
// stats
|
|
655
|
+
mi_track_malloc(p, size, zero);
|
|
656
|
+
if (p != NULL) {
|
|
657
|
+
if (!mi_heap_is_initialized(heap)) { heap = mi_prim_get_default_heap(); }
|
|
658
|
+
#if MI_STAT>1
|
|
659
|
+
mi_heap_stat_adjust_decrease(heap, malloc_requested, req_size);
|
|
660
|
+
mi_heap_stat_increase(heap, malloc_requested, size);
|
|
661
|
+
#endif
|
|
662
|
+
_mi_stat_counter_increase(&heap->tld->stats.malloc_guarded_count, 1);
|
|
663
|
+
}
|
|
664
|
+
#if MI_DEBUG>3
|
|
665
|
+
if (p != NULL && zero) {
|
|
666
|
+
mi_assert_expensive(mi_mem_is_zero(p, size));
|
|
667
|
+
}
|
|
668
|
+
#endif
|
|
669
|
+
return p;
|
|
670
|
+
}
|
|
671
|
+
#endif
|
|
672
|
+
|
|
673
|
+
// ------------------------------------------------------
|
|
674
|
+
// ensure explicit external inline definitions are emitted!
|
|
675
|
+
// ------------------------------------------------------
|
|
676
|
+
|
|
677
|
+
#ifdef __cplusplus
|
|
678
|
+
void* _mi_externs[] = {
|
|
679
|
+
(void*)&_mi_page_malloc,
|
|
680
|
+
(void*)&_mi_page_malloc_zero,
|
|
681
|
+
(void*)&_mi_heap_malloc_zero,
|
|
682
|
+
(void*)&_mi_heap_malloc_zero_ex,
|
|
683
|
+
(void*)&mi_malloc,
|
|
684
|
+
(void*)&mi_malloc_small,
|
|
685
|
+
(void*)&mi_zalloc_small,
|
|
686
|
+
(void*)&mi_heap_malloc,
|
|
687
|
+
(void*)&mi_heap_zalloc,
|
|
688
|
+
(void*)&mi_heap_malloc_small,
|
|
689
|
+
// (void*)&mi_heap_alloc_new,
|
|
690
|
+
// (void*)&mi_heap_alloc_new_n
|
|
691
|
+
};
|
|
692
|
+
#endif
|