@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.
Files changed (104) hide show
  1. package/.github/skills/yo-async-effects/async-effects-recipes.md +6 -6
  2. package/.github/skills/yo-core-patterns/core-patterns-cheatsheet.md +34 -0
  3. package/.github/skills/yo-syntax/syntax-cheatsheet.md +441 -2
  4. package/out/cjs/index.cjs +563 -567
  5. package/out/cjs/yo-cli.cjs +656 -651
  6. package/out/cjs/yo-lsp.cjs +614 -618
  7. package/out/esm/index.mjs +582 -586
  8. package/out/types/src/codegen/codegen-c.d.ts +2 -2
  9. package/out/types/src/codegen/functions/collection.d.ts +2 -2
  10. package/out/types/src/codegen/functions/context.d.ts +3 -2
  11. package/out/types/src/codegen/types/collection.d.ts +2 -2
  12. package/out/types/src/codegen/utils/index.d.ts +4 -1
  13. package/out/types/src/doc/builder.d.ts +2 -2
  14. package/out/types/src/evaluator/calls/closure-type.d.ts +2 -2
  15. package/out/types/src/evaluator/calls/record-type.d.ts +11 -0
  16. package/out/types/src/evaluator/context.d.ts +8 -9
  17. package/out/types/src/evaluator/index.d.ts +3 -3
  18. package/out/types/src/evaluator/types/record.d.ts +14 -0
  19. package/out/types/src/evaluator/types/validation.d.ts +2 -2
  20. package/out/types/src/evaluator/values/anonymous-module.d.ts +5 -5
  21. package/out/types/src/evaluator/values/impl.d.ts +1 -1
  22. package/out/types/src/expr.d.ts +2 -4
  23. package/out/types/src/function-value.d.ts +1 -1
  24. package/out/types/src/lsp/document-manager.d.ts +1 -1
  25. package/out/types/src/module-manager.d.ts +3 -3
  26. package/out/types/src/test-runner.d.ts +1 -0
  27. package/out/types/src/types/creators.d.ts +3 -4
  28. package/out/types/src/types/definitions.d.ts +8 -19
  29. package/out/types/src/types/guards.d.ts +3 -3
  30. package/out/types/src/types/tags.d.ts +0 -1
  31. package/out/types/src/types/utils.d.ts +1 -1
  32. package/out/types/src/value-tag.d.ts +0 -1
  33. package/out/types/src/value.d.ts +6 -13
  34. package/out/types/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +1 -1
  36. package/std/error.yo +6 -6
  37. package/std/prelude.yo +1 -7
  38. package/vendor/mimalloc/.github/workflows/release.yaml +55 -0
  39. package/vendor/mimalloc/.github/workflows/stale.yaml +27 -0
  40. package/vendor/mimalloc/.github/workflows/test.yaml +163 -0
  41. package/vendor/mimalloc/CMakeLists.txt +52 -33
  42. package/vendor/mimalloc/azure-pipelines.yml +4 -3
  43. package/vendor/mimalloc/bin/bundle.bat +74 -0
  44. package/vendor/mimalloc/bin/bundle.sh +232 -0
  45. package/vendor/mimalloc/cmake/mimalloc-config-version.cmake +2 -2
  46. package/vendor/mimalloc/contrib/docker/alpine/Dockerfile +1 -1
  47. package/vendor/mimalloc/contrib/docker/alpine-arm32v7/Dockerfile +2 -2
  48. package/vendor/mimalloc/contrib/docker/alpine-x86/Dockerfile +1 -1
  49. package/vendor/mimalloc/contrib/docker/manylinux-x64/Dockerfile +1 -1
  50. package/vendor/mimalloc/contrib/vcpkg/portfile.cmake +4 -3
  51. package/vendor/mimalloc/contrib/vcpkg/vcpkg.json +1 -1
  52. package/vendor/mimalloc/doc/mimalloc-doc.h +42 -4
  53. package/vendor/mimalloc/doc/release-notes.md +15 -0
  54. package/vendor/mimalloc/ide/vs2022/mimalloc-lib.vcxproj +3 -3
  55. package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj +511 -0
  56. package/vendor/mimalloc/ide/vs2022/mimalloc-override-static-lib.vcxproj.filters +117 -0
  57. package/vendor/mimalloc/ide/vs2022/mimalloc-test-dep.vcxproj +360 -0
  58. package/vendor/mimalloc/ide/vs2022/mimalloc-test-override-static.vcxproj +310 -0
  59. package/vendor/mimalloc/ide/vs2022/mimalloc.sln +92 -35
  60. package/vendor/mimalloc/include/mimalloc/atomic.h +178 -182
  61. package/vendor/mimalloc/include/mimalloc/bits.h +8 -10
  62. package/vendor/mimalloc/include/mimalloc/internal.h +76 -32
  63. package/vendor/mimalloc/include/mimalloc/prim.h +25 -18
  64. package/vendor/mimalloc/include/mimalloc/track.h +7 -2
  65. package/vendor/mimalloc/include/mimalloc/types.h +57 -29
  66. package/vendor/mimalloc/include/mimalloc-override.h +10 -10
  67. package/vendor/mimalloc/include/mimalloc-stats.h +18 -6
  68. package/vendor/mimalloc/include/mimalloc.h +22 -12
  69. package/vendor/mimalloc/readme.md +42 -17
  70. package/vendor/mimalloc/src/alloc-aligned.c +13 -11
  71. package/vendor/mimalloc/src/alloc-override.c +97 -17
  72. package/vendor/mimalloc/src/alloc-posix.c +44 -27
  73. package/vendor/mimalloc/src/alloc.c +73 -23
  74. package/vendor/mimalloc/src/arena-meta.c +3 -3
  75. package/vendor/mimalloc/src/arena.c +380 -192
  76. package/vendor/mimalloc/src/bitmap.c +68 -18
  77. package/vendor/mimalloc/src/bitmap.h +8 -4
  78. package/vendor/mimalloc/src/free.c +83 -47
  79. package/vendor/mimalloc/src/heap.c +94 -40
  80. package/vendor/mimalloc/src/init.c +273 -102
  81. package/vendor/mimalloc/src/libc.c +53 -8
  82. package/vendor/mimalloc/src/options.c +43 -40
  83. package/vendor/mimalloc/src/os.c +110 -45
  84. package/vendor/mimalloc/src/page-map.c +14 -8
  85. package/vendor/mimalloc/src/page-queue.c +9 -6
  86. package/vendor/mimalloc/src/page.c +26 -16
  87. package/vendor/mimalloc/src/prim/emscripten/prim.c +10 -1
  88. package/vendor/mimalloc/src/prim/osx/alloc-override-zone.c +35 -16
  89. package/vendor/mimalloc/src/prim/unix/prim.c +26 -22
  90. package/vendor/mimalloc/src/prim/wasi/prim.c +7 -4
  91. package/vendor/mimalloc/src/prim/windows/prim.c +247 -44
  92. package/vendor/mimalloc/src/random.c +8 -3
  93. package/vendor/mimalloc/src/stats.c +59 -48
  94. package/vendor/mimalloc/src/theap.c +85 -44
  95. package/vendor/mimalloc/src/threadlocal.c +102 -41
  96. package/vendor/mimalloc/test/main-override-static.c +31 -2
  97. package/vendor/mimalloc/test/main-override.c +27 -14
  98. package/vendor/mimalloc/test/main-static-dep.cpp +46 -0
  99. package/vendor/mimalloc/test/main-static-dep.h +11 -0
  100. package/vendor/mimalloc/test/test-api-fill.c +2 -2
  101. package/vendor/mimalloc/test/test-stress.c +3 -3
  102. package/vendor/mimalloc/test/test-wrong.c +11 -7
  103. package/out/types/src/evaluator/calls/module-type.d.ts +0 -11
  104. package/out/types/src/evaluator/types/module.d.ts +0 -19
