@shd101wyy/yo 0.1.24 → 0.1.26
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/.github/skills/yo-async-effects/async-effects-recipes.md +6 -6
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +34 -0
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +441 -2
- package/out/cjs/index.cjs +563 -567
- package/out/cjs/yo-cli.cjs +656 -651
- package/out/cjs/yo-lsp.cjs +614 -618
- package/out/esm/index.mjs +582 -586
- package/out/types/src/codegen/codegen-c.d.ts +2 -2
- package/out/types/src/codegen/functions/collection.d.ts +2 -2
- package/out/types/src/codegen/functions/context.d.ts +3 -2
- package/out/types/src/codegen/types/collection.d.ts +2 -2
- package/out/types/src/codegen/utils/index.d.ts +4 -1
- package/out/types/src/doc/builder.d.ts +2 -2
- package/out/types/src/evaluator/calls/closure-type.d.ts +2 -2
- package/out/types/src/evaluator/calls/record-type.d.ts +11 -0
- package/out/types/src/evaluator/context.d.ts +8 -9
- package/out/types/src/evaluator/index.d.ts +3 -3
- package/out/types/src/evaluator/types/record.d.ts +14 -0
- package/out/types/src/evaluator/types/validation.d.ts +2 -2
- package/out/types/src/evaluator/values/anonymous-module.d.ts +5 -5
- package/out/types/src/evaluator/values/impl.d.ts +1 -1
- package/out/types/src/expr.d.ts +2 -4
- package/out/types/src/function-value.d.ts +1 -1
- package/out/types/src/lsp/document-manager.d.ts +1 -1
- package/out/types/src/module-manager.d.ts +3 -3
- package/out/types/src/test-runner.d.ts +1 -0
- package/out/types/src/types/creators.d.ts +3 -4
- package/out/types/src/types/definitions.d.ts +8 -19
- package/out/types/src/types/guards.d.ts +3 -3
- package/out/types/src/types/tags.d.ts +0 -1
- package/out/types/src/types/utils.d.ts +1 -1
- package/out/types/src/value-tag.d.ts +0 -1
- package/out/types/src/value.d.ts +6 -13
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/error.yo +6 -6
- package/std/prelude.yo +1 -7
- package/vendor/mimalloc/.github/workflows/release.yaml +55 -0
- package/vendor/mimalloc/.github/workflows/stale.yaml +27 -0
- package/vendor/mimalloc/.github/workflows/test.yaml +163 -0
- package/vendor/mimalloc/CMakeLists.txt +52 -33
- package/vendor/mimalloc/azure-pipelines.yml +4 -3
- package/vendor/mimalloc/bin/bundle.bat +74 -0
- package/vendor/mimalloc/bin/bundle.sh +232 -0
- package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +2 -2
- package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +1 -1
- package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +2 -2
- package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +1 -1
- package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +1 -1
- package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +4 -3
- package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +1 -1
- package/vendor/mimalloc/doc/mimalloc-doc.h +42 -4
- package/vendor/mimalloc/doc/release-notes.md +15 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +3 -3
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj +511 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj.filters +117 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-dep.vcxproj +360 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc-test-override-static.vcxproj +310 -0
- package/vendor/mimalloc/ide/vs2022/mimalloc.sln +92 -35
- package/vendor/mimalloc/include/mimalloc/atomic.h +178 -182
- package/vendor/mimalloc/include/mimalloc/bits.h +8 -10
- package/vendor/mimalloc/include/mimalloc/internal.h +76 -32
- package/vendor/mimalloc/include/mimalloc/prim.h +25 -18
- package/vendor/mimalloc/include/mimalloc/track.h +7 -2
- package/vendor/mimalloc/include/mimalloc/types.h +57 -29
- package/vendor/mimalloc/include/mimalloc-override.h +10 -10
- package/vendor/mimalloc/include/mimalloc-stats.h +18 -6
- package/vendor/mimalloc/include/mimalloc.h +22 -12
- package/vendor/mimalloc/readme.md +42 -17
- package/vendor/mimalloc/src/alloc-aligned.c +13 -11
- package/vendor/mimalloc/src/alloc-override.c +97 -17
- package/vendor/mimalloc/src/alloc-posix.c +44 -27
- package/vendor/mimalloc/src/alloc.c +73 -23
- package/vendor/mimalloc/src/arena-meta.c +3 -3
- package/vendor/mimalloc/src/arena.c +380 -192
- package/vendor/mimalloc/src/bitmap.c +68 -18
- package/vendor/mimalloc/src/bitmap.h +8 -4
- package/vendor/mimalloc/src/free.c +83 -47
- package/vendor/mimalloc/src/heap.c +94 -40
- package/vendor/mimalloc/src/init.c +273 -102
- package/vendor/mimalloc/src/libc.c +53 -8
- package/vendor/mimalloc/src/options.c +43 -40
- package/vendor/mimalloc/src/os.c +110 -45
- package/vendor/mimalloc/src/page-map.c +14 -8
- package/vendor/mimalloc/src/page-queue.c +9 -6
- package/vendor/mimalloc/src/page.c +26 -16
- package/vendor/mimalloc/src/prim/emscripten/prim.c +10 -1
- package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +35 -16
- package/vendor/mimalloc/src/prim/unix/prim.c +26 -22
- package/vendor/mimalloc/src/prim/wasi/prim.c +7 -4
- package/vendor/mimalloc/src/prim/windows/prim.c +247 -44
- package/vendor/mimalloc/src/random.c +8 -3
- package/vendor/mimalloc/src/stats.c +59 -48
- package/vendor/mimalloc/src/theap.c +85 -44
- package/vendor/mimalloc/src/threadlocal.c +102 -41
- package/vendor/mimalloc/test/main-override-static.c +31 -2
- package/vendor/mimalloc/test/main-override.c +27 -14
- package/vendor/mimalloc/test/main-static-dep.cpp +46 -0
- package/vendor/mimalloc/test/main-static-dep.h +11 -0
- package/vendor/mimalloc/test/test-api-fill.c +2 -2
- package/vendor/mimalloc/test/test-stress.c +3 -3
- package/vendor/mimalloc/test/test-wrong.c +11 -7
- package/out/types/src/evaluator/calls/module-type.d.ts +0 -11
- package/out/types/src/evaluator/types/module.d.ts +0 -19
|
@@ -22,6 +22,7 @@ char _mi_toupper(char c) {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
int _mi_strnicmp(const char* s, const char* t, size_t n) {
|
|
25
|
+
mi_assert_internal(s!=NULL && t!=NULL);
|
|
25
26
|
if (n == 0) return 0;
|
|
26
27
|
for (; *s != 0 && *t != 0 && n > 0; s++, t++, n--) {
|
|
27
28
|
if (_mi_toupper(*s) != _mi_toupper(*t)) break;
|
|
@@ -29,6 +30,15 @@ int _mi_strnicmp(const char* s, const char* t, size_t n) {
|
|
|
29
30
|
return (n == 0 ? 0 : *s - *t);
|
|
30
31
|
}
|
|
31
32
|
|
|
33
|
+
bool _mi_streq(const char* s, const char* t) {
|
|
34
|
+
if (s==NULL && t==NULL) return true;
|
|
35
|
+
if (s==NULL || t==NULL) return false;
|
|
36
|
+
for (; *s != 0 && *t != 0; s++, t++) {
|
|
37
|
+
if (*s != *t) break;
|
|
38
|
+
}
|
|
39
|
+
return (*s == *t);
|
|
40
|
+
}
|
|
41
|
+
|
|
32
42
|
void _mi_strlcpy(char* dest, const char* src, size_t dest_size) {
|
|
33
43
|
if (dest==NULL || src==NULL || dest_size == 0) return;
|
|
34
44
|
// copy until end of src, or when dest is (almost) full
|
|
@@ -51,13 +61,6 @@ void _mi_strlcat(char* dest, const char* src, size_t dest_size) {
|
|
|
51
61
|
_mi_strlcpy(dest, src, dest_size);
|
|
52
62
|
}
|
|
53
63
|
|
|
54
|
-
size_t _mi_strlen(const char* s) {
|
|
55
|
-
if (s==NULL) return 0;
|
|
56
|
-
size_t len = 0;
|
|
57
|
-
while(s[len] != 0) { len++; }
|
|
58
|
-
return len;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
64
|
size_t _mi_strnlen(const char* s, size_t max_len) {
|
|
62
65
|
if (s==NULL) return 0;
|
|
63
66
|
size_t len = 0;
|
|
@@ -65,6 +68,10 @@ size_t _mi_strnlen(const char* s, size_t max_len) {
|
|
|
65
68
|
return len;
|
|
66
69
|
}
|
|
67
70
|
|
|
71
|
+
size_t _mi_strlen(const char* s) {
|
|
72
|
+
return _mi_strnlen(s,PTRDIFF_MAX);
|
|
73
|
+
}
|
|
74
|
+
|
|
68
75
|
char* _mi_strnstr(char* s, size_t max_len, const char* pat) {
|
|
69
76
|
if (s==NULL) return NULL;
|
|
70
77
|
if (pat==NULL) return s;
|
|
@@ -94,6 +101,43 @@ bool _mi_getenv(const char* name, char* result, size_t result_size) {
|
|
|
94
101
|
}
|
|
95
102
|
#endif
|
|
96
103
|
|
|
104
|
+
|
|
105
|
+
// --------------------------------------------------------
|
|
106
|
+
// Define our own primitives for doing an action once
|
|
107
|
+
// --------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
// Returns `true` only on the first invocation, signifying we can execute an action once.
|
|
110
|
+
// If it returns `true`, the caller should call `_mi_atomic_once_release` after performing the action.
|
|
111
|
+
// Other threads (than the initial thread that entered) will block until `_mi_atomic_once_release` has been called.
|
|
112
|
+
bool _mi_atomic_once_enter(mi_atomic_once_t* once) {
|
|
113
|
+
const uintptr_t once_tid = mi_atomic_load_acquire(&once->tid);
|
|
114
|
+
if mi_likely(once_tid == 1) {
|
|
115
|
+
return false; // already executed
|
|
116
|
+
}
|
|
117
|
+
const mi_threadid_t current_tid = _mi_thread_id();
|
|
118
|
+
if (once_tid == current_tid) {
|
|
119
|
+
return false; // recursive invocation; we need this for process_init for example
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
mi_lock_acquire(&once->lock);
|
|
123
|
+
uintptr_t expected = 0;
|
|
124
|
+
if (mi_atomic_cas_strong_acq_rel(&once->tid, &expected, current_tid)) { // could use atomic_load/store as well
|
|
125
|
+
return true; // should execute and release
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
mi_lock_release(&once->lock);
|
|
129
|
+
return false; // already another thread entered and released
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
void _mi_atomic_once_release(mi_atomic_once_t* once) {
|
|
134
|
+
if (mi_atomic_load_acquire(&once->tid)>1) { // paranoia
|
|
135
|
+
mi_atomic_store_release(&once->tid,1); // done executing
|
|
136
|
+
mi_lock_release(&once->lock);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
|
|
97
141
|
// --------------------------------------------------------
|
|
98
142
|
// Define our own limited `_mi_vsnprintf` and `_mi_snprintf`
|
|
99
143
|
// This is mostly to avoid calling these when libc is not yet
|
|
@@ -244,7 +288,8 @@ int _mi_vsnprintf(char* buf, size_t bufsize, const char* fmt, va_list args) {
|
|
|
244
288
|
else x = va_arg(args, unsigned int);
|
|
245
289
|
}
|
|
246
290
|
else if (c == 'p') {
|
|
247
|
-
|
|
291
|
+
void* const p = va_arg(args, void*);
|
|
292
|
+
x = (uintptr_t)p;
|
|
248
293
|
mi_outs("0x", &out, end);
|
|
249
294
|
start = out;
|
|
250
295
|
width = (width >= 2 ? width - 2 : 0);
|
|
@@ -77,7 +77,7 @@ int mi_version(void) mi_attr_noexcept {
|
|
|
77
77
|
#endif
|
|
78
78
|
|
|
79
79
|
#ifndef MI_DEFAULT_GUARDED_SAMPLE_RATE
|
|
80
|
-
#if MI_GUARDED
|
|
80
|
+
#if MI_GUARDED && !MI_DEBUG
|
|
81
81
|
#define MI_DEFAULT_GUARDED_SAMPLE_RATE 4000
|
|
82
82
|
#else
|
|
83
83
|
#define MI_DEFAULT_GUARDED_SAMPLE_RATE 0
|
|
@@ -136,11 +136,7 @@ static mi_option_desc_t mi_options[_mi_option_last] =
|
|
|
136
136
|
{ 0, MI_OPTION_UNINIT, MI_OPTION(deprecated_page_reset) }, // reset page memory on free
|
|
137
137
|
{ 0, MI_OPTION_UNINIT, MI_OPTION(deprecated_abandoned_page_purge) },
|
|
138
138
|
{ 0, MI_OPTION_UNINIT, MI_OPTION(deprecated_segment_reset) }, // reset segment memory on free (needs eager commit)
|
|
139
|
-
#if defined(__NetBSD__)
|
|
140
|
-
{ 0, MI_OPTION_UNINIT, MI_OPTION(eager_commit_delay) }, // the first N segments per thread are not eagerly committed
|
|
141
|
-
#else
|
|
142
139
|
{ 1, MI_OPTION_UNINIT, MI_OPTION(deprecated_eager_commit_delay) },
|
|
143
|
-
#endif
|
|
144
140
|
{ 1000,MI_OPTION_UNINIT, MI_OPTION_LEGACY(purge_delay,reset_delay) }, // purge delay in milli-seconds
|
|
145
141
|
{ 0, MI_OPTION_UNINIT, MI_OPTION(use_numa_nodes) }, // 0 = use available numa nodes, otherwise use at most N nodes.
|
|
146
142
|
{ 0, MI_OPTION_UNINIT, MI_OPTION_LEGACY(disallow_os_alloc,limit_os_alloc) }, // 1 = do not use OS memory for allocation (but only reserved arenas)
|
|
@@ -179,9 +175,10 @@ static mi_option_desc_t mi_options[_mi_option_last] =
|
|
|
179
175
|
MI_OPTION_UNINIT, MI_OPTION(page_cross_thread_max_reclaim) }, // don't reclaim (small) pages across threads if we already own N pages in that size class
|
|
180
176
|
{ MI_DEFAULT_ALLOW_THP,
|
|
181
177
|
MI_OPTION_UNINIT, MI_OPTION(allow_thp) }, // allow transparent huge pages? (=1) (on Android =0 by default). Set to 0 to disable THP for the process.
|
|
182
|
-
{ 0, MI_OPTION_UNINIT, MI_OPTION(minimal_purge_size) }, // set minimal purge size (in KiB) (=0).
|
|
178
|
+
{ 0, MI_OPTION_UNINIT, MI_OPTION(minimal_purge_size) }, // set minimal purge size (in KiB) (=0). Using 0 resolves to either 64 (or 2048 if `mi_option_allow_thp==2`).
|
|
183
179
|
{ MI_DEFAULT_ARENA_MAX_OBJECT_SIZE,
|
|
184
180
|
MI_OPTION_UNINIT, MI_OPTION(arena_max_object_size) }, // set maximal object size that can be allocated in an arena (in KiB) (=2GiB on 64-bit).
|
|
181
|
+
{ 0, MI_OPTION_UNINIT, MI_OPTION(arena_is_numa_local) }, // associate local numa node with an initial arena allocation
|
|
185
182
|
};
|
|
186
183
|
|
|
187
184
|
static void mi_option_init(mi_option_desc_t* desc);
|
|
@@ -221,8 +218,8 @@ void _mi_options_post_init(void) {
|
|
|
221
218
|
mi_decl_export void mi_options_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept
|
|
222
219
|
{
|
|
223
220
|
// show version
|
|
224
|
-
const int vermajor = MI_MALLOC_VERSION/
|
|
225
|
-
const int verminor = (MI_MALLOC_VERSION%
|
|
221
|
+
const int vermajor = MI_MALLOC_VERSION/10000;
|
|
222
|
+
const int verminor = (MI_MALLOC_VERSION%10000)/100;
|
|
226
223
|
const int verpatch = (MI_MALLOC_VERSION%100);
|
|
227
224
|
_mi_fprintf(out, arg, "v%i.%i.%i%s%s (built on %s, %s)\n", vermajor, verminor, verpatch,
|
|
228
225
|
#if defined(MI_CMAKE_BUILD_TYPE)
|
|
@@ -291,7 +288,9 @@ mi_decl_nodiscard size_t mi_option_get_size(mi_option_t option) {
|
|
|
291
288
|
const long x = mi_option_get(option);
|
|
292
289
|
size_t size = (x < 0 ? 0 : (size_t)x);
|
|
293
290
|
if (mi_option_has_size_in_kib(option)) {
|
|
294
|
-
size
|
|
291
|
+
if (mi_mul_overflow(size, MI_KiB, &size)) {
|
|
292
|
+
size = MI_MAX_ALLOC_SIZE;
|
|
293
|
+
}
|
|
295
294
|
}
|
|
296
295
|
return size;
|
|
297
296
|
}
|
|
@@ -355,36 +354,41 @@ static void mi_cdecl mi_out_stderr(const char* msg, void* arg) {
|
|
|
355
354
|
#ifndef MI_MAX_DELAY_OUTPUT
|
|
356
355
|
#define MI_MAX_DELAY_OUTPUT ((size_t)(16*1024))
|
|
357
356
|
#endif
|
|
358
|
-
static char
|
|
357
|
+
static char out_buf[MI_MAX_DELAY_OUTPUT+1];
|
|
359
358
|
static _Atomic(size_t) out_len;
|
|
359
|
+
static mi_lock_t out_buf_lock = MI_LOCK_INITIALIZER;
|
|
360
360
|
|
|
361
361
|
static void mi_cdecl mi_out_buf(const char* msg, void* arg) {
|
|
362
362
|
MI_UNUSED(arg);
|
|
363
363
|
if (msg==NULL) return;
|
|
364
|
-
if (
|
|
364
|
+
if (mi_atomic_load_acquire(&out_len)>=MI_MAX_DELAY_OUTPUT) return;
|
|
365
365
|
size_t n = _mi_strlen(msg);
|
|
366
|
-
if (n==0) return;
|
|
367
|
-
//
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
366
|
+
if (n==0 || n >= MI_MAX_DELAY_OUTPUT) return;
|
|
367
|
+
// copy msg into the buffer
|
|
368
|
+
mi_lock(&out_buf_lock) {
|
|
369
|
+
const size_t start = mi_atomic_add_acq_rel(&out_len, n);
|
|
370
|
+
if (start < MI_MAX_DELAY_OUTPUT) {
|
|
371
|
+
// check bound
|
|
372
|
+
if (start+n >= MI_MAX_DELAY_OUTPUT) {
|
|
373
|
+
n = MI_MAX_DELAY_OUTPUT-start-1;
|
|
374
|
+
}
|
|
375
|
+
_mi_memcpy(&out_buf[start], msg, n);
|
|
376
|
+
}
|
|
373
377
|
}
|
|
374
|
-
mi_assert_internal(start + n <= MI_MAX_DELAY_OUTPUT);
|
|
375
|
-
_mi_memcpy(&mi_output_buffer[start], msg, n);
|
|
376
378
|
}
|
|
377
379
|
|
|
378
380
|
static void mi_out_buf_flush(mi_output_fun* out, bool no_more_buf, void* arg) {
|
|
379
381
|
if (out==NULL) return;
|
|
380
382
|
// claim (if `no_more_buf == true`, no more output will be added after this point)
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
383
|
+
mi_lock(&out_buf_lock) {
|
|
384
|
+
size_t count = mi_atomic_add_acq_rel(&out_len, (no_more_buf ? MI_MAX_DELAY_OUTPUT : 1));
|
|
385
|
+
// and output the current contents
|
|
386
|
+
if (count>MI_MAX_DELAY_OUTPUT) count = MI_MAX_DELAY_OUTPUT;
|
|
387
|
+
out_buf[count] = 0;
|
|
388
|
+
out(out_buf,arg);
|
|
389
|
+
if (!no_more_buf) {
|
|
390
|
+
out_buf[count] = '\n'; // if continue with the buffer, insert a newline
|
|
391
|
+
}
|
|
388
392
|
}
|
|
389
393
|
}
|
|
390
394
|
|
|
@@ -402,30 +406,29 @@ static void mi_cdecl mi_out_buf_stderr(const char* msg, void* arg) {
|
|
|
402
406
|
// Default output handler
|
|
403
407
|
// --------------------------------------------------------
|
|
404
408
|
|
|
405
|
-
//
|
|
406
|
-
//
|
|
407
|
-
static
|
|
409
|
+
// The program should only install a single output handler from a single thread
|
|
410
|
+
// since otherwise the argument and output function may not match.
|
|
411
|
+
static _Atomic(void*) mi_out_default; // = // is `mi_output_fun*` (but some platforms don't support atomic function pointers)
|
|
408
412
|
static _Atomic(void*) mi_out_arg; // = NULL
|
|
409
413
|
|
|
410
414
|
static mi_output_fun* mi_out_get_default(void** parg) {
|
|
415
|
+
mi_output_fun* const out = (mi_output_fun*)mi_atomic_load_ptr_acquire(void,&mi_out_default);
|
|
411
416
|
if (parg != NULL) { *parg = mi_atomic_load_ptr_acquire(void,&mi_out_arg); }
|
|
412
|
-
mi_output_fun* out = mi_out_default;
|
|
413
417
|
return (out == NULL ? &mi_out_buf : out);
|
|
414
418
|
}
|
|
415
419
|
|
|
416
420
|
void mi_register_output(mi_output_fun* out, void* arg) mi_attr_noexcept {
|
|
417
|
-
mi_out_default
|
|
421
|
+
mi_atomic_store_ptr_release(void,&mi_out_default, (void*)(out == NULL ? &mi_out_stderr : out)); // stop using the delayed output buffer
|
|
418
422
|
mi_atomic_store_ptr_release(void,&mi_out_arg, arg);
|
|
419
|
-
if (out!=NULL) mi_out_buf_flush(out,true,arg);
|
|
423
|
+
if (out!=NULL) { mi_out_buf_flush(out,true,arg); } // output all the delayed output now
|
|
420
424
|
}
|
|
421
425
|
|
|
422
426
|
// add stderr to the delayed output after the module is loaded
|
|
423
427
|
static void mi_add_stderr_output(void) {
|
|
424
428
|
mi_assert_internal(mi_out_default == NULL);
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
}
|
|
429
|
+
mi_out_buf_flush(&mi_out_stderr, false, NULL); // flush current contents to stderr
|
|
430
|
+
mi_atomic_store_ptr_release(void,&mi_out_default,(void*)&mi_out_buf_stderr); // and add stderr to the delayed output
|
|
431
|
+
mi_atomic_store_ptr_release(void,&mi_out_arg,NULL);
|
|
429
432
|
}
|
|
430
433
|
|
|
431
434
|
// --------------------------------------------------------
|
|
@@ -649,11 +652,11 @@ static void mi_option_init(mi_option_desc_t* desc) {
|
|
|
649
652
|
buf[i] = _mi_toupper(s[i]);
|
|
650
653
|
}
|
|
651
654
|
buf[len] = 0;
|
|
652
|
-
if (buf[0] == 0 ||
|
|
655
|
+
if (buf[0] == 0 || _mi_streq(buf,"1") || _mi_streq(buf,"TRUE") || _mi_streq(buf,"YES") || _mi_streq(buf,"ON")) {
|
|
653
656
|
desc->value = 1;
|
|
654
657
|
desc->init = MI_OPTION_INITIALIZED;
|
|
655
658
|
}
|
|
656
|
-
else if (
|
|
659
|
+
else if (_mi_streq(buf,"0") || _mi_streq(buf,"FALSE") || _mi_streq(buf,"NO") || _mi_streq(buf,"OFF")) {
|
|
657
660
|
desc->value = 0;
|
|
658
661
|
desc->init = MI_OPTION_INITIALIZED;
|
|
659
662
|
}
|
|
@@ -672,7 +675,7 @@ static void mi_option_init(mi_option_desc_t* desc) {
|
|
|
672
675
|
else { size = (size + MI_KiB - 1) / MI_KiB; }
|
|
673
676
|
if (end[0] == 'I' && end[1] == 'B') { end += 2; } // KiB, MiB, GiB, TiB
|
|
674
677
|
else if (*end == 'B') { end++; } // Kb, Mb, Gb, Tb
|
|
675
|
-
if (overflow || size > MI_MAX_ALLOC_SIZE) { size = (MI_MAX_ALLOC_SIZE / MI_KiB); }
|
|
678
|
+
if (overflow || size > (MI_MAX_ALLOC_SIZE / MI_KiB)) { size = (MI_MAX_ALLOC_SIZE / MI_KiB); }
|
|
676
679
|
value = (size > LONG_MAX ? LONG_MAX : (long)size);
|
|
677
680
|
}
|
|
678
681
|
if (*end == 0) {
|
package/vendor/mimalloc/src/os.c
CHANGED
|
@@ -57,7 +57,7 @@ size_t _mi_os_minimal_purge_size(void) {
|
|
|
57
57
|
if (minsize != 0) {
|
|
58
58
|
return _mi_align_up(minsize, _mi_os_page_size());
|
|
59
59
|
}
|
|
60
|
-
else if (mi_os_mem_config.has_transparent_huge_pages &&
|
|
60
|
+
else if (mi_os_mem_config.has_transparent_huge_pages && mi_option_get(mi_option_allow_thp) == 2) {
|
|
61
61
|
return _mi_os_large_page_size();
|
|
62
62
|
}
|
|
63
63
|
else {
|
|
@@ -106,10 +106,57 @@ void _mi_os_init(void) {
|
|
|
106
106
|
bool _mi_os_decommit(void* addr, size_t size);
|
|
107
107
|
bool _mi_os_commit(void* addr, size_t size, bool* is_zero);
|
|
108
108
|
|
|
109
|
+
// On systems with enough virtual address bits, we can do efficient aligned allocation by using
|
|
110
|
+
// the 2TiB to 30TiB area to allocate those. If we have at least 46 bits of virtual address
|
|
111
|
+
// space (64TiB) we use this technique. (but see issue #939)
|
|
112
|
+
#if (MI_INTPTR_SIZE >= 8) && !defined(MI_NO_ALIGNED_HINT) // && !defined(WIN32) && !defined(ANDROID)
|
|
113
|
+
|
|
114
|
+
// Return a MI_HINT_ALIGN (4MiB) aligned address that is probably available.
|
|
115
|
+
// If this returns NULL, the OS will determine the address but on some OS's that may not be
|
|
116
|
+
// properly aligned which can be more costly as it needs to be adjusted afterwards.
|
|
117
|
+
// For a size > 16GiB this always returns NULL in order to guarantee good ASLR randomization;
|
|
118
|
+
// (otherwise an initial large allocation of say 2TiB has a 50% chance to include (known) addresses
|
|
119
|
+
// in the middle of the 2TiB - 6TiB address range (see issue #372))
|
|
120
|
+
|
|
121
|
+
#define MI_HINT_ALIGN ((uintptr_t)4 << 20) // 4MiB alignment
|
|
122
|
+
#define MI_HINT_BASE ((uintptr_t)2 << 40) // 2TiB start
|
|
123
|
+
#define MI_HINT_AREA ((uintptr_t)4 << 40) // upto (2+4) 6TiB (since before win8 there is "only" 8TiB available to processes)
|
|
124
|
+
#define MI_HINT_MAX ((uintptr_t)30 << 40) // wrap after 30TiB (area after 32TiB is used for huge OS pages)
|
|
125
|
+
|
|
126
|
+
void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size)
|
|
127
|
+
{
|
|
128
|
+
static mi_decl_cache_align _Atomic(uintptr_t) aligned_base; // = 0
|
|
129
|
+
|
|
130
|
+
// todo: perhaps only do alignment hints if THP is enabled?
|
|
131
|
+
if (try_alignment <= mi_os_mem_config.alloc_granularity || try_alignment > MI_HINT_ALIGN) return NULL;
|
|
132
|
+
if (mi_os_mem_config.virtual_address_bits < 46) return NULL; // < 64TiB virtual address space
|
|
133
|
+
size = _mi_align_up(size, MI_HINT_ALIGN);
|
|
134
|
+
if (size > 16*MI_GiB) return NULL; // guarantee the chance of fixed valid address is at least 1/(MI_HINT_AREA / 1<<34)
|
|
135
|
+
size += MI_HINT_ALIGN; // put in virtual gaps between hinted blocks; this splits VLA's but increases guarded areas.
|
|
136
|
+
|
|
137
|
+
uintptr_t hint = mi_atomic_add_acq_rel(&aligned_base, size);
|
|
138
|
+
if (hint == 0 || hint > MI_HINT_MAX) { // wrap or initialize
|
|
139
|
+
uintptr_t init = MI_HINT_BASE;
|
|
140
|
+
#if (MI_SECURE>=1 || defined(NDEBUG)) // security: randomize start of aligned allocations unless in debug mode
|
|
141
|
+
mi_theap_t* const theap = _mi_theap_default(); // don't use `mi_theap_get_default()` as that can cause allocation recursively (issue #1267)
|
|
142
|
+
if (!mi_theap_is_initialized(theap)) return NULL; // no hint as we lack randomness at this point
|
|
143
|
+
const uintptr_t r = _mi_theap_random_next(theap);
|
|
144
|
+
init = init + ((MI_HINT_ALIGN * ((r>>17) & 0xFFFFF)) % MI_HINT_AREA); // (randomly 20 bits)*4MiB == 0 to 4TiB
|
|
145
|
+
#endif
|
|
146
|
+
uintptr_t expected = hint + size;
|
|
147
|
+
mi_atomic_cas_strong_acq_rel(&aligned_base, &expected, init);
|
|
148
|
+
hint = mi_atomic_add_acq_rel(&aligned_base, size); // this may still give 0 or > MI_HINT_MAX but that is ok, it is a hint after all
|
|
149
|
+
}
|
|
150
|
+
mi_assert_internal(hint%MI_HINT_ALIGN == 0);
|
|
151
|
+
if (hint%try_alignment != 0) return NULL;
|
|
152
|
+
return (void*)hint;
|
|
153
|
+
}
|
|
154
|
+
#else
|
|
109
155
|
void* _mi_os_get_aligned_hint(size_t try_alignment, size_t size) {
|
|
110
|
-
|
|
111
|
-
|
|
156
|
+
MI_UNUSED(try_alignment); MI_UNUSED(size);
|
|
157
|
+
return NULL;
|
|
112
158
|
}
|
|
159
|
+
#endif
|
|
113
160
|
|
|
114
161
|
|
|
115
162
|
/* -----------------------------------------------------------
|
|
@@ -251,6 +298,13 @@ static void* mi_os_prim_alloc_at(void* hint_addr, size_t size, size_t try_alignm
|
|
|
251
298
|
if (size == 0) return NULL;
|
|
252
299
|
if (!commit) { allow_large = false; }
|
|
253
300
|
if (try_alignment == 0) { try_alignment = 1; } // avoid 0 to ensure there will be no divide by zero when aligning
|
|
301
|
+
|
|
302
|
+
// try to align along large OS page size for larger allocations
|
|
303
|
+
const size_t large_page_size = mi_os_mem_config.large_page_size;
|
|
304
|
+
if (large_page_size > 0 && hint_addr == NULL && size >= 8*large_page_size && _mi_is_power_of_two(try_alignment) && try_alignment < large_page_size) {
|
|
305
|
+
try_alignment = large_page_size;
|
|
306
|
+
}
|
|
307
|
+
|
|
254
308
|
*is_zero = false;
|
|
255
309
|
void* p = NULL;
|
|
256
310
|
int err = _mi_prim_alloc(hint_addr, size, try_alignment, commit, allow_large, is_large, is_zero, &p);
|
|
@@ -280,27 +334,30 @@ static void* mi_os_prim_alloc(size_t size, size_t try_alignment, bool commit, bo
|
|
|
280
334
|
|
|
281
335
|
// Primitive aligned allocation from the OS.
|
|
282
336
|
// This function guarantees the allocated memory is aligned.
|
|
283
|
-
static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large,
|
|
337
|
+
static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit, bool allow_large, mi_memid_t* memid) {
|
|
338
|
+
mi_assert_internal(memid!=NULL);
|
|
284
339
|
mi_assert_internal(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0));
|
|
285
340
|
mi_assert_internal(size > 0 && (size % _mi_os_page_size()) == 0);
|
|
286
|
-
|
|
287
|
-
mi_assert_internal(is_zero != NULL);
|
|
288
|
-
mi_assert_internal(base != NULL);
|
|
341
|
+
*memid = _mi_memid_none();
|
|
289
342
|
if (!commit) allow_large = false;
|
|
290
343
|
if (!(alignment >= _mi_os_page_size() && ((alignment & (alignment - 1)) == 0))) return NULL;
|
|
291
344
|
size = _mi_align_up(size, _mi_os_page_size());
|
|
292
345
|
|
|
293
|
-
// try a direct allocation if the alignment is below the default, or
|
|
294
|
-
const bool try_direct_alloc = (alignment <= mi_os_mem_config.alloc_granularity || alignment
|
|
346
|
+
// try a direct allocation if the alignment is below the default, or less than or equal to 1/4 fraction of the size.
|
|
347
|
+
const bool try_direct_alloc = (alignment <= mi_os_mem_config.alloc_granularity || alignment <= size/4);
|
|
295
348
|
|
|
349
|
+
bool os_is_large = false;
|
|
350
|
+
bool os_is_zero = false;
|
|
351
|
+
void* os_base = NULL;
|
|
352
|
+
size_t os_size = size;
|
|
296
353
|
void* p = NULL;
|
|
297
354
|
if (try_direct_alloc) {
|
|
298
|
-
p = mi_os_prim_alloc(size, alignment, commit, allow_large,
|
|
355
|
+
p = mi_os_prim_alloc(size, alignment, commit, allow_large, &os_is_large, &os_is_zero);
|
|
299
356
|
}
|
|
300
357
|
|
|
301
358
|
// aligned already?
|
|
302
|
-
if (p != NULL && (
|
|
303
|
-
|
|
359
|
+
if (p != NULL && _mi_is_aligned(p,alignment)) {
|
|
360
|
+
os_base = p;
|
|
304
361
|
}
|
|
305
362
|
else {
|
|
306
363
|
// if not aligned, free it, overallocate, and unmap around it
|
|
@@ -315,43 +372,47 @@ static void* mi_os_prim_alloc_aligned(size_t size, size_t alignment, bool commit
|
|
|
315
372
|
|
|
316
373
|
if (!mi_os_mem_config.has_partial_free) { // win32 virtualAlloc cannot free parts of an allocated block
|
|
317
374
|
// over-allocate uncommitted (virtual) memory
|
|
318
|
-
p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */,
|
|
375
|
+
p = mi_os_prim_alloc(over_size, 1 /*alignment*/, false /* commit? */, false /* allow_large */, &os_is_large, &os_is_zero);
|
|
319
376
|
if (p == NULL) return NULL;
|
|
320
377
|
|
|
321
378
|
// set p to the aligned part in the full region
|
|
322
|
-
// note:
|
|
323
|
-
// this is
|
|
324
|
-
|
|
379
|
+
// note: Windows VirtualFree needs the actual base pointer
|
|
380
|
+
// this is handled though by having the `base` field in the memid
|
|
381
|
+
os_base = p; // remember the base
|
|
382
|
+
os_size = over_size;
|
|
325
383
|
p = _mi_align_up_ptr(p, alignment);
|
|
326
384
|
|
|
327
385
|
// explicitly commit only the aligned part
|
|
328
386
|
if (commit) {
|
|
329
387
|
if (!_mi_os_commit(p, size, NULL)) {
|
|
330
|
-
mi_os_prim_free(
|
|
388
|
+
mi_os_prim_free(os_base, over_size, 0, NULL);
|
|
331
389
|
return NULL;
|
|
332
390
|
}
|
|
333
391
|
}
|
|
334
392
|
}
|
|
335
393
|
else { // mmap can free inside an allocation
|
|
336
394
|
// overallocate...
|
|
337
|
-
p = mi_os_prim_alloc(over_size, 1, commit, false,
|
|
395
|
+
p = mi_os_prim_alloc(over_size, 1, commit, false, &os_is_large, &os_is_zero);
|
|
338
396
|
if (p == NULL) return NULL;
|
|
339
397
|
|
|
340
398
|
// and selectively unmap parts around the over-allocated area.
|
|
341
|
-
void* aligned_p = _mi_align_up_ptr(p, alignment);
|
|
342
|
-
size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p;
|
|
343
|
-
size_t mid_size = _mi_align_up(size, _mi_os_page_size());
|
|
344
|
-
size_t post_size = over_size - pre_size - mid_size;
|
|
399
|
+
void* const aligned_p = _mi_align_up_ptr(p, alignment);
|
|
400
|
+
const size_t pre_size = (uint8_t*)aligned_p - (uint8_t*)p;
|
|
401
|
+
const size_t mid_size = _mi_align_up(size, _mi_os_page_size());
|
|
402
|
+
const size_t post_size = over_size - pre_size - mid_size;
|
|
345
403
|
mi_assert_internal(pre_size < over_size&& post_size < over_size&& mid_size >= size);
|
|
346
404
|
if (pre_size > 0) { mi_os_prim_free(p, pre_size, (commit ? pre_size : 0), NULL); }
|
|
347
405
|
if (post_size > 0) { mi_os_prim_free((uint8_t*)aligned_p + mid_size, post_size, (commit ? post_size : 0), NULL); }
|
|
348
406
|
// we can return the aligned pointer on `mmap` systems
|
|
349
407
|
p = aligned_p;
|
|
350
|
-
|
|
408
|
+
os_base = aligned_p; // since we freed the pre part, `*base == p`.
|
|
409
|
+
os_size = mid_size;
|
|
351
410
|
}
|
|
352
411
|
}
|
|
353
412
|
|
|
354
|
-
mi_assert_internal(p
|
|
413
|
+
mi_assert_internal(p != NULL && os_base != NULL && _mi_is_aligned(p,alignment));
|
|
414
|
+
mi_assert_internal(os_base <= p && size <= os_size);
|
|
415
|
+
*memid = _mi_memid_create_os(os_base,os_size,commit,os_is_zero,os_is_large);
|
|
355
416
|
return p;
|
|
356
417
|
}
|
|
357
418
|
|
|
@@ -383,16 +444,9 @@ void* _mi_os_alloc_aligned(size_t size, size_t alignment, bool commit, bool allo
|
|
|
383
444
|
size = _mi_os_good_alloc_size(size);
|
|
384
445
|
alignment = _mi_align_up(alignment, _mi_os_page_size());
|
|
385
446
|
|
|
386
|
-
|
|
387
|
-
bool os_is_zero = false;
|
|
388
|
-
void* os_base = NULL;
|
|
389
|
-
void* p = mi_os_prim_alloc_aligned(size, alignment, commit, allow_large, &os_is_large, &os_is_zero, &os_base );
|
|
447
|
+
void* p = mi_os_prim_alloc_aligned(size, alignment, commit, allow_large, memid );
|
|
390
448
|
if (p == NULL) return NULL;
|
|
391
449
|
|
|
392
|
-
*memid = _mi_memid_create_os(p, size, commit, os_is_zero, os_is_large);
|
|
393
|
-
memid->mem.os.base = os_base;
|
|
394
|
-
memid->mem.os.size += ((uint8_t*)p - (uint8_t*)os_base); // todo: return from prim_alloc_aligned?
|
|
395
|
-
|
|
396
450
|
mi_assert_internal(memid->mem.os.size >= size);
|
|
397
451
|
mi_assert_internal(_mi_is_aligned(p,alignment));
|
|
398
452
|
if (commit) { mi_assert_internal(memid->initially_committed); }
|
|
@@ -435,6 +489,7 @@ void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t offse
|
|
|
435
489
|
mi_assert(offset <= size);
|
|
436
490
|
mi_assert((alignment % _mi_os_page_size()) == 0);
|
|
437
491
|
*memid = _mi_memid_none();
|
|
492
|
+
if (offset > size) return NULL;
|
|
438
493
|
if (offset == 0) {
|
|
439
494
|
// regular aligned allocation
|
|
440
495
|
return _mi_os_alloc_aligned(size, alignment, commit, allow_large, memid);
|
|
@@ -442,6 +497,7 @@ void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t offse
|
|
|
442
497
|
else {
|
|
443
498
|
// overallocate to align at an offset
|
|
444
499
|
const size_t extra = _mi_align_up(offset, alignment) - offset;
|
|
500
|
+
if (size >= SIZE_MAX - extra) return NULL; // too large
|
|
445
501
|
const size_t oversize = size + extra;
|
|
446
502
|
void* const start = _mi_os_alloc_aligned(oversize, alignment, commit, allow_large, memid);
|
|
447
503
|
if (start == NULL) return NULL;
|
|
@@ -449,7 +505,7 @@ void* _mi_os_alloc_aligned_at_offset(size_t size, size_t alignment, size_t offse
|
|
|
449
505
|
void* const p = (uint8_t*)start + extra;
|
|
450
506
|
mi_assert(_mi_is_aligned((uint8_t*)p + offset, alignment));
|
|
451
507
|
// decommit the overallocation at the start
|
|
452
|
-
if (commit && extra
|
|
508
|
+
if (commit && extra >= _mi_os_page_size()) {
|
|
453
509
|
_mi_os_decommit(start, extra);
|
|
454
510
|
}
|
|
455
511
|
return p;
|
|
@@ -469,9 +525,9 @@ static void* mi_os_page_align_areax(bool conservative, void* addr, size_t size,
|
|
|
469
525
|
|
|
470
526
|
// page align conservatively within the range, or liberally straddling pages outside the range
|
|
471
527
|
void* start = (conservative ? _mi_align_up_ptr(addr, _mi_os_page_size())
|
|
472
|
-
|
|
473
|
-
void* end
|
|
474
|
-
|
|
528
|
+
: _mi_align_down_ptr(addr, _mi_os_page_size()));
|
|
529
|
+
void* end = (conservative ? _mi_align_down_ptr((uint8_t*)addr + size, _mi_os_page_size())
|
|
530
|
+
: _mi_align_up_ptr((uint8_t*)addr + size, _mi_os_page_size()));
|
|
475
531
|
ptrdiff_t diff = (uint8_t*)end - (uint8_t*)start;
|
|
476
532
|
if (diff <= 0) return NULL;
|
|
477
533
|
|
|
@@ -519,7 +575,6 @@ bool _mi_os_commit(void* addr, size_t size, bool* is_zero) {
|
|
|
519
575
|
|
|
520
576
|
static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, size_t stat_size) {
|
|
521
577
|
mi_assert_internal(needs_recommit!=NULL);
|
|
522
|
-
mi_os_stat_decrease(committed, stat_size);
|
|
523
578
|
|
|
524
579
|
// page align
|
|
525
580
|
size_t csize;
|
|
@@ -532,6 +587,9 @@ static bool mi_os_decommit_ex(void* addr, size_t size, bool* needs_recommit, siz
|
|
|
532
587
|
if (err != 0) {
|
|
533
588
|
_mi_warning_message("cannot decommit OS memory (error: %d (0x%x), address: %p, size: 0x%zx bytes)\n", err, err, start, csize);
|
|
534
589
|
}
|
|
590
|
+
else if (*needs_recommit) {
|
|
591
|
+
mi_os_stat_decrease(committed, stat_size);
|
|
592
|
+
}
|
|
535
593
|
mi_assert_internal(err == 0);
|
|
536
594
|
return (err == 0);
|
|
537
595
|
}
|
|
@@ -663,10 +721,16 @@ static uint8_t* mi_os_claim_huge_pages(size_t pages, size_t* total_size) {
|
|
|
663
721
|
if (start == 0) {
|
|
664
722
|
// Initialize the start address after the 32TiB area
|
|
665
723
|
start = ((uintptr_t)8 << 40); // 8TiB virtual start address
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
724
|
+
#if (MI_SECURE>0 || MI_DEBUG==0) // security: randomize start of huge pages unless in debug mode
|
|
725
|
+
mi_theap_t* const theap = _mi_theap_default(); // don't use `mi_theap_get_default()` as that can cause allocation recursively (issue #1267)
|
|
726
|
+
if (mi_theap_is_initialized(theap)) { // todo: or no hint at all if we lack randomness?
|
|
727
|
+
const uintptr_t r = _mi_theap_random_next(theap);
|
|
728
|
+
start = start + ((uintptr_t)MI_HUGE_OS_PAGE_SIZE * ((r>>17) & 0x0FFF)); // (randomly 12bits)*1GiB == between 0 to 4TiB
|
|
729
|
+
}
|
|
730
|
+
else {
|
|
731
|
+
_mi_warning_message("failed to randomize the start address of huge pages allocation (%zu bytes at %p)", size, start);
|
|
732
|
+
}
|
|
733
|
+
#endif
|
|
670
734
|
}
|
|
671
735
|
end = start + size;
|
|
672
736
|
} while (!mi_atomic_cas_weak_acq_rel(&mi_huge_start, &huge_start, end));
|
|
@@ -739,16 +803,17 @@ void* _mi_os_alloc_huge_os_pages(size_t pages, int numa_node, mi_msecs_t max_mse
|
|
|
739
803
|
}
|
|
740
804
|
}
|
|
741
805
|
}
|
|
742
|
-
|
|
806
|
+
const size_t allocated = page * MI_HUGE_OS_PAGE_SIZE;
|
|
807
|
+
mi_assert_internal(allocated <= size);
|
|
743
808
|
if (pages_reserved != NULL) { *pages_reserved = page; }
|
|
744
|
-
if (psize != NULL) { *psize =
|
|
809
|
+
if (psize != NULL) { *psize = allocated; }
|
|
745
810
|
if (page != 0) {
|
|
746
811
|
mi_assert(start != NULL);
|
|
747
|
-
*memid = _mi_memid_create_os(start,
|
|
812
|
+
*memid = _mi_memid_create_os(start, allocated, true /* is committed */, all_zero, true /* is_large */);
|
|
748
813
|
memid->memkind = MI_MEM_OS_HUGE;
|
|
749
814
|
mi_assert(memid->is_pinned);
|
|
750
815
|
#ifdef MI_TRACK_ASAN
|
|
751
|
-
if (all_zero) { mi_track_mem_defined(start,
|
|
816
|
+
if (all_zero) { mi_track_mem_defined(start,allocated); }
|
|
752
817
|
#endif
|
|
753
818
|
}
|
|
754
819
|
return (page == 0 ? NULL : start);
|
|
@@ -42,6 +42,9 @@ bool _mi_page_map_init(void) {
|
|
|
42
42
|
if (vbits >= 48) { vbits = 47; }
|
|
43
43
|
#endif
|
|
44
44
|
}
|
|
45
|
+
if (vbits < MI_ARENA_SLICE_SHIFT) {
|
|
46
|
+
vbits = MI_ARENA_SLICE_SHIFT;
|
|
47
|
+
}
|
|
45
48
|
|
|
46
49
|
// Allocate the page map and commit bits
|
|
47
50
|
mi_page_map_max_address = (void*)(vbits >= MI_SIZE_BITS ? (SIZE_MAX - MI_ARENA_SLICE_SIZE + 1) : (MI_PU(1) << vbits));
|
|
@@ -127,13 +130,13 @@ static size_t mi_page_map_get_idx(mi_page_t* page, uint8_t** page_start, size_t*
|
|
|
127
130
|
size_t page_size;
|
|
128
131
|
*page_start = mi_page_area(page, &page_size);
|
|
129
132
|
if (page_size > MI_LARGE_PAGE_SIZE) { page_size = MI_LARGE_PAGE_SIZE - MI_ARENA_SLICE_SIZE; } // furthest interior pointer
|
|
130
|
-
*slice_count = mi_slice_count_of_size(page_size) + ((
|
|
133
|
+
*slice_count = mi_slice_count_of_size(page_size) + ((*page_start - mi_page_slice_start(page))/MI_ARENA_SLICE_SIZE); // add for large aligned blocks
|
|
131
134
|
return _mi_page_map_index(page);
|
|
132
135
|
}
|
|
133
136
|
|
|
134
137
|
bool _mi_page_map_register(mi_page_t* page) {
|
|
135
138
|
mi_assert_internal(page != NULL);
|
|
136
|
-
mi_assert_internal(_mi_is_aligned(page, MI_PAGE_ALIGN));
|
|
139
|
+
mi_assert_internal(_mi_is_aligned(mi_page_slice_start(page), MI_PAGE_ALIGN));
|
|
137
140
|
mi_assert_internal(_mi_page_map != NULL); // should be initialized before multi-thread access!
|
|
138
141
|
if mi_unlikely(_mi_page_map == NULL) {
|
|
139
142
|
if (!_mi_page_map_init()) return false;
|
|
@@ -193,7 +196,7 @@ mi_decl_nodiscard mi_decl_export bool mi_is_in_heap_region(const void* p) mi_att
|
|
|
193
196
|
|
|
194
197
|
// A 2-level page map
|
|
195
198
|
#define MI_PAGE_MAP_SUB_SIZE (MI_PAGE_MAP_SUB_COUNT * sizeof(mi_page_t*))
|
|
196
|
-
#define MI_PAGE_MAP_ENTRIES_PER_CBIT (MI_PAGE_MAP_COUNT / MI_BFIELD_BITS)
|
|
199
|
+
#define MI_PAGE_MAP_ENTRIES_PER_CBIT (MI_PAGE_MAP_COUNT < MI_BFIELD_BITS ? 1 : (MI_PAGE_MAP_COUNT / MI_BFIELD_BITS))
|
|
197
200
|
|
|
198
201
|
mi_decl_cache_align _Atomic(mi_submap_t)* _mi_page_map;
|
|
199
202
|
static size_t mi_page_map_count;
|
|
@@ -236,6 +239,9 @@ bool _mi_page_map_init(void) {
|
|
|
236
239
|
if (vbits >= 48) { vbits = 47; }
|
|
237
240
|
#endif
|
|
238
241
|
}
|
|
242
|
+
if (vbits < MI_PAGE_MAP_SUB_SHIFT + MI_ARENA_SLICE_SHIFT) {
|
|
243
|
+
vbits = MI_PAGE_MAP_SUB_SHIFT + MI_ARENA_SLICE_SHIFT;
|
|
244
|
+
}
|
|
239
245
|
|
|
240
246
|
// Allocate the page map and commit bits
|
|
241
247
|
mi_assert(MI_MAX_VABITS >= vbits);
|
|
@@ -308,7 +314,7 @@ void _mi_page_map_unsafe_destroy(mi_subproc_t* subproc) {
|
|
|
308
314
|
mi_page_map_count = 0;
|
|
309
315
|
mi_page_map_memid = _mi_memid_none();
|
|
310
316
|
mi_page_map_max_address = NULL;
|
|
311
|
-
mi_atomic_store_release(&mi_page_map_commit, 0);
|
|
317
|
+
mi_atomic_store_release(&mi_page_map_commit, (mi_bfield_t)0);
|
|
312
318
|
}
|
|
313
319
|
|
|
314
320
|
|
|
@@ -383,13 +389,13 @@ static size_t mi_page_map_get_idx(mi_page_t* page, size_t* sub_idx, size_t* slic
|
|
|
383
389
|
size_t page_size;
|
|
384
390
|
uint8_t* page_start = mi_page_area(page, &page_size);
|
|
385
391
|
if (page_size > MI_LARGE_PAGE_SIZE) { page_size = MI_LARGE_PAGE_SIZE - MI_ARENA_SLICE_SIZE; } // furthest interior pointer
|
|
386
|
-
*slice_count = mi_slice_count_of_size(page_size) + ((page_start - (
|
|
387
|
-
return _mi_page_map_index(
|
|
392
|
+
*slice_count = mi_slice_count_of_size(page_size) + ((page_start - mi_page_slice_start(page))/MI_ARENA_SLICE_SIZE); // add for large aligned blocks
|
|
393
|
+
return _mi_page_map_index(page_start, sub_idx);
|
|
388
394
|
}
|
|
389
395
|
|
|
390
396
|
bool _mi_page_map_register(mi_page_t* page) {
|
|
391
397
|
mi_assert_internal(page != NULL);
|
|
392
|
-
mi_assert_internal(_mi_is_aligned(page, MI_PAGE_ALIGN));
|
|
398
|
+
mi_assert_internal(_mi_is_aligned(mi_page_slice_start(page), MI_PAGE_ALIGN));
|
|
393
399
|
mi_assert_internal(_mi_page_map != NULL); // should be initialized before multi-thread access!
|
|
394
400
|
if mi_unlikely(_mi_page_map == NULL) {
|
|
395
401
|
if (!_mi_page_map_init()) return false;
|
|
@@ -404,7 +410,7 @@ bool _mi_page_map_register(mi_page_t* page) {
|
|
|
404
410
|
void _mi_page_map_unregister(mi_page_t* page) {
|
|
405
411
|
mi_assert_internal(_mi_page_map != NULL);
|
|
406
412
|
mi_assert_internal(page != NULL);
|
|
407
|
-
mi_assert_internal(_mi_is_aligned(page, MI_PAGE_ALIGN));
|
|
413
|
+
mi_assert_internal(_mi_is_aligned(mi_page_slice_start(page), MI_PAGE_ALIGN));
|
|
408
414
|
if mi_unlikely(_mi_page_map == NULL) return;
|
|
409
415
|
// get index and count
|
|
410
416
|
size_t slice_count;
|