diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 608 |
1 files changed, 149 insertions, 459 deletions
diff --git a/src/alloc.c b/src/alloc.c index e8637471bc7..fb7d35b5590 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -24,9 +24,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 24 | 24 | ||
| 25 | #include <stdio.h> | 25 | #include <stdio.h> |
| 26 | #include <limits.h> /* For CHAR_BIT. */ | 26 | #include <limits.h> /* For CHAR_BIT. */ |
| 27 | #include <setjmp.h> | ||
| 28 | 27 | ||
| 29 | #include <signal.h> | 28 | #ifdef ENABLE_CHECKING |
| 29 | #include <signal.h> /* For SIGABRT. */ | ||
| 30 | #endif | ||
| 30 | 31 | ||
| 31 | #ifdef HAVE_PTHREAD | 32 | #ifdef HAVE_PTHREAD |
| 32 | #include <pthread.h> | 33 | #include <pthread.h> |
| @@ -42,9 +43,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 42 | #include "keyboard.h" | 43 | #include "keyboard.h" |
| 43 | #include "frame.h" | 44 | #include "frame.h" |
| 44 | #include "blockinput.h" | 45 | #include "blockinput.h" |
| 45 | #include "syssignal.h" | ||
| 46 | #include "termhooks.h" /* For struct terminal. */ | 46 | #include "termhooks.h" /* For struct terminal. */ |
| 47 | #include <setjmp.h> | 47 | |
| 48 | #include <verify.h> | 48 | #include <verify.h> |
| 49 | 49 | ||
| 50 | /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. | 50 | /* GC_CHECK_MARKED_OBJECTS means do sanity checks on allocated objects. |
| @@ -69,6 +69,9 @@ extern void *sbrk (); | |||
| 69 | 69 | ||
| 70 | #include <fcntl.h> | 70 | #include <fcntl.h> |
| 71 | 71 | ||
| 72 | #ifdef USE_GTK | ||
| 73 | # include "gtkutil.h" | ||
| 74 | #endif | ||
| 72 | #ifdef WINDOWSNT | 75 | #ifdef WINDOWSNT |
| 73 | #include "w32.h" | 76 | #include "w32.h" |
| 74 | #endif | 77 | #endif |
| @@ -82,66 +85,8 @@ extern void *sbrk (); | |||
| 82 | 85 | ||
| 83 | #define MMAP_MAX_AREAS 100000000 | 86 | #define MMAP_MAX_AREAS 100000000 |
| 84 | 87 | ||
| 85 | #else /* not DOUG_LEA_MALLOC */ | ||
| 86 | |||
| 87 | /* The following come from gmalloc.c. */ | ||
| 88 | |||
| 89 | extern size_t _bytes_used; | ||
| 90 | extern size_t __malloc_extra_blocks; | ||
| 91 | extern void *_malloc_internal (size_t); | ||
| 92 | extern void _free_internal (void *); | ||
| 93 | |||
| 94 | #endif /* not DOUG_LEA_MALLOC */ | 88 | #endif /* not DOUG_LEA_MALLOC */ |
| 95 | 89 | ||
| 96 | #if ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT | ||
| 97 | #ifdef HAVE_PTHREAD | ||
| 98 | |||
| 99 | /* When GTK uses the file chooser dialog, different backends can be loaded | ||
| 100 | dynamically. One such a backend is the Gnome VFS backend that gets loaded | ||
| 101 | if you run Gnome. That backend creates several threads and also allocates | ||
| 102 | memory with malloc. | ||
| 103 | |||
| 104 | Also, gconf and gsettings may create several threads. | ||
| 105 | |||
| 106 | If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_* | ||
| 107 | functions below are called from malloc, there is a chance that one | ||
| 108 | of these threads preempts the Emacs main thread and the hook variables | ||
| 109 | end up in an inconsistent state. So we have a mutex to prevent that (note | ||
| 110 | that the backend handles concurrent access to malloc within its own threads | ||
| 111 | but Emacs code running in the main thread is not included in that control). | ||
| 112 | |||
| 113 | When UNBLOCK_INPUT is called, reinvoke_input_signal may be called. If this | ||
| 114 | happens in one of the backend threads we will have two threads that tries | ||
| 115 | to run Emacs code at once, and the code is not prepared for that. | ||
| 116 | To prevent that, we only call BLOCK/UNBLOCK from the main thread. */ | ||
| 117 | |||
| 118 | static pthread_mutex_t alloc_mutex; | ||
| 119 | |||
| 120 | #define BLOCK_INPUT_ALLOC \ | ||
| 121 | do \ | ||
| 122 | { \ | ||
| 123 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 124 | BLOCK_INPUT; \ | ||
| 125 | pthread_mutex_lock (&alloc_mutex); \ | ||
| 126 | } \ | ||
| 127 | while (0) | ||
| 128 | #define UNBLOCK_INPUT_ALLOC \ | ||
| 129 | do \ | ||
| 130 | { \ | ||
| 131 | pthread_mutex_unlock (&alloc_mutex); \ | ||
| 132 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 133 | UNBLOCK_INPUT; \ | ||
| 134 | } \ | ||
| 135 | while (0) | ||
| 136 | |||
| 137 | #else /* ! defined HAVE_PTHREAD */ | ||
| 138 | |||
| 139 | #define BLOCK_INPUT_ALLOC BLOCK_INPUT | ||
| 140 | #define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT | ||
| 141 | |||
| 142 | #endif /* ! defined HAVE_PTHREAD */ | ||
| 143 | #endif /* ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT */ | ||
| 144 | |||
| 145 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer | 90 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer |
| 146 | to a struct Lisp_String. */ | 91 | to a struct Lisp_String. */ |
| 147 | 92 | ||
| @@ -200,10 +145,6 @@ static char *spare_memory[7]; | |||
| 200 | 145 | ||
| 201 | #define SPARE_MEMORY (1 << 14) | 146 | #define SPARE_MEMORY (1 << 14) |
| 202 | 147 | ||
| 203 | /* Number of extra blocks malloc should get when it needs more core. */ | ||
| 204 | |||
| 205 | static int malloc_hysteresis; | ||
| 206 | |||
| 207 | /* Initialize it to a nonzero value to force it into data space | 148 | /* Initialize it to a nonzero value to force it into data space |
| 208 | (rather than bss space). That way unexec will remap it into text | 149 | (rather than bss space). That way unexec will remap it into text |
| 209 | space (pure), on some systems. We have not implemented the | 150 | space (pure), on some systems. We have not implemented the |
| @@ -275,6 +216,7 @@ static void gc_sweep (void); | |||
| 275 | static Lisp_Object make_pure_vector (ptrdiff_t); | 216 | static Lisp_Object make_pure_vector (ptrdiff_t); |
| 276 | static void mark_glyph_matrix (struct glyph_matrix *); | 217 | static void mark_glyph_matrix (struct glyph_matrix *); |
| 277 | static void mark_face_cache (struct face_cache *); | 218 | static void mark_face_cache (struct face_cache *); |
| 219 | static void mark_buffer (struct buffer *); | ||
| 278 | 220 | ||
| 279 | #if !defined REL_ALLOC || defined SYSTEM_MALLOC | 221 | #if !defined REL_ALLOC || defined SYSTEM_MALLOC |
| 280 | static void refill_memory_reserve (void); | 222 | static void refill_memory_reserve (void); |
| @@ -407,12 +349,12 @@ static void mark_memory (void *, void *); | |||
| 407 | static void mem_init (void); | 349 | static void mem_init (void); |
| 408 | static struct mem_node *mem_insert (void *, void *, enum mem_type); | 350 | static struct mem_node *mem_insert (void *, void *, enum mem_type); |
| 409 | static void mem_insert_fixup (struct mem_node *); | 351 | static void mem_insert_fixup (struct mem_node *); |
| 410 | #endif | ||
| 411 | static void mem_rotate_left (struct mem_node *); | 352 | static void mem_rotate_left (struct mem_node *); |
| 412 | static void mem_rotate_right (struct mem_node *); | 353 | static void mem_rotate_right (struct mem_node *); |
| 413 | static void mem_delete (struct mem_node *); | 354 | static void mem_delete (struct mem_node *); |
| 414 | static void mem_delete_fixup (struct mem_node *); | 355 | static void mem_delete_fixup (struct mem_node *); |
| 415 | static inline struct mem_node *mem_find (void *); | 356 | static inline struct mem_node *mem_find (void *); |
| 357 | #endif | ||
| 416 | 358 | ||
| 417 | 359 | ||
| 418 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | 360 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS |
| @@ -581,39 +523,17 @@ xmalloc_get_size (unsigned char *ptr) | |||
| 581 | } | 523 | } |
| 582 | 524 | ||
| 583 | 525 | ||
| 584 | /* The call depth in overrun_check functions. For example, this might happen: | ||
| 585 | xmalloc() | ||
| 586 | overrun_check_malloc() | ||
| 587 | -> malloc -> (via hook)_-> emacs_blocked_malloc | ||
| 588 | -> overrun_check_malloc | ||
| 589 | call malloc (hooks are NULL, so real malloc is called). | ||
| 590 | malloc returns 10000. | ||
| 591 | add overhead, return 10016. | ||
| 592 | <- (back in overrun_check_malloc) | ||
| 593 | add overhead again, return 10032 | ||
| 594 | xmalloc returns 10032. | ||
| 595 | |||
| 596 | (time passes). | ||
| 597 | |||
| 598 | xfree(10032) | ||
| 599 | overrun_check_free(10032) | ||
| 600 | decrease overhead | ||
| 601 | free(10016) <- crash, because 10000 is the original pointer. */ | ||
| 602 | |||
| 603 | static ptrdiff_t check_depth; | ||
| 604 | |||
| 605 | /* Like malloc, but wraps allocated block with header and trailer. */ | 526 | /* Like malloc, but wraps allocated block with header and trailer. */ |
| 606 | 527 | ||
| 607 | static void * | 528 | static void * |
| 608 | overrun_check_malloc (size_t size) | 529 | overrun_check_malloc (size_t size) |
| 609 | { | 530 | { |
| 610 | register unsigned char *val; | 531 | register unsigned char *val; |
| 611 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 532 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 612 | if (SIZE_MAX - overhead < size) | 533 | emacs_abort (); |
| 613 | abort (); | ||
| 614 | 534 | ||
| 615 | val = malloc (size + overhead); | 535 | val = malloc (size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 616 | if (val && check_depth == 1) | 536 | if (val) |
| 617 | { | 537 | { |
| 618 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 538 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 619 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 539 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -621,7 +541,6 @@ overrun_check_malloc (size_t size) | |||
| 621 | memcpy (val + size, xmalloc_overrun_check_trailer, | 541 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 622 | XMALLOC_OVERRUN_CHECK_SIZE); | 542 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 623 | } | 543 | } |
| 624 | --check_depth; | ||
| 625 | return val; | 544 | return val; |
| 626 | } | 545 | } |
| 627 | 546 | ||
| @@ -633,12 +552,10 @@ static void * | |||
| 633 | overrun_check_realloc (void *block, size_t size) | 552 | overrun_check_realloc (void *block, size_t size) |
| 634 | { | 553 | { |
| 635 | register unsigned char *val = (unsigned char *) block; | 554 | register unsigned char *val = (unsigned char *) block; |
| 636 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 555 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 637 | if (SIZE_MAX - overhead < size) | 556 | emacs_abort (); |
| 638 | abort (); | ||
| 639 | 557 | ||
| 640 | if (val | 558 | if (val |
| 641 | && check_depth == 1 | ||
| 642 | && memcmp (xmalloc_overrun_check_header, | 559 | && memcmp (xmalloc_overrun_check_header, |
| 643 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 560 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 644 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 561 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -646,15 +563,15 @@ overrun_check_realloc (void *block, size_t size) | |||
| 646 | size_t osize = xmalloc_get_size (val); | 563 | size_t osize = xmalloc_get_size (val); |
| 647 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, | 564 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, |
| 648 | XMALLOC_OVERRUN_CHECK_SIZE)) | 565 | XMALLOC_OVERRUN_CHECK_SIZE)) |
| 649 | abort (); | 566 | emacs_abort (); |
| 650 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); | 567 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); |
| 651 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 568 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 652 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); | 569 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); |
| 653 | } | 570 | } |
| 654 | 571 | ||
| 655 | val = realloc (val, size + overhead); | 572 | val = realloc (val, size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 656 | 573 | ||
| 657 | if (val && check_depth == 1) | 574 | if (val) |
| 658 | { | 575 | { |
| 659 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 576 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 660 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 577 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -662,7 +579,6 @@ overrun_check_realloc (void *block, size_t size) | |||
| 662 | memcpy (val + size, xmalloc_overrun_check_trailer, | 579 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 663 | XMALLOC_OVERRUN_CHECK_SIZE); | 580 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 664 | } | 581 | } |
| 665 | --check_depth; | ||
| 666 | return val; | 582 | return val; |
| 667 | } | 583 | } |
| 668 | 584 | ||
| @@ -673,9 +589,7 @@ overrun_check_free (void *block) | |||
| 673 | { | 589 | { |
| 674 | unsigned char *val = (unsigned char *) block; | 590 | unsigned char *val = (unsigned char *) block; |
| 675 | 591 | ||
| 676 | ++check_depth; | ||
| 677 | if (val | 592 | if (val |
| 678 | && check_depth == 1 | ||
| 679 | && memcmp (xmalloc_overrun_check_header, | 593 | && memcmp (xmalloc_overrun_check_header, |
| 680 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 594 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 681 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 595 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -683,7 +597,7 @@ overrun_check_free (void *block) | |||
| 683 | size_t osize = xmalloc_get_size (val); | 597 | size_t osize = xmalloc_get_size (val); |
| 684 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, | 598 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, |
| 685 | XMALLOC_OVERRUN_CHECK_SIZE)) | 599 | XMALLOC_OVERRUN_CHECK_SIZE)) |
| 686 | abort (); | 600 | emacs_abort (); |
| 687 | #ifdef XMALLOC_CLEAR_FREE_MEMORY | 601 | #ifdef XMALLOC_CLEAR_FREE_MEMORY |
| 688 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 602 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 689 | memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD); | 603 | memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| @@ -695,7 +609,6 @@ overrun_check_free (void *block) | |||
| 695 | } | 609 | } |
| 696 | 610 | ||
| 697 | free (val); | 611 | free (val); |
| 698 | --check_depth; | ||
| 699 | } | 612 | } |
| 700 | 613 | ||
| 701 | #undef malloc | 614 | #undef malloc |
| @@ -706,14 +619,33 @@ overrun_check_free (void *block) | |||
| 706 | #define free overrun_check_free | 619 | #define free overrun_check_free |
| 707 | #endif | 620 | #endif |
| 708 | 621 | ||
| 709 | #ifdef SYNC_INPUT | 622 | /* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol |
| 710 | /* When using SYNC_INPUT, we don't call malloc from a signal handler, so | 623 | BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger. |
| 711 | there's no need to block input around malloc. */ | 624 | If that variable is set, block input while in one of Emacs's memory |
| 712 | #define MALLOC_BLOCK_INPUT ((void)0) | 625 | allocation functions. There should be no need for this debugging |
| 713 | #define MALLOC_UNBLOCK_INPUT ((void)0) | 626 | option, since signal handlers do not allocate memory, but Emacs |
| 627 | formerly allocated memory in signal handlers and this compile-time | ||
| 628 | option remains as a way to help debug the issue should it rear its | ||
| 629 | ugly head again. */ | ||
| 630 | #ifdef XMALLOC_BLOCK_INPUT_CHECK | ||
| 631 | bool block_input_in_memory_allocators EXTERNALLY_VISIBLE; | ||
| 632 | static void | ||
| 633 | malloc_block_input (void) | ||
| 634 | { | ||
| 635 | if (block_input_in_memory_allocators) | ||
| 636 | BLOCK_INPUT; | ||
| 637 | } | ||
| 638 | static void | ||
| 639 | malloc_unblock_input (void) | ||
| 640 | { | ||
| 641 | if (block_input_in_memory_allocators) | ||
| 642 | UNBLOCK_INPUT; | ||
| 643 | } | ||
| 644 | # define MALLOC_BLOCK_INPUT malloc_block_input () | ||
| 645 | # define MALLOC_UNBLOCK_INPUT malloc_unblock_input () | ||
| 714 | #else | 646 | #else |
| 715 | #define MALLOC_BLOCK_INPUT BLOCK_INPUT | 647 | # define MALLOC_BLOCK_INPUT ((void) 0) |
| 716 | #define MALLOC_UNBLOCK_INPUT UNBLOCK_INPUT | 648 | # define MALLOC_UNBLOCK_INPUT ((void) 0) |
| 717 | #endif | 649 | #endif |
| 718 | 650 | ||
| 719 | /* Like malloc but check for no memory and block interrupt input.. */ | 651 | /* Like malloc but check for no memory and block interrupt input.. */ |
| @@ -782,8 +714,7 @@ xfree (void *block) | |||
| 782 | free (block); | 714 | free (block); |
| 783 | MALLOC_UNBLOCK_INPUT; | 715 | MALLOC_UNBLOCK_INPUT; |
| 784 | /* We don't call refill_memory_reserve here | 716 | /* We don't call refill_memory_reserve here |
| 785 | because that duplicates doing so in emacs_blocked_free | 717 | because in practice the call in r_alloc_free seems to suffice. */ |
| 786 | and the criterion should go there. */ | ||
| 787 | } | 718 | } |
| 788 | 719 | ||
| 789 | 720 | ||
| @@ -1210,256 +1141,6 @@ lisp_align_free (void *block) | |||
| 1210 | } | 1141 | } |
| 1211 | 1142 | ||
| 1212 | 1143 | ||
| 1213 | #ifndef SYSTEM_MALLOC | ||
| 1214 | |||
| 1215 | /* Arranging to disable input signals while we're in malloc. | ||
| 1216 | |||
| 1217 | This only works with GNU malloc. To help out systems which can't | ||
| 1218 | use GNU malloc, all the calls to malloc, realloc, and free | ||
| 1219 | elsewhere in the code should be inside a BLOCK_INPUT/UNBLOCK_INPUT | ||
| 1220 | pair; unfortunately, we have no idea what C library functions | ||
| 1221 | might call malloc, so we can't really protect them unless you're | ||
| 1222 | using GNU malloc. Fortunately, most of the major operating systems | ||
| 1223 | can use GNU malloc. */ | ||
| 1224 | |||
| 1225 | #ifndef SYNC_INPUT | ||
| 1226 | /* When using SYNC_INPUT, we don't call malloc from a signal handler, so | ||
| 1227 | there's no need to block input around malloc. */ | ||
| 1228 | |||
| 1229 | #ifndef DOUG_LEA_MALLOC | ||
| 1230 | extern void * (*__malloc_hook) (size_t, const void *); | ||
| 1231 | extern void * (*__realloc_hook) (void *, size_t, const void *); | ||
| 1232 | extern void (*__free_hook) (void *, const void *); | ||
| 1233 | /* Else declared in malloc.h, perhaps with an extra arg. */ | ||
| 1234 | #endif /* DOUG_LEA_MALLOC */ | ||
| 1235 | static void * (*old_malloc_hook) (size_t, const void *); | ||
| 1236 | static void * (*old_realloc_hook) (void *, size_t, const void*); | ||
| 1237 | static void (*old_free_hook) (void*, const void*); | ||
| 1238 | |||
| 1239 | #ifdef DOUG_LEA_MALLOC | ||
| 1240 | # define BYTES_USED (mallinfo ().uordblks) | ||
| 1241 | #else | ||
| 1242 | # define BYTES_USED _bytes_used | ||
| 1243 | #endif | ||
| 1244 | |||
| 1245 | #ifdef GC_MALLOC_CHECK | ||
| 1246 | static bool dont_register_blocks; | ||
| 1247 | #endif | ||
| 1248 | |||
| 1249 | static size_t bytes_used_when_reconsidered; | ||
| 1250 | |||
| 1251 | /* Value of _bytes_used, when spare_memory was freed. */ | ||
| 1252 | |||
| 1253 | static size_t bytes_used_when_full; | ||
| 1254 | |||
| 1255 | /* This function is used as the hook for free to call. */ | ||
| 1256 | |||
| 1257 | static void | ||
| 1258 | emacs_blocked_free (void *ptr, const void *ptr2) | ||
| 1259 | { | ||
| 1260 | BLOCK_INPUT_ALLOC; | ||
| 1261 | |||
| 1262 | #ifdef GC_MALLOC_CHECK | ||
| 1263 | if (ptr) | ||
| 1264 | { | ||
| 1265 | struct mem_node *m; | ||
| 1266 | |||
| 1267 | m = mem_find (ptr); | ||
| 1268 | if (m == MEM_NIL || m->start != ptr) | ||
| 1269 | { | ||
| 1270 | fprintf (stderr, | ||
| 1271 | "Freeing `%p' which wasn't allocated with malloc\n", ptr); | ||
| 1272 | abort (); | ||
| 1273 | } | ||
| 1274 | else | ||
| 1275 | { | ||
| 1276 | /* fprintf (stderr, "free %p...%p (%p)\n", m->start, m->end, ptr); */ | ||
| 1277 | mem_delete (m); | ||
| 1278 | } | ||
| 1279 | } | ||
| 1280 | #endif /* GC_MALLOC_CHECK */ | ||
| 1281 | |||
| 1282 | __free_hook = old_free_hook; | ||
| 1283 | free (ptr); | ||
| 1284 | |||
| 1285 | /* If we released our reserve (due to running out of memory), | ||
| 1286 | and we have a fair amount free once again, | ||
| 1287 | try to set aside another reserve in case we run out once more. */ | ||
| 1288 | if (! NILP (Vmemory_full) | ||
| 1289 | /* Verify there is enough space that even with the malloc | ||
| 1290 | hysteresis this call won't run out again. | ||
| 1291 | The code here is correct as long as SPARE_MEMORY | ||
| 1292 | is substantially larger than the block size malloc uses. */ | ||
| 1293 | && (bytes_used_when_full | ||
| 1294 | > ((bytes_used_when_reconsidered = BYTES_USED) | ||
| 1295 | + max (malloc_hysteresis, 4) * SPARE_MEMORY))) | ||
| 1296 | refill_memory_reserve (); | ||
| 1297 | |||
| 1298 | __free_hook = emacs_blocked_free; | ||
| 1299 | UNBLOCK_INPUT_ALLOC; | ||
| 1300 | } | ||
| 1301 | |||
| 1302 | |||
| 1303 | /* This function is the malloc hook that Emacs uses. */ | ||
| 1304 | |||
| 1305 | static void * | ||
| 1306 | emacs_blocked_malloc (size_t size, const void *ptr) | ||
| 1307 | { | ||
| 1308 | void *value; | ||
| 1309 | |||
| 1310 | BLOCK_INPUT_ALLOC; | ||
| 1311 | __malloc_hook = old_malloc_hook; | ||
| 1312 | #ifdef DOUG_LEA_MALLOC | ||
| 1313 | /* Segfaults on my system. --lorentey */ | ||
| 1314 | /* mallopt (M_TOP_PAD, malloc_hysteresis * 4096); */ | ||
| 1315 | #else | ||
| 1316 | __malloc_extra_blocks = malloc_hysteresis; | ||
| 1317 | #endif | ||
| 1318 | |||
| 1319 | value = malloc (size); | ||
| 1320 | |||
| 1321 | #ifdef GC_MALLOC_CHECK | ||
| 1322 | { | ||
| 1323 | struct mem_node *m = mem_find (value); | ||
| 1324 | if (m != MEM_NIL) | ||
| 1325 | { | ||
| 1326 | fprintf (stderr, "Malloc returned %p which is already in use\n", | ||
| 1327 | value); | ||
| 1328 | fprintf (stderr, "Region in use is %p...%p, %td bytes, type %d\n", | ||
| 1329 | m->start, m->end, (char *) m->end - (char *) m->start, | ||
| 1330 | m->type); | ||
| 1331 | abort (); | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | if (!dont_register_blocks) | ||
| 1335 | { | ||
| 1336 | mem_insert (value, (char *) value + max (1, size), allocated_mem_type); | ||
| 1337 | allocated_mem_type = MEM_TYPE_NON_LISP; | ||
| 1338 | } | ||
| 1339 | } | ||
| 1340 | #endif /* GC_MALLOC_CHECK */ | ||
| 1341 | |||
| 1342 | __malloc_hook = emacs_blocked_malloc; | ||
| 1343 | UNBLOCK_INPUT_ALLOC; | ||
| 1344 | |||
| 1345 | /* fprintf (stderr, "%p malloc\n", value); */ | ||
| 1346 | return value; | ||
| 1347 | } | ||
| 1348 | |||
| 1349 | |||
| 1350 | /* This function is the realloc hook that Emacs uses. */ | ||
| 1351 | |||
| 1352 | static void * | ||
| 1353 | emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2) | ||
| 1354 | { | ||
| 1355 | void *value; | ||
| 1356 | |||
| 1357 | BLOCK_INPUT_ALLOC; | ||
| 1358 | __realloc_hook = old_realloc_hook; | ||
| 1359 | |||
| 1360 | #ifdef GC_MALLOC_CHECK | ||
| 1361 | if (ptr) | ||
| 1362 | { | ||
| 1363 | struct mem_node *m = mem_find (ptr); | ||
| 1364 | if (m == MEM_NIL || m->start != ptr) | ||
| 1365 | { | ||
| 1366 | fprintf (stderr, | ||
| 1367 | "Realloc of %p which wasn't allocated with malloc\n", | ||
| 1368 | ptr); | ||
| 1369 | abort (); | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | mem_delete (m); | ||
| 1373 | } | ||
| 1374 | |||
| 1375 | /* fprintf (stderr, "%p -> realloc\n", ptr); */ | ||
| 1376 | |||
| 1377 | /* Prevent malloc from registering blocks. */ | ||
| 1378 | dont_register_blocks = 1; | ||
| 1379 | #endif /* GC_MALLOC_CHECK */ | ||
| 1380 | |||
| 1381 | value = realloc (ptr, size); | ||
| 1382 | |||
| 1383 | #ifdef GC_MALLOC_CHECK | ||
| 1384 | dont_register_blocks = 0; | ||
| 1385 | |||
| 1386 | { | ||
| 1387 | struct mem_node *m = mem_find (value); | ||
| 1388 | if (m != MEM_NIL) | ||
| 1389 | { | ||
| 1390 | fprintf (stderr, "Realloc returns memory that is already in use\n"); | ||
| 1391 | abort (); | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | /* Can't handle zero size regions in the red-black tree. */ | ||
| 1395 | mem_insert (value, (char *) value + max (size, 1), MEM_TYPE_NON_LISP); | ||
| 1396 | } | ||
| 1397 | |||
| 1398 | /* fprintf (stderr, "%p <- realloc\n", value); */ | ||
| 1399 | #endif /* GC_MALLOC_CHECK */ | ||
| 1400 | |||
| 1401 | __realloc_hook = emacs_blocked_realloc; | ||
| 1402 | UNBLOCK_INPUT_ALLOC; | ||
| 1403 | |||
| 1404 | return value; | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | |||
| 1408 | #ifdef HAVE_PTHREAD | ||
| 1409 | /* Called from Fdump_emacs so that when the dumped Emacs starts, it has a | ||
| 1410 | normal malloc. Some thread implementations need this as they call | ||
| 1411 | malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then | ||
| 1412 | calls malloc because it is the first call, and we have an endless loop. */ | ||
| 1413 | |||
| 1414 | void | ||
| 1415 | reset_malloc_hooks (void) | ||
| 1416 | { | ||
| 1417 | __free_hook = old_free_hook; | ||
| 1418 | __malloc_hook = old_malloc_hook; | ||
| 1419 | __realloc_hook = old_realloc_hook; | ||
| 1420 | } | ||
| 1421 | #endif /* HAVE_PTHREAD */ | ||
| 1422 | |||
| 1423 | |||
| 1424 | /* Called from main to set up malloc to use our hooks. */ | ||
| 1425 | |||
| 1426 | void | ||
| 1427 | uninterrupt_malloc (void) | ||
| 1428 | { | ||
| 1429 | #ifdef HAVE_PTHREAD | ||
| 1430 | #ifdef DOUG_LEA_MALLOC | ||
| 1431 | pthread_mutexattr_t attr; | ||
| 1432 | |||
| 1433 | /* GLIBC has a faster way to do this, but let's keep it portable. | ||
| 1434 | This is according to the Single UNIX Specification. */ | ||
| 1435 | pthread_mutexattr_init (&attr); | ||
| 1436 | pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); | ||
| 1437 | pthread_mutex_init (&alloc_mutex, &attr); | ||
| 1438 | #else /* !DOUG_LEA_MALLOC */ | ||
| 1439 | /* Some systems such as Solaris 2.6 don't have a recursive mutex, | ||
| 1440 | and the bundled gmalloc.c doesn't require it. */ | ||
| 1441 | pthread_mutex_init (&alloc_mutex, NULL); | ||
| 1442 | #endif /* !DOUG_LEA_MALLOC */ | ||
| 1443 | #endif /* HAVE_PTHREAD */ | ||
| 1444 | |||
| 1445 | if (__free_hook != emacs_blocked_free) | ||
| 1446 | old_free_hook = __free_hook; | ||
| 1447 | __free_hook = emacs_blocked_free; | ||
| 1448 | |||
| 1449 | if (__malloc_hook != emacs_blocked_malloc) | ||
| 1450 | old_malloc_hook = __malloc_hook; | ||
| 1451 | __malloc_hook = emacs_blocked_malloc; | ||
| 1452 | |||
| 1453 | if (__realloc_hook != emacs_blocked_realloc) | ||
| 1454 | old_realloc_hook = __realloc_hook; | ||
| 1455 | __realloc_hook = emacs_blocked_realloc; | ||
| 1456 | } | ||
| 1457 | |||
| 1458 | #endif /* not SYNC_INPUT */ | ||
| 1459 | #endif /* not SYSTEM_MALLOC */ | ||
| 1460 | |||
| 1461 | |||
| 1462 | |||
| 1463 | /*********************************************************************** | 1144 | /*********************************************************************** |
| 1464 | Interval Allocation | 1145 | Interval Allocation |
| 1465 | ***********************************************************************/ | 1146 | ***********************************************************************/ |
| @@ -1505,8 +1186,6 @@ make_interval (void) | |||
| 1505 | { | 1186 | { |
| 1506 | INTERVAL val; | 1187 | INTERVAL val; |
| 1507 | 1188 | ||
| 1508 | /* eassert (!handling_signal); */ | ||
| 1509 | |||
| 1510 | MALLOC_BLOCK_INPUT; | 1189 | MALLOC_BLOCK_INPUT; |
| 1511 | 1190 | ||
| 1512 | if (interval_free_list) | 1191 | if (interval_free_list) |
| @@ -1801,7 +1480,7 @@ string_bytes (struct Lisp_String *s) | |||
| 1801 | if (!PURE_POINTER_P (s) | 1480 | if (!PURE_POINTER_P (s) |
| 1802 | && s->data | 1481 | && s->data |
| 1803 | && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) | 1482 | && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) |
| 1804 | abort (); | 1483 | emacs_abort (); |
| 1805 | return nbytes; | 1484 | return nbytes; |
| 1806 | } | 1485 | } |
| 1807 | 1486 | ||
| @@ -1875,7 +1554,7 @@ check_string_free_list (void) | |||
| 1875 | while (s != NULL) | 1554 | while (s != NULL) |
| 1876 | { | 1555 | { |
| 1877 | if ((uintptr_t) s < 1024) | 1556 | if ((uintptr_t) s < 1024) |
| 1878 | abort (); | 1557 | emacs_abort (); |
| 1879 | s = NEXT_FREE_LISP_STRING (s); | 1558 | s = NEXT_FREE_LISP_STRING (s); |
| 1880 | } | 1559 | } |
| 1881 | } | 1560 | } |
| @@ -1890,8 +1569,6 @@ allocate_string (void) | |||
| 1890 | { | 1569 | { |
| 1891 | struct Lisp_String *s; | 1570 | struct Lisp_String *s; |
| 1892 | 1571 | ||
| 1893 | /* eassert (!handling_signal); */ | ||
| 1894 | |||
| 1895 | MALLOC_BLOCK_INPUT; | 1572 | MALLOC_BLOCK_INPUT; |
| 1896 | 1573 | ||
| 1897 | /* If the free-list is empty, allocate a new string_block, and | 1574 | /* If the free-list is empty, allocate a new string_block, and |
| @@ -2104,7 +1781,7 @@ sweep_strings (void) | |||
| 2104 | back-pointer so that we know it's free. */ | 1781 | back-pointer so that we know it's free. */ |
| 2105 | #ifdef GC_CHECK_STRING_BYTES | 1782 | #ifdef GC_CHECK_STRING_BYTES |
| 2106 | if (string_bytes (s) != SDATA_NBYTES (data)) | 1783 | if (string_bytes (s) != SDATA_NBYTES (data)) |
| 2107 | abort (); | 1784 | emacs_abort (); |
| 2108 | #else | 1785 | #else |
| 2109 | data->u.nbytes = STRING_BYTES (s); | 1786 | data->u.nbytes = STRING_BYTES (s); |
| 2110 | #endif | 1787 | #endif |
| @@ -2215,7 +1892,7 @@ compact_small_strings (void) | |||
| 2215 | /* Check that the string size recorded in the string is the | 1892 | /* Check that the string size recorded in the string is the |
| 2216 | same as the one recorded in the sdata structure. */ | 1893 | same as the one recorded in the sdata structure. */ |
| 2217 | if (s && string_bytes (s) != SDATA_NBYTES (from)) | 1894 | if (s && string_bytes (s) != SDATA_NBYTES (from)) |
| 2218 | abort (); | 1895 | emacs_abort (); |
| 2219 | #endif /* GC_CHECK_STRING_BYTES */ | 1896 | #endif /* GC_CHECK_STRING_BYTES */ |
| 2220 | 1897 | ||
| 2221 | nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from); | 1898 | nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from); |
| @@ -2228,7 +1905,7 @@ compact_small_strings (void) | |||
| 2228 | if (memcmp (string_overrun_cookie, | 1905 | if (memcmp (string_overrun_cookie, |
| 2229 | (char *) from_end - GC_STRING_OVERRUN_COOKIE_SIZE, | 1906 | (char *) from_end - GC_STRING_OVERRUN_COOKIE_SIZE, |
| 2230 | GC_STRING_OVERRUN_COOKIE_SIZE)) | 1907 | GC_STRING_OVERRUN_COOKIE_SIZE)) |
| 2231 | abort (); | 1908 | emacs_abort (); |
| 2232 | #endif | 1909 | #endif |
| 2233 | 1910 | ||
| 2234 | /* Non-NULL S means it's alive. Copy its data. */ | 1911 | /* Non-NULL S means it's alive. Copy its data. */ |
| @@ -2485,7 +2162,7 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | |||
| 2485 | struct Lisp_String *s; | 2162 | struct Lisp_String *s; |
| 2486 | 2163 | ||
| 2487 | if (nchars < 0) | 2164 | if (nchars < 0) |
| 2488 | abort (); | 2165 | emacs_abort (); |
| 2489 | if (!nbytes) | 2166 | if (!nbytes) |
| 2490 | return empty_multibyte_string; | 2167 | return empty_multibyte_string; |
| 2491 | 2168 | ||
| @@ -2583,8 +2260,6 @@ make_float (double float_value) | |||
| 2583 | { | 2260 | { |
| 2584 | register Lisp_Object val; | 2261 | register Lisp_Object val; |
| 2585 | 2262 | ||
| 2586 | /* eassert (!handling_signal); */ | ||
| 2587 | |||
| 2588 | MALLOC_BLOCK_INPUT; | 2263 | MALLOC_BLOCK_INPUT; |
| 2589 | 2264 | ||
| 2590 | if (float_free_list) | 2265 | if (float_free_list) |
| @@ -2692,8 +2367,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2692 | { | 2367 | { |
| 2693 | register Lisp_Object val; | 2368 | register Lisp_Object val; |
| 2694 | 2369 | ||
| 2695 | /* eassert (!handling_signal); */ | ||
| 2696 | |||
| 2697 | MALLOC_BLOCK_INPUT; | 2370 | MALLOC_BLOCK_INPUT; |
| 2698 | 2371 | ||
| 2699 | if (cons_free_list) | 2372 | if (cons_free_list) |
| @@ -2806,7 +2479,7 @@ listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...) | |||
| 2806 | else if (type == CONSTYPE_HEAP) | 2479 | else if (type == CONSTYPE_HEAP) |
| 2807 | val = Fcons (objp[i], val); | 2480 | val = Fcons (objp[i], val); |
| 2808 | else | 2481 | else |
| 2809 | abort (); | 2482 | emacs_abort (); |
| 2810 | } | 2483 | } |
| 2811 | return val; | 2484 | return val; |
| 2812 | } | 2485 | } |
| @@ -3199,9 +2872,6 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 3199 | 2872 | ||
| 3200 | MALLOC_BLOCK_INPUT; | 2873 | MALLOC_BLOCK_INPUT; |
| 3201 | 2874 | ||
| 3202 | /* This gets triggered by code which I haven't bothered to fix. --Stef */ | ||
| 3203 | /* eassert (!handling_signal); */ | ||
| 3204 | |||
| 3205 | if (len == 0) | 2875 | if (len == 0) |
| 3206 | p = XVECTOR (zero_vector); | 2876 | p = XVECTOR (zero_vector); |
| 3207 | else | 2877 | else |
| @@ -3278,7 +2948,10 @@ allocate_buffer (void) | |||
| 3278 | 2948 | ||
| 3279 | XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text) | 2949 | XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text) |
| 3280 | - header_size) / word_size); | 2950 | - header_size) / word_size); |
| 3281 | /* Note that the fields of B are not initialized. */ | 2951 | /* Put B on the chain of all buffers including killed ones. */ |
| 2952 | b->header.next.buffer = all_buffers; | ||
| 2953 | all_buffers = b; | ||
| 2954 | /* Note that the rest fields of B are not initialized. */ | ||
| 3282 | return b; | 2955 | return b; |
| 3283 | } | 2956 | } |
| 3284 | 2957 | ||
| @@ -3483,8 +3156,6 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3483 | 3156 | ||
| 3484 | CHECK_STRING (name); | 3157 | CHECK_STRING (name); |
| 3485 | 3158 | ||
| 3486 | /* eassert (!handling_signal); */ | ||
| 3487 | |||
| 3488 | MALLOC_BLOCK_INPUT; | 3159 | MALLOC_BLOCK_INPUT; |
| 3489 | 3160 | ||
| 3490 | if (symbol_free_list) | 3161 | if (symbol_free_list) |
| @@ -3569,8 +3240,6 @@ allocate_misc (enum Lisp_Misc_Type type) | |||
| 3569 | { | 3240 | { |
| 3570 | Lisp_Object val; | 3241 | Lisp_Object val; |
| 3571 | 3242 | ||
| 3572 | /* eassert (!handling_signal); */ | ||
| 3573 | |||
| 3574 | MALLOC_BLOCK_INPUT; | 3243 | MALLOC_BLOCK_INPUT; |
| 3575 | 3244 | ||
| 3576 | if (marker_free_list) | 3245 | if (marker_free_list) |
| @@ -3674,7 +3343,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) | |||
| 3674 | struct Lisp_Marker *m; | 3343 | struct Lisp_Marker *m; |
| 3675 | 3344 | ||
| 3676 | /* No dead buffers here. */ | 3345 | /* No dead buffers here. */ |
| 3677 | eassert (!NILP (BVAR (buf, name))); | 3346 | eassert (BUFFER_LIVE_P (buf)); |
| 3678 | 3347 | ||
| 3679 | /* Every character is at least one byte. */ | 3348 | /* Every character is at least one byte. */ |
| 3680 | eassert (charpos <= bytepos); | 3349 | eassert (charpos <= bytepos); |
| @@ -3790,12 +3459,6 @@ memory_full (size_t nbytes) | |||
| 3790 | lisp_free (spare_memory[i]); | 3459 | lisp_free (spare_memory[i]); |
| 3791 | spare_memory[i] = 0; | 3460 | spare_memory[i] = 0; |
| 3792 | } | 3461 | } |
| 3793 | |||
| 3794 | /* Record the space now used. When it decreases substantially, | ||
| 3795 | we can refill the memory reserve. */ | ||
| 3796 | #if !defined SYSTEM_MALLOC && !defined SYNC_INPUT | ||
| 3797 | bytes_used_when_full = BYTES_USED; | ||
| 3798 | #endif | ||
| 3799 | } | 3462 | } |
| 3800 | 3463 | ||
| 3801 | /* This used to call error, but if we've run out of memory, we could | 3464 | /* This used to call error, but if we've run out of memory, we could |
| @@ -3916,7 +3579,7 @@ mem_insert (void *start, void *end, enum mem_type type) | |||
| 3916 | while (c != MEM_NIL) | 3579 | while (c != MEM_NIL) |
| 3917 | { | 3580 | { |
| 3918 | if (start >= c->start && start < c->end) | 3581 | if (start >= c->start && start < c->end) |
| 3919 | abort (); | 3582 | emacs_abort (); |
| 3920 | parent = c; | 3583 | parent = c; |
| 3921 | c = start < c->start ? c->left : c->right; | 3584 | c = start < c->start ? c->left : c->right; |
| 3922 | } | 3585 | } |
| @@ -3933,9 +3596,9 @@ mem_insert (void *start, void *end, enum mem_type type) | |||
| 3933 | 3596 | ||
| 3934 | /* Create a new node. */ | 3597 | /* Create a new node. */ |
| 3935 | #ifdef GC_MALLOC_CHECK | 3598 | #ifdef GC_MALLOC_CHECK |
| 3936 | x = _malloc_internal (sizeof *x); | 3599 | x = malloc (sizeof *x); |
| 3937 | if (x == NULL) | 3600 | if (x == NULL) |
| 3938 | abort (); | 3601 | emacs_abort (); |
| 3939 | #else | 3602 | #else |
| 3940 | x = xmalloc (sizeof *x); | 3603 | x = xmalloc (sizeof *x); |
| 3941 | #endif | 3604 | #endif |
| @@ -4157,7 +3820,7 @@ mem_delete (struct mem_node *z) | |||
| 4157 | mem_delete_fixup (x); | 3820 | mem_delete_fixup (x); |
| 4158 | 3821 | ||
| 4159 | #ifdef GC_MALLOC_CHECK | 3822 | #ifdef GC_MALLOC_CHECK |
| 4160 | _free_internal (y); | 3823 | free (y); |
| 4161 | #else | 3824 | #else |
| 4162 | xfree (y); | 3825 | xfree (y); |
| 4163 | #endif | 3826 | #endif |
| @@ -4610,7 +4273,7 @@ mark_maybe_pointer (void *p) | |||
| 4610 | break; | 4273 | break; |
| 4611 | 4274 | ||
| 4612 | default: | 4275 | default: |
| 4613 | abort (); | 4276 | emacs_abort (); |
| 4614 | } | 4277 | } |
| 4615 | 4278 | ||
| 4616 | if (!NILP (obj)) | 4279 | if (!NILP (obj)) |
| @@ -4754,14 +4417,14 @@ test_setjmp (void) | |||
| 4754 | { | 4417 | { |
| 4755 | char buf[10]; | 4418 | char buf[10]; |
| 4756 | register int x; | 4419 | register int x; |
| 4757 | jmp_buf jbuf; | 4420 | sys_jmp_buf jbuf; |
| 4758 | 4421 | ||
| 4759 | /* Arrange for X to be put in a register. */ | 4422 | /* Arrange for X to be put in a register. */ |
| 4760 | sprintf (buf, "1"); | 4423 | sprintf (buf, "1"); |
| 4761 | x = strlen (buf); | 4424 | x = strlen (buf); |
| 4762 | x = 2 * x - 1; | 4425 | x = 2 * x - 1; |
| 4763 | 4426 | ||
| 4764 | setjmp (jbuf); | 4427 | sys_setjmp (jbuf); |
| 4765 | if (longjmps_done == 1) | 4428 | if (longjmps_done == 1) |
| 4766 | { | 4429 | { |
| 4767 | /* Came here after the longjmp at the end of the function. | 4430 | /* Came here after the longjmp at the end of the function. |
| @@ -4786,7 +4449,7 @@ test_setjmp (void) | |||
| 4786 | ++longjmps_done; | 4449 | ++longjmps_done; |
| 4787 | x = 2; | 4450 | x = 2; |
| 4788 | if (longjmps_done == 1) | 4451 | if (longjmps_done == 1) |
| 4789 | longjmp (jbuf, 1); | 4452 | sys_longjmp (jbuf, 1); |
| 4790 | } | 4453 | } |
| 4791 | 4454 | ||
| 4792 | #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */ | 4455 | #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */ |
| @@ -4807,7 +4470,7 @@ check_gcpros (void) | |||
| 4807 | if (!survives_gc_p (p->var[i])) | 4470 | if (!survives_gc_p (p->var[i])) |
| 4808 | /* FIXME: It's not necessarily a bug. It might just be that the | 4471 | /* FIXME: It's not necessarily a bug. It might just be that the |
| 4809 | GCPRO is unnecessary or should release the object sooner. */ | 4472 | GCPRO is unnecessary or should release the object sooner. */ |
| 4810 | abort (); | 4473 | emacs_abort (); |
| 4811 | } | 4474 | } |
| 4812 | 4475 | ||
| 4813 | #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 4476 | #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| @@ -4892,7 +4555,7 @@ mark_stack (void) | |||
| 4892 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ | 4555 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ |
| 4893 | union aligned_jmpbuf { | 4556 | union aligned_jmpbuf { |
| 4894 | Lisp_Object o; | 4557 | Lisp_Object o; |
| 4895 | jmp_buf j; | 4558 | sys_jmp_buf j; |
| 4896 | } j; | 4559 | } j; |
| 4897 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; | 4560 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_base; |
| 4898 | #endif | 4561 | #endif |
| @@ -4928,7 +4591,7 @@ mark_stack (void) | |||
| 4928 | } | 4591 | } |
| 4929 | #endif /* GC_SETJMP_WORKS */ | 4592 | #endif /* GC_SETJMP_WORKS */ |
| 4930 | 4593 | ||
| 4931 | setjmp (j.j); | 4594 | sys_setjmp (j.j); |
| 4932 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; | 4595 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; |
| 4933 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ | 4596 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ |
| 4934 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ | 4597 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ |
| @@ -4978,7 +4641,8 @@ valid_pointer_p (void *p) | |||
| 4978 | #endif | 4641 | #endif |
| 4979 | } | 4642 | } |
| 4980 | 4643 | ||
| 4981 | /* Return 1 if OBJ is a valid lisp object. | 4644 | /* Return 2 if OBJ is a killed or special buffer object. |
| 4645 | Return 1 if OBJ is a valid lisp object. | ||
| 4982 | Return 0 if OBJ is NOT a valid lisp object. | 4646 | Return 0 if OBJ is NOT a valid lisp object. |
| 4983 | Return -1 if we cannot validate OBJ. | 4647 | Return -1 if we cannot validate OBJ. |
| 4984 | This function can be quite slow, | 4648 | This function can be quite slow, |
| @@ -4999,6 +4663,9 @@ valid_lisp_object_p (Lisp_Object obj) | |||
| 4999 | if (PURE_POINTER_P (p)) | 4663 | if (PURE_POINTER_P (p)) |
| 5000 | return 1; | 4664 | return 1; |
| 5001 | 4665 | ||
| 4666 | if (p == &buffer_defaults || p == &buffer_local_symbols) | ||
| 4667 | return 2; | ||
| 4668 | |||
| 5002 | #if !GC_MARK_STACK | 4669 | #if !GC_MARK_STACK |
| 5003 | return valid_pointer_p (p); | 4670 | return valid_pointer_p (p); |
| 5004 | #else | 4671 | #else |
| @@ -5024,7 +4691,7 @@ valid_lisp_object_p (Lisp_Object obj) | |||
| 5024 | return 0; | 4691 | return 0; |
| 5025 | 4692 | ||
| 5026 | case MEM_TYPE_BUFFER: | 4693 | case MEM_TYPE_BUFFER: |
| 5027 | return live_buffer_p (m, p); | 4694 | return live_buffer_p (m, p) ? 1 : 2; |
| 5028 | 4695 | ||
| 5029 | case MEM_TYPE_CONS: | 4696 | case MEM_TYPE_CONS: |
| 5030 | return live_cons_p (m, p); | 4697 | return live_cons_p (m, p); |
| @@ -5348,7 +5015,7 @@ staticpro (Lisp_Object *varaddress) | |||
| 5348 | { | 5015 | { |
| 5349 | staticvec[staticidx++] = varaddress; | 5016 | staticvec[staticidx++] = varaddress; |
| 5350 | if (staticidx >= NSTATICS) | 5017 | if (staticidx >= NSTATICS) |
| 5351 | abort (); | 5018 | emacs_abort (); |
| 5352 | } | 5019 | } |
| 5353 | 5020 | ||
| 5354 | 5021 | ||
| @@ -5403,7 +5070,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5403 | Lisp_Object retval = Qnil; | 5070 | Lisp_Object retval = Qnil; |
| 5404 | 5071 | ||
| 5405 | if (abort_on_gc) | 5072 | if (abort_on_gc) |
| 5406 | abort (); | 5073 | emacs_abort (); |
| 5407 | 5074 | ||
| 5408 | /* Can't GC if pure storage overflowed because we can't determine | 5075 | /* Can't GC if pure storage overflowed because we can't determine |
| 5409 | if something is a pure object or not. */ | 5076 | if something is a pure object or not. */ |
| @@ -5466,6 +5133,9 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5466 | 5133 | ||
| 5467 | /* Mark all the special slots that serve as the roots of accessibility. */ | 5134 | /* Mark all the special slots that serve as the roots of accessibility. */ |
| 5468 | 5135 | ||
| 5136 | mark_buffer (&buffer_defaults); | ||
| 5137 | mark_buffer (&buffer_local_symbols); | ||
| 5138 | |||
| 5469 | for (i = 0; i < staticidx; i++) | 5139 | for (i = 0; i < staticidx; i++) |
| 5470 | mark_object (*staticvec[i]); | 5140 | mark_object (*staticvec[i]); |
| 5471 | 5141 | ||
| @@ -5478,10 +5148,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5478 | mark_kboards (); | 5148 | mark_kboards (); |
| 5479 | 5149 | ||
| 5480 | #ifdef USE_GTK | 5150 | #ifdef USE_GTK |
| 5481 | { | 5151 | xg_mark_data (); |
| 5482 | extern void xg_mark_data (void); | ||
| 5483 | xg_mark_data (); | ||
| 5484 | } | ||
| 5485 | #endif | 5152 | #endif |
| 5486 | 5153 | ||
| 5487 | #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ | 5154 | #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ |
| @@ -5853,6 +5520,32 @@ mark_buffer (struct buffer *buffer) | |||
| 5853 | mark_buffer (buffer->base_buffer); | 5520 | mark_buffer (buffer->base_buffer); |
| 5854 | } | 5521 | } |
| 5855 | 5522 | ||
| 5523 | /* Remove killed buffers or items whose car is a killed buffer from | ||
| 5524 | LIST, and mark other items. Return changed LIST, which is marked. */ | ||
| 5525 | |||
| 5526 | static Lisp_Object | ||
| 5527 | mark_discard_killed_buffers (Lisp_Object list) | ||
| 5528 | { | ||
| 5529 | Lisp_Object tail, *prev = &list; | ||
| 5530 | |||
| 5531 | for (tail = list; CONSP (tail) && !CONS_MARKED_P (XCONS (tail)); | ||
| 5532 | tail = XCDR (tail)) | ||
| 5533 | { | ||
| 5534 | Lisp_Object tem = XCAR (tail); | ||
| 5535 | if (CONSP (tem)) | ||
| 5536 | tem = XCAR (tem); | ||
| 5537 | if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem))) | ||
| 5538 | *prev = XCDR (tail); | ||
| 5539 | else | ||
| 5540 | { | ||
| 5541 | CONS_MARK (XCONS (tail)); | ||
| 5542 | mark_object (XCAR (tail)); | ||
| 5543 | prev = &XCDR_AS_LVALUE (tail); | ||
| 5544 | } | ||
| 5545 | } | ||
| 5546 | return list; | ||
| 5547 | } | ||
| 5548 | |||
| 5856 | /* Determine type of generic Lisp_Object and mark it accordingly. */ | 5549 | /* Determine type of generic Lisp_Object and mark it accordingly. */ |
| 5857 | 5550 | ||
| 5858 | void | 5551 | void |
| @@ -5887,7 +5580,7 @@ mark_object (Lisp_Object arg) | |||
| 5887 | do { \ | 5580 | do { \ |
| 5888 | m = mem_find (po); \ | 5581 | m = mem_find (po); \ |
| 5889 | if (m == MEM_NIL) \ | 5582 | if (m == MEM_NIL) \ |
| 5890 | abort (); \ | 5583 | emacs_abort (); \ |
| 5891 | } while (0) | 5584 | } while (0) |
| 5892 | 5585 | ||
| 5893 | /* Check that the object pointed to by PO is live, using predicate | 5586 | /* Check that the object pointed to by PO is live, using predicate |
| @@ -5895,7 +5588,7 @@ mark_object (Lisp_Object arg) | |||
| 5895 | #define CHECK_LIVE(LIVEP) \ | 5588 | #define CHECK_LIVE(LIVEP) \ |
| 5896 | do { \ | 5589 | do { \ |
| 5897 | if (!LIVEP (m, po)) \ | 5590 | if (!LIVEP (m, po)) \ |
| 5898 | abort (); \ | 5591 | emacs_abort (); \ |
| 5899 | } while (0) | 5592 | } while (0) |
| 5900 | 5593 | ||
| 5901 | /* Check both of the above conditions. */ | 5594 | /* Check both of the above conditions. */ |
| @@ -5940,10 +5633,8 @@ mark_object (Lisp_Object arg) | |||
| 5940 | 5633 | ||
| 5941 | #ifdef GC_CHECK_MARKED_OBJECTS | 5634 | #ifdef GC_CHECK_MARKED_OBJECTS |
| 5942 | m = mem_find (po); | 5635 | m = mem_find (po); |
| 5943 | if (m == MEM_NIL && !SUBRP (obj) | 5636 | if (m == MEM_NIL && !SUBRP (obj)) |
| 5944 | && po != &buffer_defaults | 5637 | emacs_abort (); |
| 5945 | && po != &buffer_local_symbols) | ||
| 5946 | abort (); | ||
| 5947 | #endif /* GC_CHECK_MARKED_OBJECTS */ | 5638 | #endif /* GC_CHECK_MARKED_OBJECTS */ |
| 5948 | 5639 | ||
| 5949 | if (ptr->header.size & PSEUDOVECTOR_FLAG) | 5640 | if (ptr->header.size & PSEUDOVECTOR_FLAG) |
| @@ -5959,15 +5650,14 @@ mark_object (Lisp_Object arg) | |||
| 5959 | { | 5650 | { |
| 5960 | case PVEC_BUFFER: | 5651 | case PVEC_BUFFER: |
| 5961 | #ifdef GC_CHECK_MARKED_OBJECTS | 5652 | #ifdef GC_CHECK_MARKED_OBJECTS |
| 5962 | if (po != &buffer_defaults && po != &buffer_local_symbols) | 5653 | { |
| 5963 | { | 5654 | struct buffer *b; |
| 5964 | struct buffer *b; | 5655 | FOR_EACH_BUFFER (b) |
| 5965 | FOR_EACH_BUFFER (b) | 5656 | if (b == po) |
| 5966 | if (b == po) | 5657 | break; |
| 5967 | break; | 5658 | if (b == NULL) |
| 5968 | if (b == NULL) | 5659 | emacs_abort (); |
| 5969 | abort (); | 5660 | } |
| 5970 | } | ||
| 5971 | #endif /* GC_CHECK_MARKED_OBJECTS */ | 5661 | #endif /* GC_CHECK_MARKED_OBJECTS */ |
| 5972 | mark_buffer ((struct buffer *) ptr); | 5662 | mark_buffer ((struct buffer *) ptr); |
| 5973 | break; | 5663 | break; |
| @@ -5992,22 +5682,31 @@ mark_object (Lisp_Object arg) | |||
| 5992 | break; | 5682 | break; |
| 5993 | 5683 | ||
| 5994 | case PVEC_FRAME: | 5684 | case PVEC_FRAME: |
| 5995 | { | 5685 | mark_vectorlike (ptr); |
| 5996 | mark_vectorlike (ptr); | 5686 | mark_face_cache (((struct frame *) ptr)->face_cache); |
| 5997 | mark_face_cache (((struct frame *) ptr)->face_cache); | ||
| 5998 | } | ||
| 5999 | break; | 5687 | break; |
| 6000 | 5688 | ||
| 6001 | case PVEC_WINDOW: | 5689 | case PVEC_WINDOW: |
| 6002 | { | 5690 | { |
| 6003 | struct window *w = (struct window *) ptr; | 5691 | struct window *w = (struct window *) ptr; |
| 5692 | bool leaf = NILP (w->hchild) && NILP (w->vchild); | ||
| 5693 | |||
| 5694 | /* For live windows, Lisp code filters out killed buffers | ||
| 5695 | from both buffer lists. For dead windows, we do it here | ||
| 5696 | in attempt to help GC to reclaim killed buffers faster. */ | ||
| 5697 | if (leaf && NILP (w->buffer)) | ||
| 5698 | { | ||
| 5699 | wset_prev_buffers | ||
| 5700 | (w, mark_discard_killed_buffers (w->prev_buffers)); | ||
| 5701 | wset_next_buffers | ||
| 5702 | (w, mark_discard_killed_buffers (w->next_buffers)); | ||
| 5703 | } | ||
| 6004 | 5704 | ||
| 6005 | mark_vectorlike (ptr); | 5705 | mark_vectorlike (ptr); |
| 6006 | /* Mark glyphs for leaf windows. Marking window | 5706 | /* Mark glyphs for leaf windows. Marking window |
| 6007 | matrices is sufficient because frame matrices | 5707 | matrices is sufficient because frame matrices |
| 6008 | use the same glyph memory. */ | 5708 | use the same glyph memory. */ |
| 6009 | if (NILP (w->hchild) && NILP (w->vchild) | 5709 | if (leaf && w->current_matrix) |
| 6010 | && w->current_matrix) | ||
| 6011 | { | 5710 | { |
| 6012 | mark_glyph_matrix (w->current_matrix); | 5711 | mark_glyph_matrix (w->current_matrix); |
| 6013 | mark_glyph_matrix (w->desired_matrix); | 5712 | mark_glyph_matrix (w->desired_matrix); |
| @@ -6042,7 +5741,7 @@ mark_object (Lisp_Object arg) | |||
| 6042 | break; | 5741 | break; |
| 6043 | 5742 | ||
| 6044 | case PVEC_FREE: | 5743 | case PVEC_FREE: |
| 6045 | abort (); | 5744 | emacs_abort (); |
| 6046 | 5745 | ||
| 6047 | default: | 5746 | default: |
| 6048 | mark_vectorlike (ptr); | 5747 | mark_vectorlike (ptr); |
| @@ -6074,10 +5773,14 @@ mark_object (Lisp_Object arg) | |||
| 6074 | case SYMBOL_LOCALIZED: | 5773 | case SYMBOL_LOCALIZED: |
| 6075 | { | 5774 | { |
| 6076 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); | 5775 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); |
| 6077 | /* If the value is forwarded to a buffer or keyboard field, | 5776 | Lisp_Object where = blv->where; |
| 6078 | these are marked when we see the corresponding object. | 5777 | /* If the value is set up for a killed buffer or deleted |
| 6079 | And if it's forwarded to a C variable, either it's not | 5778 | frame, restore it's global binding. If the value is |
| 6080 | a Lisp_Object var, or it's staticpro'd already. */ | 5779 | forwarded to a C variable, either it's not a Lisp_Object |
| 5780 | var, or it's staticpro'd already. */ | ||
| 5781 | if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) | ||
| 5782 | || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) | ||
| 5783 | swap_in_global_binding (ptr); | ||
| 6081 | mark_object (blv->where); | 5784 | mark_object (blv->where); |
| 6082 | mark_object (blv->valcell); | 5785 | mark_object (blv->valcell); |
| 6083 | mark_object (blv->defcell); | 5786 | mark_object (blv->defcell); |
| @@ -6089,7 +5792,7 @@ mark_object (Lisp_Object arg) | |||
| 6089 | And if it's forwarded to a C variable, either it's not | 5792 | And if it's forwarded to a C variable, either it's not |
| 6090 | a Lisp_Object var, or it's staticpro'd already. */ | 5793 | a Lisp_Object var, or it's staticpro'd already. */ |
| 6091 | break; | 5794 | break; |
| 6092 | default: abort (); | 5795 | default: emacs_abort (); |
| 6093 | } | 5796 | } |
| 6094 | if (!PURE_POINTER_P (XSTRING (ptr->name))) | 5797 | if (!PURE_POINTER_P (XSTRING (ptr->name))) |
| 6095 | MARK_STRING (XSTRING (ptr->name)); | 5798 | MARK_STRING (XSTRING (ptr->name)); |
| @@ -6143,7 +5846,7 @@ mark_object (Lisp_Object arg) | |||
| 6143 | break; | 5846 | break; |
| 6144 | 5847 | ||
| 6145 | default: | 5848 | default: |
| 6146 | abort (); | 5849 | emacs_abort (); |
| 6147 | } | 5850 | } |
| 6148 | break; | 5851 | break; |
| 6149 | 5852 | ||
| @@ -6165,7 +5868,7 @@ mark_object (Lisp_Object arg) | |||
| 6165 | obj = ptr->u.cdr; | 5868 | obj = ptr->u.cdr; |
| 6166 | cdr_count++; | 5869 | cdr_count++; |
| 6167 | if (cdr_count == mark_object_loop_halt) | 5870 | if (cdr_count == mark_object_loop_halt) |
| 6168 | abort (); | 5871 | emacs_abort (); |
| 6169 | goto loop; | 5872 | goto loop; |
| 6170 | } | 5873 | } |
| 6171 | 5874 | ||
| @@ -6178,7 +5881,7 @@ mark_object (Lisp_Object arg) | |||
| 6178 | break; | 5881 | break; |
| 6179 | 5882 | ||
| 6180 | default: | 5883 | default: |
| 6181 | abort (); | 5884 | emacs_abort (); |
| 6182 | } | 5885 | } |
| 6183 | 5886 | ||
| 6184 | #undef CHECK_LIVE | 5887 | #undef CHECK_LIVE |
| @@ -6247,7 +5950,7 @@ survives_gc_p (Lisp_Object obj) | |||
| 6247 | break; | 5950 | break; |
| 6248 | 5951 | ||
| 6249 | default: | 5952 | default: |
| 6250 | abort (); | 5953 | emacs_abort (); |
| 6251 | } | 5954 | } |
| 6252 | 5955 | ||
| 6253 | return survives_p || PURE_POINTER_P ((void *) XPNTR (obj)); | 5956 | return survives_p || PURE_POINTER_P ((void *) XPNTR (obj)); |
| @@ -6685,21 +6388,14 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) | |||
| 6685 | 6388 | ||
| 6686 | #ifdef ENABLE_CHECKING | 6389 | #ifdef ENABLE_CHECKING |
| 6687 | 6390 | ||
| 6688 | # include <execinfo.h> | ||
| 6689 | |||
| 6690 | bool suppress_checking; | 6391 | bool suppress_checking; |
| 6691 | 6392 | ||
| 6692 | void | 6393 | void |
| 6693 | die (const char *msg, const char *file, int line) | 6394 | die (const char *msg, const char *file, int line) |
| 6694 | { | 6395 | { |
| 6695 | enum { NPOINTERS_MAX = 500 }; | ||
| 6696 | void *buffer[NPOINTERS_MAX]; | ||
| 6697 | int npointers; | ||
| 6698 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", | 6396 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", |
| 6699 | file, line, msg); | 6397 | file, line, msg); |
| 6700 | npointers = backtrace (buffer, NPOINTERS_MAX); | 6398 | fatal_error_backtrace (SIGABRT, INT_MAX); |
| 6701 | backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); | ||
| 6702 | abort (); | ||
| 6703 | } | 6399 | } |
| 6704 | #endif | 6400 | #endif |
| 6705 | 6401 | ||
| @@ -6725,12 +6421,6 @@ init_alloc_once (void) | |||
| 6725 | init_strings (); | 6421 | init_strings (); |
| 6726 | init_vectors (); | 6422 | init_vectors (); |
| 6727 | 6423 | ||
| 6728 | #ifdef REL_ALLOC | ||
| 6729 | malloc_hysteresis = 32; | ||
| 6730 | #else | ||
| 6731 | malloc_hysteresis = 0; | ||
| 6732 | #endif | ||
| 6733 | |||
| 6734 | refill_memory_reserve (); | 6424 | refill_memory_reserve (); |
| 6735 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; | 6425 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; |
| 6736 | } | 6426 | } |