@@ -97,7 +97,6 @@ terms of the MIT license. A copy of the license can be found in the file
97
97
  #define mi_atomic_increment_acq_rel(p) mi_atomic_add_acq_rel(p,(uintptr_t)1)
98
98
  #define mi_atomic_decrement_acq_rel(p) mi_atomic_sub_acq_rel(p,(uintptr_t)1)
99
99
 
100
- static inline void mi_atomic_yield(void);
101
100
  static inline intptr_t mi_atomic_addi(_Atomic(intptr_t)*p, intptr_t add);
102
101
  static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub);
103
102
 
@@ -159,14 +158,18 @@ static inline void mi_atomic_maxi64_relaxed(volatile int64_t* p, int64_t x) {
159
158
 
160
159
  #elif defined(_MSC_VER)
161
160
 
162
- // Legacy MSVC plain C compilation wrapper that uses Interlocked operations to model C11 atomics.
161
+ // Deprecated: MSVC plain C compilation wrapper that uses Interlocked operations to model C11 atomics.
162
+ // It is recommended to always compile as C++ when using MSVC.
163
+
163
164
  #include <intrin.h>
164
165
  #ifdef _WIN64
165
- typedef LONG64 msc_intptr_t;
166
- #define MI_64(f) f##64
166
+ typedef LONG64 msc_intptr_t;
167
+ #define MI_MSC_64(f) f##64
168
+ #define MI_MSC_XX(f) f##64
167
169
  #else
168
- typedef LONG msc_intptr_t;
169
- #define MI_64(f) f
170
+ typedef LONG msc_intptr_t;
171
+ #define MI_MSC_64(f) f
172
+ #define MI_MSC_XX(f) f##32
170
173
  #endif
171
174
 
172
175
  typedef enum mi_memory_order_e {
@@ -180,23 +183,23 @@ typedef enum mi_memory_order_e {
180
183
 
181
184
  static inline uintptr_t mi_atomic_fetch_add_explicit(_Atomic(uintptr_t)*p, uintptr_t add, mi_memory_order mo) {
182
185
  (void)(mo);
183
- return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add);
186
+ return (uintptr_t)MI_MSC_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, (msc_intptr_t)add);
184
187
  }
185
188
  static inline uintptr_t mi_atomic_fetch_sub_explicit(_Atomic(uintptr_t)*p, uintptr_t sub, mi_memory_order mo) {
186
189
  (void)(mo);
187
- return (uintptr_t)MI_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, -((msc_intptr_t)sub));
190
+ return (uintptr_t)MI_MSC_64(_InterlockedExchangeAdd)((volatile msc_intptr_t*)p, -((msc_intptr_t)sub));
188
191
  }
