@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
|
@@ -117,7 +117,7 @@ static void mi_stat_counter_add_mt(mi_stat_counter_t* stat, const mi_stat_counte
|
|
|
117
117
|
|
|
118
118
|
// must be thread safe as it is called from stats_merge
|
|
119
119
|
static void mi_stats_add(mi_stats_t* stats, const mi_stats_t* src) {
|
|
120
|
-
if (stats==src) return;
|
|
120
|
+
if (stats==NULL || src==NULL || stats==src) return;
|
|
121
121
|
|
|
122
122
|
// copy all fields
|
|
123
123
|
MI_STAT_FIELDS()
|
|
@@ -214,10 +214,9 @@ static void mi_stat_print_ex(const mi_stat_count_t* stat, const char* msg, int64
|
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
else {
|
|
217
|
-
mi_print_amount(stat->peak,
|
|
218
|
-
mi_print_amount(stat->total,
|
|
219
|
-
|
|
220
|
-
mi_print_amount(stat->current, 1, out, arg);
|
|
217
|
+
mi_print_amount(stat->peak, 0, out, arg);
|
|
218
|
+
mi_print_amount(stat->total, 0, out, arg);
|
|
219
|
+
mi_print_amount(stat->current, 0, out, arg);
|
|
221
220
|
_mi_fprintf(out, arg, "\n");
|
|
222
221
|
}
|
|
223
222
|
}
|
|
@@ -237,16 +236,21 @@ static void mi_stat_total_print(const mi_stat_count_t* stat, const char* msg, in
|
|
|
237
236
|
|
|
238
237
|
static void mi_stat_counter_print(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg ) {
|
|
239
238
|
_mi_fprintf(out, arg, " %-10s:", msg);
|
|
240
|
-
mi_print_amount(stat->total,
|
|
239
|
+
mi_print_amount(stat->total, 0, out, arg);
|
|
241
240
|
_mi_fprintf(out, arg, "\n");
|
|
242
241
|
}
|
|
243
242
|
|
|
243
|
+
static void mi_stat_counter_print_size(const mi_stat_counter_t* stat, const char* msg, mi_output_fun* out, void* arg ) {
|
|
244
|
+
_mi_fprintf(out, arg, " %-10s:", msg);
|
|
245
|
+
mi_print_amount(stat->total, 1, out, arg);
|
|
246
|
+
_mi_fprintf(out, arg, "\n");
|
|
247
|
+
}
|
|
244
248
|
|
|
245
|
-
static void mi_stat_average_print(
|
|
249
|
+
static void mi_stat_average_print(int64_t count, int64_t total, const char* msg, mi_output_fun* out, void* arg) {
|
|
246
250
|
const int64_t avg_tens = (count == 0 ? 0 : (total*10 / count));
|
|
247
|
-
const
|
|
248
|
-
const
|
|
249
|
-
_mi_fprintf(out, arg, " %-10s: %
|
|
251
|
+
const int64_t avg_whole = avg_tens/10;
|
|
252
|
+
const int64_t avg_frac1 = avg_tens%10;
|
|
253
|
+
_mi_fprintf(out, arg, " %-10s: %5lld.%lld avg\n", msg, avg_whole, avg_frac1);
|
|
250
254
|
}
|
|
251
255
|
|
|
252
256
|
|
|
@@ -335,7 +339,7 @@ mi_decl_export void mi_process_info_print_out(mi_output_fun* out, void* arg) mi_
|
|
|
335
339
|
_mi_fprintf(out, arg, "\n");
|
|
336
340
|
}
|
|
337
341
|
|
|
338
|
-
void _mi_stats_print(const char* name, size_t id, mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_attr_noexcept {
|
|
342
|
+
void _mi_stats_print(const char* name, size_t id, const mi_stats_t* stats, mi_output_fun* out0, void* arg0) mi_attr_noexcept {
|
|
339
343
|
// wrap the output function to be line buffered
|
|
340
344
|
char buf[256]; _mi_memzero_var(buf);
|
|
341
345
|
buffered_t buffer = { out0, arg0, NULL, 0, 255 };
|
|
@@ -352,8 +356,8 @@ void _mi_stats_print(const char* name, size_t id, mi_stats_t* stats, mi_output_f
|
|
|
352
356
|
mi_stats_print_bins(stats->malloc_bins, MI_BIN_HUGE, out, arg);
|
|
353
357
|
#endif
|
|
354
358
|
#if MI_STAT
|
|
355
|
-
mi_stat_print(&stats->malloc_normal, "binned", (stats->malloc_normal_count.total == 0 ? 1 :
|
|
356
|
-
mi_stat_print(&stats->malloc_huge, "huge", (stats->malloc_huge_count.total == 0 ? 1 :
|
|
359
|
+
mi_stat_print(&stats->malloc_normal, "binned", (stats->malloc_normal_count.total == 0 ? -1 : 1), out, arg);
|
|
360
|
+
mi_stat_print(&stats->malloc_huge, "huge", (stats->malloc_huge_count.total == 0 ? -1 : 1), out, arg);
|
|
357
361
|
mi_stat_count_t total = { 0,0,0 };
|
|
358
362
|
mi_stat_count_add_mt(&total, &stats->malloc_normal);
|
|
359
363
|
mi_stat_count_add_mt(&total, &stats->malloc_huge);
|
|
@@ -371,8 +375,8 @@ void _mi_stats_print(const char* name, size_t id, mi_stats_t* stats, mi_output_f
|
|
|
371
375
|
// mi_stat_print(&stats->segments, "segments", -1, out, arg);
|
|
372
376
|
// mi_stat_print(&stats->segments_abandoned, "-abandoned", -1, out, arg);
|
|
373
377
|
// mi_stat_print(&stats->segments_cache, "-cached", -1, out, arg);
|
|
374
|
-
mi_stat_print(&stats->pages, "pages",
|
|
375
|
-
mi_stat_print(&stats->pages_abandoned, "abandoned",
|
|
378
|
+
mi_stat_print(&stats->pages, "pages", 0, out, arg);
|
|
379
|
+
mi_stat_print(&stats->pages_abandoned, "abandoned", 0, out, arg);
|
|
376
380
|
mi_stat_counter_print(&stats->pages_reclaim_on_alloc, "reclaima", out, arg);
|
|
377
381
|
mi_stat_counter_print(&stats->pages_reclaim_on_free, "reclaimf", out, arg);
|
|
378
382
|
mi_stat_counter_print(&stats->pages_reabandon_full, "reabandon", out, arg);
|
|
@@ -387,8 +391,8 @@ void _mi_stats_print(const char* name, size_t id, mi_stats_t* stats, mi_output_f
|
|
|
387
391
|
mi_print_header("arenas", out, arg);
|
|
388
392
|
mi_stat_print_ex(&stats->reserved, "reserved", 1, out, arg, "");
|
|
389
393
|
mi_stat_print_ex(&stats->committed, "committed", 1, out, arg, "");
|
|
390
|
-
|
|
391
|
-
|
|
394
|
+
mi_stat_counter_print_size(&stats->reset, "reset", out, arg);
|
|
395
|
+
mi_stat_counter_print_size(&stats->purged, "purged", out, arg);
|
|
392
396
|
|
|
393
397
|
mi_stat_counter_print(&stats->arena_count, "arenas", out, arg);
|
|
394
398
|
mi_stat_counter_print(&stats->arena_rollback_count, "rollback", out, arg);
|
|
@@ -397,11 +401,13 @@ void _mi_stats_print(const char* name, size_t id, mi_stats_t* stats, mi_output_f
|
|
|
397
401
|
mi_stat_counter_print(&stats->reset_calls, "resets", out, arg);
|
|
398
402
|
mi_stat_counter_print(&stats->purge_calls, "purges", out, arg);
|
|
399
403
|
mi_stat_counter_print(&stats->malloc_guarded_count, "guarded", out, arg);
|
|
400
|
-
mi_stat_print_ex(&stats->
|
|
404
|
+
mi_stat_print_ex(&stats->theaps, "theaps", 0, out, arg, "");
|
|
405
|
+
mi_stat_print_ex(&stats->heaps, "heaps", 0, out, arg, "");
|
|
406
|
+
mi_stat_counter_print(&stats->heaps_delete_wait, "heap waits", out, arg);
|
|
401
407
|
_mi_fprintf(out, arg, "\n");
|
|
402
408
|
|
|
403
409
|
mi_print_header("process", out, arg);
|
|
404
|
-
mi_stat_print_ex(&stats->threads, "threads",
|
|
410
|
+
mi_stat_print_ex(&stats->threads, "threads", 0, out, arg, "");
|
|
405
411
|
_mi_fprintf(out, arg, " %-10s: %5i\n", "numa nodes", _mi_os_numa_node_count());
|
|
406
412
|
mi_process_info_print_out(out, arg);
|
|
407
413
|
}
|
|
@@ -416,7 +422,7 @@ void _mi_stats_init(void) {
|
|
|
416
422
|
if (mi_process_start == 0) { mi_process_start = _mi_clock_start(); };
|
|
417
423
|
}
|
|
418
424
|
|
|
419
|
-
static void mi_stats_add_into(mi_stats_t* to, mi_stats_t* from) {
|
|
425
|
+
static void mi_stats_add_into(mi_stats_t* to, const mi_stats_t* from) {
|
|
420
426
|
mi_assert_internal(to != NULL && from != NULL);
|
|
421
427
|
if (to == from) return;
|
|
422
428
|
mi_stats_add(to, from);
|
|
@@ -429,14 +435,14 @@ void _mi_stats_merge_into(mi_stats_t* to, mi_stats_t* from) {
|
|
|
429
435
|
_mi_memzero(from, sizeof(mi_stats_t));
|
|
430
436
|
}
|
|
431
437
|
|
|
432
|
-
static mi_stats_t* mi_stats_merge_theap_to_heap(mi_theap_t* theap) mi_attr_noexcept {
|
|
438
|
+
static const mi_stats_t* mi_stats_merge_theap_to_heap(mi_theap_t* theap) mi_attr_noexcept {
|
|
433
439
|
mi_stats_t* stats = &theap->stats;
|
|
434
|
-
mi_stats_t* heap_stats = &theap->
|
|
440
|
+
mi_stats_t* heap_stats = &_mi_theap_heap(theap)->stats;
|
|
435
441
|
_mi_stats_merge_into( heap_stats, stats );
|
|
436
442
|
return heap_stats;
|
|
437
443
|
}
|
|
438
444
|
|
|
439
|
-
static mi_stats_t* mi_heap_get_stats(mi_heap_t* heap) {
|
|
445
|
+
static const mi_stats_t* mi_heap_get_stats(mi_heap_t* heap) {
|
|
440
446
|
if (heap==NULL) { heap = mi_heap_main(); }
|
|
441
447
|
mi_theap_t* theap = _mi_heap_theap_peek(heap);
|
|
442
448
|
if (theap==NULL) return &heap->stats;
|
|
@@ -473,7 +479,7 @@ void mi_subproc_heap_stats_print_out(mi_subproc_id_t subproc_id, mi_output_fun*
|
|
|
473
479
|
mi_subproc_t* subproc = _mi_subproc_from_id(subproc_id);
|
|
474
480
|
if (subproc==NULL) return;
|
|
475
481
|
mi_heap_print_visit_info_t vinfo = { out, arg };
|
|
476
|
-
mi_subproc_visit_heaps(
|
|
482
|
+
mi_subproc_visit_heaps(subproc_id, &mi_heap_print_visitor, &vinfo);
|
|
477
483
|
_mi_stats_print("subproc", subproc->subproc_seq, &subproc->stats, out, arg);
|
|
478
484
|
}
|
|
479
485
|
|
|
@@ -482,7 +488,7 @@ void mi_subproc_heap_stats_print_out(mi_subproc_id_t subproc_id, mi_output_fun*
|
|
|
482
488
|
void mi_subproc_stats_print_out(mi_subproc_id_t subproc_id, mi_output_fun* out, void* arg) mi_attr_noexcept {
|
|
483
489
|
mi_subproc_t* subproc = _mi_subproc_from_id(subproc_id);
|
|
484
490
|
if (subproc==NULL) return;
|
|
485
|
-
mi_stats_t_decl(stats);
|
|
491
|
+
mi_stats_t_decl(stats);
|
|
486
492
|
if (mi_subproc_stats_get(subproc_id, &stats)) {
|
|
487
493
|
_mi_stats_print("subproc", subproc->subproc_seq, &stats, out, arg);
|
|
488
494
|
}
|
|
@@ -502,7 +508,7 @@ void mi_stats_print(void* out) mi_attr_noexcept {
|
|
|
502
508
|
void mi_thread_stats_print_out(mi_output_fun* out, void* arg) mi_attr_noexcept {
|
|
503
509
|
mi_theap_t* theap = _mi_theap_default();
|
|
504
510
|
if (theap==NULL || !mi_theap_is_initialized(theap)) return;
|
|
505
|
-
_mi_stats_print("heap", theap->
|
|
511
|
+
_mi_stats_print("heap", _mi_theap_heap(theap)->heap_seq, &theap->stats, out, arg);
|
|
506
512
|
mi_stats_merge_theap_to_heap(_mi_theap_default());
|
|
507
513
|
}
|
|
508
514
|
|
|
@@ -537,12 +543,15 @@ mi_msecs_t _mi_clock_end(mi_msecs_t start) {
|
|
|
537
543
|
|
|
538
544
|
mi_decl_export void mi_process_info(size_t* elapsed_msecs, size_t* user_msecs, size_t* system_msecs, size_t* current_rss, size_t* peak_rss, size_t* current_commit, size_t* peak_commit, size_t* page_faults) mi_attr_noexcept
|
|
539
545
|
{
|
|
540
|
-
mi_subproc_t* subproc = _mi_subproc_main();
|
|
541
546
|
mi_process_info_t pinfo;
|
|
542
547
|
_mi_memzero_var(pinfo);
|
|
543
548
|
pinfo.elapsed = _mi_clock_end(mi_process_start);
|
|
544
|
-
|
|
545
|
-
|
|
549
|
+
{ const mi_subproc_t* subproc = _mi_subproc_main();
|
|
550
|
+
if (subproc!=NULL) {
|
|
551
|
+
pinfo.current_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)(&subproc->stats.committed.current)));
|
|
552
|
+
pinfo.peak_commit = (size_t)(mi_atomic_loadi64_relaxed((_Atomic(int64_t)*)(&subproc->stats.committed.peak)));
|
|
553
|
+
}
|
|
554
|
+
}
|
|
546
555
|
pinfo.current_rss = pinfo.current_commit;
|
|
547
556
|
pinfo.peak_rss = pinfo.peak_commit;
|
|
548
557
|
pinfo.utime = 0;
|
|
@@ -575,34 +584,36 @@ size_t mi_stats_get_bin_size(size_t bin) mi_attr_noexcept {
|
|
|
575
584
|
return _mi_bin_size(bin);
|
|
576
585
|
}
|
|
577
586
|
|
|
578
|
-
static bool
|
|
579
|
-
if (
|
|
580
|
-
if (
|
|
581
|
-
_mi_memcpy(
|
|
587
|
+
static bool mi_stats_copy(mi_stats_t* stats_to, const mi_stats_t* stats_from) mi_attr_noexcept {
|
|
588
|
+
if (stats_to == NULL || stats_to->size != sizeof(mi_stats_t) || stats_to->version != MI_STAT_VERSION) return false;
|
|
589
|
+
if (stats_from == NULL || stats_from->size != stats_to->size) return false;
|
|
590
|
+
_mi_memcpy(stats_to, stats_from, stats_to->size);
|
|
582
591
|
return true;
|
|
583
592
|
}
|
|
584
593
|
|
|
585
594
|
bool mi_subproc_stats_get_exclusive(mi_subproc_id_t subproc_id, mi_stats_t* stats) mi_attr_noexcept {
|
|
586
|
-
|
|
595
|
+
const mi_subproc_t* subproc = _mi_subproc_from_id(subproc_id);
|
|
596
|
+
if (subproc==NULL) return false;
|
|
597
|
+
return mi_stats_copy(stats,&subproc->stats);
|
|
587
598
|
}
|
|
588
599
|
|
|
589
600
|
bool mi_heap_stats_get(mi_heap_t* heap, mi_stats_t* stats) mi_attr_noexcept {
|
|
590
|
-
return
|
|
601
|
+
return mi_stats_copy(stats, mi_heap_get_stats(heap));
|
|
591
602
|
}
|
|
592
603
|
|
|
593
604
|
|
|
594
605
|
static bool mi_cdecl mi_heap_aggregate_visitor(mi_heap_t* heap, void* arg) {
|
|
595
606
|
mi_stats_t* stats = (mi_stats_t*)arg;
|
|
596
|
-
mi_stats_add_into(stats,
|
|
607
|
+
mi_stats_add_into(stats, mi_heap_get_stats(heap));
|
|
597
608
|
return true;
|
|
598
609
|
}
|
|
599
610
|
|
|
600
611
|
bool mi_subproc_stats_get(mi_subproc_id_t subproc_id, mi_stats_t* stats) mi_attr_noexcept {
|
|
612
|
+
if (stats==NULL) return false;
|
|
601
613
|
mi_subproc_t* subproc = _mi_subproc_from_id(subproc_id);
|
|
602
|
-
if (
|
|
603
|
-
|
|
604
|
-
mi_subproc_visit_heaps(
|
|
605
|
-
mi_stats_add_into(stats, &subproc->stats);
|
|
614
|
+
if (subproc == NULL) return false;
|
|
615
|
+
if (!mi_stats_copy(stats, &subproc->stats)) return false;
|
|
616
|
+
mi_subproc_visit_heaps(subproc_id, &mi_heap_aggregate_visitor, stats);
|
|
606
617
|
return true;
|
|
607
618
|
}
|
|
608
619
|
|
|
@@ -651,7 +662,7 @@ static void mi_json_buf_print(mi_json_buf_t* hbuf, const char* msg) {
|
|
|
651
662
|
hbuf->buf[hbuf->used] = 0;
|
|
652
663
|
}
|
|
653
664
|
|
|
654
|
-
static void mi_json_buf_print_count_bin(mi_json_buf_t* hbuf, const char* prefix, mi_stat_count_t* stat, size_t bin, bool add_comma) {
|
|
665
|
+
static void mi_json_buf_print_count_bin(mi_json_buf_t* hbuf, const char* prefix, const mi_stat_count_t* stat, size_t bin, bool add_comma) {
|
|
655
666
|
const size_t binsize = mi_stats_get_bin_size(bin);
|
|
656
667
|
const size_t pagesize = (binsize <= MI_SMALL_MAX_OBJ_SIZE ? MI_SMALL_PAGE_SIZE :
|
|
657
668
|
(binsize <= MI_MEDIUM_MAX_OBJ_SIZE ? MI_MEDIUM_PAGE_SIZE :
|
|
@@ -662,7 +673,7 @@ static void mi_json_buf_print_count_bin(mi_json_buf_t* hbuf, const char* prefix,
|
|
|
662
673
|
mi_json_buf_print(hbuf, buf);
|
|
663
674
|
}
|
|
664
675
|
|
|
665
|
-
static void mi_json_buf_print_count_cbin(mi_json_buf_t* hbuf, const char* prefix, mi_stat_count_t* stat, mi_chunkbin_t bin, bool add_comma) {
|
|
676
|
+
static void mi_json_buf_print_count_cbin(mi_json_buf_t* hbuf, const char* prefix, const mi_stat_count_t* stat, mi_chunkbin_t bin, bool add_comma) {
|
|
666
677
|
const char* cbin = " ";
|
|
667
678
|
switch(bin) {
|
|
668
679
|
case MI_CBIN_SMALL: cbin = "S"; break;
|
|
@@ -678,14 +689,14 @@ static void mi_json_buf_print_count_cbin(mi_json_buf_t* hbuf, const char* prefix
|
|
|
678
689
|
mi_json_buf_print(hbuf, buf);
|
|
679
690
|
}
|
|
680
691
|
|
|
681
|
-
static void mi_json_buf_print_count(mi_json_buf_t* hbuf, const char* prefix, mi_stat_count_t* stat, bool add_comma) {
|
|
692
|
+
static void mi_json_buf_print_count(mi_json_buf_t* hbuf, const char* prefix, const mi_stat_count_t* stat, bool add_comma) {
|
|
682
693
|
char buf[128];
|
|
683
694
|
_mi_snprintf(buf, 128, "%s{ \"total\": %lld, \"peak\": %lld, \"current\": %lld }%s\n", prefix, stat->total, stat->peak, stat->current, (add_comma ? "," : ""));
|
|
684
695
|
buf[127] = 0;
|
|
685
696
|
mi_json_buf_print(hbuf, buf);
|
|
686
697
|
}
|
|
687
698
|
|
|
688
|
-
static void mi_json_buf_print_count_value(mi_json_buf_t* hbuf, const char* name, mi_stat_count_t* stat) {
|
|
699
|
+
static void mi_json_buf_print_count_value(mi_json_buf_t* hbuf, const char* name, const mi_stat_count_t* stat) {
|
|
689
700
|
char buf[128];
|
|
690
701
|
_mi_snprintf(buf, 128, " \"%s\": ", name);
|
|
691
702
|
buf[127] = 0;
|
|
@@ -707,14 +718,14 @@ static void mi_json_buf_print_size(mi_json_buf_t* hbuf, const char* name, size_t
|
|
|
707
718
|
mi_json_buf_print(hbuf, buf);
|
|
708
719
|
}
|
|
709
720
|
|
|
710
|
-
static void mi_json_buf_print_counter_value(mi_json_buf_t* hbuf, const char* name, mi_stat_counter_t* stat) {
|
|
721
|
+
static void mi_json_buf_print_counter_value(mi_json_buf_t* hbuf, const char* name, const mi_stat_counter_t* stat) {
|
|
711
722
|
mi_json_buf_print_value(hbuf, name, stat->total);
|
|
712
723
|
}
|
|
713
724
|
|
|
714
725
|
#define MI_STAT_COUNT(stat) mi_json_buf_print_count_value(&hbuf, #stat, &stats->stat);
|
|
715
726
|
#define MI_STAT_COUNTER(stat) mi_json_buf_print_counter_value(&hbuf, #stat, &stats->stat);
|
|
716
727
|
|
|
717
|
-
static char* mi_stats_get_json_from(mi_stats_t* stats, size_t output_size, char* output_buf) mi_attr_noexcept {
|
|
728
|
+
static char* mi_stats_get_json_from(const mi_stats_t* stats, size_t output_size, char* output_buf) mi_attr_noexcept {
|
|
718
729
|
if (stats==NULL || stats->size!=sizeof(mi_stats_t) || stats->version!=MI_STAT_VERSION) return NULL;
|
|
719
730
|
mi_json_buf_t hbuf = { NULL, 0, 0, true };
|
|
720
731
|
if (output_size > 0 && output_buf != NULL) {
|
|
@@ -769,7 +780,7 @@ static char* mi_stats_get_json_from(mi_stats_t* stats, size_t output_size, char*
|
|
|
769
780
|
for (size_t i = 0; i < MI_CBIN_COUNT; i++) {
|
|
770
781
|
mi_json_buf_print_count_cbin(&hbuf, " ", &stats->chunk_bins[i], (mi_chunkbin_t)i, i!=MI_CBIN_COUNT-1);
|
|
771
782
|
}
|
|
772
|
-
mi_json_buf_print(&hbuf, " ]\n");
|
|
783
|
+
mi_json_buf_print(&hbuf, " ]\n");
|
|
773
784
|
mi_json_buf_print(&hbuf, "}\n");
|
|
774
785
|
if (hbuf.used >= hbuf.size) {
|
|
775
786
|
// failed
|
|
@@ -786,7 +797,7 @@ char* mi_subproc_stats_get_json(mi_subproc_id_t subproc_id, size_t buf_size, cha
|
|
|
786
797
|
if (subproc==NULL) return NULL;
|
|
787
798
|
mi_stats_t_decl(stats);
|
|
788
799
|
if (!mi_subproc_stats_get(subproc_id,&stats)) return NULL;
|
|
789
|
-
return mi_stats_get_json_from(&
|
|
800
|
+
return mi_stats_get_json_from(&stats, buf_size, buf);
|
|
790
801
|
}
|
|
791
802
|
|
|
792
803
|
char* mi_heap_stats_get_json(mi_heap_t* heap, size_t buf_size, char* buf) mi_attr_noexcept {
|
|
@@ -21,7 +21,7 @@ terms of the MIT license. A copy of the license can be found in the file
|
|
|
21
21
|
typedef bool (theap_page_visitor_fun)(mi_theap_t* theap, mi_page_queue_t* pq, mi_page_t* page, void* arg1, void* arg2);
|
|
22
22
|
|
|
23
23
|
// Visit all pages in a theap; returns `false` if break was called.
|
|
24
|
-
static bool mi_theap_visit_pages(mi_theap_t* theap, theap_page_visitor_fun* fn, void* arg1, void* arg2)
|
|
24
|
+
static bool mi_theap_visit_pages(mi_theap_t* theap, theap_page_visitor_fun* fn, bool include_full, void* arg1, void* arg2)
|
|
25
25
|
{
|
|
26
26
|
if (theap==NULL || theap->page_count==0) return 0;
|
|
27
27
|
|
|
@@ -31,7 +31,8 @@ static bool mi_theap_visit_pages(mi_theap_t* theap, theap_page_visitor_fun* fn,
|
|
|
31
31
|
size_t count = 0;
|
|
32
32
|
#endif
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
const size_t max_bin = (include_full ? MI_BIN_FULL : MI_BIN_FULL - 1);
|
|
35
|
+
for (size_t i = 0; i <= max_bin; i++) {
|
|
35
36
|
mi_page_queue_t* pq = &theap->pages[i];
|
|
36
37
|
mi_page_t* page = pq->first;
|
|
37
38
|
while(page != NULL) {
|
|
@@ -44,7 +45,7 @@ static bool mi_theap_visit_pages(mi_theap_t* theap, theap_page_visitor_fun* fn,
|
|
|
44
45
|
page = next; // and continue
|
|
45
46
|
}
|
|
46
47
|
}
|
|
47
|
-
mi_assert_internal(count == total);
|
|
48
|
+
mi_assert_internal(!include_full || count == total);
|
|
48
49
|
return true;
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -62,7 +63,7 @@ static bool mi_theap_page_is_valid(mi_theap_t* theap, mi_page_queue_t* pq, mi_pa
|
|
|
62
63
|
#if MI_DEBUG>=3
|
|
63
64
|
static bool mi_theap_is_valid(mi_theap_t* theap) {
|
|
64
65
|
mi_assert_internal(theap!=NULL);
|
|
65
|
-
mi_theap_visit_pages(theap, &mi_theap_page_is_valid, NULL, NULL);
|
|
66
|
+
mi_theap_visit_pages(theap, &mi_theap_page_is_valid, true, NULL, NULL);
|
|
66
67
|
for (size_t bin = 0; bin < MI_BIN_COUNT; bin++) {
|
|
67
68
|
mi_assert_internal(_mi_page_queue_is_valid(theap, &theap->pages[bin]));
|
|
68
69
|
}
|
|
@@ -109,7 +110,7 @@ static bool mi_theap_page_collect(mi_theap_t* theap, mi_page_queue_t* pq, mi_pag
|
|
|
109
110
|
|
|
110
111
|
static void mi_theap_merge_stats(mi_theap_t* theap) {
|
|
111
112
|
mi_assert_internal(mi_theap_is_initialized(theap));
|
|
112
|
-
_mi_stats_merge_into(&theap->
|
|
113
|
+
_mi_stats_merge_into(&_mi_theap_heap(theap)->stats, &theap->stats);
|
|
113
114
|
}
|
|
114
115
|
|
|
115
116
|
static void mi_theap_collect_ex(mi_theap_t* theap, mi_collect_t collect)
|
|
@@ -127,7 +128,7 @@ static void mi_theap_collect_ex(mi_theap_t* theap, mi_collect_t collect)
|
|
|
127
128
|
_mi_theap_collect_retired(theap, force);
|
|
128
129
|
|
|
129
130
|
// collect all pages owned by this thread
|
|
130
|
-
mi_theap_visit_pages(theap, &mi_theap_page_collect, &collect, NULL);
|
|
131
|
+
mi_theap_visit_pages(theap, &mi_theap_page_collect, (collect!=MI_NORMAL), &collect, NULL); // dont normally visit full pages, see issue #1220
|
|
131
132
|
|
|
132
133
|
// collect arenas (this is program wide so don't force purges on abandonment of threads)
|
|
133
134
|
//mi_atomic_storei64_release(&theap->tld->subproc->purge_expire, 1);
|
|
@@ -173,11 +174,14 @@ mi_theap_t* mi_theap_get_default(void) {
|
|
|
173
174
|
void _mi_theap_init(mi_theap_t* theap, mi_heap_t* heap, mi_tld_t* tld)
|
|
174
175
|
{
|
|
175
176
|
mi_assert_internal(theap!=NULL);
|
|
177
|
+
mi_assert_internal(heap!=NULL);
|
|
176
178
|
mi_memid_t memid = theap->memid;
|
|
177
179
|
_mi_memcpy_aligned(theap, &_mi_theap_empty, sizeof(mi_theap_t));
|
|
178
180
|
theap->memid = memid;
|
|
179
|
-
theap->
|
|
181
|
+
theap->refcount = 1;
|
|
180
182
|
theap->tld = tld; // avoid reading the thread-local tld during initialization
|
|
183
|
+
mi_atomic_store_ptr_relaxed(mi_heap_t,&theap->heap,heap);
|
|
184
|
+
mi_assert_internal(theap->stats.size == sizeof(mi_stats_t));
|
|
181
185
|
|
|
182
186
|
_mi_theap_options_init(theap);
|
|
183
187
|
if (theap->tld->is_in_threadpool) {
|
|
@@ -191,11 +195,14 @@ void _mi_theap_init(mi_theap_t* theap, mi_heap_t* heap, mi_tld_t* tld)
|
|
|
191
195
|
}
|
|
192
196
|
|
|
193
197
|
// push on the thread local theaps list
|
|
194
|
-
mi_theap_t* head =
|
|
195
|
-
theap->
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
198
|
+
mi_theap_t* head = NULL;
|
|
199
|
+
mi_lock(&theap->tld->theaps_lock) {
|
|
200
|
+
head = theap->tld->theaps;
|
|
201
|
+
theap->tprev = NULL;
|
|
202
|
+
theap->tnext = head;
|
|
203
|
+
if (head!=NULL) { head->tprev = theap; }
|
|
204
|
+
theap->tld->theaps = theap;
|
|
205
|
+
}
|
|
199
206
|
|
|
200
207
|
// initialize random
|
|
201
208
|
if (head == NULL) { // first theap in this thread?
|
|
@@ -210,6 +217,7 @@ void _mi_theap_init(mi_theap_t* theap, mi_heap_t* heap, mi_tld_t* tld)
|
|
|
210
217
|
}
|
|
211
218
|
theap->cookie = _mi_theap_random_next(theap) | 1;
|
|
212
219
|
_mi_theap_guarded_init(theap);
|
|
220
|
+
mi_subproc_stat_increase(_mi_subproc(),theaps,1);
|
|
213
221
|
|
|
214
222
|
// push on the heap's theap list
|
|
215
223
|
mi_lock(&heap->theaps_lock) {
|
|
@@ -256,37 +264,70 @@ uintptr_t _mi_theap_random_next(mi_theap_t* theap) {
|
|
|
256
264
|
return _mi_random_next(&theap->random);
|
|
257
265
|
}
|
|
258
266
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
267
|
+
static void mi_theap_free_mem(mi_theap_t* theap) {
|
|
268
|
+
if (theap!=NULL) {
|
|
269
|
+
mi_subproc_stat_decrease(_mi_subproc(),theaps,1);
|
|
270
|
+
// free the used memory
|
|
271
|
+
if (theap->memid.memkind == MI_MEM_HEAP_MAIN) { // note: for now unused as it would access theap_default stats in mi_free of the current theap
|
|
272
|
+
mi_assert_internal(_mi_is_heap_main(mi_heap_of(theap)));
|
|
273
|
+
mi_free(theap);
|
|
274
|
+
}
|
|
275
|
+
else if (theap->memid.memkind == MI_MEM_META) {
|
|
276
|
+
_mi_meta_free(theap, sizeof(*theap), theap->memid);
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
_mi_arenas_free(theap, _mi_align_up(sizeof(*theap),MI_ARENA_MIN_OBJ_SIZE), theap->memid ); // issue #1168, avoid assertion failure
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
264
283
|
|
|
265
|
-
|
|
266
|
-
|
|
284
|
+
void _mi_theap_incref(mi_theap_t* theap) {
|
|
285
|
+
if (theap!=NULL && theap->memid.memkind > MI_MEM_STATIC) {
|
|
286
|
+
mi_atomic_increment_acq_rel(&theap->refcount);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
267
289
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (theap->
|
|
271
|
-
|
|
272
|
-
|
|
290
|
+
void _mi_theap_decref(mi_theap_t* theap) {
|
|
291
|
+
if (theap!=NULL && theap->memid.memkind > MI_MEM_STATIC) {
|
|
292
|
+
if (mi_atomic_decrement_acq_rel(&theap->refcount) == 1) {
|
|
293
|
+
mi_theap_free_mem(theap);
|
|
294
|
+
}
|
|
273
295
|
}
|
|
296
|
+
}
|
|
274
297
|
|
|
275
|
-
// remove ourselves from the thread local theaps list
|
|
276
|
-
if (theap->tnext != NULL) { theap->tnext->tprev = theap->tprev; }
|
|
277
|
-
if (theap->tprev != NULL) { theap->tprev->tnext = theap->tnext; }
|
|
278
|
-
else { mi_assert_internal(theap->tld->theaps == theap); theap->tld->theaps = theap->tnext; }
|
|
279
298
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
299
|
+
// called from `mi_theap_delete` to free the internal theap resources.
|
|
300
|
+
bool _mi_theap_free(mi_theap_t* theap, bool acquire_heap_theaps_lock, bool acquire_tld_theaps_lock) {
|
|
301
|
+
mi_assert(theap != NULL);
|
|
302
|
+
if (theap==NULL) return true;
|
|
303
|
+
|
|
304
|
+
mi_heap_t* const heap = mi_atomic_exchange_ptr_acq_rel(mi_heap_t, &theap->heap, NULL);
|
|
305
|
+
if (heap==NULL) {
|
|
306
|
+
// concurrent interaction, retry in an outer loop (as the other thread may be blocked on our lock)
|
|
307
|
+
return false;
|
|
287
308
|
}
|
|
288
309
|
else {
|
|
289
|
-
|
|
310
|
+
// merge stats to the owning heap
|
|
311
|
+
_mi_stats_merge_into(&heap->stats, &theap->stats);
|
|
312
|
+
|
|
313
|
+
// remove ourselves from the heap theaps list
|
|
314
|
+
mi_lock_maybe(&heap->theaps_lock, acquire_heap_theaps_lock) {
|
|
315
|
+
if (theap->hnext != NULL) { theap->hnext->hprev = theap->hprev; }
|
|
316
|
+
if (theap->hprev != NULL) { theap->hprev->hnext = theap->hnext; }
|
|
317
|
+
else { mi_assert_internal(heap->theaps == theap); heap->theaps = theap->hnext; }
|
|
318
|
+
theap->hnext = theap->hprev = NULL;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// remove ourselves from the thread local theaps list
|
|
322
|
+
mi_lock_maybe(&theap->tld->theaps_lock, acquire_tld_theaps_lock) {
|
|
323
|
+
if (theap->tnext != NULL) { theap->tnext->tprev = theap->tprev; }
|
|
324
|
+
if (theap->tprev != NULL) { theap->tprev->tnext = theap->tnext; }
|
|
325
|
+
else { mi_assert_internal(theap->tld->theaps == theap); theap->tld->theaps = theap->tnext; }
|
|
326
|
+
theap->tnext = theap->tprev = NULL;
|
|
327
|
+
}
|
|
328
|
+
theap->tld = NULL;
|
|
329
|
+
_mi_theap_decref(theap);
|
|
330
|
+
return true;
|
|
290
331
|
}
|
|
291
332
|
}
|
|
292
333
|
|
|
@@ -411,7 +452,7 @@ void _mi_theap_unsafe_destroy_all(mi_theap_t* theap) {
|
|
|
411
452
|
----------------------------------------------------------- */
|
|
412
453
|
|
|
413
454
|
// Safe delete a theap without freeing any still allocated blocks in that theap.
|
|
414
|
-
void _mi_theap_delete(mi_theap_t* theap)
|
|
455
|
+
void _mi_theap_delete(mi_theap_t* theap, bool acquire_tld_theaps_lock)
|
|
415
456
|
{
|
|
416
457
|
mi_assert(theap != NULL);
|
|
417
458
|
mi_assert(mi_theap_is_initialized(theap));
|
|
@@ -422,7 +463,7 @@ void _mi_theap_delete(mi_theap_t* theap)
|
|
|
422
463
|
_mi_theap_collect_abandon(theap);
|
|
423
464
|
|
|
424
465
|
mi_assert_internal(theap->page_count==0);
|
|
425
|
-
_mi_theap_free(theap);
|
|
466
|
+
_mi_theap_free(theap, true /* acquire heap->theaps_lock */, acquire_tld_theaps_lock);
|
|
426
467
|
}
|
|
427
468
|
|
|
428
469
|
|
|
@@ -435,7 +476,7 @@ void mi_theap_unload(mi_theap_t* theap) {
|
|
|
435
476
|
mi_assert(mi_theap_is_initialized(theap));
|
|
436
477
|
mi_assert_expensive(mi_theap_is_valid(theap));
|
|
437
478
|
if (theap==NULL || !mi_theap_is_initialized(theap)) return;
|
|
438
|
-
if (theap->
|
|
479
|
+
if (_mi_theap_heap(theap)->exclusive_arena == NULL) {
|
|
439
480
|
_mi_warning_message("cannot unload theaps that are not associated with an exclusive arena\n");
|
|
440
481
|
return;
|
|
441
482
|
}
|
|
@@ -455,7 +496,7 @@ void mi_theap_unload(mi_theap_t* theap) {
|
|
|
455
496
|
bool mi_theap_reload(mi_theap_t* theap, mi_arena_id_t arena_id) {
|
|
456
497
|
mi_assert(mi_theap_is_initialized(theap));
|
|
457
498
|
if (theap==NULL || !mi_theap_is_initialized(theap)) return false;
|
|
458
|
-
if (theap->
|
|
499
|
+
if (_mi_theap_heap(theap)->exclusive_arena == NULL) {
|
|
459
500
|
_mi_warning_message("cannot reload theaps that were not associated with an exclusive arena\n");
|
|
460
501
|
return false;
|
|
461
502
|
}
|
|
@@ -464,8 +505,8 @@ bool mi_theap_reload(mi_theap_t* theap, mi_arena_id_t arena_id) {
|
|
|
464
505
|
return false;
|
|
465
506
|
}
|
|
466
507
|
mi_arena_t* arena = _mi_arena_from_id(arena_id);
|
|
467
|
-
if (theap->
|
|
468
|
-
_mi_warning_message("trying to reload a theap at a different arena address: %p vs %p\n", theap->
|
|
508
|
+
if (_mi_theap_heap(theap)->exclusive_arena != arena) {
|
|
509
|
+
_mi_warning_message("trying to reload a theap at a different arena address: %p vs %p\n", _mi_theap_heap(theap)->exclusive_arena, arena);
|
|
469
510
|
return false;
|
|
470
511
|
}
|
|
471
512
|
|
|
@@ -645,7 +686,7 @@ static bool mi_theap_visit_areas_page(mi_theap_t* theap, mi_page_queue_t* pq, mi
|
|
|
645
686
|
// Visit all theap pages as areas
|
|
646
687
|
static bool mi_theap_visit_areas(const mi_theap_t* theap, mi_theap_area_visit_fun* visitor, void* arg) {
|
|
647
688
|
if (visitor == NULL) return false;
|
|
648
|
-
return mi_theap_visit_pages((mi_theap_t*)theap, &mi_theap_visit_areas_page, (void*)(visitor), arg); // note: function pointer to void* :-{
|
|
689
|
+
return mi_theap_visit_pages((mi_theap_t*)theap, &mi_theap_visit_areas_page, true, (void*)(visitor), arg); // note: function pointer to void* :-{
|
|
649
690
|
}
|
|
650
691
|
|
|
651
692
|
// Just to pass arguments
|
|
@@ -657,7 +698,7 @@ typedef struct mi_visit_blocks_args_s {
|
|
|
657
698
|
|
|
658
699
|
static bool mi_theap_area_visitor(const mi_theap_t* theap, const mi_theap_area_ex_t* xarea, void* arg) {
|
|
659
700
|
mi_visit_blocks_args_t* args = (mi_visit_blocks_args_t*)arg;
|
|
660
|
-
if (!args->visitor(theap
|
|
701
|
+
if (!args->visitor(_mi_theap_heap(theap), &xarea->area, NULL, xarea->area.block_size, args->arg)) return false;
|
|
661
702
|
if (args->visit_blocks) {
|
|
662
703
|
return _mi_theap_area_visit_blocks(&xarea->area, xarea->page, args->visitor, args->arg);
|
|
663
704
|
}
|