memory.c (27649B)
1 // Various routines dealing with allocation and deallocation of memory. 2 3 #include <assert.h> 4 #include <inttypes.h> 5 #include <stdbool.h> 6 #include <stdint.h> 7 #include <stdlib.h> 8 #include <string.h> 9 #include <time.h> 10 11 #include "nvim/api/extmark.h" 12 #include "nvim/api/private/helpers.h" 13 #include "nvim/api/ui.h" 14 #include "nvim/arglist.h" 15 #include "nvim/ascii_defs.h" 16 #include "nvim/buffer_defs.h" 17 #include "nvim/buffer_updates.h" 18 #include "nvim/channel.h" 19 #include "nvim/context.h" 20 #include "nvim/decoration_provider.h" 21 #include "nvim/drawline.h" 22 #include "nvim/errors.h" 23 #include "nvim/eval.h" 24 #include "nvim/gettext_defs.h" 25 #include "nvim/globals.h" 26 #include "nvim/highlight.h" 27 #include "nvim/highlight_group.h" 28 #include "nvim/insexpand.h" 29 #include "nvim/lua/executor.h" 30 #include "nvim/main.h" 31 #include "nvim/map_defs.h" 32 #include "nvim/mapping.h" 33 #include "nvim/memfile.h" 34 #include "nvim/memory.h" 35 #include "nvim/message.h" 36 #include "nvim/option_vars.h" 37 #include "nvim/sign.h" 38 #include "nvim/state_defs.h" 39 #include "nvim/statusline.h" 40 #include "nvim/types_defs.h" 41 #include "nvim/ui.h" 42 #include "nvim/ui_client.h" 43 #include "nvim/ui_compositor.h" 44 #include "nvim/usercmd.h" 45 46 #ifdef UNIT_TESTING 47 # define malloc(size) mem_malloc(size) 48 # define calloc(count, size) mem_calloc(count, size) 49 # define realloc(ptr, size) mem_realloc(ptr, size) 50 # define free(ptr) mem_free(ptr) 51 MemMalloc mem_malloc = &malloc; 52 MemFree mem_free = &free; 53 MemCalloc mem_calloc = &calloc; 54 MemRealloc mem_realloc = &realloc; 55 #endif 56 57 #include "memory.c.generated.h" 58 59 #ifdef EXITFREE 60 bool entered_free_all_mem = false; 61 #endif 62 63 /// Try to free memory. Used when trying to recover from out of memory errors. 64 /// @see {xmalloc} 65 static void try_to_free_memory(void) 66 { 67 static bool trying_to_free = false; 68 // avoid recursive calls 69 if (trying_to_free) { 70 return; 71 } 72 trying_to_free = true; 73 74 // free any scrollback text 75 clear_sb_text(true); 76 // Try to save all buffers and release as many blocks as possible 77 mf_release_all(); 78 79 arena_free_reuse_blks(); 80 81 trying_to_free = false; 82 } 83 84 /// Avoid repeating the error message many times (they take 1 second each). 85 /// `did_outofmem_msg` is reset when a character is read. 86 static void do_outofmem_msg(size_t size) 87 { 88 if (did_outofmem_msg) { 89 return; 90 } 91 92 // Don't hide this message 93 emsg_silent = 0; 94 95 // Must come first to avoid coming back here when printing the error 96 // message fails, e.g. when setting v:errmsg. 97 did_outofmem_msg = true; 98 99 semsg(_("E342: Out of memory! (allocating %" PRIu64 " bytes)"), (uint64_t)size); 100 } 101 102 /// malloc() wrapper 103 /// 104 /// try_malloc() is a malloc() wrapper that tries to free some memory before 105 /// trying again. 106 /// 107 /// @see {try_to_free_memory} 108 /// @param size 109 /// @return pointer to allocated space. NULL if out of memory 110 void *try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) 111 { 112 size_t allocated_size = size ? size : 1; 113 void *ret = malloc(allocated_size); 114 if (!ret) { 115 try_to_free_memory(); 116 ret = malloc(allocated_size); 117 } 118 return ret; 119 } 120 121 /// try_malloc() wrapper that shows an out-of-memory error message to the user 122 /// before returning NULL 123 /// 124 /// @see {try_malloc} 125 /// @param size 126 /// @return pointer to allocated space. NULL if out of memory 127 void *verbose_try_malloc(size_t size) FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) 128 { 129 void *ret = try_malloc(size); 130 if (!ret) { 131 do_outofmem_msg(size); 132 } 133 return ret; 134 } 135 136 /// malloc() wrapper that never returns NULL 137 /// 138 /// xmalloc() succeeds or gracefully aborts when out of memory. 139 /// Before aborting try to free some memory and call malloc again. 140 /// 141 /// @see {try_to_free_memory} 142 /// @param size 143 /// @return pointer to allocated space. Never NULL 144 void *xmalloc(size_t size) 145 FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(1) FUNC_ATTR_NONNULL_RET 146 { 147 void *ret = try_malloc(size); 148 if (!ret) { 149 preserve_exit(e_outofmem); 150 } 151 return ret; 152 } 153 154 /// free() wrapper that delegates to the backing memory manager 155 /// 156 /// @note Use XFREE_CLEAR() instead, if possible. 157 void xfree(void *ptr) 158 { 159 free(ptr); 160 } 161 162 /// calloc() wrapper 163 /// 164 /// @see {xmalloc} 165 /// @param count 166 /// @param size 167 /// @return pointer to allocated space. Never NULL 168 void *xcalloc(size_t count, size_t size) 169 FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE_PROD(1, 2) FUNC_ATTR_NONNULL_RET 170 { 171 size_t allocated_count = count && size ? count : 1; 172 size_t allocated_size = count && size ? size : 1; 173 void *ret = calloc(allocated_count, allocated_size); 174 if (!ret) { 175 try_to_free_memory(); 176 ret = calloc(allocated_count, allocated_size); 177 if (!ret) { 178 preserve_exit(e_outofmem); 179 } 180 } 181 return ret; 182 } 183 184 /// realloc() wrapper 185 /// 186 /// @see {xmalloc} 187 /// @param size 188 /// @return pointer to reallocated space. Never NULL 189 void *xrealloc(void *ptr, size_t size) 190 FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALLOC_SIZE(2) FUNC_ATTR_NONNULL_RET 191 { 192 size_t allocated_size = size ? size : 1; 193 void *ret = realloc(ptr, allocated_size); 194 if (!ret) { 195 try_to_free_memory(); 196 ret = realloc(ptr, allocated_size); 197 if (!ret) { 198 preserve_exit(e_outofmem); 199 } 200 } 201 return ret; 202 } 203 204 /// xmalloc() wrapper that allocates size + 1 bytes and zeroes the last byte 205 /// 206 /// Commonly used to allocate strings, e.g. `char *s = xmallocz(len)`. 207 /// 208 /// @see {xmalloc} 209 /// @param size 210 /// @return pointer to allocated space. Never NULL 211 void *xmallocz(size_t size) 212 FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT 213 { 214 size_t total_size = size + 1; 215 if (total_size < size) { 216 preserve_exit(_("Nvim: Data too large to fit into virtual memory space\n")); 217 } 218 219 void *ret = xmalloc(total_size); 220 ((char *)ret)[size] = NUL; 221 222 return ret; 223 } 224 225 /// Allocates (len + 1) bytes of memory, duplicates `len` bytes of 226 /// `data` to the allocated memory, zero terminates the allocated memory, 227 /// and returns a pointer to the allocated memory. If the allocation fails, 228 /// the program dies. 229 /// 230 /// @see {xmalloc} 231 /// @param data Pointer to the data that will be copied 232 /// @param len number of bytes that will be copied 233 void *xmemdupz(const void *data, size_t len) 234 FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT 235 FUNC_ATTR_NONNULL_ALL 236 { 237 return memcpy(xmallocz(len), data, len); 238 } 239 240 /// Copies `len` bytes of `src` to `dst` and zero terminates it. 241 /// 242 /// @see {xstrlcpy} 243 /// @param[out] dst Buffer to store the result. 244 /// @param[in] src Buffer to be copied. 245 /// @param[in] len Number of bytes to be copied. 246 void *xmemcpyz(void *dst, const void *src, size_t len) 247 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET 248 { 249 memcpy(dst, src, len); 250 ((char *)dst)[len] = NUL; 251 return dst; 252 } 253 254 #ifndef HAVE_STRNLEN 255 size_t xstrnlen(const char *s, size_t n) 256 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE 257 { 258 const char *end = memchr(s, NUL, n); 259 if (end == NULL) { 260 return n; 261 } 262 return (size_t)(end - s); 263 } 264 #endif 265 266 /// A version of strchr() that returns a pointer to the terminating NUL if it 267 /// doesn't find `c`. 268 /// 269 /// @param str The string to search. 270 /// @param c The char to look for. 271 /// @returns a pointer to the first instance of `c`, or to the NUL terminator 272 /// if not found. 273 char *xstrchrnul(const char *str, char c) 274 FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE 275 { 276 const char *p = strchr(str, c); 277 return p ? (char *)p : (char *)(str + strlen(str)); 278 } 279 280 /// A version of memchr() that returns a pointer one past the end 281 /// if it doesn't find `c`. 282 /// 283 /// @param addr The address of the memory object. 284 /// @param c The char to look for. 285 /// @param size The size of the memory object. 286 /// @returns a pointer to the first instance of `c`, or one past the end if not 287 /// found. 288 void *xmemscan(const void *addr, char c, size_t size) 289 FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE 290 { 291 const char *p = memchr(addr, c, size); 292 return p ? (char *)p : (char *)addr + size; 293 } 294 295 /// Replaces every instance of `c` with `x`. 296 /// 297 /// @warning Will read past `str + strlen(str)` if `c == NUL`. 298 /// 299 /// @param str A NUL-terminated string. 300 /// @param c The unwanted byte. 301 /// @param x The replacement. 302 void strchrsub(char *str, char c, char x) 303 FUNC_ATTR_NONNULL_ALL 304 { 305 assert(c != NUL); 306 while ((str = strchr(str, c))) { 307 *str++ = x; 308 } 309 } 310 311 /// Replaces every instance of `c` with `x`. 312 /// 313 /// @param data An object in memory. May contain NULs. 314 /// @param c The unwanted byte. 315 /// @param x The replacement. 316 /// @param len The length of data. 317 void memchrsub(void *data, char c, char x, size_t len) 318 FUNC_ATTR_NONNULL_ALL 319 { 320 char *p = data; 321 char *end = (char *)data + len; 322 while ((p = memchr(p, c, (size_t)(end - p)))) { 323 *p++ = x; 324 } 325 } 326 327 /// Counts the number of occurrences of `c` in `str`. 328 /// 329 /// @warning Unsafe if `c == NUL`. 330 /// 331 /// @param str Pointer to the string to search. 332 /// @param c The byte to search for. 333 /// @returns the number of occurrences of `c` in `str`. 334 size_t strcnt(const char *str, char c) 335 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE 336 { 337 assert(c != 0); 338 size_t cnt = 0; 339 while ((str = strchr(str, c))) { 340 cnt++; 341 str++; // Skip the instance of c. 342 } 343 return cnt; 344 } 345 346 /// Counts the number of occurrences of byte `c` in `data[len]`. 347 /// 348 /// @param data Pointer to the data to search. 349 /// @param c The byte to search for. 350 /// @param len The length of `data`. 351 /// @returns the number of occurrences of `c` in `data[len]`. 352 size_t memcnt(const void *data, char c, size_t len) 353 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE 354 { 355 size_t cnt = 0; 356 const char *ptr = data; 357 const char *end = ptr + len; 358 while ((ptr = memchr(ptr, c, (size_t)(end - ptr))) != NULL) { 359 cnt++; 360 ptr++; // Skip the instance of c. 361 } 362 return cnt; 363 } 364 365 /// Copies the string pointed to by src (including the terminating NUL 366 /// character) into the array pointed to by dst. 367 /// 368 /// @returns pointer to the terminating NUL char copied into the dst buffer. 369 /// This is the only difference with strcpy(), which returns dst. 370 /// 371 /// WARNING: If copying takes place between objects that overlap, the behavior 372 /// is undefined. 373 /// 374 /// Nvim version of POSIX 2008 stpcpy(3). We do not require POSIX 2008, so 375 /// implement our own version. 376 /// 377 /// @param dst 378 /// @param src 379 char *xstpcpy(char *restrict dst, const char *restrict src) 380 FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL 381 { 382 const size_t len = strlen(src); 383 return (char *)memcpy(dst, src, len + 1) + len; 384 } 385 386 /// Copies not more than n bytes (bytes that follow a NUL character are not 387 /// copied) from the array pointed to by src to the array pointed to by dst. 388 /// 389 /// If a NUL character is written to the destination, xstpncpy() returns the 390 /// address of the first such NUL character. Otherwise, it shall return 391 /// &dst[maxlen]. 392 /// 393 /// WARNING: If copying takes place between objects that overlap, the behavior 394 /// is undefined. 395 /// 396 /// WARNING: xstpncpy will ALWAYS write maxlen bytes. If src is shorter than 397 /// maxlen, zeroes will be written to the remaining bytes. 398 /// 399 /// @param dst 400 /// @param src 401 /// @param maxlen 402 char *xstpncpy(char *restrict dst, const char *restrict src, size_t maxlen) 403 FUNC_ATTR_NONNULL_RET FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL 404 { 405 const char *p = memchr(src, NUL, maxlen); 406 if (p) { 407 size_t srclen = (size_t)(p - src); 408 memcpy(dst, src, srclen); 409 memset(dst + srclen, 0, maxlen - srclen); 410 return dst + srclen; 411 } else { 412 memcpy(dst, src, maxlen); 413 return dst + maxlen; 414 } 415 } 416 417 /// xstrlcpy - Copy a NUL-terminated string into a sized buffer 418 /// 419 /// Compatible with *BSD strlcpy: the result is always a valid NUL-terminated 420 /// string that fits in the buffer (unless, of course, the buffer size is 421 /// zero). It does not pad out the result like strncpy() does. 422 /// 423 /// @param[out] dst Buffer to store the result. 424 /// @param[in] src String to be copied. 425 /// @param[in] dsize Size of `dst`. 426 /// 427 /// @return Length of `src`. May be greater than `dsize - 1`, which would mean 428 /// that string was truncated. 429 size_t xstrlcpy(char *restrict dst, const char *restrict src, size_t dsize) 430 FUNC_ATTR_NONNULL_ALL 431 { 432 size_t slen = strlen(src); 433 434 if (dsize) { 435 size_t len = MIN(slen, dsize - 1); 436 memcpy(dst, src, len); 437 dst[len] = NUL; 438 } 439 440 return slen; // Does not include NUL. 441 } 442 443 /// Appends `src` to string `dst` of size `dsize` (unlike strncat, dsize is the 444 /// full size of `dst`, not space left). At most dsize-1 characters 445 /// will be copied. Always NUL terminates. `src` and `dst` may overlap. 446 /// 447 /// @see vim_strcat from Vim. 448 /// @see strlcat from OpenBSD. 449 /// 450 /// @param[in,out] dst Buffer to be appended-to. Must have a NUL byte. 451 /// @param[in] src String to put at the end of `dst`. 452 /// @param[in] dsize Size of `dst` including NUL byte. Must be greater than 0. 453 /// 454 /// @return Length of the resulting string as if destination size was #SIZE_MAX. 455 /// May be greater than `dsize - 1`, which would mean that string was 456 /// truncated. 457 size_t xstrlcat(char *const dst, const char *const src, const size_t dsize) 458 FUNC_ATTR_NONNULL_ALL 459 { 460 assert(dsize > 0); 461 const size_t dlen = strlen(dst); 462 assert(dlen < dsize); 463 const size_t slen = strlen(src); 464 465 if (slen > dsize - dlen - 1) { 466 memmove(dst + dlen, src, dsize - dlen - 1); 467 dst[dsize - 1] = NUL; 468 } else { 469 memmove(dst + dlen, src, slen + 1); 470 } 471 472 return slen + dlen; // Does not include NUL. 473 } 474 475 /// strdup() wrapper 476 /// 477 /// @see {xmalloc} 478 /// @param str 0-terminated string that will be copied 479 /// @return pointer to a copy of the string 480 char *xstrdup(const char *str) 481 FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET 482 FUNC_ATTR_NONNULL_ALL 483 { 484 return xmemdupz(str, strlen(str)); 485 } 486 487 /// strdup() wrapper 488 /// 489 /// Unlike xstrdup() allocates a new empty string if it receives NULL. 490 char *xstrdupnul(const char *const str) 491 FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET 492 { 493 if (str == NULL) { 494 return xmallocz(0); 495 } 496 return xstrdup(str); 497 } 498 499 /// A version of memchr that starts the search at `src + len`. 500 /// 501 /// Based on glibc's memrchr. 502 /// 503 /// @param src The source memory object. 504 /// @param c The byte to search for. 505 /// @param len The length of the memory object. 506 /// @returns a pointer to the found byte in src[len], or NULL. 507 void *xmemrchr(const void *src, uint8_t c, size_t len) 508 FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE 509 { 510 while (len--) { 511 if (((uint8_t *)src)[len] == c) { 512 return (uint8_t *)src + len; 513 } 514 } 515 return NULL; 516 } 517 518 /// strndup() wrapper 519 /// 520 /// @see {xmalloc} 521 /// @param str 0-terminated string that will be copied 522 /// @return pointer to a copy of the string 523 char *xstrndup(const char *str, size_t len) 524 FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_RET 525 FUNC_ATTR_NONNULL_ALL 526 { 527 const char *p = memchr(str, NUL, len); 528 return xmemdupz(str, p ? (size_t)(p - str) : len); 529 } 530 531 /// Duplicates a chunk of memory using xmalloc 532 /// 533 /// @see {xmalloc} 534 /// @param data pointer to the chunk 535 /// @param len size of the chunk 536 /// @return a pointer 537 void *xmemdup(const void *data, size_t len) 538 FUNC_ATTR_MALLOC FUNC_ATTR_ALLOC_SIZE(2) FUNC_ATTR_NONNULL_RET 539 FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL 540 { 541 return memcpy(xmalloc(len), data, len); 542 } 543 544 /// Returns true if strings `a` and `b` are equal. Arguments may be NULL. 545 bool strequal(const char *a, const char *b) 546 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 547 { 548 return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0); 549 } 550 551 /// Returns true if first `n` characters of strings `a` and `b` are equal. Arguments may be NULL. 552 bool strnequal(const char *a, const char *b, size_t n) 553 FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT 554 { 555 return (a == NULL && b == NULL) || (a && b && strncmp(a, b, n) == 0); 556 } 557 558 /// Writes time_t to "buf[8]". 559 void time_to_bytes(time_t time_, uint8_t buf[8]) 560 { 561 // time_t can be up to 8 bytes in size, more than uintmax_t in 32 bits 562 // systems, thus we can't use put_bytes() here. 563 for (size_t i = 7, bufi = 0; bufi < 8; i--, bufi++) { 564 buf[bufi] = (uint8_t)((uint64_t)time_ >> (i * 8)); 565 } 566 } 567 568 /// Iterative merge sort for doubly linked list. 569 /// O(NlogN) worst case, and stable. 570 /// - The list is divided into blocks of increasing size (1, 2, 4, 8, ...). 571 /// - Each pair of blocks is merged in sorted order. 572 /// - Merged blocks are reconnected to build the sorted list. 573 void *mergesort_list(void *head, MergeSortGetFunc get_next, MergeSortSetFunc set_next, 574 MergeSortGetFunc get_prev, MergeSortSetFunc set_prev, 575 MergeSortCompareFunc compare) 576 { 577 if (!head || !get_next(head)) { 578 return head; 579 } 580 581 // Count length 582 int n = 0; 583 void *curr = head; 584 while (curr) { 585 n++; 586 curr = get_next(curr); 587 } 588 589 for (int size = 1; size < n; size *= 2) { 590 void *new_head = NULL; 591 void *tail = NULL; 592 curr = head; 593 594 while (curr) { 595 // Split two runs 596 void *left = curr; 597 void *right = left; 598 for (int i = 0; i < size && right; i++) { 599 right = get_next(right); 600 } 601 602 void *next = right; 603 for (int i = 0; i < size && next; i++) { 604 next = get_next(next); 605 } 606 607 // Break links 608 void *l_end = right ? get_prev(right) : NULL; 609 if (l_end) { 610 set_next(l_end, NULL); 611 } 612 if (right) { 613 set_prev(right, NULL); 614 } 615 616 void *r_end = next ? get_prev(next) : NULL; 617 if (r_end) { 618 set_next(r_end, NULL); 619 } 620 if (next) { 621 set_prev(next, NULL); 622 } 623 624 // Merge 625 void *merged = NULL; 626 void *merged_tail = NULL; 627 628 while (left || right) { 629 void *chosen = NULL; 630 if (!left) { 631 chosen = right; 632 right = get_next(right); 633 } else if (!right) { 634 chosen = left; 635 left = get_next(left); 636 } else if (compare(left, right) <= 0) { 637 chosen = left; 638 left = get_next(left); 639 } else { 640 chosen = right; 641 right = get_next(right); 642 } 643 644 if (merged_tail) { 645 set_next(merged_tail, chosen); 646 set_prev(chosen, merged_tail); 647 merged_tail = chosen; 648 } else { 649 merged = merged_tail = chosen; 650 set_prev(chosen, NULL); 651 } 652 } 653 654 // Connect to full list 655 if (!new_head) { 656 new_head = merged; 657 } else { 658 set_next(tail, merged); 659 set_prev(merged, tail); 660 } 661 662 // Move tail to end 663 while (get_next(merged_tail)) { 664 merged_tail = get_next(merged_tail); 665 } 666 tail = merged_tail; 667 668 curr = next; 669 } 670 671 head = new_head; 672 } 673 674 return head; 675 } 676 677 #define REUSE_MAX 4 678 679 static struct consumed_blk *arena_reuse_blk; 680 static size_t arena_reuse_blk_count = 0; 681 682 static void arena_free_reuse_blks(void) 683 { 684 while (arena_reuse_blk_count > 0) { 685 struct consumed_blk *blk = arena_reuse_blk; 686 arena_reuse_blk = arena_reuse_blk->prev; 687 xfree(blk); 688 arena_reuse_blk_count--; 689 } 690 } 691 692 /// Finish the allocations in an arena. 693 /// 694 /// This does not immediately free the memory, but leaves existing allocated 695 /// objects valid, and returns an opaque ArenaMem handle, which can be used to 696 /// free the allocations using `arena_mem_free`, when the objects allocated 697 /// from the arena are not needed anymore. 698 ArenaMem arena_finish(Arena *arena) 699 { 700 struct consumed_blk *res = (struct consumed_blk *)arena->cur_blk; 701 *arena = (Arena)ARENA_EMPTY; 702 return res; 703 } 704 705 /// allocate a block of ARENA_BLOCK_SIZE 706 /// 707 /// free it with free_block 708 void *alloc_block(void) 709 { 710 if (arena_reuse_blk_count > 0) { 711 void *retval = (char *)arena_reuse_blk; 712 arena_reuse_blk = arena_reuse_blk->prev; 713 arena_reuse_blk_count--; 714 return retval; 715 } else { 716 arena_alloc_count++; 717 return xmalloc(ARENA_BLOCK_SIZE); 718 } 719 } 720 721 void arena_alloc_block(Arena *arena) 722 { 723 struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk; 724 arena->cur_blk = alloc_block(); 725 arena->pos = 0; 726 arena->size = ARENA_BLOCK_SIZE; 727 struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true); 728 blk->prev = prev_blk; 729 } 730 731 static size_t arena_align_offset(uint64_t off) 732 { 733 #define ARENA_ALIGN MAX(sizeof(void *), sizeof(double)) 734 return ((off + (ARENA_ALIGN - 1)) & ~(ARENA_ALIGN - 1)); 735 #undef ARENA_ALIGN 736 } 737 738 /// @param arena if NULL, do a global allocation. caller must then free the value! 739 /// @param size if zero, will still return a non-null pointer, but not a usable or unique one 740 void *arena_alloc(Arena *arena, size_t size, bool align) 741 { 742 if (!arena) { 743 return xmalloc(size); 744 } 745 if (!arena->cur_blk) { 746 arena_alloc_block(arena); 747 } 748 size_t alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos; 749 if (alloc_pos + size > arena->size) { 750 if (size > (ARENA_BLOCK_SIZE - sizeof(struct consumed_blk)) >> 1) { 751 // if allocation is too big, allocate a large block with the requested 752 // size, but still with block pointer head. We do this even for 753 // arena->size / 2, as there likely is space left for the next 754 // small allocation in the current block. 755 arena_alloc_count++; 756 size_t hdr_size = sizeof(struct consumed_blk); 757 size_t aligned_hdr_size = (align ? arena_align_offset(hdr_size) : hdr_size); 758 char *alloc = xmalloc(size + aligned_hdr_size); 759 760 // to simplify free-list management, arena->cur_blk must 761 // always be a normal, ARENA_BLOCK_SIZE sized, block 762 struct consumed_blk *cur_blk = (struct consumed_blk *)arena->cur_blk; 763 struct consumed_blk *fix_blk = (struct consumed_blk *)alloc; 764 fix_blk->prev = cur_blk->prev; 765 cur_blk->prev = fix_blk; 766 return alloc + aligned_hdr_size; 767 } else { 768 arena_alloc_block(arena); // resets arena->pos 769 alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos; 770 } 771 } 772 773 char *mem = arena->cur_blk + alloc_pos; 774 arena->pos = alloc_pos + size; 775 return mem; 776 } 777 778 void free_block(void *block) 779 { 780 if (arena_reuse_blk_count < REUSE_MAX) { 781 struct consumed_blk *reuse_blk = block; 782 reuse_blk->prev = arena_reuse_blk; 783 arena_reuse_blk = reuse_blk; 784 arena_reuse_blk_count++; 785 } else { 786 xfree(block); 787 } 788 } 789 790 void arena_mem_free(ArenaMem mem) 791 { 792 struct consumed_blk *b = mem; 793 // peel of the first block, as it is guaranteed to be ARENA_BLOCK_SIZE, 794 // not a custom fix_blk 795 if (b != NULL) { 796 struct consumed_blk *reuse_blk = b; 797 b = b->prev; 798 free_block(reuse_blk); 799 } 800 801 while (b) { 802 struct consumed_blk *prev = b->prev; 803 xfree(b); 804 b = prev; 805 } 806 } 807 808 char *arena_allocz(Arena *arena, size_t size) 809 { 810 char *mem = arena_alloc(arena, size + 1, false); 811 mem[size] = NUL; 812 return mem; 813 } 814 815 char *arena_memdupz(Arena *arena, const char *buf, size_t size) 816 FUNC_ATTR_NONNULL_ARG(2) 817 { 818 char *mem = arena_allocz(arena, size); 819 memcpy(mem, buf, size); 820 return mem; 821 } 822 823 char *arena_strdup(Arena *arena, const char *str) 824 FUNC_ATTR_NONNULL_ARG(2) 825 { 826 return arena_memdupz(arena, str, strlen(str)); 827 } 828 829 #if defined(EXITFREE) 830 831 # include "nvim/autocmd.h" 832 # include "nvim/buffer.h" 833 # include "nvim/cmdhist.h" 834 # include "nvim/diff.h" 835 # include "nvim/edit.h" 836 # include "nvim/ex_cmds.h" 837 # include "nvim/ex_docmd.h" 838 # include "nvim/file_search.h" 839 # include "nvim/getchar.h" 840 # include "nvim/grid.h" 841 # include "nvim/mark.h" 842 # include "nvim/msgpack_rpc/channel.h" 843 # include "nvim/option.h" 844 # include "nvim/os/os.h" 845 # include "nvim/quickfix.h" 846 # include "nvim/regexp.h" 847 # include "nvim/register.h" 848 # include "nvim/search.h" 849 # include "nvim/spell.h" 850 # include "nvim/tag.h" 851 # include "nvim/window.h" 852 853 // Free everything that we allocated. 854 // Can be used to detect memory leaks, e.g., with ccmalloc. 855 // NOTE: This is tricky! Things are freed that functions depend on. Don't be 856 // surprised if Vim crashes... 857 // Some things can't be freed, esp. things local to a library function. 858 void free_all_mem(void) 859 { 860 buf_T *buf, *nextbuf; 861 862 // When we cause a crash here it is caught and Vim tries to exit cleanly. 863 // Don't try freeing everything again. 864 if (entered_free_all_mem) { 865 return; 866 } 867 entered_free_all_mem = true; 868 // Don't want to trigger autocommands from here on. 869 block_autocmds(); 870 871 // Close all tabs and windows. Reset 'equalalways' to avoid redraws. 872 p_ea = false; 873 if (first_tabpage != NULL && first_tabpage->tp_next != NULL) { 874 do_cmdline_cmd("tabonly!"); 875 } 876 877 // Free all spell info. 878 spell_free_all(); 879 880 // Clear user commands (before deleting buffers). 881 ex_comclear(NULL); 882 883 if (curbuf != NULL) { 884 // Clear menus. 885 do_cmdline_cmd("aunmenu *"); 886 do_cmdline_cmd("tlunmenu *"); 887 do_cmdline_cmd("menutranslate clear"); 888 889 // Clear mappings, abbreviations, breakpoints. 890 // NB: curbuf not used with local=false arg 891 map_clear_mode(curbuf, MAP_ALL_MODES, false, false); 892 map_clear_mode(curbuf, MAP_ALL_MODES, false, true); 893 do_cmdline_cmd("breakdel *"); 894 do_cmdline_cmd("profdel *"); 895 do_cmdline_cmd("set keymap="); 896 } 897 898 free_titles(); 899 free_findfile(); 900 901 // Obviously named calls. 902 free_all_autocmds(); 903 free_all_marks(); 904 alist_clear(&global_alist); 905 free_homedir(); 906 free_users(); 907 free_search_patterns(); 908 free_old_sub(); 909 free_last_insert(); 910 free_insexpand_stuff(); 911 free_prev_shellcmd(); 912 free_regexp_stuff(); 913 free_tag_stuff(); 914 free_cd_dir(); 915 free_signs(); 916 set_expr_line(NULL); 917 if (curtab != NULL) { 918 diff_clear(curtab); 919 } 920 clear_sb_text(true); // free any scrollback text 921 922 // Free some global vars. 923 xfree(last_cmdline); 924 xfree(new_last_cmdline); 925 set_keep_msg(NULL, 0); 926 927 // Clear cmdline history. 928 p_hi = 0; 929 init_history(); 930 931 free_quickfix(); 932 933 // Close all script inputs. 934 close_all_scripts(); 935 936 if (curwin != NULL) { 937 // Destroy all windows. Must come before freeing buffers. 938 win_free_all(); 939 } 940 941 // Free all option values. Must come after closing windows. 942 free_all_options(); 943 944 // Free all buffers. Reset 'autochdir' to avoid accessing things that 945 // were freed already. 946 // Must be after eval_clear to avoid it trying to access b:changedtick after 947 // freeing it. 948 p_acd = false; 949 for (buf = firstbuf; buf != NULL;) { 950 bufref_T bufref; 951 set_bufref(&bufref, buf); 952 nextbuf = buf->b_next; 953 954 // Since options (in addition to other stuff) have been freed above we need to ensure no 955 // callbacks are called, so free them before closing the buffer. 956 buf_free_callbacks(buf); 957 958 close_buffer(NULL, buf, DOBUF_WIPE, false, false); 959 // Didn't work, try next one. 960 buf = bufref_valid(&bufref) ? nextbuf : firstbuf; 961 } 962 963 // Clear registers. 964 clear_registers(); 965 ResetRedobuff(); 966 ResetRedobuff(); 967 968 // highlight info 969 free_highlight(); 970 971 reset_last_sourcing(); 972 973 if (first_tabpage != NULL) { 974 free_tabpage(first_tabpage); 975 first_tabpage = NULL; 976 } 977 978 // message history 979 msg_hist_clear(0); 980 981 channel_free_all_mem(); 982 eval_clear(); 983 api_extmark_free_all_mem(); 984 ctx_free_all(); 985 986 map_destroy(int, &buffer_handles); 987 map_destroy(int, &window_handles); 988 map_destroy(int, &tabpage_handles); 989 990 // free screenlines (can't display anything now!) 991 grid_free_all_mem(); 992 stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size); 993 xfree(tab_page_click_defs); 994 995 clear_hl_tables(false); 996 997 check_quickfix_busy(); 998 999 decor_free_all_mem(); 1000 drawline_free_all_mem(); 1001 1002 if (ui_client_channel_id) { 1003 ui_client_free_all_mem(); 1004 } 1005 1006 remote_ui_free_all_mem(); 1007 ui_free_all_mem(); 1008 ui_comp_free_all_mem(); 1009 nlua_free_all_mem(); 1010 rpc_free_all_mem(); 1011 autocmd_free_all_mem(); 1012 1013 // should be last, in case earlier free functions deallocates arenas 1014 arena_free_reuse_blks(); 1015 } 1016 1017 #endif