189
192
  static inline uintptr_t mi_atomic_fetch_and_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
190
193
  (void)(mo);
191
- return (uintptr_t)MI_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
194
+ return (uintptr_t)MI_MSC_64(_InterlockedAnd)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
192
195
  }
193
196
  static inline uintptr_t mi_atomic_fetch_or_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
194
197
  (void)(mo);
195
- return (uintptr_t)MI_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
198
+ return (uintptr_t)MI_MSC_64(_InterlockedOr)((volatile msc_intptr_t*)p, (msc_intptr_t)x);
196
199
  }
197
200
  static inline bool mi_atomic_compare_exchange_strong_explicit(_Atomic(uintptr_t)*p, uintptr_t* expected, uintptr_t desired, mi_memory_order mo1, mi_memory_order mo2) {
198
201
  (void)(mo1); (void)(mo2);
199
- uintptr_t read = (uintptr_t)MI_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)(*expected));
202
+ const uintptr_t read = (uintptr_t)MI_MSC_64(_InterlockedCompareExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)desired, (msc_intptr_t)(*expected));
200
203
  if (read == *expected) {
201
204
  return true;
202
205
  }
@@ -210,68 +213,119 @@ static inline bool mi_atomic_compare_exchange_weak_explicit(_Atomic(uintptr_t)*p
210
213
  }
211
214
  static inline uintptr_t mi_atomic_exchange_explicit(_Atomic(uintptr_t)*p, uintptr_t exchange, mi_memory_order mo) {
212
215
  (void)(mo);
213
- return (uintptr_t)MI_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange);
216
+ return (uintptr_t)MI_MSC_64(_InterlockedExchange)((volatile msc_intptr_t*)p, (msc_intptr_t)exchange);
214
217
  }
215
218
  static inline void mi_atomic_thread_fence(mi_memory_order mo) {
216
219
  (void)(mo);
217
220
  _Atomic(uintptr_t) x = 0;
218
221
  mi_atomic_exchange_explicit(&x, 1, mo);
219
222
  }
223
+
220
224
  static inline uintptr_t mi_atomic_load_explicit(_Atomic(uintptr_t) const* p, mi_memory_order mo) {
221
225
  (void)(mo);
222
- #if defined(_M_IX86) || defined(_M_X64)
223
- return *p;
224
- #else
225
- uintptr_t x = *p;
226
- if (mo > mi_memory_order_relaxed) {
227
- while (!mi_atomic_compare_exchange_weak_explicit((_Atomic(uintptr_t)*)p, &x, x, mo, mi_memory_order_relaxed)) { /* nothing */ };
228
- }
229
- return x;
230
- #endif
226
+ // assert(mo<=mi_memory_order_acquire); // others are not used by mimalloc
227
+ #if defined(_M_IX86) || defined(_M_X64)
228
+ return (uintptr_t)MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
229
+ #elif defined(_M_ARM) || defined(_M_ARM64)
230
+ if (mo == mi_memory_order_relaxed) {
231
+ return (uintptr_t)MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
232
+ }
233
+ else if (mo <= mi_memory_order_acquire) {
234
+ return MI_MSC_XX(__ldar)((volatile const uintptr_t*)p);
235
+ }
236
+ else {
237
+ const uintptr_t u = (uintptr_t)MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
238
+ __dmb(15); // _ARM(64)_BARRIER_SY
239
+ return u;
240
+ }
241
+ #else
242
+ #warning "define mi_atomic_load_explicit for MSVC C compilation on this platform (which should be readonly, see issue #1277)"
243
+ return MI_MSC_XX(__iso_volatile_load)((volatile const intptr_t*)p);
244
+ #endif
231
245
  }
