@shd101wyy/yo 0.1.23 → 0.1.25
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 +74 -1
- package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +115 -0
- package/.github/skills/yo-syntax/syntax-cheatsheet.md +626 -6
- package/out/cjs/index.cjs +563 -564
- package/out/cjs/yo-cli.cjs +722 -715
- package/out/cjs/yo-lsp.cjs +601 -602
- package/out/esm/index.mjs +506 -507
- package/out/types/src/codegen/utils/index.d.ts +1 -0
- package/out/types/src/expr.d.ts +1 -0
- package/out/types/src/parser.d.ts +1 -0
- package/out/types/src/test-runner.d.ts +1 -0
- package/out/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/std/build.yo +2 -2
- package/std/collections/array_list.yo +26 -0
- package/std/imm/map.yo +15 -15
- package/std/imm/sorted_map.yo +14 -14
- package/std/imm/string.yo +4 -4
- package/std/prelude.yo +18 -23
- package/std/process/command.yo +8 -8
- package/std/string/string.yo +76 -55
- package/std/string/unicode.yo +6 -6
- package/std/sys/signal.yo +6 -6
- 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
|
@@ -33,46 +33,42 @@ void mi_heap_stats_merge_to_main(mi_heap_t* heap) {
|
|
|
33
33
|
_mi_stats_merge_into(&mi_heap_main()->stats, &heap->stats);
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
static mi_theap_t* mi_heap_init_theap(const mi_heap_t* const_heap)
|
|
36
|
+
static mi_decl_noinline mi_theap_t* mi_heap_init_theap(const mi_heap_t* const_heap)
|
|
37
37
|
{
|
|
38
38
|
mi_heap_t* heap = (mi_heap_t*)const_heap;
|
|
39
39
|
mi_assert_internal(heap!=NULL);
|
|
40
40
|
|
|
41
41
|
if (_mi_is_heap_main(heap)) {
|
|
42
42
|
// this can be called if the (main) thread is not yet initialized (as no allocation happened)
|
|
43
|
-
mi_thread_init()
|
|
44
|
-
mi_theap_t* theap =
|
|
45
|
-
mi_assert_internal(theap!=NULL);
|
|
43
|
+
// but `theap_main_init_get()` will call `mi_thread_init()`
|
|
44
|
+
mi_theap_t* const theap = _mi_theap_main_safe();
|
|
45
|
+
mi_assert_internal(theap!=NULL && _mi_is_heap_main(_mi_theap_heap(theap)));
|
|
46
46
|
return theap;
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
// otherwise initialize the theap for this heap
|
|
50
50
|
// get the thread local
|
|
51
|
-
|
|
52
|
-
if (heap->theap==0) {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (heap->theap==0) {
|
|
56
|
-
_mi_error_message(EFAULT, "unable to dynamically create a thread local for a heap\n");
|
|
57
|
-
return NULL;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
else {
|
|
61
|
-
// get current thread local
|
|
62
|
-
theap = (mi_theap_t*)_mi_thread_local_get(heap->theap);
|
|
51
|
+
mi_assert_internal(heap->theap != 0);
|
|
52
|
+
if (heap->theap==0) { // paranoia
|
|
53
|
+
_mi_error_message(EFAULT, "no thread-local reserved for heap (%p)\n", heap);
|
|
54
|
+
return NULL;
|
|
63
55
|
}
|
|
56
|
+
mi_theap_t* theap = (mi_theap_t*)_mi_thread_local_get(heap->theap);
|
|
64
57
|
|
|
65
58
|
// create a fresh theap?
|
|
66
59
|
if (theap==NULL) {
|
|
60
|
+
// set first an invalid value to ensure the thread local storage is allocated
|
|
61
|
+
if (!_mi_thread_local_set(heap->theap, (mi_theap_t*)1)) {
|
|
62
|
+
_mi_error_message(EFAULT, "unable to allocate memory for thread local storage\n");
|
|
63
|
+
return NULL;
|
|
64
|
+
}
|
|
65
|
+
// then allocate the theap
|
|
67
66
|
theap = _mi_theap_create(heap, _mi_theap_default_safe()->tld);
|
|
67
|
+
_mi_thread_local_set(heap->theap, theap); // Cannot fail now as it was set before. Always set so the local is valid or NULL (and not 1)
|
|
68
68
|
if (theap==NULL) {
|
|
69
69
|
_mi_error_message(EFAULT, "unable to allocate memory for a thread local heap\n");
|
|
70
70
|
return NULL;
|
|
71
|
-
}
|
|
72
|
-
if (!_mi_thread_local_set(heap->theap, theap)) {
|
|
73
|
-
_mi_error_message(EFAULT, "unable to allocate memory for a thread local storage\n");
|
|
74
|
-
return NULL;
|
|
75
|
-
}
|
|
71
|
+
}
|
|
76
72
|
}
|
|
77
73
|
return theap;
|
|
78
74
|
}
|
|
@@ -81,7 +77,7 @@ static mi_theap_t* mi_heap_init_theap(const mi_heap_t* const_heap)
|
|
|
81
77
|
// get the theap for a heap without initializing (and return NULL in that case)
|
|
82
78
|
mi_theap_t* _mi_heap_theap_get_peek(const mi_heap_t* heap) {
|
|
83
79
|
if (heap==NULL || _mi_is_heap_main(heap)) {
|
|
84
|
-
return
|
|
80
|
+
return _mi_theap_main_safe();
|
|
85
81
|
}
|
|
86
82
|
else {
|
|
87
83
|
return (mi_theap_t*)_mi_thread_local_get(heap->theap);
|
|
@@ -103,17 +99,26 @@ mi_theap_t* _mi_heap_theap_get_or_init(const mi_heap_t* heap)
|
|
|
103
99
|
|
|
104
100
|
mi_heap_t* mi_heap_new_in_arena(mi_arena_id_t exclusive_arena_id) {
|
|
105
101
|
// always allocate heap data in the (subprocess) main heap
|
|
106
|
-
mi_heap_t* heap_main = mi_heap_main();
|
|
102
|
+
mi_heap_t* const heap_main = mi_heap_main();
|
|
107
103
|
// todo: allocate heap data in the exclusive arena ?
|
|
108
|
-
mi_heap_t* heap = (mi_heap_t*)mi_heap_zalloc( heap_main, sizeof(mi_heap_t) );
|
|
104
|
+
mi_heap_t* const heap = (mi_heap_t*)mi_heap_zalloc( heap_main, sizeof(mi_heap_t) );
|
|
109
105
|
if (heap==NULL) return NULL;
|
|
110
106
|
|
|
107
|
+
// reserve a thread local slot for this heap (see also issue #1230)
|
|
108
|
+
const mi_thread_local_t theap_slot = _mi_thread_local_create();
|
|
109
|
+
if (theap_slot == 0) {
|
|
110
|
+
_mi_error_message(EFAULT, "unable to dynamically create a thread local for a heap\n");
|
|
111
|
+
mi_free(heap);
|
|
112
|
+
return NULL;
|
|
113
|
+
}
|
|
114
|
+
|
|
111
115
|
// init fields
|
|
116
|
+
heap->theap = theap_slot;
|
|
112
117
|
heap->subproc = heap_main->subproc;
|
|
113
118
|
heap->heap_seq = mi_atomic_increment_relaxed(&heap_main->subproc->heap_total_count);
|
|
114
119
|
heap->exclusive_arena = _mi_arena_from_id(exclusive_arena_id);
|
|
115
120
|
heap->numa_node = -1; // no initial affinity
|
|
116
|
-
|
|
121
|
+
mi_stats_header_init(&heap->stats);
|
|
117
122
|
mi_lock_init(&heap->theaps_lock);
|
|
118
123
|
mi_lock_init(&heap->os_abandoned_pages_lock);
|
|
119
124
|
mi_lock_init(&heap->arena_pages_lock);
|
|
@@ -135,22 +140,41 @@ mi_heap_t* mi_heap_new(void) {
|
|
|
135
140
|
return mi_heap_new_in_arena(0);
|
|
136
141
|
}
|
|
137
142
|
|
|
138
|
-
// free
|
|
143
|
+
// free all theaps belonging to this heap (without deleting their pages as we do this arena wise for efficiency)
|
|
144
|
+
static void mi_heap_free_theaps(mi_heap_t* heap) {
|
|
145
|
+
// This can run concurrently with a thread that terminates (see `init.c:mi_thread_theaps_done`),
|
|
146
|
+
// and we need to ensure we free theaps atomically.
|
|
147
|
+
// We do this in a loop where we release the theaps_lock at every potential re-iteration to unblock
|
|
148
|
+
// potential concurrent thread termination which tries to remove the theap from our theaps list.
|
|
149
|
+
bool all_freed;
|
|
150
|
+
do {
|
|
151
|
+
all_freed = true;
|
|
152
|
+
mi_theap_t* theap = NULL;
|
|
153
|
+
mi_lock(&heap->theaps_lock) {
|
|
154
|
+
theap = heap->theaps;
|
|
155
|
+
while(theap != NULL) {
|
|
156
|
+
mi_theap_t* next = theap->hnext;
|
|
157
|
+
if (!_mi_theap_free(theap, false /* dont re-acquire the heap->theaps_lock */, true /* acquire the tld->theaps_lock though */ )) {
|
|
158
|
+
all_freed = false;
|
|
159
|
+
}
|
|
160
|
+
theap = next;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (!all_freed) {
|
|
164
|
+
mi_heap_stat_counter_increase(heap,heaps_delete_wait,1);
|
|
165
|
+
_mi_prim_thread_yield();
|
|
166
|
+
}
|
|
167
|
+
else {
|
|
168
|
+
mi_assert_internal(heap->theaps==NULL);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
while(!all_freed);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// free the heap resources (assuming the pages are already moved/destroyed, and all theaps have been freed)
|
|
139
175
|
static void mi_heap_free(mi_heap_t* heap) {
|
|
140
176
|
mi_assert_internal(heap!=NULL && !_mi_is_heap_main(heap));
|
|
141
177
|
|
|
142
|
-
// free all theaps belonging to this heap
|
|
143
|
-
mi_theap_t* theap = NULL;
|
|
144
|
-
mi_lock(&heap->theaps_lock) { theap = heap->theaps; }
|
|
145
|
-
while(theap != NULL) {
|
|
146
|
-
mi_theap_t* next = NULL;
|
|
147
|
-
mi_lock(&heap->theaps_lock) { next = theap->hnext; }
|
|
148
|
-
_mi_theap_free(theap);
|
|
149
|
-
theap = next;
|
|
150
|
-
}
|
|
151
|
-
mi_lock(&heap->theaps_lock) { theap = heap->theaps; }
|
|
152
|
-
mi_assert_internal(theap==NULL);
|
|
153
|
-
|
|
154
178
|
// free all arena pages infos
|
|
155
179
|
mi_lock(&heap->arena_pages_lock) {
|
|
156
180
|
for (size_t i = 0; i < MI_MAX_ARENAS; i++) {
|
|
@@ -175,6 +199,7 @@ static void mi_heap_free(mi_heap_t* heap) {
|
|
|
175
199
|
_mi_thread_local_free(heap->theap);
|
|
176
200
|
mi_lock_done(&heap->theaps_lock);
|
|
177
201
|
mi_lock_done(&heap->os_abandoned_pages_lock);
|
|
202
|
+
mi_lock_done(&heap->arena_pages_lock);
|
|
178
203
|
mi_free(heap);
|
|
179
204
|
}
|
|
180
205
|
|
|
@@ -184,18 +209,25 @@ void mi_heap_delete(mi_heap_t* heap) {
|
|
|
184
209
|
_mi_warning_message("cannot delete the main heap\n");
|
|
185
210
|
return;
|
|
186
211
|
}
|
|
212
|
+
mi_heap_free_theaps(heap);
|
|
187
213
|
_mi_heap_move_pages(heap, mi_heap_main());
|
|
188
214
|
mi_heap_free(heap);
|
|
189
215
|
}
|
|
190
216
|
|
|
217
|
+
void _mi_heap_force_destroy(mi_heap_t* heap) {
|
|
218
|
+
if (heap==NULL) return;
|
|
219
|
+
mi_heap_free_theaps(heap);
|
|
220
|
+
_mi_heap_destroy_pages(heap);
|
|
221
|
+
if (!_mi_is_heap_main(heap)) { mi_heap_free(heap); } // todo: release locks of the main heap?
|
|
222
|
+
}
|
|
223
|
+
|
|
191
224
|
void mi_heap_destroy(mi_heap_t* heap) {
|
|
192
225
|
if (heap==NULL) return;
|
|
193
226
|
if (_mi_is_heap_main(heap)) {
|
|
194
227
|
_mi_warning_message("cannot destroy the main heap\n");
|
|
195
228
|
return;
|
|
196
229
|
}
|
|
197
|
-
|
|
198
|
-
mi_heap_free(heap);
|
|
230
|
+
_mi_heap_force_destroy(heap);
|
|
199
231
|
}
|
|
200
232
|
|
|
201
233
|
mi_heap_t* mi_heap_of(const void* p) {
|
|
@@ -217,3 +249,25 @@ bool mi_heap_contains(const mi_heap_t* heap, const void* p) {
|
|
|
217
249
|
bool mi_check_owned(const void* p) {
|
|
218
250
|
return mi_any_heap_contains(p);
|
|
219
251
|
}
|
|
252
|
+
|
|
253
|
+
// unsafe heap utilization function for DragonFly (see issue #1258)
|
|
254
|
+
// If the page of pointer `p` belongs to `heap` (or `heap==NULL`) and has less than `perc_threshold` used blocks in its used area return `true`.
|
|
255
|
+
// This function is unsafe in general as it assumes we are the only thread accessing the page of `p`.
|
|
256
|
+
bool mi_unsafe_heap_page_is_under_utilized(mi_heap_t* heap, void* p, size_t perc_threshold) mi_attr_noexcept {
|
|
257
|
+
if (p==NULL) return false;
|
|
258
|
+
const mi_page_t* const page = _mi_safe_ptr_page(p); // Get the page containing this pointer
|
|
259
|
+
if (page==NULL || page->used==page->capacity || page->capacity < page->reserved) return false;
|
|
260
|
+
// If the page is the head of the queue, it is currently being used for
|
|
261
|
+
// allocations; we skip it to avoid immediate thrashing.
|
|
262
|
+
if (page->prev == NULL) return false;
|
|
263
|
+
|
|
264
|
+
// match heap?
|
|
265
|
+
const mi_heap_t* const page_heap = mi_page_heap(page);
|
|
266
|
+
if (page_heap==NULL) return false;
|
|
267
|
+
if (heap!=NULL && page_heap!=heap) return false;
|
|
268
|
+
|
|
269
|
+
// check utilization
|
|
270
|
+
if (page->capacity==0) return false;
|
|
271
|
+
if (perc_threshold>=100) return true;
|
|
272
|
+
return (perc_threshold >= ((100UL*page->used) / page->capacity));
|
|
273
|
+
}
|