|
29 | 29 | #include <pthread.h>
|
30 | 30 | #include <execinfo.h>
|
31 | 31 |
|
| 32 | +#if __has_include(<malloc/malloc.h>) |
| 33 | +#include <malloc/malloc.h> |
| 34 | +#endif |
| 35 | + |
32 | 36 | _CF_EXPORT_SCOPE_BEGIN
|
33 | 37 |
|
34 | 38 | struct __CFSwiftObject {
|
@@ -345,6 +349,54 @@ CF_EXPORT CFStringRef _CFXDGCreateCacheDirectoryPath(void);
|
345 | 349 | /// a single base directory relative to which user-specific runtime files and other file objects should be placed. This directory is defined by the environment variable $XDG_RUNTIME_DIR.
|
346 | 350 | CF_EXPORT CFStringRef _CFXDGCreateRuntimeDirectoryPath(void);
|
347 | 351 |
|
| 352 | + |
| 353 | +typedef struct { |
| 354 | + void *_Nonnull memory; |
| 355 | + size_t capacity; |
| 356 | + _Bool onStack; |
| 357 | +} _ConditionalAllocationBuffer; |
| 358 | + |
| 359 | +static inline _Bool _resizeConditionalAllocationBuffer(_ConditionalAllocationBuffer *_Nonnull buffer, size_t amt) { |
| 360 | +#if TARGET_OS_MAC |
| 361 | + size_t amount = malloc_good_size(amt); |
| 362 | +#else |
| 363 | + size_t amount = amt; |
| 364 | +#endif |
| 365 | + if (amount <= buffer->capacity) { return true; } |
| 366 | + void *newMemory; |
| 367 | + if (buffer->onStack) { |
| 368 | + newMemory = malloc(amount); |
| 369 | + if (newMemory == NULL) { return false; } |
| 370 | + memcpy(newMemory, buffer->memory, buffer->capacity); |
| 371 | + buffer->onStack = false; |
| 372 | + } else { |
| 373 | + newMemory = realloc(buffer->memory, amount); |
| 374 | + if (newMemory == NULL) { return false; } |
| 375 | + } |
| 376 | + if (newMemory == NULL) { return false; } |
| 377 | + buffer->memory = newMemory; |
| 378 | + buffer->capacity = amount; |
| 379 | + return true; |
| 380 | +} |
| 381 | + |
| 382 | +static inline _Bool _withStackOrHeapBuffer(size_t amount, void (__attribute__((noescape)) ^ _Nonnull applier)(_ConditionalAllocationBuffer *_Nonnull)) { |
| 383 | + _ConditionalAllocationBuffer buffer; |
| 384 | +#if TARGET_OS_MAC |
| 385 | + buffer.capacity = malloc_good_size(amount); |
| 386 | +#else |
| 387 | + buffer.capacity = amount; |
| 388 | +#endif |
| 389 | + buffer.onStack = (_CFIsMainThread() != 0 ? buffer.capacity < 2048 : buffer.capacity < 512); |
| 390 | + buffer.memory = buffer.onStack ? alloca(buffer.capacity) : malloc(buffer.capacity); |
| 391 | + if (buffer.memory == NULL) { return false; } |
| 392 | + applier(&buffer); |
| 393 | + if (!buffer.onStack) { |
| 394 | + free(buffer.memory); |
| 395 | + } |
| 396 | + return true; |
| 397 | +} |
| 398 | + |
| 399 | + |
348 | 400 | _CF_EXPORT_SCOPE_END
|
349 | 401 |
|
350 | 402 | #endif /* __COREFOUNDATION_FORSWIFTFOUNDATIONONLY__ */
|
0 commit comments