232
246
  static inline void mi_atomic_store_explicit(_Atomic(uintptr_t)*p, uintptr_t x, mi_memory_order mo) {
233
247
  (void)(mo);
234
- #if defined(_M_IX86) || defined(_M_X64)
235
- *p = x;
236
- #else
237
- mi_atomic_exchange_explicit(p, x, mo);
238
- #endif
248
+ // assert(mo<=mi_memory_order_release); // others are not used by mimalloc
249
+ #if defined(_M_IX86) || defined(_M_X64)
250
+ MI_MSC_XX(__iso_volatile_store)((volatile intptr_t*)p, x);
251
+ #elif defined(_M_ARM) || defined(_M_ARM64)
252
+ if (mo == mi_memory_order_relaxed) {
253
+ MI_MSC_XX(__iso_volatile_store)((volatile intptr_t*)p, x);
254
+ }
255
+ else if (mo <= mi_memory_order_release) {
256
+ MI_MSC_XX(__stlr)((volatile uintptr_t*)p,x);
257
+ }
258
+ else {
259
+ mi_atomic_exchange_explicit(p, x, mo);
260
+ }
261
+ #else
262
+ mi_atomic_exchange_explicit(p, x, mo);
263
+ #endif
239
264
  }
265
+
240
266
  static inline int64_t mi_atomic_loadi64_explicit(_Atomic(int64_t)*p, mi_memory_order mo) {
241
267
  (void)(mo);
242
- #if defined(_M_X64)
243
- return *p;
244
- #else
245
- int64_t old = *p;
246
- int64_t x = old;
247
- while ((old = InterlockedCompareExchange64(p, x, old)) != x) {
248
- x = old;
249
- }
250
- return x;
251
- #endif
268
+ // assert(mo<=mi_memory_order_acquire); // others are not used by mimalloc
269
+ #if defined(_M_IX86) || defined(_M_X64)
270
+ return __iso_volatile_load64((volatile const int64_t*)p);
271
+ #elif defined(_M_ARM) || defined(_M_ARM64)
272
+ if (mo == mi_memory_order_relaxed) {
273
+ return __iso_volatile_load64((volatile const int64_t*)p);
274
+ }
275
+ #if defined(_M_ARM64)
276
+ else if (mo <= mi_memory_order_acquire) {
277
+ return __ldar64((volatile const uintptr_t*)p);
278
+ }
279
+ #endif
280
+ else {
281
+ const int64_t i = __iso_volatile_load64((volatile const int64_t*)p);
282
+ __dmb(15); // _ARM(64)_BARRIER_SY
283
+ return i;
284
+ }
285
+ #else
286
+ #warning "define mi_atomic_loadi64_explicit for MSVC C compilation on this platform (which should be readonly, see issue #1277)"
287
+ return __iso_volatile_load64((volatile const int64_t*)p);
288
+ #endif
252
289
  }
290
+
253
291
  static inline void mi_atomic_storei64_explicit(_Atomic(int64_t)*p, int64_t x, mi_memory_order mo) {
254
292
  (void)(mo);
255
- #if defined(x_M_IX86) || defined(_M_X64)
256
- *p = x;
257
- #else
258
- InterlockedExchange64(p, x);
259
- #endif
293
+ // assert(mo<=mi_memory_order_release); // others are not used by mimalloc
294
+ #if defined(_M_IX86) || defined(_M_X64)
295
+ __iso_volatile_store64((volatile int64_t*)p,x);
296
+ #elif defined(_M_ARM) || defined(_M_ARM64)
297
+ if (mo == mi_memory_order_relaxed) {
298
+ __iso_volatile_store64((volatile int64_t*)p,x);
299
+ }
300
+ #if defined(_M_ARM64)
301
+ else if (mo == mi_memory_order_release) {
302
+ __stlr64((volatile uint64_t*)p, (uint64_t)x);
303
+ }
304
+ #endif
305
+ else {
306
+ InterlockedExchange64(p, x);
307
+ }
308
+ #else
309
+ InterlockedExchange64(p, x);
310
+ #endif
260
311
  }
261
312
 
262
313
  // These are used by the statistics
263
314
  static inline int64_t mi_atomic_addi64_relaxed(volatile _Atomic(int64_t)*p, int64_t add) {
264
- #ifdef _WIN64
265
- return (int64_t)mi_atomic_addi((int64_t*)p, add);
266
- #else
267
- int64_t current;
268
- int64_t sum;
269
- do {
270
- current = *p;
271
- sum = current + add;
272
- } while (_InterlockedCompareExchange64(p, sum, current) != current);
273
- return current;
274
- #endif
315
+ #ifdef _WIN64
316
+ return (int64_t)mi_atomic_addi((int64_t*)p, add);
317
+ #elif defined(_M_ARM)
318
+ return _InterlockedExchangeAdd64(p, add);
319
+ #else
320
+ // x86
321
+ int64_t current;
322
+ int64_t sum;
323
+ do {
324
+ current = __iso_volatile_load64((volatile const int64_t*)p);
325
+ sum = current + add;
326
+ } while (_InterlockedCompareExchange64(p, sum, current) != current);
327
+ return current;
328
+ #endif
275
329
  }
276
330
 
277
331
  static inline void mi_atomic_void_addi64_relaxed(volatile int64_t* p, const volatile int64_t* padd) {
@@ -293,7 +347,7 @@ static inline void mi_atomic_addi64_acq_rel(volatile _Atomic(int64_t*)p, int64_t
293
347
  }
294
348
 
295
349
  static inline bool mi_atomic_casi64_strong_acq_rel(volatile _Atomic(int64_t*)p, int64_t* exp, int64_t des) {
296
- int64_t read = _InterlockedCompareExchange64(p, des, *exp);
350
+ const int64_t read = _InterlockedCompareExchange64(p, des, *exp);
297
351
  if (read == *exp) {
298
352
  return true;
299
353
  }
@@ -337,21 +391,12 @@ static inline intptr_t mi_atomic_subi(_Atomic(intptr_t)*p, intptr_t sub) {
337
391
 
338
392
 
339
393
  // ----------------------------------------------------------------------
340
- // Once and Guard
394
+ // Guard
341
395
  // ----------------------------------------------------------------------
342
396
 
343
- typedef _Atomic(uintptr_t) mi_atomic_once_t;
344
-
345
- // Returns true only on the first invocation
346
- static inline bool mi_atomic_once( mi_atomic_once_t* once ) {
347
- if (mi_atomic_load_relaxed(once) != 0) return false; // quick test
348
- uintptr_t expected = 0;
349
- return mi_atomic_cas_strong_acq_rel(once, &expected, (uintptr_t)1); // try to set to 1
350
- }
351
-
352
397
  typedef _Atomic(uintptr_t) mi_atomic_guard_t;
353
398
 
354
- // Allows only one thread to execute at a time
399
+ // Allows only one thread to execute at a time (without blocking anyone)
355
400
  #define mi_atomic_guard(guard) \
356
401
  uintptr_t _mi_guard_expected = 0; \
357
402
  for(bool _mi_guard_once = true; \
@@ -359,77 +404,6 @@ typedef _Atomic(uintptr_t) mi_atomic_guard_t;
359
404
  (mi_atomic_store_release(guard,(uintptr_t)0), _mi_guard_once = false) )
360
405
 
361
406
 
362
-
363
- // ----------------------------------------------------------------------
364
- // Yield
365
- // ----------------------------------------------------------------------
366
-
367
- #if defined(__cplusplus)
368
- #include <thread>
369
- static inline void mi_atomic_yield(void) {
370
- std::this_thread::yield();
371
- }
372
- #elif defined(_WIN32)
373
- static inline void mi_atomic_yield(void) {
374
- YieldProcessor();
375
- }
376
- #elif defined(__SSE2__)
377
- #include <emmintrin.h>
378
- static inline void mi_atomic_yield(void) {
379
- _mm_pause();
380
- }
381
- #elif (defined(__GNUC__) || defined(__clang__)) && \
382
- (defined(__x86_64__) || defined(__i386__) || \
383
- defined(__aarch64__) || defined(__arm__) || \
384
- defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__POWERPC__))
385
- #if defined(__x86_64__) || defined(__i386__)
386
- static inline void mi_atomic_yield(void) {
387
- __asm__ volatile ("pause" ::: "memory");
388
- }
389
- #elif defined(__aarch64__)
390
- static inline void mi_atomic_yield(void) {
391
- __asm__ volatile("wfe");
392
- }
393
- #elif defined(__arm__)
394
- #if __ARM_ARCH >= 7
395
- static inline void mi_atomic_yield(void) {
396
- __asm__ volatile("yield" ::: "memory");
397
- }
398
- #else
399
- static inline void mi_atomic_yield(void) {
400
- __asm__ volatile ("nop" ::: "memory");
401
- }
402
- #endif
403
- #elif defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) || defined(__POWERPC__)
404
- #ifdef __APPLE__
405
- static inline void mi_atomic_yield(void) {
406
- __asm__ volatile ("or r27,r27,r27" ::: "memory");
407
- }
408
- #else
409
- static inline void mi_atomic_yield(void) {
410
- __asm__ __volatile__ ("or 27,27,27" ::: "memory");
411
- }
412
- #endif
413
- #endif
414
- #elif defined(__sun)
415
- // Fallback for other archs
416
- #include <synch.h>
417
- static inline void mi_atomic_yield(void) {
418
- smt_pause();
419
- }
420
- #elif defined(__wasi__)
421
- #include <sched.h>
422
- static inline void mi_atomic_yield(void) {
423
- sched_yield();
424
- }
425
- #else
426
- #include <unistd.h>
427
- static inline void mi_atomic_yield(void) {
428
- sleep(0);
429
- }
430
- #endif
431
-
432
-
433
407
  // ----------------------------------------------------------------------
434
408
  // Locks
435
409
  // These should be light-weight in-process only locks.
@@ -439,95 +413,90 @@ static inline void mi_atomic_yield(void) {
439
413
  #pragma warning(disable:26110) // unlock with holding lock
440
414
  #endif
441
415
 
442
- #define mi_lock(lock) for(bool _go = (mi_lock_acquire(lock),true); _go; (mi_lock_release(lock), _go=false) )
416
+ #define mi_lock(lock) for(bool _mi_go = (mi_lock_acquire(lock),true); _mi_go; (mi_lock_release(lock), _mi_go=false) )
417
+ #define mi_lock_maybe(lock,acquire) for(bool _mi_go = (acquire ? (mi_lock_acquire(lock),true) : true); _mi_go; _mi_go = (acquire ? (mi_lock_release(lock),false) : false) )
418
+
443
419
 
444
420
  #if defined(_WIN32)
445
421
 
446
- #if 1
447
- #define mi_lock_t SRWLOCK // slim reader-writer lock
422
+ typedef struct mi_lock_s {
423
+ SRWLOCK mutex; // slim reader-writer lock
424
+ } mi_lock_t;
448
425
 
449
- static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
450
- return TryAcquireSRWLockExclusive(lock);
451
- }
452
- static inline void mi_lock_acquire(mi_lock_t* lock) {
453
- AcquireSRWLockExclusive(lock);
454
- }
455
- static inline void mi_lock_release(mi_lock_t* lock) {
456
- ReleaseSRWLockExclusive(lock);
457
- }
458
- static inline void mi_lock_init(mi_lock_t* lock) {
459
- InitializeSRWLock(lock);
460
- }
461
- static inline void mi_lock_done(mi_lock_t* lock) {
462
- (void)(lock);
463
- }
464
-
465
- #else
466
- #define mi_lock_t CRITICAL_SECTION
426
+ #define MI_LOCK_INITIALIZER { SRWLOCK_INIT }
467
427
 
468
428
  static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
469
- return TryEnterCriticalSection(lock);
429
+ return TryAcquireSRWLockExclusive(&lock->mutex);
470
430
  }
471
431
  static inline void mi_lock_acquire(mi_lock_t* lock) {
472
- EnterCriticalSection(lock);
432
+ AcquireSRWLockExclusive(&lock->mutex);
473
433
  }
474
434
  static inline void mi_lock_release(mi_lock_t* lock) {
475
- LeaveCriticalSection(lock);
435
+ ReleaseSRWLockExclusive(&lock->mutex);
476
436
  }
477
437
  static inline void mi_lock_init(mi_lock_t* lock) {
478
- InitializeCriticalSection(lock);
438
+ InitializeSRWLock(&lock->mutex);
479
439
  }
480
440
  static inline void mi_lock_done(mi_lock_t* lock) {
481
- DeleteCriticalSection(lock);
441
+ (void)(lock);
482
442
  }
483
443
 
484
- #endif
485
-
486
444
  #elif defined(MI_USE_PTHREADS)
487
445
 
488
446
  #include <string.h> // memcpy
489
447
  void _mi_error_message(int err, const char* fmt, ...);
490
448
 
491
- #define mi_lock_t pthread_mutex_t
449
+ typedef struct mi_lock_s {
450
+ pthread_mutex_t mutex;
451
+ } mi_lock_t;
452
+
453
+ #define MI_LOCK_INITIALIZER { PTHREAD_MUTEX_INITIALIZER }
492
454
 
493
455
  static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
494
- return (pthread_mutex_trylock(lock) == 0);
456
+ return (pthread_mutex_trylock(&lock->mutex) == 0);
495
457
  }
496
458
  static inline void mi_lock_acquire(mi_lock_t* lock) {
497
- const int err = pthread_mutex_lock(lock);
459
+ const int err = pthread_mutex_lock(&lock->mutex);
498
460
  if (err != 0) {
499
461
  _mi_error_message(err, "internal error: lock cannot be acquired (err %i)\n", err);
500
462
  }
501
463
  }
502
464
  static inline void mi_lock_release(mi_lock_t* lock) {
503
- pthread_mutex_unlock(lock);
465
+ pthread_mutex_unlock(&lock->mutex);
504
466
  }
505
467
  static inline void mi_lock_init(mi_lock_t* lock) {
506
468
  if(lock==NULL) return;
507
- // use instead of pthread_mutex_init since that can cause allocation on some platforms (and recursively initialize)
508
- const mi_lock_t temp_lock = PTHREAD_MUTEX_INITIALIZER;
509
- memcpy(lock,&temp_lock,sizeof(temp_lock));
469
+ // use this instead of pthread_mutex_init since that can cause allocation on some platforms (and recursively initialize)
470
+ const pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
471
+ memcpy(&lock->mutex,&mutex,sizeof(mutex));
510
472
  }
511
473
  static inline void mi_lock_done(mi_lock_t* lock) {
512
- pthread_mutex_destroy(lock);
474
+ pthread_mutex_destroy(&lock->mutex);
513
475
  }
514
476
 
515
477
  #elif defined(__cplusplus)
516
478
 
479
+ #include <thread>
517
480
  #include <mutex>
518
- #define mi_lock_t std::mutex
481
+ #include <new>
482
+
483
+ typedef struct mi_lock_s {
484
+ std::mutex mutex;
485
+ } mi_lock_t;
486
+
487
+ #define MI_LOCK_INITIALIZER { }
519
488
 
520
489
  static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
521
- return lock->try_lock();
490
+ return lock->mutex.try_lock();
522
491
  }
523
492
  static inline void mi_lock_acquire(mi_lock_t* lock) {
524
- lock->lock();
493
+ lock->mutex.lock();
525
494
  }
526
495
  static inline void mi_lock_release(mi_lock_t* lock) {
527
- lock->unlock();
496
+ lock->mutex.unlock();
528
497
  }
529
498
  static inline void mi_lock_init(mi_lock_t* lock) {
530
- (void)(lock);
499
+ new(&lock->mutex) std::mutex();
531
500
  }
532
501
  static inline void mi_lock_done(mi_lock_t* lock) {
533
502
  (void)(lock);
@@ -537,21 +506,32 @@ static inline void mi_lock_done(mi_lock_t* lock) {
537
506
 
538
507
  // fall back to poor man's locks.
539
508
  // this should only be the case in a single-threaded environment (like __wasi__)
509
+ #include <errno.h>
510
+ #ifndef EFAULT
511
+ #define EFAULT (14)
512
+ #endif
513
+ void _mi_error_message(int err, const char* fmt, ...);
514
+ void _mi_prim_thread_yield(void);
515
+
516
+ typedef struct mi_lock_s {
517
+ _Atomic(uintptr_t) mutex;
518
+ } mi_lock_t;
540
519
 
541
- #define mi_lock_t _Atomic(uintptr_t)
520
+ #define MI_LOCK_INITIALIZER { MI_ATOMIC_VAR_INIT(0) }
542
521
 
543
522
  static inline bool mi_lock_try_acquire(mi_lock_t* lock) {
544
523
  uintptr_t expected = 0;
545
- return mi_atomic_cas_strong_acq_rel(lock, &expected, (uintptr_t)1);
524
+ return mi_atomic_cas_strong_acq_rel(&lock->mutex, &expected, (uintptr_t)1);
546
525
  }
547
526
  static inline void mi_lock_acquire(mi_lock_t* lock) {
548
- for (int i = 0; i < 1000; i++) { // for at most 1000 tries?
527
+ for (int i = 0; i < 10000; i++) { // for at most 10000 tries?
549
528
  if (mi_lock_try_acquire(lock)) return;
550
- mi_atomic_yield();
529
+ _mi_prim_thread_yield();
551
530
  }
531
+ _mi_error_message(EFAULT, "internal error: lock cannot be acquired (due to lack of native lock primitives)\n");
552
532
  }
553
533
  static inline void mi_lock_release(mi_lock_t* lock) {
554
- mi_atomic_store_release(lock, (uintptr_t)0);
534
+ mi_atomic_store_release(&lock->mutex, (uintptr_t)0);
555
535
  }
556
536
  static inline void mi_lock_init(mi_lock_t* lock) {
557
537
  mi_lock_release(lock);
@@ -563,4 +543,20 @@ static inline void mi_lock_done(mi_lock_t* lock) {
563
543
  #endif
564
544
 
565
545
 
566
- #endif // MI_ATOMIC_H
546
+ typedef struct mi_atomic_once_s {
547
+ _Atomic(uintptr_t) tid;
548
+ mi_lock_t lock;
549
+ } mi_atomic_once_t;
550
+
551
+ // Returns `true` only on the first invocation, signifying we can execute an action once.
552
+ // If it returns `true`, the caller should call `_mi_atomic_once_release` after performing the action.
553
+ // Other threads (than the initial thread that entered) will block until `_mi_atomic_once_release` has been called.
554
+ bool _mi_atomic_once_enter(mi_atomic_once_t* once); // defined in `libc.c`
555
+ void _mi_atomic_once_release(mi_atomic_once_t* once); // defined in `libc.c`
556
+
557
+ #define mi_atomic_do_once \
558
+ static mi_atomic_once_t _mi_once = { MI_ATOMIC_VAR_INIT(0), MI_LOCK_INITIALIZER }; \
559
+ for(bool _mi_exec = _mi_atomic_once_enter(&_mi_once); _mi_exec; (_mi_atomic_once_release(&_mi_once),_mi_exec=false))
560
+
561
+
562
+ #endif // __MIMALLOC_ATOMIC_H
@@ -108,6 +108,9 @@ typedef int32_t mi_ssize_t;
108
108
  #if MI_ARCH_X64 && (defined(__AVX2__) || defined(__BMI2__)) && !defined(__BMI1__) // msvc
109
109
  #define __BMI1__ 1
110
110
  #endif
111
+ #if MI_ARCH_X64 && defined(__AVX2__) && !defined(__LZCNT__) // msvc
112
+ #define __LZCNT__ 1
113
+ #endif
111
114
 
112
115
  // Define big endian if needed
113
116
  // #define MI_BIG_ENDIAN 1
@@ -123,9 +126,9 @@ typedef int32_t mi_ssize_t;
123
126
  #define MI_MAX_VABITS (32)
124
127
  #endif
125
128
 
126
- // use a flat page-map (or a 2-level one)
129
+ // use a flat page-map or a 2-level one
127
130
  #ifndef MI_PAGE_MAP_FLAT
128
- #if MI_MAX_VABITS <= 40 && !defined(__APPLE__)
131
+ #if MI_MAX_VABITS <= 40 && !defined(__APPLE__) && MI_SECURE==0 && !MI_PAGE_META_IS_SEPARATED
129
132
  #define MI_PAGE_MAP_FLAT 1
130
133
  #else
131
134
  #define MI_PAGE_MAP_FLAT 0
@@ -222,11 +225,11 @@ static inline size_t mi_ctz(size_t x) {
222
225
  }
223
226
 
224
227
  static inline size_t mi_clz(size_t x) {
225
- #if defined(__GNUC__) && MI_ARCH_X64 && defined(__BMI1__) // on x64 lzcnt is defined for 0
228
+ #if defined(__GNUC__) && MI_ARCH_X64 && defined(__LZCNT__) // on x64 lzcnt is defined for 0
226
229
  size_t r;
227
230
  __asm ("lzcnt\t%1, %0" : "=r"(r) : "r"(x) : "cc");
228
231
  return r;
229
- #elif defined(_MSC_VER) && MI_ARCH_X64 && defined(__BMI1__)
232
+ #elif defined(_MSC_VER) && MI_ARCH_X64 && defined(__LZCNT__)
230
233
  return _lzcnt_u64(x);
231
234
  #elif defined(_MSC_VER) && (MI_ARCH_X64 || MI_ARCH_X86 || MI_ARCH_ARM64 || MI_ARCH_ARM32)
232
235
  unsigned long idx;
@@ -273,12 +276,7 @@ static inline bool mi_bsf(size_t x, size_t* idx) {
273
276
  // return false if `x==0` (with `*idx` undefined) and true otherwise,
274
277
  // with the `idx` is set to the bit index (`0 <= *idx < MI_BFIELD_BITS`).
275
278
  static inline bool mi_bsr(size_t x, size_t* idx) {
276
- #if defined(__GNUC__) && MI_ARCH_X64 && defined(__BMI1__) && (!defined(__clang_major__) || __clang_major__ >= 9)
277
- // on x64 the carry flag is set on zero which gives better codegen
278
- bool is_zero;
279
- __asm ("lzcnt\t%2, %1" : "=@ccc"(is_zero), "=r"(*idx) : "r"(x) : "cc");
280
- return !is_zero;
281
- #elif 0 && defined(_MSC_VER) && (MI_ARCH_X64 || MI_ARCH_X86 || MI_ARCH_ARM64 || MI_ARCH_ARM32)
279
+ #if 0 && defined(_MSC_VER) && (MI_ARCH_X64 || MI_ARCH_X86 || MI_ARCH_ARM64 || MI_ARCH_ARM32)
282
280
  unsigned long i;
283
281
  return (mi_msc_builtinz(_BitScanReverse)(&i, x) ? (*idx = (size_t)i, true) : false);
284
282
  #else