diff options
| author | Tom Tromey | 2012-12-17 07:56:22 -0700 |
|---|---|---|
| committer | Tom Tromey | 2012-12-17 07:56:22 -0700 |
| commit | 3d6eced1ae51ffd0a782130e7c334052277e2724 (patch) | |
| tree | 5d1d2ad7cd3374f922886c4a72062511a035c168 /src/alloc.c | |
| parent | bf69f522a9e135f9aa483cedd53e71e915f2bf75 (diff) | |
| parent | 7c3d167f48d6262ee4e5512aa50a07ee96bc1509 (diff) | |
| download | emacs-3d6eced1ae51ffd0a782130e7c334052277e2724.tar.gz emacs-3d6eced1ae51ffd0a782130e7c334052277e2724.zip | |
merge from trunk
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 957 |
1 files changed, 380 insertions, 577 deletions
diff --git a/src/alloc.c b/src/alloc.c index 859961781e0..d091a9cdf55 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. |
| @@ -63,10 +63,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 63 | #endif | 63 | #endif |
| 64 | 64 | ||
| 65 | #include <unistd.h> | 65 | #include <unistd.h> |
| 66 | #ifndef HAVE_UNISTD_H | ||
| 67 | extern void *sbrk (); | ||
| 68 | #endif | ||
| 69 | |||
| 70 | #include <fcntl.h> | 66 | #include <fcntl.h> |
| 71 | 67 | ||
| 72 | #ifdef USE_GTK | 68 | #ifdef USE_GTK |
| @@ -74,6 +70,7 @@ extern void *sbrk (); | |||
| 74 | #endif | 70 | #endif |
| 75 | #ifdef WINDOWSNT | 71 | #ifdef WINDOWSNT |
| 76 | #include "w32.h" | 72 | #include "w32.h" |
| 73 | #include "w32heap.h" /* for sbrk */ | ||
| 77 | #endif | 74 | #endif |
| 78 | 75 | ||
| 79 | #ifdef DOUG_LEA_MALLOC | 76 | #ifdef DOUG_LEA_MALLOC |
| @@ -85,66 +82,8 @@ extern void *sbrk (); | |||
| 85 | 82 | ||
| 86 | #define MMAP_MAX_AREAS 100000000 | 83 | #define MMAP_MAX_AREAS 100000000 |
| 87 | 84 | ||
| 88 | #else /* not DOUG_LEA_MALLOC */ | ||
| 89 | |||
| 90 | /* The following come from gmalloc.c. */ | ||
| 91 | |||
| 92 | extern size_t _bytes_used; | ||
| 93 | extern size_t __malloc_extra_blocks; | ||
| 94 | extern void *_malloc_internal (size_t); | ||
| 95 | extern void _free_internal (void *); | ||
| 96 | |||
| 97 | #endif /* not DOUG_LEA_MALLOC */ | 85 | #endif /* not DOUG_LEA_MALLOC */ |
| 98 | 86 | ||
| 99 | #if ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT | ||
| 100 | #ifdef HAVE_PTHREAD | ||
| 101 | |||
| 102 | /* When GTK uses the file chooser dialog, different backends can be loaded | ||
| 103 | dynamically. One such a backend is the Gnome VFS backend that gets loaded | ||
| 104 | if you run Gnome. That backend creates several threads and also allocates | ||
| 105 | memory with malloc. | ||
| 106 | |||
| 107 | Also, gconf and gsettings may create several threads. | ||
| 108 | |||
| 109 | If Emacs sets malloc hooks (! SYSTEM_MALLOC) and the emacs_blocked_* | ||
| 110 | functions below are called from malloc, there is a chance that one | ||
| 111 | of these threads preempts the Emacs main thread and the hook variables | ||
| 112 | end up in an inconsistent state. So we have a mutex to prevent that (note | ||
| 113 | that the backend handles concurrent access to malloc within its own threads | ||
| 114 | but Emacs code running in the main thread is not included in that control). | ||
| 115 | |||
| 116 | When UNBLOCK_INPUT is called, reinvoke_input_signal may be called. If this | ||
| 117 | happens in one of the backend threads we will have two threads that tries | ||
| 118 | to run Emacs code at once, and the code is not prepared for that. | ||
| 119 | To prevent that, we only call BLOCK/UNBLOCK from the main thread. */ | ||
| 120 | |||
| 121 | static pthread_mutex_t alloc_mutex; | ||
| 122 | |||
| 123 | #define BLOCK_INPUT_ALLOC \ | ||
| 124 | do \ | ||
| 125 | { \ | ||
| 126 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 127 | BLOCK_INPUT; \ | ||
| 128 | pthread_mutex_lock (&alloc_mutex); \ | ||
| 129 | } \ | ||
| 130 | while (0) | ||
| 131 | #define UNBLOCK_INPUT_ALLOC \ | ||
| 132 | do \ | ||
| 133 | { \ | ||
| 134 | pthread_mutex_unlock (&alloc_mutex); \ | ||
| 135 | if (pthread_equal (pthread_self (), main_thread)) \ | ||
| 136 | UNBLOCK_INPUT; \ | ||
| 137 | } \ | ||
| 138 | while (0) | ||
| 139 | |||
| 140 | #else /* ! defined HAVE_PTHREAD */ | ||
| 141 | |||
| 142 | #define BLOCK_INPUT_ALLOC BLOCK_INPUT | ||
| 143 | #define UNBLOCK_INPUT_ALLOC UNBLOCK_INPUT | ||
| 144 | |||
| 145 | #endif /* ! defined HAVE_PTHREAD */ | ||
| 146 | #endif /* ! defined SYSTEM_MALLOC && ! defined SYNC_INPUT */ | ||
| 147 | |||
| 148 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer | 87 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer |
| 149 | to a struct Lisp_String. */ | 88 | to a struct Lisp_String. */ |
| 150 | 89 | ||
| @@ -203,10 +142,6 @@ static char *spare_memory[7]; | |||
| 203 | 142 | ||
| 204 | #define SPARE_MEMORY (1 << 14) | 143 | #define SPARE_MEMORY (1 << 14) |
| 205 | 144 | ||
| 206 | /* Number of extra blocks malloc should get when it needs more core. */ | ||
| 207 | |||
| 208 | static int malloc_hysteresis; | ||
| 209 | |||
| 210 | /* Initialize it to a nonzero value to force it into data space | 145 | /* Initialize it to a nonzero value to force it into data space |
| 211 | (rather than bss space). That way unexec will remap it into text | 146 | (rather than bss space). That way unexec will remap it into text |
| 212 | space (pure), on some systems. We have not implemented the | 147 | space (pure), on some systems. We have not implemented the |
| @@ -267,6 +202,7 @@ static Lisp_Object Qintervals; | |||
| 267 | static Lisp_Object Qbuffers; | 202 | static Lisp_Object Qbuffers; |
| 268 | static Lisp_Object Qstring_bytes, Qvector_slots, Qheap; | 203 | static Lisp_Object Qstring_bytes, Qvector_slots, Qheap; |
| 269 | static Lisp_Object Qgc_cons_threshold; | 204 | static Lisp_Object Qgc_cons_threshold; |
| 205 | Lisp_Object Qautomatic_gc; | ||
| 270 | Lisp_Object Qchar_table_extra_slots; | 206 | Lisp_Object Qchar_table_extra_slots; |
| 271 | 207 | ||
| 272 | /* Hook run after GC has finished. */ | 208 | /* Hook run after GC has finished. */ |
| @@ -276,22 +212,19 @@ static Lisp_Object Qpost_gc_hook; | |||
| 276 | static void mark_terminals (void); | 212 | static void mark_terminals (void); |
| 277 | static void gc_sweep (void); | 213 | static void gc_sweep (void); |
| 278 | static Lisp_Object make_pure_vector (ptrdiff_t); | 214 | static Lisp_Object make_pure_vector (ptrdiff_t); |
| 279 | static void mark_glyph_matrix (struct glyph_matrix *); | 215 | static void mark_buffer (struct buffer *); |
| 280 | static void mark_face_cache (struct face_cache *); | ||
| 281 | 216 | ||
| 282 | #if !defined REL_ALLOC || defined SYSTEM_MALLOC | 217 | #if !defined REL_ALLOC || defined SYSTEM_MALLOC |
| 283 | static void refill_memory_reserve (void); | 218 | static void refill_memory_reserve (void); |
| 284 | #endif | 219 | #endif |
| 285 | static struct Lisp_String *allocate_string (void); | ||
| 286 | static void compact_small_strings (void); | 220 | static void compact_small_strings (void); |
| 287 | static void free_large_strings (void); | 221 | static void free_large_strings (void); |
| 288 | static void sweep_strings (void); | ||
| 289 | static void free_misc (Lisp_Object); | 222 | static void free_misc (Lisp_Object); |
| 290 | extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE; | 223 | extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE; |
| 291 | 224 | ||
| 292 | /* When scanning the C stack for live Lisp objects, Emacs keeps track | 225 | /* When scanning the C stack for live Lisp objects, Emacs keeps track of |
| 293 | of what memory allocated via lisp_malloc is intended for what | 226 | what memory allocated via lisp_malloc and lisp_align_malloc is intended |
| 294 | purpose. This enumeration specifies the type of memory. */ | 227 | for what purpose. This enumeration specifies the type of memory. */ |
| 295 | 228 | ||
| 296 | enum mem_type | 229 | enum mem_type |
| 297 | { | 230 | { |
| @@ -302,10 +235,9 @@ enum mem_type | |||
| 302 | MEM_TYPE_MISC, | 235 | MEM_TYPE_MISC, |
| 303 | MEM_TYPE_SYMBOL, | 236 | MEM_TYPE_SYMBOL, |
| 304 | MEM_TYPE_FLOAT, | 237 | MEM_TYPE_FLOAT, |
| 305 | /* We used to keep separate mem_types for subtypes of vectors such as | 238 | /* Since all non-bool pseudovectors are small enough to be |
| 306 | process, hash_table, frame, terminal, and window, but we never made | 239 | allocated from vector blocks, this memory type denotes |
| 307 | use of the distinction, so it only caused source-code complexity | 240 | large regular vectors and large bool pseudovectors. */ |
| 308 | and runtime slowdown. Minor but pointless. */ | ||
| 309 | MEM_TYPE_VECTORLIKE, | 241 | MEM_TYPE_VECTORLIKE, |
| 310 | /* Special type to denote vector blocks. */ | 242 | /* Special type to denote vector blocks. */ |
| 311 | MEM_TYPE_VECTOR_BLOCK, | 243 | MEM_TYPE_VECTOR_BLOCK, |
| @@ -313,9 +245,6 @@ enum mem_type | |||
| 313 | MEM_TYPE_SPARE | 245 | MEM_TYPE_SPARE |
| 314 | }; | 246 | }; |
| 315 | 247 | ||
| 316 | static void *lisp_malloc (size_t, enum mem_type); | ||
| 317 | |||
| 318 | |||
| 319 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK | 248 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK |
| 320 | 249 | ||
| 321 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 250 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| @@ -405,12 +334,12 @@ static void mark_memory (void *, void *); | |||
| 405 | static void mem_init (void); | 334 | static void mem_init (void); |
| 406 | static struct mem_node *mem_insert (void *, void *, enum mem_type); | 335 | static struct mem_node *mem_insert (void *, void *, enum mem_type); |
| 407 | static void mem_insert_fixup (struct mem_node *); | 336 | static void mem_insert_fixup (struct mem_node *); |
| 408 | #endif | ||
| 409 | static void mem_rotate_left (struct mem_node *); | 337 | static void mem_rotate_left (struct mem_node *); |
| 410 | static void mem_rotate_right (struct mem_node *); | 338 | static void mem_rotate_right (struct mem_node *); |
| 411 | static void mem_delete (struct mem_node *); | 339 | static void mem_delete (struct mem_node *); |
| 412 | static void mem_delete_fixup (struct mem_node *); | 340 | static void mem_delete_fixup (struct mem_node *); |
| 413 | static inline struct mem_node *mem_find (void *); | 341 | static struct mem_node *mem_find (void *); |
| 342 | #endif | ||
| 414 | 343 | ||
| 415 | 344 | ||
| 416 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | 345 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS |
| @@ -426,7 +355,7 @@ static void check_gcpros (void); | |||
| 426 | /* Addresses of staticpro'd variables. Initialize it to a nonzero | 355 | /* Addresses of staticpro'd variables. Initialize it to a nonzero |
| 427 | value; otherwise some compilers put it into BSS. */ | 356 | value; otherwise some compilers put it into BSS. */ |
| 428 | 357 | ||
| 429 | #define NSTATICS 0x650 | 358 | #define NSTATICS 0x800 |
| 430 | static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag}; | 359 | static Lisp_Object *staticvec[NSTATICS] = {&Vpurify_flag}; |
| 431 | 360 | ||
| 432 | /* Index of next unused slot in staticvec. */ | 361 | /* Index of next unused slot in staticvec. */ |
| @@ -575,39 +504,17 @@ xmalloc_get_size (unsigned char *ptr) | |||
| 575 | } | 504 | } |
| 576 | 505 | ||
| 577 | 506 | ||
| 578 | /* The call depth in overrun_check functions. For example, this might happen: | ||
| 579 | xmalloc() | ||
| 580 | overrun_check_malloc() | ||
| 581 | -> malloc -> (via hook)_-> emacs_blocked_malloc | ||
| 582 | -> overrun_check_malloc | ||
| 583 | call malloc (hooks are NULL, so real malloc is called). | ||
| 584 | malloc returns 10000. | ||
| 585 | add overhead, return 10016. | ||
| 586 | <- (back in overrun_check_malloc) | ||
| 587 | add overhead again, return 10032 | ||
| 588 | xmalloc returns 10032. | ||
| 589 | |||
| 590 | (time passes). | ||
| 591 | |||
| 592 | xfree(10032) | ||
| 593 | overrun_check_free(10032) | ||
| 594 | decrease overhead | ||
| 595 | free(10016) <- crash, because 10000 is the original pointer. */ | ||
| 596 | |||
| 597 | static ptrdiff_t check_depth; | ||
| 598 | |||
| 599 | /* Like malloc, but wraps allocated block with header and trailer. */ | 507 | /* Like malloc, but wraps allocated block with header and trailer. */ |
| 600 | 508 | ||
| 601 | static void * | 509 | static void * |
| 602 | overrun_check_malloc (size_t size) | 510 | overrun_check_malloc (size_t size) |
| 603 | { | 511 | { |
| 604 | register unsigned char *val; | 512 | register unsigned char *val; |
| 605 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 513 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 606 | if (SIZE_MAX - overhead < size) | 514 | emacs_abort (); |
| 607 | abort (); | ||
| 608 | 515 | ||
| 609 | val = malloc (size + overhead); | 516 | val = malloc (size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 610 | if (val && check_depth == 1) | 517 | if (val) |
| 611 | { | 518 | { |
| 612 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 519 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 613 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 520 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -615,7 +522,6 @@ overrun_check_malloc (size_t size) | |||
| 615 | memcpy (val + size, xmalloc_overrun_check_trailer, | 522 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 616 | XMALLOC_OVERRUN_CHECK_SIZE); | 523 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 617 | } | 524 | } |
| 618 | --check_depth; | ||
| 619 | return val; | 525 | return val; |
| 620 | } | 526 | } |
| 621 | 527 | ||
| @@ -627,12 +533,10 @@ static void * | |||
| 627 | overrun_check_realloc (void *block, size_t size) | 533 | overrun_check_realloc (void *block, size_t size) |
| 628 | { | 534 | { |
| 629 | register unsigned char *val = (unsigned char *) block; | 535 | register unsigned char *val = (unsigned char *) block; |
| 630 | int overhead = ++check_depth == 1 ? XMALLOC_OVERRUN_CHECK_OVERHEAD : 0; | 536 | if (SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD < size) |
| 631 | if (SIZE_MAX - overhead < size) | 537 | emacs_abort (); |
| 632 | abort (); | ||
| 633 | 538 | ||
| 634 | if (val | 539 | if (val |
| 635 | && check_depth == 1 | ||
| 636 | && memcmp (xmalloc_overrun_check_header, | 540 | && memcmp (xmalloc_overrun_check_header, |
| 637 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 541 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 638 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 542 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -640,15 +544,15 @@ overrun_check_realloc (void *block, size_t size) | |||
| 640 | size_t osize = xmalloc_get_size (val); | 544 | size_t osize = xmalloc_get_size (val); |
| 641 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, | 545 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, |
| 642 | XMALLOC_OVERRUN_CHECK_SIZE)) | 546 | XMALLOC_OVERRUN_CHECK_SIZE)) |
| 643 | abort (); | 547 | emacs_abort (); |
| 644 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); | 548 | memset (val + osize, 0, XMALLOC_OVERRUN_CHECK_SIZE); |
| 645 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 549 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 646 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); | 550 | memset (val, 0, XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE); |
| 647 | } | 551 | } |
| 648 | 552 | ||
| 649 | val = realloc (val, size + overhead); | 553 | val = realloc (val, size + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| 650 | 554 | ||
| 651 | if (val && check_depth == 1) | 555 | if (val) |
| 652 | { | 556 | { |
| 653 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); | 557 | memcpy (val, xmalloc_overrun_check_header, XMALLOC_OVERRUN_CHECK_SIZE); |
| 654 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 558 | val += XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| @@ -656,7 +560,6 @@ overrun_check_realloc (void *block, size_t size) | |||
| 656 | memcpy (val + size, xmalloc_overrun_check_trailer, | 560 | memcpy (val + size, xmalloc_overrun_check_trailer, |
| 657 | XMALLOC_OVERRUN_CHECK_SIZE); | 561 | XMALLOC_OVERRUN_CHECK_SIZE); |
| 658 | } | 562 | } |
| 659 | --check_depth; | ||
| 660 | return val; | 563 | return val; |
| 661 | } | 564 | } |
| 662 | 565 | ||
| @@ -667,9 +570,7 @@ overrun_check_free (void *block) | |||
| 667 | { | 570 | { |
| 668 | unsigned char *val = (unsigned char *) block; | 571 | unsigned char *val = (unsigned char *) block; |
| 669 | 572 | ||
| 670 | ++check_depth; | ||
| 671 | if (val | 573 | if (val |
| 672 | && check_depth == 1 | ||
| 673 | && memcmp (xmalloc_overrun_check_header, | 574 | && memcmp (xmalloc_overrun_check_header, |
| 674 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, | 575 | val - XMALLOC_OVERRUN_CHECK_SIZE - XMALLOC_OVERRUN_SIZE_SIZE, |
| 675 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) | 576 | XMALLOC_OVERRUN_CHECK_SIZE) == 0) |
| @@ -677,7 +578,7 @@ overrun_check_free (void *block) | |||
| 677 | size_t osize = xmalloc_get_size (val); | 578 | size_t osize = xmalloc_get_size (val); |
| 678 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, | 579 | if (memcmp (xmalloc_overrun_check_trailer, val + osize, |
| 679 | XMALLOC_OVERRUN_CHECK_SIZE)) | 580 | XMALLOC_OVERRUN_CHECK_SIZE)) |
| 680 | abort (); | 581 | emacs_abort (); |
| 681 | #ifdef XMALLOC_CLEAR_FREE_MEMORY | 582 | #ifdef XMALLOC_CLEAR_FREE_MEMORY |
| 682 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; | 583 | val -= XMALLOC_OVERRUN_CHECK_SIZE + XMALLOC_OVERRUN_SIZE_SIZE; |
| 683 | memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD); | 584 | memset (val, 0xff, osize + XMALLOC_OVERRUN_CHECK_OVERHEAD); |
| @@ -689,7 +590,6 @@ overrun_check_free (void *block) | |||
| 689 | } | 590 | } |
| 690 | 591 | ||
| 691 | free (val); | 592 | free (val); |
| 692 | --check_depth; | ||
| 693 | } | 593 | } |
| 694 | 594 | ||
| 695 | #undef malloc | 595 | #undef malloc |
| @@ -700,16 +600,42 @@ overrun_check_free (void *block) | |||
| 700 | #define free overrun_check_free | 600 | #define free overrun_check_free |
| 701 | #endif | 601 | #endif |
| 702 | 602 | ||
| 703 | #ifdef SYNC_INPUT | 603 | /* If compiled with XMALLOC_BLOCK_INPUT_CHECK, define a symbol |
| 704 | /* When using SYNC_INPUT, we don't call malloc from a signal handler, so | 604 | BLOCK_INPUT_IN_MEMORY_ALLOCATORS that is visible to the debugger. |
| 705 | there's no need to block input around malloc. */ | 605 | If that variable is set, block input while in one of Emacs's memory |
| 706 | #define MALLOC_BLOCK_INPUT ((void)0) | 606 | allocation functions. There should be no need for this debugging |
| 707 | #define MALLOC_UNBLOCK_INPUT ((void)0) | 607 | option, since signal handlers do not allocate memory, but Emacs |
| 608 | formerly allocated memory in signal handlers and this compile-time | ||
| 609 | option remains as a way to help debug the issue should it rear its | ||
| 610 | ugly head again. */ | ||
| 611 | #ifdef XMALLOC_BLOCK_INPUT_CHECK | ||
| 612 | bool block_input_in_memory_allocators EXTERNALLY_VISIBLE; | ||
| 613 | static void | ||
| 614 | malloc_block_input (void) | ||
| 615 | { | ||
| 616 | if (block_input_in_memory_allocators) | ||
| 617 | block_input (); | ||
| 618 | } | ||
| 619 | static void | ||
| 620 | malloc_unblock_input (void) | ||
| 621 | { | ||
| 622 | if (block_input_in_memory_allocators) | ||
| 623 | unblock_input (); | ||
| 624 | } | ||
| 625 | # define MALLOC_BLOCK_INPUT malloc_block_input () | ||
| 626 | # define MALLOC_UNBLOCK_INPUT malloc_unblock_input () | ||
| 708 | #else | 627 | #else |
| 709 | #define MALLOC_BLOCK_INPUT BLOCK_INPUT | 628 | # define MALLOC_BLOCK_INPUT ((void) 0) |
| 710 | #define MALLOC_UNBLOCK_INPUT UNBLOCK_INPUT | 629 | # define MALLOC_UNBLOCK_INPUT ((void) 0) |
| 711 | #endif | 630 | #endif |
| 712 | 631 | ||
| 632 | #define MALLOC_PROBE(size) \ | ||
| 633 | do { \ | ||
| 634 | if (profiler_memory_running) \ | ||
| 635 | malloc_probe (size); \ | ||
| 636 | } while (0) | ||
| 637 | |||
| 638 | |||
| 713 | /* Like malloc but check for no memory and block interrupt input.. */ | 639 | /* Like malloc but check for no memory and block interrupt input.. */ |
| 714 | 640 | ||
| 715 | void * | 641 | void * |
| @@ -723,6 +649,7 @@ xmalloc (size_t size) | |||
| 723 | 649 | ||
| 724 | if (!val && size) | 650 | if (!val && size) |
| 725 | memory_full (size); | 651 | memory_full (size); |
| 652 | MALLOC_PROBE (size); | ||
| 726 | return val; | 653 | return val; |
| 727 | } | 654 | } |
| 728 | 655 | ||
| @@ -740,6 +667,7 @@ xzalloc (size_t size) | |||
| 740 | if (!val && size) | 667 | if (!val && size) |
| 741 | memory_full (size); | 668 | memory_full (size); |
| 742 | memset (val, 0, size); | 669 | memset (val, 0, size); |
| 670 | MALLOC_PROBE (size); | ||
| 743 | return val; | 671 | return val; |
| 744 | } | 672 | } |
| 745 | 673 | ||
| @@ -761,6 +689,7 @@ xrealloc (void *block, size_t size) | |||
| 761 | 689 | ||
| 762 | if (!val && size) | 690 | if (!val && size) |
| 763 | memory_full (size); | 691 | memory_full (size); |
| 692 | MALLOC_PROBE (size); | ||
| 764 | return val; | 693 | return val; |
| 765 | } | 694 | } |
| 766 | 695 | ||
| @@ -776,8 +705,7 @@ xfree (void *block) | |||
| 776 | free (block); | 705 | free (block); |
| 777 | MALLOC_UNBLOCK_INPUT; | 706 | MALLOC_UNBLOCK_INPUT; |
| 778 | /* We don't call refill_memory_reserve here | 707 | /* We don't call refill_memory_reserve here |
| 779 | because that duplicates doing so in emacs_blocked_free | 708 | because in practice the call in r_alloc_free seems to suffice. */ |
| 780 | and the criterion should go there. */ | ||
| 781 | } | 709 | } |
| 782 | 710 | ||
| 783 | 711 | ||
| @@ -824,13 +752,17 @@ xnrealloc (void *pa, ptrdiff_t nitems, ptrdiff_t item_size) | |||
| 824 | infinity. | 752 | infinity. |
| 825 | 753 | ||
| 826 | If PA is null, then allocate a new array instead of reallocating | 754 | If PA is null, then allocate a new array instead of reallocating |
| 827 | the old one. Thus, to grow an array A without saving its old | 755 | the old one. |
| 828 | contents, invoke xfree (A) immediately followed by xgrowalloc (0, | ||
| 829 | &NITEMS, ...). | ||
| 830 | 756 | ||
| 831 | Block interrupt input as needed. If memory exhaustion occurs, set | 757 | Block interrupt input as needed. If memory exhaustion occurs, set |
| 832 | *NITEMS to zero if PA is null, and signal an error (i.e., do not | 758 | *NITEMS to zero if PA is null, and signal an error (i.e., do not |
| 833 | return). */ | 759 | return). |
| 760 | |||
| 761 | Thus, to grow an array A without saving its old contents, do | ||
| 762 | { xfree (A); A = NULL; A = xpalloc (NULL, &AITEMS, ...); }. | ||
| 763 | The A = NULL avoids a dangling pointer if xpalloc exhausts memory | ||
| 764 | and signals an error, and later this code is reexecuted and | ||
| 765 | attempts to free A. */ | ||
| 834 | 766 | ||
| 835 | void * | 767 | void * |
| 836 | xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, | 768 | xpalloc (void *pa, ptrdiff_t *nitems, ptrdiff_t nitems_incr_min, |
| @@ -879,18 +811,22 @@ xstrdup (const char *s) | |||
| 879 | return p; | 811 | return p; |
| 880 | } | 812 | } |
| 881 | 813 | ||
| 814 | /* Like putenv, but (1) use the equivalent of xmalloc and (2) the | ||
| 815 | argument is a const pointer. */ | ||
| 816 | |||
| 817 | void | ||
| 818 | xputenv (char const *string) | ||
| 819 | { | ||
| 820 | if (putenv ((char *) string) != 0) | ||
| 821 | memory_full (0); | ||
| 822 | } | ||
| 882 | 823 | ||
| 883 | /* Unwind for SAFE_ALLOCA */ | 824 | /* Unwind for SAFE_ALLOCA */ |
| 884 | 825 | ||
| 885 | Lisp_Object | 826 | Lisp_Object |
| 886 | safe_alloca_unwind (Lisp_Object arg) | 827 | safe_alloca_unwind (Lisp_Object arg) |
| 887 | { | 828 | { |
| 888 | register struct Lisp_Save_Value *p = XSAVE_VALUE (arg); | 829 | free_save_value (arg); |
| 889 | |||
| 890 | p->dogc = 0; | ||
| 891 | xfree (p->pointer); | ||
| 892 | p->pointer = 0; | ||
| 893 | free_misc (arg); | ||
| 894 | return Qnil; | 830 | return Qnil; |
| 895 | } | 831 | } |
| 896 | 832 | ||
| @@ -951,6 +887,7 @@ lisp_malloc (size_t nbytes, enum mem_type type) | |||
| 951 | MALLOC_UNBLOCK_INPUT; | 887 | MALLOC_UNBLOCK_INPUT; |
| 952 | if (!val && nbytes) | 888 | if (!val && nbytes) |
| 953 | memory_full (nbytes); | 889 | memory_full (nbytes); |
| 890 | MALLOC_PROBE (nbytes); | ||
| 954 | return val; | 891 | return val; |
| 955 | } | 892 | } |
| 956 | 893 | ||
| @@ -1156,6 +1093,8 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1156 | 1093 | ||
| 1157 | MALLOC_UNBLOCK_INPUT; | 1094 | MALLOC_UNBLOCK_INPUT; |
| 1158 | 1095 | ||
| 1096 | MALLOC_PROBE (nbytes); | ||
| 1097 | |||
| 1159 | eassert (0 == ((uintptr_t) val) % BLOCK_ALIGN); | 1098 | eassert (0 == ((uintptr_t) val) % BLOCK_ALIGN); |
| 1160 | return val; | 1099 | return val; |
| 1161 | } | 1100 | } |
| @@ -1204,256 +1143,6 @@ lisp_align_free (void *block) | |||
| 1204 | } | 1143 | } |
| 1205 | 1144 | ||
| 1206 | 1145 | ||
| 1207 | #ifndef SYSTEM_MALLOC | ||
| 1208 | |||
| 1209 | /* Arranging to disable input signals while we're in malloc. | ||
| 1210 | |||
| 1211 | This only works with GNU malloc. To help out systems which can't | ||
| 1212 | use GNU malloc, all the calls to malloc, realloc, and free | ||
| 1213 | elsewhere in the code should be inside a BLOCK_INPUT/UNBLOCK_INPUT | ||
| 1214 | pair; unfortunately, we have no idea what C library functions | ||
| 1215 | might call malloc, so we can't really protect them unless you're | ||
| 1216 | using GNU malloc. Fortunately, most of the major operating systems | ||
| 1217 | can use GNU malloc. */ | ||
| 1218 | |||
| 1219 | #ifndef SYNC_INPUT | ||
| 1220 | /* When using SYNC_INPUT, we don't call malloc from a signal handler, so | ||
| 1221 | there's no need to block input around malloc. */ | ||
| 1222 | |||
| 1223 | #ifndef DOUG_LEA_MALLOC | ||
| 1224 | extern void * (*__malloc_hook) (size_t, const void *); | ||
| 1225 | extern void * (*__realloc_hook) (void *, size_t, const void *); | ||
| 1226 | extern void (*__free_hook) (void *, const void *); | ||
| 1227 | /* Else declared in malloc.h, perhaps with an extra arg. */ | ||
| 1228 | #endif /* DOUG_LEA_MALLOC */ | ||
| 1229 | static void * (*old_malloc_hook) (size_t, const void *); | ||
| 1230 | static void * (*old_realloc_hook) (void *, size_t, const void*); | ||
| 1231 | static void (*old_free_hook) (void*, const void*); | ||
| 1232 | |||
| 1233 | #ifdef DOUG_LEA_MALLOC | ||
| 1234 | # define BYTES_USED (mallinfo ().uordblks) | ||
| 1235 | #else | ||
| 1236 | # define BYTES_USED _bytes_used | ||
| 1237 | #endif | ||
| 1238 | |||
| 1239 | #ifdef GC_MALLOC_CHECK | ||
| 1240 | static bool dont_register_blocks; | ||
| 1241 | #endif | ||
| 1242 | |||
| 1243 | static size_t bytes_used_when_reconsidered; | ||
| 1244 | |||
| 1245 | /* Value of _bytes_used, when spare_memory was freed. */ | ||
| 1246 | |||
| 1247 | static size_t bytes_used_when_full; | ||
| 1248 | |||
| 1249 | /* This function is used as the hook for free to call. */ | ||
| 1250 | |||
| 1251 | static void | ||
| 1252 | emacs_blocked_free (void *ptr, const void *ptr2) | ||
| 1253 | { | ||
| 1254 | BLOCK_INPUT_ALLOC; | ||
| 1255 | |||
| 1256 | #ifdef GC_MALLOC_CHECK | ||
| 1257 | if (ptr) | ||
| 1258 | { | ||
| 1259 | struct mem_node *m; | ||
| 1260 | |||
| 1261 | m = mem_find (ptr); | ||
| 1262 | if (m == MEM_NIL || m->start != ptr) | ||
| 1263 | { | ||
| 1264 | fprintf (stderr, | ||
| 1265 | "Freeing `%p' which wasn't allocated with malloc\n", ptr); | ||
| 1266 | abort (); | ||
| 1267 | } | ||
| 1268 | else | ||
| 1269 | { | ||
| 1270 | /* fprintf (stderr, "free %p...%p (%p)\n", m->start, m->end, ptr); */ | ||
| 1271 | mem_delete (m); | ||
| 1272 | } | ||
| 1273 | } | ||
| 1274 | #endif /* GC_MALLOC_CHECK */ | ||
| 1275 | |||
| 1276 | __free_hook = old_free_hook; | ||
| 1277 | free (ptr); | ||
| 1278 | |||
| 1279 | /* If we released our reserve (due to running out of memory), | ||
| 1280 | and we have a fair amount free once again, | ||
| 1281 | try to set aside another reserve in case we run out once more. */ | ||
| 1282 | if (! NILP (Vmemory_full) | ||
| 1283 | /* Verify there is enough space that even with the malloc | ||
| 1284 | hysteresis this call won't run out again. | ||
| 1285 | The code here is correct as long as SPARE_MEMORY | ||
| 1286 | is substantially larger than the block size malloc uses. */ | ||
| 1287 | && (bytes_used_when_full | ||
| 1288 | > ((bytes_used_when_reconsidered = BYTES_USED) | ||
| 1289 | + max (malloc_hysteresis, 4) * SPARE_MEMORY))) | ||
| 1290 | refill_memory_reserve (); | ||
| 1291 | |||
| 1292 | __free_hook = emacs_blocked_free; | ||
| 1293 | UNBLOCK_INPUT_ALLOC; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | |||
| 1297 | /* This function is the malloc hook that Emacs uses. */ | ||
| 1298 | |||
| 1299 | static void * | ||
| 1300 | emacs_blocked_malloc (size_t size, const void *ptr) | ||
| 1301 | { | ||
| 1302 | void *value; | ||
| 1303 | |||
| 1304 | BLOCK_INPUT_ALLOC; | ||
| 1305 | __malloc_hook = old_malloc_hook; | ||
| 1306 | #ifdef DOUG_LEA_MALLOC | ||
| 1307 | /* Segfaults on my system. --lorentey */ | ||
| 1308 | /* mallopt (M_TOP_PAD, malloc_hysteresis * 4096); */ | ||
| 1309 | #else | ||
| 1310 | __malloc_extra_blocks = malloc_hysteresis; | ||
| 1311 | #endif | ||
| 1312 | |||
| 1313 | value = malloc (size); | ||
| 1314 | |||
| 1315 | #ifdef GC_MALLOC_CHECK | ||
| 1316 | { | ||
| 1317 | struct mem_node *m = mem_find (value); | ||
| 1318 | if (m != MEM_NIL) | ||
| 1319 | { | ||
| 1320 | fprintf (stderr, "Malloc returned %p which is already in use\n", | ||
| 1321 | value); | ||
| 1322 | fprintf (stderr, "Region in use is %p...%p, %td bytes, type %d\n", | ||
| 1323 | m->start, m->end, (char *) m->end - (char *) m->start, | ||
| 1324 | m->type); | ||
| 1325 | abort (); | ||
| 1326 | } | ||
| 1327 | |||
| 1328 | if (!dont_register_blocks) | ||
| 1329 | { | ||
| 1330 | mem_insert (value, (char *) value + max (1, size), allocated_mem_type); | ||
| 1331 | allocated_mem_type = MEM_TYPE_NON_LISP; | ||
| 1332 | } | ||
| 1333 | } | ||
| 1334 | #endif /* GC_MALLOC_CHECK */ | ||
| 1335 | |||
| 1336 | __malloc_hook = emacs_blocked_malloc; | ||
| 1337 | UNBLOCK_INPUT_ALLOC; | ||
| 1338 | |||
| 1339 | /* fprintf (stderr, "%p malloc\n", value); */ | ||
| 1340 | return value; | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | |||
| 1344 | /* This function is the realloc hook that Emacs uses. */ | ||
| 1345 | |||
| 1346 | static void * | ||
| 1347 | emacs_blocked_realloc (void *ptr, size_t size, const void *ptr2) | ||
| 1348 | { | ||
| 1349 | void *value; | ||
| 1350 | |||
| 1351 | BLOCK_INPUT_ALLOC; | ||
| 1352 | __realloc_hook = old_realloc_hook; | ||
| 1353 | |||
| 1354 | #ifdef GC_MALLOC_CHECK | ||
| 1355 | if (ptr) | ||
| 1356 | { | ||
| 1357 | struct mem_node *m = mem_find (ptr); | ||
| 1358 | if (m == MEM_NIL || m->start != ptr) | ||
| 1359 | { | ||
| 1360 | fprintf (stderr, | ||
| 1361 | "Realloc of %p which wasn't allocated with malloc\n", | ||
| 1362 | ptr); | ||
| 1363 | abort (); | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | mem_delete (m); | ||
| 1367 | } | ||
| 1368 | |||
| 1369 | /* fprintf (stderr, "%p -> realloc\n", ptr); */ | ||
| 1370 | |||
| 1371 | /* Prevent malloc from registering blocks. */ | ||
| 1372 | dont_register_blocks = 1; | ||
| 1373 | #endif /* GC_MALLOC_CHECK */ | ||
| 1374 | |||
| 1375 | value = realloc (ptr, size); | ||
| 1376 | |||
| 1377 | #ifdef GC_MALLOC_CHECK | ||
| 1378 | dont_register_blocks = 0; | ||
| 1379 | |||
| 1380 | { | ||
| 1381 | struct mem_node *m = mem_find (value); | ||
| 1382 | if (m != MEM_NIL) | ||
| 1383 | { | ||
| 1384 | fprintf (stderr, "Realloc returns memory that is already in use\n"); | ||
| 1385 | abort (); | ||
| 1386 | } | ||
| 1387 | |||
| 1388 | /* Can't handle zero size regions in the red-black tree. */ | ||
| 1389 | mem_insert (value, (char *) value + max (size, 1), MEM_TYPE_NON_LISP); | ||
| 1390 | } | ||
| 1391 | |||
| 1392 | /* fprintf (stderr, "%p <- realloc\n", value); */ | ||
| 1393 | #endif /* GC_MALLOC_CHECK */ | ||
| 1394 | |||
| 1395 | __realloc_hook = emacs_blocked_realloc; | ||
| 1396 | UNBLOCK_INPUT_ALLOC; | ||
| 1397 | |||
| 1398 | return value; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | |||
| 1402 | #ifdef HAVE_PTHREAD | ||
| 1403 | /* Called from Fdump_emacs so that when the dumped Emacs starts, it has a | ||
| 1404 | normal malloc. Some thread implementations need this as they call | ||
| 1405 | malloc before main. The pthread_self call in BLOCK_INPUT_ALLOC then | ||
| 1406 | calls malloc because it is the first call, and we have an endless loop. */ | ||
| 1407 | |||
| 1408 | void | ||
| 1409 | reset_malloc_hooks (void) | ||
| 1410 | { | ||
| 1411 | __free_hook = old_free_hook; | ||
| 1412 | __malloc_hook = old_malloc_hook; | ||
| 1413 | __realloc_hook = old_realloc_hook; | ||
| 1414 | } | ||
| 1415 | #endif /* HAVE_PTHREAD */ | ||
| 1416 | |||
| 1417 | |||
| 1418 | /* Called from main to set up malloc to use our hooks. */ | ||
| 1419 | |||
| 1420 | void | ||
| 1421 | uninterrupt_malloc (void) | ||
| 1422 | { | ||
| 1423 | #ifdef HAVE_PTHREAD | ||
| 1424 | #ifdef DOUG_LEA_MALLOC | ||
| 1425 | pthread_mutexattr_t attr; | ||
| 1426 | |||
| 1427 | /* GLIBC has a faster way to do this, but let's keep it portable. | ||
| 1428 | This is according to the Single UNIX Specification. */ | ||
| 1429 | pthread_mutexattr_init (&attr); | ||
| 1430 | pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE); | ||
| 1431 | pthread_mutex_init (&alloc_mutex, &attr); | ||
| 1432 | #else /* !DOUG_LEA_MALLOC */ | ||
| 1433 | /* Some systems such as Solaris 2.6 don't have a recursive mutex, | ||
| 1434 | and the bundled gmalloc.c doesn't require it. */ | ||
| 1435 | pthread_mutex_init (&alloc_mutex, NULL); | ||
| 1436 | #endif /* !DOUG_LEA_MALLOC */ | ||
| 1437 | #endif /* HAVE_PTHREAD */ | ||
| 1438 | |||
| 1439 | if (__free_hook != emacs_blocked_free) | ||
| 1440 | old_free_hook = __free_hook; | ||
| 1441 | __free_hook = emacs_blocked_free; | ||
| 1442 | |||
| 1443 | if (__malloc_hook != emacs_blocked_malloc) | ||
| 1444 | old_malloc_hook = __malloc_hook; | ||
| 1445 | __malloc_hook = emacs_blocked_malloc; | ||
| 1446 | |||
| 1447 | if (__realloc_hook != emacs_blocked_realloc) | ||
| 1448 | old_realloc_hook = __realloc_hook; | ||
| 1449 | __realloc_hook = emacs_blocked_realloc; | ||
| 1450 | } | ||
| 1451 | |||
| 1452 | #endif /* not SYNC_INPUT */ | ||
| 1453 | #endif /* not SYSTEM_MALLOC */ | ||
| 1454 | |||
| 1455 | |||
| 1456 | |||
| 1457 | /*********************************************************************** | 1146 | /*********************************************************************** |
| 1458 | Interval Allocation | 1147 | Interval Allocation |
| 1459 | ***********************************************************************/ | 1148 | ***********************************************************************/ |
| @@ -1499,8 +1188,6 @@ make_interval (void) | |||
| 1499 | { | 1188 | { |
| 1500 | INTERVAL val; | 1189 | INTERVAL val; |
| 1501 | 1190 | ||
| 1502 | /* eassert (!handling_signal); */ | ||
| 1503 | |||
| 1504 | MALLOC_BLOCK_INPUT; | 1191 | MALLOC_BLOCK_INPUT; |
| 1505 | 1192 | ||
| 1506 | if (interval_free_list) | 1193 | if (interval_free_list) |
| @@ -1795,7 +1482,7 @@ string_bytes (struct Lisp_String *s) | |||
| 1795 | if (!PURE_POINTER_P (s) | 1482 | if (!PURE_POINTER_P (s) |
| 1796 | && s->data | 1483 | && s->data |
| 1797 | && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) | 1484 | && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) |
| 1798 | abort (); | 1485 | emacs_abort (); |
| 1799 | return nbytes; | 1486 | return nbytes; |
| 1800 | } | 1487 | } |
| 1801 | 1488 | ||
| @@ -1869,7 +1556,7 @@ check_string_free_list (void) | |||
| 1869 | while (s != NULL) | 1556 | while (s != NULL) |
| 1870 | { | 1557 | { |
| 1871 | if ((uintptr_t) s < 1024) | 1558 | if ((uintptr_t) s < 1024) |
| 1872 | abort (); | 1559 | emacs_abort (); |
| 1873 | s = NEXT_FREE_LISP_STRING (s); | 1560 | s = NEXT_FREE_LISP_STRING (s); |
| 1874 | } | 1561 | } |
| 1875 | } | 1562 | } |
| @@ -1884,8 +1571,6 @@ allocate_string (void) | |||
| 1884 | { | 1571 | { |
| 1885 | struct Lisp_String *s; | 1572 | struct Lisp_String *s; |
| 1886 | 1573 | ||
| 1887 | /* eassert (!handling_signal); */ | ||
| 1888 | |||
| 1889 | MALLOC_BLOCK_INPUT; | 1574 | MALLOC_BLOCK_INPUT; |
| 1890 | 1575 | ||
| 1891 | /* If the free-list is empty, allocate a new string_block, and | 1576 | /* If the free-list is empty, allocate a new string_block, and |
| @@ -2098,7 +1783,7 @@ sweep_strings (void) | |||
| 2098 | back-pointer so that we know it's free. */ | 1783 | back-pointer so that we know it's free. */ |
| 2099 | #ifdef GC_CHECK_STRING_BYTES | 1784 | #ifdef GC_CHECK_STRING_BYTES |
| 2100 | if (string_bytes (s) != SDATA_NBYTES (data)) | 1785 | if (string_bytes (s) != SDATA_NBYTES (data)) |
| 2101 | abort (); | 1786 | emacs_abort (); |
| 2102 | #else | 1787 | #else |
| 2103 | data->u.nbytes = STRING_BYTES (s); | 1788 | data->u.nbytes = STRING_BYTES (s); |
| 2104 | #endif | 1789 | #endif |
| @@ -2209,7 +1894,7 @@ compact_small_strings (void) | |||
| 2209 | /* Check that the string size recorded in the string is the | 1894 | /* Check that the string size recorded in the string is the |
| 2210 | same as the one recorded in the sdata structure. */ | 1895 | same as the one recorded in the sdata structure. */ |
| 2211 | if (s && string_bytes (s) != SDATA_NBYTES (from)) | 1896 | if (s && string_bytes (s) != SDATA_NBYTES (from)) |
| 2212 | abort (); | 1897 | emacs_abort (); |
| 2213 | #endif /* GC_CHECK_STRING_BYTES */ | 1898 | #endif /* GC_CHECK_STRING_BYTES */ |
| 2214 | 1899 | ||
| 2215 | nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from); | 1900 | nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from); |
| @@ -2222,7 +1907,7 @@ compact_small_strings (void) | |||
| 2222 | if (memcmp (string_overrun_cookie, | 1907 | if (memcmp (string_overrun_cookie, |
| 2223 | (char *) from_end - GC_STRING_OVERRUN_COOKIE_SIZE, | 1908 | (char *) from_end - GC_STRING_OVERRUN_COOKIE_SIZE, |
| 2224 | GC_STRING_OVERRUN_COOKIE_SIZE)) | 1909 | GC_STRING_OVERRUN_COOKIE_SIZE)) |
| 2225 | abort (); | 1910 | emacs_abort (); |
| 2226 | #endif | 1911 | #endif |
| 2227 | 1912 | ||
| 2228 | /* Non-NULL S means it's alive. Copy its data. */ | 1913 | /* Non-NULL S means it's alive. Copy its data. */ |
| @@ -2342,7 +2027,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2342 | val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); | 2027 | val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); |
| 2343 | 2028 | ||
| 2344 | /* No Lisp_Object to trace in there. */ | 2029 | /* No Lisp_Object to trace in there. */ |
| 2345 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0); | 2030 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2346 | 2031 | ||
| 2347 | p = XBOOL_VECTOR (val); | 2032 | p = XBOOL_VECTOR (val); |
| 2348 | p->size = XFASTINT (length); | 2033 | p->size = XFASTINT (length); |
| @@ -2479,7 +2164,7 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | |||
| 2479 | struct Lisp_String *s; | 2164 | struct Lisp_String *s; |
| 2480 | 2165 | ||
| 2481 | if (nchars < 0) | 2166 | if (nchars < 0) |
| 2482 | abort (); | 2167 | emacs_abort (); |
| 2483 | if (!nbytes) | 2168 | if (!nbytes) |
| 2484 | return empty_multibyte_string; | 2169 | return empty_multibyte_string; |
| 2485 | 2170 | ||
| @@ -2577,8 +2262,6 @@ make_float (double float_value) | |||
| 2577 | { | 2262 | { |
| 2578 | register Lisp_Object val; | 2263 | register Lisp_Object val; |
| 2579 | 2264 | ||
| 2580 | /* eassert (!handling_signal); */ | ||
| 2581 | |||
| 2582 | MALLOC_BLOCK_INPUT; | 2265 | MALLOC_BLOCK_INPUT; |
| 2583 | 2266 | ||
| 2584 | if (float_free_list) | 2267 | if (float_free_list) |
| @@ -2686,8 +2369,6 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2686 | { | 2369 | { |
| 2687 | register Lisp_Object val; | 2370 | register Lisp_Object val; |
| 2688 | 2371 | ||
| 2689 | /* eassert (!handling_signal); */ | ||
| 2690 | |||
| 2691 | MALLOC_BLOCK_INPUT; | 2372 | MALLOC_BLOCK_INPUT; |
| 2692 | 2373 | ||
| 2693 | if (cons_free_list) | 2374 | if (cons_free_list) |
| @@ -2800,7 +2481,7 @@ listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...) | |||
| 2800 | else if (type == CONSTYPE_HEAP) | 2481 | else if (type == CONSTYPE_HEAP) |
| 2801 | val = Fcons (objp[i], val); | 2482 | val = Fcons (objp[i], val); |
| 2802 | else | 2483 | else |
| 2803 | abort (); | 2484 | emacs_abort (); |
| 2804 | } | 2485 | } |
| 2805 | return val; | 2486 | return val; |
| 2806 | } | 2487 | } |
| @@ -2925,19 +2606,54 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2925 | 2606 | ||
| 2926 | #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size) | 2607 | #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size) |
| 2927 | 2608 | ||
| 2609 | /* Get and set the next field in block-allocated vectorlike objects on | ||
| 2610 | the free list. Doing it this way respects C's aliasing rules. | ||
| 2611 | We could instead make 'contents' a union, but that would mean | ||
| 2612 | changes everywhere that the code uses 'contents'. */ | ||
| 2613 | static struct Lisp_Vector * | ||
| 2614 | next_in_free_list (struct Lisp_Vector *v) | ||
| 2615 | { | ||
| 2616 | intptr_t i = XLI (v->contents[0]); | ||
| 2617 | return (struct Lisp_Vector *) i; | ||
| 2618 | } | ||
| 2619 | static void | ||
| 2620 | set_next_in_free_list (struct Lisp_Vector *v, struct Lisp_Vector *next) | ||
| 2621 | { | ||
| 2622 | v->contents[0] = XIL ((intptr_t) next); | ||
| 2623 | } | ||
| 2624 | |||
| 2928 | /* Common shortcut to setup vector on a free list. */ | 2625 | /* Common shortcut to setup vector on a free list. */ |
| 2929 | 2626 | ||
| 2930 | #define SETUP_ON_FREE_LIST(v, nbytes, index) \ | 2627 | #define SETUP_ON_FREE_LIST(v, nbytes, tmp) \ |
| 2931 | do { \ | 2628 | do { \ |
| 2932 | XSETPVECTYPESIZE (v, PVEC_FREE, nbytes); \ | 2629 | (tmp) = ((nbytes - header_size) / word_size); \ |
| 2933 | eassert ((nbytes) % roundup_size == 0); \ | 2630 | XSETPVECTYPESIZE (v, PVEC_FREE, 0, (tmp)); \ |
| 2934 | (index) = VINDEX (nbytes); \ | 2631 | eassert ((nbytes) % roundup_size == 0); \ |
| 2935 | eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ | 2632 | (tmp) = VINDEX (nbytes); \ |
| 2936 | (v)->header.next.vector = vector_free_lists[index]; \ | 2633 | eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \ |
| 2937 | vector_free_lists[index] = (v); \ | 2634 | set_next_in_free_list (v, vector_free_lists[tmp]); \ |
| 2938 | total_free_vector_slots += (nbytes) / word_size; \ | 2635 | vector_free_lists[tmp] = (v); \ |
| 2636 | total_free_vector_slots += (nbytes) / word_size; \ | ||
| 2939 | } while (0) | 2637 | } while (0) |
| 2940 | 2638 | ||
| 2639 | /* This internal type is used to maintain the list of large vectors | ||
| 2640 | which are allocated at their own, e.g. outside of vector blocks. */ | ||
| 2641 | |||
| 2642 | struct large_vector | ||
| 2643 | { | ||
| 2644 | union { | ||
| 2645 | struct large_vector *vector; | ||
| 2646 | #if USE_LSB_TAG | ||
| 2647 | /* We need to maintain ROUNDUP_SIZE alignment for the vector member. */ | ||
| 2648 | unsigned char c[vroundup (sizeof (struct large_vector *))]; | ||
| 2649 | #endif | ||
| 2650 | } next; | ||
| 2651 | struct Lisp_Vector v; | ||
| 2652 | }; | ||
| 2653 | |||
| 2654 | /* This internal type is used to maintain an underlying storage | ||
| 2655 | for small vectors. */ | ||
| 2656 | |||
| 2941 | struct vector_block | 2657 | struct vector_block |
| 2942 | { | 2658 | { |
| 2943 | char data[VECTOR_BLOCK_BYTES]; | 2659 | char data[VECTOR_BLOCK_BYTES]; |
| @@ -2955,7 +2671,7 @@ static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX]; | |||
| 2955 | 2671 | ||
| 2956 | /* Singly-linked list of large vectors. */ | 2672 | /* Singly-linked list of large vectors. */ |
| 2957 | 2673 | ||
| 2958 | static struct Lisp_Vector *large_vectors; | 2674 | static struct large_vector *large_vectors; |
| 2959 | 2675 | ||
| 2960 | /* The only vector with 0 slots, allocated from pure space. */ | 2676 | /* The only vector with 0 slots, allocated from pure space. */ |
| 2961 | 2677 | ||
| @@ -2999,7 +2715,7 @@ init_vectors (void) | |||
| 2999 | static struct Lisp_Vector * | 2715 | static struct Lisp_Vector * |
| 3000 | allocate_vector_from_block (size_t nbytes) | 2716 | allocate_vector_from_block (size_t nbytes) |
| 3001 | { | 2717 | { |
| 3002 | struct Lisp_Vector *vector, *rest; | 2718 | struct Lisp_Vector *vector; |
| 3003 | struct vector_block *block; | 2719 | struct vector_block *block; |
| 3004 | size_t index, restbytes; | 2720 | size_t index, restbytes; |
| 3005 | 2721 | ||
| @@ -3012,8 +2728,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3012 | if (vector_free_lists[index]) | 2728 | if (vector_free_lists[index]) |
| 3013 | { | 2729 | { |
| 3014 | vector = vector_free_lists[index]; | 2730 | vector = vector_free_lists[index]; |
| 3015 | vector_free_lists[index] = vector->header.next.vector; | 2731 | vector_free_lists[index] = next_in_free_list (vector); |
| 3016 | vector->header.next.nbytes = nbytes; | ||
| 3017 | total_free_vector_slots -= nbytes / word_size; | 2732 | total_free_vector_slots -= nbytes / word_size; |
| 3018 | return vector; | 2733 | return vector; |
| 3019 | } | 2734 | } |
| @@ -3027,16 +2742,14 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3027 | { | 2742 | { |
| 3028 | /* This vector is larger than requested. */ | 2743 | /* This vector is larger than requested. */ |
| 3029 | vector = vector_free_lists[index]; | 2744 | vector = vector_free_lists[index]; |
| 3030 | vector_free_lists[index] = vector->header.next.vector; | 2745 | vector_free_lists[index] = next_in_free_list (vector); |
| 3031 | vector->header.next.nbytes = nbytes; | ||
| 3032 | total_free_vector_slots -= nbytes / word_size; | 2746 | total_free_vector_slots -= nbytes / word_size; |
| 3033 | 2747 | ||
| 3034 | /* Excess bytes are used for the smaller vector, | 2748 | /* Excess bytes are used for the smaller vector, |
| 3035 | which should be set on an appropriate free list. */ | 2749 | which should be set on an appropriate free list. */ |
| 3036 | restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; | 2750 | restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; |
| 3037 | eassert (restbytes % roundup_size == 0); | 2751 | eassert (restbytes % roundup_size == 0); |
| 3038 | rest = ADVANCE (vector, nbytes); | 2752 | SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index); |
| 3039 | SETUP_ON_FREE_LIST (rest, restbytes, index); | ||
| 3040 | return vector; | 2753 | return vector; |
| 3041 | } | 2754 | } |
| 3042 | 2755 | ||
| @@ -3045,7 +2758,6 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3045 | 2758 | ||
| 3046 | /* New vector will be at the beginning of this block. */ | 2759 | /* New vector will be at the beginning of this block. */ |
| 3047 | vector = (struct Lisp_Vector *) block->data; | 2760 | vector = (struct Lisp_Vector *) block->data; |
| 3048 | vector->header.next.nbytes = nbytes; | ||
| 3049 | 2761 | ||
| 3050 | /* If the rest of space from this block is large enough | 2762 | /* If the rest of space from this block is large enough |
| 3051 | for one-slot vector at least, set up it on a free list. */ | 2763 | for one-slot vector at least, set up it on a free list. */ |
| @@ -3053,11 +2765,10 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3053 | if (restbytes >= VBLOCK_BYTES_MIN) | 2765 | if (restbytes >= VBLOCK_BYTES_MIN) |
| 3054 | { | 2766 | { |
| 3055 | eassert (restbytes % roundup_size == 0); | 2767 | eassert (restbytes % roundup_size == 0); |
| 3056 | rest = ADVANCE (vector, nbytes); | 2768 | SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index); |
| 3057 | SETUP_ON_FREE_LIST (rest, restbytes, index); | ||
| 3058 | } | 2769 | } |
| 3059 | return vector; | 2770 | return vector; |
| 3060 | } | 2771 | } |
| 3061 | 2772 | ||
| 3062 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ | 2773 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ |
| 3063 | 2774 | ||
| @@ -3065,15 +2776,30 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3065 | ((char *) (vector) <= (block)->data \ | 2776 | ((char *) (vector) <= (block)->data \ |
| 3066 | + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) | 2777 | + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) |
| 3067 | 2778 | ||
| 3068 | /* Number of bytes used by vector-block-allocated object. This is the only | 2779 | /* Return the memory footprint of V in bytes. */ |
| 3069 | place where we actually use the `nbytes' field of the vector-header. | ||
| 3070 | I.e. we could get rid of the `nbytes' field by computing it based on the | ||
| 3071 | vector-type. */ | ||
| 3072 | 2780 | ||
| 3073 | #define PSEUDOVECTOR_NBYTES(vector) \ | 2781 | static ptrdiff_t |
| 3074 | (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \ | 2782 | vector_nbytes (struct Lisp_Vector *v) |
| 3075 | ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \ | 2783 | { |
| 3076 | : vector->header.next.nbytes) | 2784 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; |
| 2785 | |||
| 2786 | if (size & PSEUDOVECTOR_FLAG) | ||
| 2787 | { | ||
| 2788 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) | ||
| 2789 | size = (bool_header_size | ||
| 2790 | + (((struct Lisp_Bool_Vector *) v)->size | ||
| 2791 | + BOOL_VECTOR_BITS_PER_CHAR - 1) | ||
| 2792 | / BOOL_VECTOR_BITS_PER_CHAR); | ||
| 2793 | else | ||
| 2794 | size = (header_size | ||
| 2795 | + ((size & PSEUDOVECTOR_SIZE_MASK) | ||
| 2796 | + ((size & PSEUDOVECTOR_REST_MASK) | ||
| 2797 | >> PSEUDOVECTOR_SIZE_BITS)) * word_size); | ||
| 2798 | } | ||
| 2799 | else | ||
| 2800 | size = header_size + size * word_size; | ||
| 2801 | return vroundup (size); | ||
| 2802 | } | ||
| 3077 | 2803 | ||
| 3078 | /* Reclaim space used by unmarked vectors. */ | 2804 | /* Reclaim space used by unmarked vectors. */ |
| 3079 | 2805 | ||
| @@ -3081,7 +2807,8 @@ static void | |||
| 3081 | sweep_vectors (void) | 2807 | sweep_vectors (void) |
| 3082 | { | 2808 | { |
| 3083 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; | 2809 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; |
| 3084 | struct Lisp_Vector *vector, *next, **vprev = &large_vectors; | 2810 | struct large_vector *lv, **lvprev = &large_vectors; |
| 2811 | struct Lisp_Vector *vector, *next; | ||
| 3085 | 2812 | ||
| 3086 | total_vectors = total_vector_slots = total_free_vector_slots = 0; | 2813 | total_vectors = total_vector_slots = total_free_vector_slots = 0; |
| 3087 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); | 2814 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); |
| @@ -3091,6 +2818,7 @@ sweep_vectors (void) | |||
| 3091 | for (block = vector_blocks; block; block = *bprev) | 2818 | for (block = vector_blocks; block; block = *bprev) |
| 3092 | { | 2819 | { |
| 3093 | bool free_this_block = 0; | 2820 | bool free_this_block = 0; |
| 2821 | ptrdiff_t nbytes; | ||
| 3094 | 2822 | ||
| 3095 | for (vector = (struct Lisp_Vector *) block->data; | 2823 | for (vector = (struct Lisp_Vector *) block->data; |
| 3096 | VECTOR_IN_BLOCK (vector, block); vector = next) | 2824 | VECTOR_IN_BLOCK (vector, block); vector = next) |
| @@ -3099,13 +2827,13 @@ sweep_vectors (void) | |||
| 3099 | { | 2827 | { |
| 3100 | VECTOR_UNMARK (vector); | 2828 | VECTOR_UNMARK (vector); |
| 3101 | total_vectors++; | 2829 | total_vectors++; |
| 3102 | total_vector_slots += vector->header.next.nbytes / word_size; | 2830 | nbytes = vector_nbytes (vector); |
| 3103 | next = ADVANCE (vector, vector->header.next.nbytes); | 2831 | total_vector_slots += nbytes / word_size; |
| 2832 | next = ADVANCE (vector, nbytes); | ||
| 3104 | } | 2833 | } |
| 3105 | else | 2834 | else |
| 3106 | { | 2835 | { |
| 3107 | ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector); | 2836 | ptrdiff_t total_bytes; |
| 3108 | ptrdiff_t total_bytes = nbytes; | ||
| 3109 | 2837 | ||
| 3110 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD)) | 2838 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_THREAD)) |
| 3111 | finalize_one_thread ((struct thread_state *) vector); | 2839 | finalize_one_thread ((struct thread_state *) vector); |
| @@ -3114,6 +2842,8 @@ sweep_vectors (void) | |||
| 3114 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR)) | 2842 | else if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_CONDVAR)) |
| 3115 | finalize_one_condvar ((struct Lisp_CondVar *) vector); | 2843 | finalize_one_condvar ((struct Lisp_CondVar *) vector); |
| 3116 | 2844 | ||
| 2845 | nbytes = vector_nbytes (vector); | ||
| 2846 | total_bytes = nbytes; | ||
| 3117 | next = ADVANCE (vector, nbytes); | 2847 | next = ADVANCE (vector, nbytes); |
| 3118 | 2848 | ||
| 3119 | /* While NEXT is not marked, try to coalesce with VECTOR, | 2849 | /* While NEXT is not marked, try to coalesce with VECTOR, |
| @@ -3123,7 +2853,7 @@ sweep_vectors (void) | |||
| 3123 | { | 2853 | { |
| 3124 | if (VECTOR_MARKED_P (next)) | 2854 | if (VECTOR_MARKED_P (next)) |
| 3125 | break; | 2855 | break; |
| 3126 | nbytes = PSEUDOVECTOR_NBYTES (next); | 2856 | nbytes = vector_nbytes (next); |
| 3127 | total_bytes += nbytes; | 2857 | total_bytes += nbytes; |
| 3128 | next = ADVANCE (next, nbytes); | 2858 | next = ADVANCE (next, nbytes); |
| 3129 | } | 2859 | } |
| @@ -3157,8 +2887,9 @@ sweep_vectors (void) | |||
| 3157 | 2887 | ||
| 3158 | /* Sweep large vectors. */ | 2888 | /* Sweep large vectors. */ |
| 3159 | 2889 | ||
| 3160 | for (vector = large_vectors; vector; vector = *vprev) | 2890 | for (lv = large_vectors; lv; lv = *lvprev) |
| 3161 | { | 2891 | { |
| 2892 | vector = &lv->v; | ||
| 3162 | if (VECTOR_MARKED_P (vector)) | 2893 | if (VECTOR_MARKED_P (vector)) |
| 3163 | { | 2894 | { |
| 3164 | VECTOR_UNMARK (vector); | 2895 | VECTOR_UNMARK (vector); |
| @@ -3180,12 +2911,12 @@ sweep_vectors (void) | |||
| 3180 | else | 2911 | else |
| 3181 | total_vector_slots | 2912 | total_vector_slots |
| 3182 | += header_size / word_size + vector->header.size; | 2913 | += header_size / word_size + vector->header.size; |
| 3183 | vprev = &vector->header.next.vector; | 2914 | lvprev = &lv->next.vector; |
| 3184 | } | 2915 | } |
| 3185 | else | 2916 | else |
| 3186 | { | 2917 | { |
| 3187 | *vprev = vector->header.next.vector; | 2918 | *lvprev = lv->next.vector; |
| 3188 | lisp_free (vector); | 2919 | lisp_free (lv); |
| 3189 | } | 2920 | } |
| 3190 | } | 2921 | } |
| 3191 | } | 2922 | } |
| @@ -3200,9 +2931,6 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 3200 | 2931 | ||
| 3201 | MALLOC_BLOCK_INPUT; | 2932 | MALLOC_BLOCK_INPUT; |
| 3202 | 2933 | ||
| 3203 | /* This gets triggered by code which I haven't bothered to fix. --Stef */ | ||
| 3204 | /* eassert (!handling_signal); */ | ||
| 3205 | |||
| 3206 | if (len == 0) | 2934 | if (len == 0) |
| 3207 | p = XVECTOR (zero_vector); | 2935 | p = XVECTOR (zero_vector); |
| 3208 | else | 2936 | else |
| @@ -3220,9 +2948,12 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 3220 | p = allocate_vector_from_block (vroundup (nbytes)); | 2948 | p = allocate_vector_from_block (vroundup (nbytes)); |
| 3221 | else | 2949 | else |
| 3222 | { | 2950 | { |
| 3223 | p = lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); | 2951 | struct large_vector *lv |
| 3224 | p->header.next.vector = large_vectors; | 2952 | = lisp_malloc (sizeof (*lv) + (len - 1) * word_size, |
| 3225 | large_vectors = p; | 2953 | MEM_TYPE_VECTORLIKE); |
| 2954 | lv->next.vector = large_vectors; | ||
| 2955 | large_vectors = lv; | ||
| 2956 | p = &lv->v; | ||
| 3226 | } | 2957 | } |
| 3227 | 2958 | ||
| 3228 | #ifdef DOUG_LEA_MALLOC | 2959 | #ifdef DOUG_LEA_MALLOC |
| @@ -3259,16 +2990,21 @@ allocate_vector (EMACS_INT len) | |||
| 3259 | /* Allocate other vector-like structures. */ | 2990 | /* Allocate other vector-like structures. */ |
| 3260 | 2991 | ||
| 3261 | struct Lisp_Vector * | 2992 | struct Lisp_Vector * |
| 3262 | allocate_pseudovector (int memlen, int lisplen, int tag) | 2993 | allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag) |
| 3263 | { | 2994 | { |
| 3264 | struct Lisp_Vector *v = allocate_vectorlike (memlen); | 2995 | struct Lisp_Vector *v = allocate_vectorlike (memlen); |
| 3265 | int i; | 2996 | int i; |
| 3266 | 2997 | ||
| 2998 | /* Catch bogus values. */ | ||
| 2999 | eassert (tag <= PVEC_FONT); | ||
| 3000 | eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1); | ||
| 3001 | eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1); | ||
| 3002 | |||
| 3267 | /* Only the first lisplen slots will be traced normally by the GC. */ | 3003 | /* Only the first lisplen slots will be traced normally by the GC. */ |
| 3268 | for (i = 0; i < lisplen; ++i) | 3004 | for (i = 0; i < lisplen; ++i) |
| 3269 | v->contents[i] = Qnil; | 3005 | v->contents[i] = Qnil; |
| 3270 | 3006 | ||
| 3271 | XSETPVECTYPESIZE (v, tag, lisplen); | 3007 | XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen); |
| 3272 | return v; | 3008 | return v; |
| 3273 | } | 3009 | } |
| 3274 | 3010 | ||
| @@ -3277,9 +3013,11 @@ allocate_buffer (void) | |||
| 3277 | { | 3013 | { |
| 3278 | struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER); | 3014 | struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER); |
| 3279 | 3015 | ||
| 3280 | XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text) | 3016 | BUFFER_PVEC_INIT (b); |
| 3281 | - header_size) / word_size); | 3017 | /* Put B on the chain of all buffers including killed ones. */ |
| 3282 | /* Note that the fields of B are not initialized. */ | 3018 | b->next = all_buffers; |
| 3019 | all_buffers = b; | ||
| 3020 | /* Note that the rest fields of B are not initialized. */ | ||
| 3283 | return b; | 3021 | return b; |
| 3284 | } | 3022 | } |
| 3285 | 3023 | ||
| @@ -3413,7 +3151,7 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3413 | ptrdiff_t i; | 3151 | ptrdiff_t i; |
| 3414 | register struct Lisp_Vector *p; | 3152 | register struct Lisp_Vector *p; |
| 3415 | 3153 | ||
| 3416 | /* We used to purecopy everything here, if purify-flga was set. This worked | 3154 | /* We used to purecopy everything here, if purify-flag was set. This worked |
| 3417 | OK for Emacs-23, but with Emacs-24's lexical binding code, it can be | 3155 | OK for Emacs-23, but with Emacs-24's lexical binding code, it can be |
| 3418 | dangerous, since make-byte-code is used during execution to build | 3156 | dangerous, since make-byte-code is used during execution to build |
| 3419 | closures, so any closure built during the preload phase would end up | 3157 | closures, so any closure built during the preload phase would end up |
| @@ -3476,7 +3214,7 @@ static struct Lisp_Symbol *symbol_free_list; | |||
| 3476 | 3214 | ||
| 3477 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, | 3215 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, |
| 3478 | doc: /* Return a newly allocated uninterned symbol whose name is NAME. | 3216 | doc: /* Return a newly allocated uninterned symbol whose name is NAME. |
| 3479 | Its value and function definition are void, and its property list is nil. */) | 3217 | Its value is void, and its function definition and property list are nil. */) |
| 3480 | (Lisp_Object name) | 3218 | (Lisp_Object name) |
| 3481 | { | 3219 | { |
| 3482 | register Lisp_Object val; | 3220 | register Lisp_Object val; |
| @@ -3484,8 +3222,6 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3484 | 3222 | ||
| 3485 | CHECK_STRING (name); | 3223 | CHECK_STRING (name); |
| 3486 | 3224 | ||
| 3487 | /* eassert (!handling_signal); */ | ||
| 3488 | |||
| 3489 | MALLOC_BLOCK_INPUT; | 3225 | MALLOC_BLOCK_INPUT; |
| 3490 | 3226 | ||
| 3491 | if (symbol_free_list) | 3227 | if (symbol_free_list) |
| @@ -3515,7 +3251,7 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3515 | set_symbol_plist (val, Qnil); | 3251 | set_symbol_plist (val, Qnil); |
| 3516 | p->redirect = SYMBOL_PLAINVAL; | 3252 | p->redirect = SYMBOL_PLAINVAL; |
| 3517 | SET_SYMBOL_VAL (p, Qunbound); | 3253 | SET_SYMBOL_VAL (p, Qunbound); |
| 3518 | set_symbol_function (val, Qunbound); | 3254 | set_symbol_function (val, Qnil); |
| 3519 | set_symbol_next (val, NULL); | 3255 | set_symbol_next (val, NULL); |
| 3520 | p->gcmarkbit = 0; | 3256 | p->gcmarkbit = 0; |
| 3521 | p->interned = SYMBOL_UNINTERNED; | 3257 | p->interned = SYMBOL_UNINTERNED; |
| @@ -3570,8 +3306,6 @@ allocate_misc (enum Lisp_Misc_Type type) | |||
| 3570 | { | 3306 | { |
| 3571 | Lisp_Object val; | 3307 | Lisp_Object val; |
| 3572 | 3308 | ||
| 3573 | /* eassert (!handling_signal); */ | ||
| 3574 | |||
| 3575 | MALLOC_BLOCK_INPUT; | 3309 | MALLOC_BLOCK_INPUT; |
| 3576 | 3310 | ||
| 3577 | if (marker_free_list) | 3311 | if (marker_free_list) |
| @@ -3633,6 +3367,19 @@ make_save_value (void *pointer, ptrdiff_t integer) | |||
| 3633 | return val; | 3367 | return val; |
| 3634 | } | 3368 | } |
| 3635 | 3369 | ||
| 3370 | /* Free a Lisp_Misc_Save_Value object. */ | ||
| 3371 | |||
| 3372 | void | ||
| 3373 | free_save_value (Lisp_Object save) | ||
| 3374 | { | ||
| 3375 | register struct Lisp_Save_Value *p = XSAVE_VALUE (save); | ||
| 3376 | |||
| 3377 | p->dogc = 0; | ||
| 3378 | xfree (p->pointer); | ||
| 3379 | p->pointer = NULL; | ||
| 3380 | free_misc (save); | ||
| 3381 | } | ||
| 3382 | |||
| 3636 | /* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */ | 3383 | /* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */ |
| 3637 | 3384 | ||
| 3638 | Lisp_Object | 3385 | Lisp_Object |
| @@ -3675,7 +3422,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) | |||
| 3675 | struct Lisp_Marker *m; | 3422 | struct Lisp_Marker *m; |
| 3676 | 3423 | ||
| 3677 | /* No dead buffers here. */ | 3424 | /* No dead buffers here. */ |
| 3678 | eassert (!NILP (BVAR (buf, name))); | 3425 | eassert (BUFFER_LIVE_P (buf)); |
| 3679 | 3426 | ||
| 3680 | /* Every character is at least one byte. */ | 3427 | /* Every character is at least one byte. */ |
| 3681 | eassert (charpos <= bytepos); | 3428 | eassert (charpos <= bytepos); |
| @@ -3791,12 +3538,6 @@ memory_full (size_t nbytes) | |||
| 3791 | lisp_free (spare_memory[i]); | 3538 | lisp_free (spare_memory[i]); |
| 3792 | spare_memory[i] = 0; | 3539 | spare_memory[i] = 0; |
| 3793 | } | 3540 | } |
| 3794 | |||
| 3795 | /* Record the space now used. When it decreases substantially, | ||
| 3796 | we can refill the memory reserve. */ | ||
| 3797 | #if !defined SYSTEM_MALLOC && !defined SYNC_INPUT | ||
| 3798 | bytes_used_when_full = BYTES_USED; | ||
| 3799 | #endif | ||
| 3800 | } | 3541 | } |
| 3801 | 3542 | ||
| 3802 | /* This used to call error, but if we've run out of memory, we could | 3543 | /* This used to call error, but if we've run out of memory, we could |
| @@ -3873,7 +3614,7 @@ mem_init (void) | |||
| 3873 | /* Value is a pointer to the mem_node containing START. Value is | 3614 | /* Value is a pointer to the mem_node containing START. Value is |
| 3874 | MEM_NIL if there is no node in the tree containing START. */ | 3615 | MEM_NIL if there is no node in the tree containing START. */ |
| 3875 | 3616 | ||
| 3876 | static inline struct mem_node * | 3617 | static struct mem_node * |
| 3877 | mem_find (void *start) | 3618 | mem_find (void *start) |
| 3878 | { | 3619 | { |
| 3879 | struct mem_node *p; | 3620 | struct mem_node *p; |
| @@ -3917,7 +3658,7 @@ mem_insert (void *start, void *end, enum mem_type type) | |||
| 3917 | while (c != MEM_NIL) | 3658 | while (c != MEM_NIL) |
| 3918 | { | 3659 | { |
| 3919 | if (start >= c->start && start < c->end) | 3660 | if (start >= c->start && start < c->end) |
| 3920 | abort (); | 3661 | emacs_abort (); |
| 3921 | parent = c; | 3662 | parent = c; |
| 3922 | c = start < c->start ? c->left : c->right; | 3663 | c = start < c->start ? c->left : c->right; |
| 3923 | } | 3664 | } |
| @@ -3934,9 +3675,9 @@ mem_insert (void *start, void *end, enum mem_type type) | |||
| 3934 | 3675 | ||
| 3935 | /* Create a new node. */ | 3676 | /* Create a new node. */ |
| 3936 | #ifdef GC_MALLOC_CHECK | 3677 | #ifdef GC_MALLOC_CHECK |
| 3937 | x = _malloc_internal (sizeof *x); | 3678 | x = malloc (sizeof *x); |
| 3938 | if (x == NULL) | 3679 | if (x == NULL) |
| 3939 | abort (); | 3680 | emacs_abort (); |
| 3940 | #else | 3681 | #else |
| 3941 | x = xmalloc (sizeof *x); | 3682 | x = xmalloc (sizeof *x); |
| 3942 | #endif | 3683 | #endif |
| @@ -4158,7 +3899,7 @@ mem_delete (struct mem_node *z) | |||
| 4158 | mem_delete_fixup (x); | 3899 | mem_delete_fixup (x); |
| 4159 | 3900 | ||
| 4160 | #ifdef GC_MALLOC_CHECK | 3901 | #ifdef GC_MALLOC_CHECK |
| 4161 | _free_internal (y); | 3902 | free (y); |
| 4162 | #else | 3903 | #else |
| 4163 | xfree (y); | 3904 | xfree (y); |
| 4164 | #endif | 3905 | #endif |
| @@ -4249,7 +3990,7 @@ mem_delete_fixup (struct mem_node *x) | |||
| 4249 | /* Value is non-zero if P is a pointer to a live Lisp string on | 3990 | /* Value is non-zero if P is a pointer to a live Lisp string on |
| 4250 | the heap. M is a pointer to the mem_block for P. */ | 3991 | the heap. M is a pointer to the mem_block for P. */ |
| 4251 | 3992 | ||
| 4252 | static inline bool | 3993 | static bool |
| 4253 | live_string_p (struct mem_node *m, void *p) | 3994 | live_string_p (struct mem_node *m, void *p) |
| 4254 | { | 3995 | { |
| 4255 | if (m->type == MEM_TYPE_STRING) | 3996 | if (m->type == MEM_TYPE_STRING) |
| @@ -4272,7 +4013,7 @@ live_string_p (struct mem_node *m, void *p) | |||
| 4272 | /* Value is non-zero if P is a pointer to a live Lisp cons on | 4013 | /* Value is non-zero if P is a pointer to a live Lisp cons on |
| 4273 | the heap. M is a pointer to the mem_block for P. */ | 4014 | the heap. M is a pointer to the mem_block for P. */ |
| 4274 | 4015 | ||
| 4275 | static inline bool | 4016 | static bool |
| 4276 | live_cons_p (struct mem_node *m, void *p) | 4017 | live_cons_p (struct mem_node *m, void *p) |
| 4277 | { | 4018 | { |
| 4278 | if (m->type == MEM_TYPE_CONS) | 4019 | if (m->type == MEM_TYPE_CONS) |
| @@ -4298,7 +4039,7 @@ live_cons_p (struct mem_node *m, void *p) | |||
| 4298 | /* Value is non-zero if P is a pointer to a live Lisp symbol on | 4039 | /* Value is non-zero if P is a pointer to a live Lisp symbol on |
| 4299 | the heap. M is a pointer to the mem_block for P. */ | 4040 | the heap. M is a pointer to the mem_block for P. */ |
| 4300 | 4041 | ||
| 4301 | static inline bool | 4042 | static bool |
| 4302 | live_symbol_p (struct mem_node *m, void *p) | 4043 | live_symbol_p (struct mem_node *m, void *p) |
| 4303 | { | 4044 | { |
| 4304 | if (m->type == MEM_TYPE_SYMBOL) | 4045 | if (m->type == MEM_TYPE_SYMBOL) |
| @@ -4324,7 +4065,7 @@ live_symbol_p (struct mem_node *m, void *p) | |||
| 4324 | /* Value is non-zero if P is a pointer to a live Lisp float on | 4065 | /* Value is non-zero if P is a pointer to a live Lisp float on |
| 4325 | the heap. M is a pointer to the mem_block for P. */ | 4066 | the heap. M is a pointer to the mem_block for P. */ |
| 4326 | 4067 | ||
| 4327 | static inline bool | 4068 | static bool |
| 4328 | live_float_p (struct mem_node *m, void *p) | 4069 | live_float_p (struct mem_node *m, void *p) |
| 4329 | { | 4070 | { |
| 4330 | if (m->type == MEM_TYPE_FLOAT) | 4071 | if (m->type == MEM_TYPE_FLOAT) |
| @@ -4348,7 +4089,7 @@ live_float_p (struct mem_node *m, void *p) | |||
| 4348 | /* Value is non-zero if P is a pointer to a live Lisp Misc on | 4089 | /* Value is non-zero if P is a pointer to a live Lisp Misc on |
| 4349 | the heap. M is a pointer to the mem_block for P. */ | 4090 | the heap. M is a pointer to the mem_block for P. */ |
| 4350 | 4091 | ||
| 4351 | static inline bool | 4092 | static bool |
| 4352 | live_misc_p (struct mem_node *m, void *p) | 4093 | live_misc_p (struct mem_node *m, void *p) |
| 4353 | { | 4094 | { |
| 4354 | if (m->type == MEM_TYPE_MISC) | 4095 | if (m->type == MEM_TYPE_MISC) |
| @@ -4374,7 +4115,7 @@ live_misc_p (struct mem_node *m, void *p) | |||
| 4374 | /* Value is non-zero if P is a pointer to a live vector-like object. | 4115 | /* Value is non-zero if P is a pointer to a live vector-like object. |
| 4375 | M is a pointer to the mem_block for P. */ | 4116 | M is a pointer to the mem_block for P. */ |
| 4376 | 4117 | ||
| 4377 | static inline bool | 4118 | static bool |
| 4378 | live_vector_p (struct mem_node *m, void *p) | 4119 | live_vector_p (struct mem_node *m, void *p) |
| 4379 | { | 4120 | { |
| 4380 | if (m->type == MEM_TYPE_VECTOR_BLOCK) | 4121 | if (m->type == MEM_TYPE_VECTOR_BLOCK) |
| @@ -4391,16 +4132,15 @@ live_vector_p (struct mem_node *m, void *p) | |||
| 4391 | while (VECTOR_IN_BLOCK (vector, block) | 4132 | while (VECTOR_IN_BLOCK (vector, block) |
| 4392 | && vector <= (struct Lisp_Vector *) p) | 4133 | && vector <= (struct Lisp_Vector *) p) |
| 4393 | { | 4134 | { |
| 4394 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) | 4135 | if (!PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) && vector == p) |
| 4395 | vector = ADVANCE (vector, (vector->header.size | ||
| 4396 | & PSEUDOVECTOR_SIZE_MASK)); | ||
| 4397 | else if (vector == p) | ||
| 4398 | return 1; | 4136 | return 1; |
| 4399 | else | 4137 | else |
| 4400 | vector = ADVANCE (vector, vector->header.next.nbytes); | 4138 | vector = ADVANCE (vector, vector_nbytes (vector)); |
| 4401 | } | 4139 | } |
| 4402 | } | 4140 | } |
| 4403 | else if (m->type == MEM_TYPE_VECTORLIKE && p == m->start) | 4141 | else if (m->type == MEM_TYPE_VECTORLIKE |
| 4142 | && (char *) p == ((char *) m->start | ||
| 4143 | + offsetof (struct large_vector, v))) | ||
| 4404 | /* This memory node corresponds to a large vector. */ | 4144 | /* This memory node corresponds to a large vector. */ |
| 4405 | return 1; | 4145 | return 1; |
| 4406 | return 0; | 4146 | return 0; |
| @@ -4410,7 +4150,7 @@ live_vector_p (struct mem_node *m, void *p) | |||
| 4410 | /* Value is non-zero if P is a pointer to a live buffer. M is a | 4150 | /* Value is non-zero if P is a pointer to a live buffer. M is a |
| 4411 | pointer to the mem_block for P. */ | 4151 | pointer to the mem_block for P. */ |
| 4412 | 4152 | ||
| 4413 | static inline bool | 4153 | static bool |
| 4414 | live_buffer_p (struct mem_node *m, void *p) | 4154 | live_buffer_p (struct mem_node *m, void *p) |
| 4415 | { | 4155 | { |
| 4416 | /* P must point to the start of the block, and the buffer | 4156 | /* P must point to the start of the block, and the buffer |
| @@ -4476,7 +4216,7 @@ DEFUN ("gc-status", Fgc_status, Sgc_status, 0, 0, "", | |||
| 4476 | 4216 | ||
| 4477 | /* Mark OBJ if we can prove it's a Lisp_Object. */ | 4217 | /* Mark OBJ if we can prove it's a Lisp_Object. */ |
| 4478 | 4218 | ||
| 4479 | static inline void | 4219 | static void |
| 4480 | mark_maybe_object (Lisp_Object obj) | 4220 | mark_maybe_object (Lisp_Object obj) |
| 4481 | { | 4221 | { |
| 4482 | void *po; | 4222 | void *po; |
| @@ -4545,7 +4285,7 @@ mark_maybe_object (Lisp_Object obj) | |||
| 4545 | /* If P points to Lisp data, mark that as live if it isn't already | 4285 | /* If P points to Lisp data, mark that as live if it isn't already |
| 4546 | marked. */ | 4286 | marked. */ |
| 4547 | 4287 | ||
| 4548 | static inline void | 4288 | static void |
| 4549 | mark_maybe_pointer (void *p) | 4289 | mark_maybe_pointer (void *p) |
| 4550 | { | 4290 | { |
| 4551 | struct mem_node *m; | 4291 | struct mem_node *m; |
| @@ -4611,7 +4351,7 @@ mark_maybe_pointer (void *p) | |||
| 4611 | break; | 4351 | break; |
| 4612 | 4352 | ||
| 4613 | default: | 4353 | default: |
| 4614 | abort (); | 4354 | emacs_abort (); |
| 4615 | } | 4355 | } |
| 4616 | 4356 | ||
| 4617 | if (!NILP (obj)) | 4357 | if (!NILP (obj)) |
| @@ -4755,14 +4495,14 @@ test_setjmp (void) | |||
| 4755 | { | 4495 | { |
| 4756 | char buf[10]; | 4496 | char buf[10]; |
| 4757 | register int x; | 4497 | register int x; |
| 4758 | jmp_buf jbuf; | 4498 | sys_jmp_buf jbuf; |
| 4759 | 4499 | ||
| 4760 | /* Arrange for X to be put in a register. */ | 4500 | /* Arrange for X to be put in a register. */ |
| 4761 | sprintf (buf, "1"); | 4501 | sprintf (buf, "1"); |
| 4762 | x = strlen (buf); | 4502 | x = strlen (buf); |
| 4763 | x = 2 * x - 1; | 4503 | x = 2 * x - 1; |
| 4764 | 4504 | ||
| 4765 | _setjmp (jbuf); | 4505 | sys_setjmp (jbuf); |
| 4766 | if (longjmps_done == 1) | 4506 | if (longjmps_done == 1) |
| 4767 | { | 4507 | { |
| 4768 | /* Came here after the longjmp at the end of the function. | 4508 | /* Came here after the longjmp at the end of the function. |
| @@ -4787,7 +4527,7 @@ test_setjmp (void) | |||
| 4787 | ++longjmps_done; | 4527 | ++longjmps_done; |
| 4788 | x = 2; | 4528 | x = 2; |
| 4789 | if (longjmps_done == 1) | 4529 | if (longjmps_done == 1) |
| 4790 | _longjmp (jbuf, 1); | 4530 | sys_longjmp (jbuf, 1); |
| 4791 | } | 4531 | } |
| 4792 | 4532 | ||
| 4793 | #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */ | 4533 | #endif /* not GC_SAVE_REGISTERS_ON_STACK && not GC_SETJMP_WORKS */ |
| @@ -4808,7 +4548,7 @@ check_gcpros (void) | |||
| 4808 | if (!survives_gc_p (p->var[i])) | 4548 | if (!survives_gc_p (p->var[i])) |
| 4809 | /* FIXME: It's not necessarily a bug. It might just be that the | 4549 | /* FIXME: It's not necessarily a bug. It might just be that the |
| 4810 | GCPRO is unnecessary or should release the object sooner. */ | 4550 | GCPRO is unnecessary or should release the object sooner. */ |
| 4811 | abort (); | 4551 | emacs_abort (); |
| 4812 | } | 4552 | } |
| 4813 | 4553 | ||
| 4814 | #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 4554 | #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| @@ -4912,7 +4652,7 @@ flush_stack_call_func (void (*func) (void *arg), void *arg) | |||
| 4912 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ | 4652 | /* jmp_buf may not be aligned enough on darwin-ppc64 */ |
| 4913 | union aligned_jmpbuf { | 4653 | union aligned_jmpbuf { |
| 4914 | Lisp_Object o; | 4654 | Lisp_Object o; |
| 4915 | jmp_buf j; | 4655 | sys_jmp_buf j; |
| 4916 | } j; | 4656 | } j; |
| 4917 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_bottom; | 4657 | volatile bool stack_grows_down_p = (char *) &j > (char *) stack_bottom; |
| 4918 | #endif | 4658 | #endif |
| @@ -4948,7 +4688,7 @@ flush_stack_call_func (void (*func) (void *arg), void *arg) | |||
| 4948 | } | 4688 | } |
| 4949 | #endif /* GC_SETJMP_WORKS */ | 4689 | #endif /* GC_SETJMP_WORKS */ |
| 4950 | 4690 | ||
| 4951 | _setjmp (j.j); | 4691 | sys_setjmp (j.j); |
| 4952 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; | 4692 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; |
| 4953 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ | 4693 | #endif /* not GC_SAVE_REGISTERS_ON_STACK */ |
| 4954 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ | 4694 | #endif /* not HAVE___BUILTIN_UNWIND_INIT */ |
| @@ -4986,7 +4726,8 @@ valid_pointer_p (void *p) | |||
| 4986 | #endif | 4726 | #endif |
| 4987 | } | 4727 | } |
| 4988 | 4728 | ||
| 4989 | /* Return 1 if OBJ is a valid lisp object. | 4729 | /* Return 2 if OBJ is a killed or special buffer object. |
| 4730 | Return 1 if OBJ is a valid lisp object. | ||
| 4990 | Return 0 if OBJ is NOT a valid lisp object. | 4731 | Return 0 if OBJ is NOT a valid lisp object. |
| 4991 | Return -1 if we cannot validate OBJ. | 4732 | Return -1 if we cannot validate OBJ. |
| 4992 | This function can be quite slow, | 4733 | This function can be quite slow, |
| @@ -5007,6 +4748,9 @@ valid_lisp_object_p (Lisp_Object obj) | |||
| 5007 | if (PURE_POINTER_P (p)) | 4748 | if (PURE_POINTER_P (p)) |
| 5008 | return 1; | 4749 | return 1; |
| 5009 | 4750 | ||
| 4751 | if (p == &buffer_defaults || p == &buffer_local_symbols) | ||
| 4752 | return 2; | ||
| 4753 | |||
| 5010 | #if !GC_MARK_STACK | 4754 | #if !GC_MARK_STACK |
| 5011 | return valid_pointer_p (p); | 4755 | return valid_pointer_p (p); |
| 5012 | #else | 4756 | #else |
| @@ -5032,7 +4776,7 @@ valid_lisp_object_p (Lisp_Object obj) | |||
| 5032 | return 0; | 4776 | return 0; |
| 5033 | 4777 | ||
| 5034 | case MEM_TYPE_BUFFER: | 4778 | case MEM_TYPE_BUFFER: |
| 5035 | return live_buffer_p (m, p); | 4779 | return live_buffer_p (m, p) ? 1 : 2; |
| 5036 | 4780 | ||
| 5037 | case MEM_TYPE_CONS: | 4781 | case MEM_TYPE_CONS: |
| 5038 | return live_cons_p (m, p); | 4782 | return live_cons_p (m, p); |
| @@ -5356,7 +5100,7 @@ staticpro (Lisp_Object *varaddress) | |||
| 5356 | { | 5100 | { |
| 5357 | staticvec[staticidx++] = varaddress; | 5101 | staticvec[staticidx++] = varaddress; |
| 5358 | if (staticidx >= NSTATICS) | 5102 | if (staticidx >= NSTATICS) |
| 5359 | abort (); | 5103 | fatal ("NSTATICS too small; try increasing and recompiling Emacs."); |
| 5360 | } | 5104 | } |
| 5361 | 5105 | ||
| 5362 | 5106 | ||
| @@ -5378,12 +5122,29 @@ inhibit_garbage_collection (void) | |||
| 5378 | /* Used to avoid possible overflows when | 5122 | /* Used to avoid possible overflows when |
| 5379 | converting from C to Lisp integers. */ | 5123 | converting from C to Lisp integers. */ |
| 5380 | 5124 | ||
| 5381 | static inline Lisp_Object | 5125 | static Lisp_Object |
| 5382 | bounded_number (EMACS_INT number) | 5126 | bounded_number (EMACS_INT number) |
| 5383 | { | 5127 | { |
| 5384 | return make_number (min (MOST_POSITIVE_FIXNUM, number)); | 5128 | return make_number (min (MOST_POSITIVE_FIXNUM, number)); |
| 5385 | } | 5129 | } |
| 5386 | 5130 | ||
| 5131 | /* Calculate total bytes of live objects. */ | ||
| 5132 | |||
| 5133 | static size_t | ||
| 5134 | total_bytes_of_live_objects (void) | ||
| 5135 | { | ||
| 5136 | size_t tot = 0; | ||
| 5137 | tot += total_conses * sizeof (struct Lisp_Cons); | ||
| 5138 | tot += total_symbols * sizeof (struct Lisp_Symbol); | ||
| 5139 | tot += total_markers * sizeof (union Lisp_Misc); | ||
| 5140 | tot += total_string_bytes; | ||
| 5141 | tot += total_vector_slots * word_size; | ||
| 5142 | tot += total_floats * sizeof (struct Lisp_Float); | ||
| 5143 | tot += total_intervals * sizeof (struct interval); | ||
| 5144 | tot += total_strings * sizeof (struct Lisp_String); | ||
| 5145 | return tot; | ||
| 5146 | } | ||
| 5147 | |||
| 5387 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5148 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 5388 | doc: /* Reclaim storage for Lisp objects no longer needed. | 5149 | doc: /* Reclaim storage for Lisp objects no longer needed. |
| 5389 | Garbage collection happens automatically if you cons more than | 5150 | Garbage collection happens automatically if you cons more than |
| @@ -5409,15 +5170,25 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5409 | ptrdiff_t count = SPECPDL_INDEX (); | 5170 | ptrdiff_t count = SPECPDL_INDEX (); |
| 5410 | EMACS_TIME start; | 5171 | EMACS_TIME start; |
| 5411 | Lisp_Object retval = Qnil; | 5172 | Lisp_Object retval = Qnil; |
| 5173 | size_t tot_before = 0; | ||
| 5174 | struct backtrace backtrace; | ||
| 5412 | 5175 | ||
| 5413 | if (abort_on_gc) | 5176 | if (abort_on_gc) |
| 5414 | abort (); | 5177 | emacs_abort (); |
| 5415 | 5178 | ||
| 5416 | /* Can't GC if pure storage overflowed because we can't determine | 5179 | /* Can't GC if pure storage overflowed because we can't determine |
| 5417 | if something is a pure object or not. */ | 5180 | if something is a pure object or not. */ |
| 5418 | if (pure_bytes_used_before_overflow) | 5181 | if (pure_bytes_used_before_overflow) |
| 5419 | return Qnil; | 5182 | return Qnil; |
| 5420 | 5183 | ||
| 5184 | /* Record this function, so it appears on the profiler's backtraces. */ | ||
| 5185 | backtrace.next = backtrace_list; | ||
| 5186 | backtrace.function = Qautomatic_gc; | ||
| 5187 | backtrace.args = &Qnil; | ||
| 5188 | backtrace.nargs = 0; | ||
| 5189 | backtrace.debug_on_exit = 0; | ||
| 5190 | backtrace_list = &backtrace; | ||
| 5191 | |||
| 5421 | check_cons_list (); | 5192 | check_cons_list (); |
| 5422 | 5193 | ||
| 5423 | /* Don't keep undo information around forever. | 5194 | /* Don't keep undo information around forever. |
| @@ -5425,6 +5196,9 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5425 | FOR_EACH_BUFFER (nextb) | 5196 | FOR_EACH_BUFFER (nextb) |
| 5426 | compact_buffer (nextb); | 5197 | compact_buffer (nextb); |
| 5427 | 5198 | ||
| 5199 | if (profiler_memory_running) | ||
| 5200 | tot_before = total_bytes_of_live_objects (); | ||
| 5201 | |||
| 5428 | start = current_emacs_time (); | 5202 | start = current_emacs_time (); |
| 5429 | 5203 | ||
| 5430 | /* In case user calls debug_print during GC, | 5204 | /* In case user calls debug_print during GC, |
| @@ -5466,7 +5240,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5466 | if (garbage_collection_messages) | 5240 | if (garbage_collection_messages) |
| 5467 | message1_nolog ("Garbage collecting..."); | 5241 | message1_nolog ("Garbage collecting..."); |
| 5468 | 5242 | ||
| 5469 | BLOCK_INPUT; | 5243 | block_input (); |
| 5470 | 5244 | ||
| 5471 | shrink_regexp_cache (); | 5245 | shrink_regexp_cache (); |
| 5472 | 5246 | ||
| @@ -5474,6 +5248,9 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5474 | 5248 | ||
| 5475 | /* Mark all the special slots that serve as the roots of accessibility. */ | 5249 | /* Mark all the special slots that serve as the roots of accessibility. */ |
| 5476 | 5250 | ||
| 5251 | mark_buffer (&buffer_defaults); | ||
| 5252 | mark_buffer (&buffer_local_symbols); | ||
| 5253 | |||
| 5477 | for (i = 0; i < staticidx; i++) | 5254 | for (i = 0; i < staticidx; i++) |
| 5478 | mark_object (*staticvec[i]); | 5255 | mark_object (*staticvec[i]); |
| 5479 | 5256 | ||
| @@ -5548,12 +5325,12 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5548 | dump_zombies (); | 5325 | dump_zombies (); |
| 5549 | #endif | 5326 | #endif |
| 5550 | 5327 | ||
| 5551 | UNBLOCK_INPUT; | ||
| 5552 | |||
| 5553 | check_cons_list (); | 5328 | check_cons_list (); |
| 5554 | 5329 | ||
| 5555 | gc_in_progress = 0; | 5330 | gc_in_progress = 0; |
| 5556 | 5331 | ||
| 5332 | unblock_input (); | ||
| 5333 | |||
| 5557 | consing_since_gc = 0; | 5334 | consing_since_gc = 0; |
| 5558 | if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10) | 5335 | if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10) |
| 5559 | gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10; | 5336 | gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10; |
| @@ -5561,16 +5338,7 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5561 | gc_relative_threshold = 0; | 5338 | gc_relative_threshold = 0; |
| 5562 | if (FLOATP (Vgc_cons_percentage)) | 5339 | if (FLOATP (Vgc_cons_percentage)) |
| 5563 | { /* Set gc_cons_combined_threshold. */ | 5340 | { /* Set gc_cons_combined_threshold. */ |
| 5564 | double tot = 0; | 5341 | double tot = total_bytes_of_live_objects (); |
| 5565 | |||
| 5566 | tot += total_conses * sizeof (struct Lisp_Cons); | ||
| 5567 | tot += total_symbols * sizeof (struct Lisp_Symbol); | ||
| 5568 | tot += total_markers * sizeof (union Lisp_Misc); | ||
| 5569 | tot += total_string_bytes; | ||
| 5570 | tot += total_vector_slots * word_size; | ||
| 5571 | tot += total_floats * sizeof (struct Lisp_Float); | ||
| 5572 | tot += total_intervals * sizeof (struct interval); | ||
| 5573 | tot += total_strings * sizeof (struct Lisp_String); | ||
| 5574 | 5342 | ||
| 5575 | tot *= XFLOAT_DATA (Vgc_cons_percentage); | 5343 | tot *= XFLOAT_DATA (Vgc_cons_percentage); |
| 5576 | if (0 < tot) | 5344 | if (0 < tot) |
| @@ -5673,6 +5441,17 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5673 | 5441 | ||
| 5674 | gcs_done++; | 5442 | gcs_done++; |
| 5675 | 5443 | ||
| 5444 | /* Collect profiling data. */ | ||
| 5445 | if (profiler_memory_running) | ||
| 5446 | { | ||
| 5447 | size_t swept = 0; | ||
| 5448 | size_t tot_after = total_bytes_of_live_objects (); | ||
| 5449 | if (tot_before > tot_after) | ||
| 5450 | swept = tot_before - tot_after; | ||
| 5451 | malloc_probe (swept); | ||
| 5452 | } | ||
| 5453 | |||
| 5454 | backtrace_list = backtrace.next; | ||
| 5676 | return retval; | 5455 | return retval; |
| 5677 | } | 5456 | } |
| 5678 | 5457 | ||
| @@ -5826,6 +5605,33 @@ mark_buffer (struct buffer *buffer) | |||
| 5826 | mark_buffer (buffer->base_buffer); | 5605 | mark_buffer (buffer->base_buffer); |
| 5827 | } | 5606 | } |
| 5828 | 5607 | ||
| 5608 | /* Remove killed buffers or items whose car is a killed buffer from | ||
| 5609 | LIST, and mark other items. Return changed LIST, which is marked. */ | ||
| 5610 | |||
| 5611 | static Lisp_Object | ||
| 5612 | mark_discard_killed_buffers (Lisp_Object list) | ||
| 5613 | { | ||
| 5614 | Lisp_Object tail, *prev = &list; | ||
| 5615 | |||
| 5616 | for (tail = list; CONSP (tail) && !CONS_MARKED_P (XCONS (tail)); | ||
| 5617 | tail = XCDR (tail)) | ||
| 5618 | { | ||
| 5619 | Lisp_Object tem = XCAR (tail); | ||
| 5620 | if (CONSP (tem)) | ||
| 5621 | tem = XCAR (tem); | ||
| 5622 | if (BUFFERP (tem) && !BUFFER_LIVE_P (XBUFFER (tem))) | ||
| 5623 | *prev = XCDR (tail); | ||
| 5624 | else | ||
| 5625 | { | ||
| 5626 | CONS_MARK (XCONS (tail)); | ||
| 5627 | mark_object (XCAR (tail)); | ||
| 5628 | prev = &XCDR_AS_LVALUE (tail); | ||
| 5629 | } | ||
| 5630 | } | ||
| 5631 | mark_object (tail); | ||
| 5632 | return list; | ||
| 5633 | } | ||
| 5634 | |||
| 5829 | /* Determine type of generic Lisp_Object and mark it accordingly. */ | 5635 | /* Determine type of generic Lisp_Object and mark it accordingly. */ |
| 5830 | 5636 | ||
| 5831 | void | 5637 | void |
| @@ -5860,7 +5666,7 @@ mark_object (Lisp_Object arg) | |||
| 5860 | do { \ | 5666 | do { \ |
| 5861 | m = mem_find (po); \ | 5667 | m = mem_find (po); \ |
| 5862 | if (m == MEM_NIL) \ | 5668 | if (m == MEM_NIL) \ |
| 5863 | abort (); \ | 5669 | emacs_abort (); \ |
| 5864 | } while (0) | 5670 | } while (0) |
| 5865 | 5671 | ||
| 5866 | /* Check that the object pointed to by PO is live, using predicate | 5672 | /* Check that the object pointed to by PO is live, using predicate |
| @@ -5868,7 +5674,7 @@ mark_object (Lisp_Object arg) | |||
| 5868 | #define CHECK_LIVE(LIVEP) \ | 5674 | #define CHECK_LIVE(LIVEP) \ |
| 5869 | do { \ | 5675 | do { \ |
| 5870 | if (!LIVEP (m, po)) \ | 5676 | if (!LIVEP (m, po)) \ |
| 5871 | abort (); \ | 5677 | emacs_abort (); \ |
| 5872 | } while (0) | 5678 | } while (0) |
| 5873 | 5679 | ||
| 5874 | /* Check both of the above conditions. */ | 5680 | /* Check both of the above conditions. */ |
| @@ -5913,17 +5719,15 @@ mark_object (Lisp_Object arg) | |||
| 5913 | 5719 | ||
| 5914 | #ifdef GC_CHECK_MARKED_OBJECTS | 5720 | #ifdef GC_CHECK_MARKED_OBJECTS |
| 5915 | m = mem_find (po); | 5721 | m = mem_find (po); |
| 5916 | if (m == MEM_NIL && !SUBRP (obj) | 5722 | if (m == MEM_NIL && !SUBRP (obj)) |
| 5917 | && po != &buffer_defaults | 5723 | emacs_abort (); |
| 5918 | && po != &buffer_local_symbols) | ||
| 5919 | abort (); | ||
| 5920 | #endif /* GC_CHECK_MARKED_OBJECTS */ | 5724 | #endif /* GC_CHECK_MARKED_OBJECTS */ |
| 5921 | 5725 | ||
| 5922 | if (ptr->header.size & PSEUDOVECTOR_FLAG) | 5726 | if (ptr->header.size & PSEUDOVECTOR_FLAG) |
| 5923 | pvectype = ((ptr->header.size & PVEC_TYPE_MASK) | 5727 | pvectype = ((ptr->header.size & PVEC_TYPE_MASK) |
| 5924 | >> PSEUDOVECTOR_SIZE_BITS); | 5728 | >> PSEUDOVECTOR_AREA_BITS); |
| 5925 | else | 5729 | else |
| 5926 | pvectype = 0; | 5730 | pvectype = PVEC_NORMAL_VECTOR; |
| 5927 | 5731 | ||
| 5928 | if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) | 5732 | if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) |
| 5929 | CHECK_LIVE (live_vector_p); | 5733 | CHECK_LIVE (live_vector_p); |
| @@ -5932,15 +5736,14 @@ mark_object (Lisp_Object arg) | |||
| 5932 | { | 5736 | { |
| 5933 | case PVEC_BUFFER: | 5737 | case PVEC_BUFFER: |
| 5934 | #ifdef GC_CHECK_MARKED_OBJECTS | 5738 | #ifdef GC_CHECK_MARKED_OBJECTS |
| 5935 | if (po != &buffer_defaults && po != &buffer_local_symbols) | 5739 | { |
| 5936 | { | 5740 | struct buffer *b; |
| 5937 | struct buffer *b; | 5741 | FOR_EACH_BUFFER (b) |
| 5938 | FOR_EACH_BUFFER (b) | 5742 | if (b == po) |
| 5939 | if (b == po) | 5743 | break; |
| 5940 | break; | 5744 | if (b == NULL) |
| 5941 | if (b == NULL) | 5745 | emacs_abort (); |
| 5942 | abort (); | 5746 | } |
| 5943 | } | ||
| 5944 | #endif /* GC_CHECK_MARKED_OBJECTS */ | 5747 | #endif /* GC_CHECK_MARKED_OBJECTS */ |
| 5945 | mark_buffer ((struct buffer *) ptr); | 5748 | mark_buffer ((struct buffer *) ptr); |
| 5946 | break; | 5749 | break; |
| @@ -5965,26 +5768,34 @@ mark_object (Lisp_Object arg) | |||
| 5965 | break; | 5768 | break; |
| 5966 | 5769 | ||
| 5967 | case PVEC_FRAME: | 5770 | case PVEC_FRAME: |
| 5968 | { | 5771 | mark_vectorlike (ptr); |
| 5969 | mark_vectorlike (ptr); | 5772 | mark_face_cache (((struct frame *) ptr)->face_cache); |
| 5970 | mark_face_cache (((struct frame *) ptr)->face_cache); | ||
| 5971 | } | ||
| 5972 | break; | 5773 | break; |
| 5973 | 5774 | ||
| 5974 | case PVEC_WINDOW: | 5775 | case PVEC_WINDOW: |
| 5975 | { | 5776 | { |
| 5976 | struct window *w = (struct window *) ptr; | 5777 | struct window *w = (struct window *) ptr; |
| 5778 | bool leaf = NILP (w->hchild) && NILP (w->vchild); | ||
| 5977 | 5779 | ||
| 5978 | mark_vectorlike (ptr); | 5780 | mark_vectorlike (ptr); |
| 5781 | |||
| 5979 | /* Mark glyphs for leaf windows. Marking window | 5782 | /* Mark glyphs for leaf windows. Marking window |
| 5980 | matrices is sufficient because frame matrices | 5783 | matrices is sufficient because frame matrices |
| 5981 | use the same glyph memory. */ | 5784 | use the same glyph memory. */ |
| 5982 | if (NILP (w->hchild) && NILP (w->vchild) | 5785 | if (leaf && w->current_matrix) |
| 5983 | && w->current_matrix) | ||
| 5984 | { | 5786 | { |
| 5985 | mark_glyph_matrix (w->current_matrix); | 5787 | mark_glyph_matrix (w->current_matrix); |
| 5986 | mark_glyph_matrix (w->desired_matrix); | 5788 | mark_glyph_matrix (w->desired_matrix); |
| 5987 | } | 5789 | } |
| 5790 | |||
| 5791 | /* Filter out killed buffers from both buffer lists | ||
| 5792 | in attempt to help GC to reclaim killed buffers faster. | ||
| 5793 | We can do it elsewhere for live windows, but this is the | ||
| 5794 | best place to do it for dead windows. */ | ||
| 5795 | wset_prev_buffers | ||
| 5796 | (w, mark_discard_killed_buffers (w->prev_buffers)); | ||
| 5797 | wset_next_buffers | ||
| 5798 | (w, mark_discard_killed_buffers (w->next_buffers)); | ||
| 5988 | } | 5799 | } |
| 5989 | break; | 5800 | break; |
| 5990 | 5801 | ||
| @@ -5993,6 +5804,9 @@ mark_object (Lisp_Object arg) | |||
| 5993 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; | 5804 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; |
| 5994 | 5805 | ||
| 5995 | mark_vectorlike (ptr); | 5806 | mark_vectorlike (ptr); |
| 5807 | mark_object (h->test.name); | ||
| 5808 | mark_object (h->test.user_hash_function); | ||
| 5809 | mark_object (h->test.user_cmp_function); | ||
| 5996 | /* If hash table is not weak, mark all keys and values. | 5810 | /* If hash table is not weak, mark all keys and values. |
| 5997 | For weak tables, mark only the vector. */ | 5811 | For weak tables, mark only the vector. */ |
| 5998 | if (NILP (h->weak)) | 5812 | if (NILP (h->weak)) |
| @@ -6015,7 +5829,7 @@ mark_object (Lisp_Object arg) | |||
| 6015 | break; | 5829 | break; |
| 6016 | 5830 | ||
| 6017 | case PVEC_FREE: | 5831 | case PVEC_FREE: |
| 6018 | abort (); | 5832 | emacs_abort (); |
| 6019 | 5833 | ||
| 6020 | default: | 5834 | default: |
| 6021 | mark_vectorlike (ptr); | 5835 | mark_vectorlike (ptr); |
| @@ -6047,10 +5861,14 @@ mark_object (Lisp_Object arg) | |||
| 6047 | case SYMBOL_LOCALIZED: | 5861 | case SYMBOL_LOCALIZED: |
| 6048 | { | 5862 | { |
| 6049 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); | 5863 | struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); |
| 6050 | /* If the value is forwarded to a buffer or keyboard field, | 5864 | Lisp_Object where = blv->where; |
| 6051 | these are marked when we see the corresponding object. | 5865 | /* If the value is set up for a killed buffer or deleted |
| 6052 | And if it's forwarded to a C variable, either it's not | 5866 | frame, restore it's global binding. If the value is |
| 6053 | a Lisp_Object var, or it's staticpro'd already. */ | 5867 | forwarded to a C variable, either it's not a Lisp_Object |
| 5868 | var, or it's staticpro'd already. */ | ||
| 5869 | if ((BUFFERP (where) && !BUFFER_LIVE_P (XBUFFER (where))) | ||
| 5870 | || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))) | ||
| 5871 | swap_in_global_binding (ptr); | ||
| 6054 | mark_object (blv->where); | 5872 | mark_object (blv->where); |
| 6055 | mark_object (blv->valcell); | 5873 | mark_object (blv->valcell); |
| 6056 | mark_object (blv->defcell); | 5874 | mark_object (blv->defcell); |
| @@ -6062,7 +5880,7 @@ mark_object (Lisp_Object arg) | |||
| 6062 | And if it's forwarded to a C variable, either it's not | 5880 | And if it's forwarded to a C variable, either it's not |
| 6063 | a Lisp_Object var, or it's staticpro'd already. */ | 5881 | a Lisp_Object var, or it's staticpro'd already. */ |
| 6064 | break; | 5882 | break; |
| 6065 | default: abort (); | 5883 | default: emacs_abort (); |
| 6066 | } | 5884 | } |
| 6067 | if (!PURE_POINTER_P (XSTRING (ptr->name))) | 5885 | if (!PURE_POINTER_P (XSTRING (ptr->name))) |
| 6068 | MARK_STRING (XSTRING (ptr->name)); | 5886 | MARK_STRING (XSTRING (ptr->name)); |
| @@ -6116,7 +5934,7 @@ mark_object (Lisp_Object arg) | |||
| 6116 | break; | 5934 | break; |
| 6117 | 5935 | ||
| 6118 | default: | 5936 | default: |
| 6119 | abort (); | 5937 | emacs_abort (); |
| 6120 | } | 5938 | } |
| 6121 | break; | 5939 | break; |
| 6122 | 5940 | ||
| @@ -6138,7 +5956,7 @@ mark_object (Lisp_Object arg) | |||
| 6138 | obj = ptr->u.cdr; | 5956 | obj = ptr->u.cdr; |
| 6139 | cdr_count++; | 5957 | cdr_count++; |
| 6140 | if (cdr_count == mark_object_loop_halt) | 5958 | if (cdr_count == mark_object_loop_halt) |
| 6141 | abort (); | 5959 | emacs_abort (); |
| 6142 | goto loop; | 5960 | goto loop; |
| 6143 | } | 5961 | } |
| 6144 | 5962 | ||
| @@ -6151,7 +5969,7 @@ mark_object (Lisp_Object arg) | |||
| 6151 | break; | 5969 | break; |
| 6152 | 5970 | ||
| 6153 | default: | 5971 | default: |
| 6154 | abort (); | 5972 | emacs_abort (); |
| 6155 | } | 5973 | } |
| 6156 | 5974 | ||
| 6157 | #undef CHECK_LIVE | 5975 | #undef CHECK_LIVE |
| @@ -6220,7 +6038,7 @@ survives_gc_p (Lisp_Object obj) | |||
| 6220 | break; | 6038 | break; |
| 6221 | 6039 | ||
| 6222 | default: | 6040 | default: |
| 6223 | abort (); | 6041 | emacs_abort (); |
| 6224 | } | 6042 | } |
| 6225 | 6043 | ||
| 6226 | return survives_p || PURE_POINTER_P ((void *) XPNTR (obj)); | 6044 | return survives_p || PURE_POINTER_P ((void *) XPNTR (obj)); |
| @@ -6534,19 +6352,14 @@ gc_sweep (void) | |||
| 6534 | 6352 | ||
| 6535 | /* Free all unmarked buffers */ | 6353 | /* Free all unmarked buffers */ |
| 6536 | { | 6354 | { |
| 6537 | register struct buffer *buffer = all_buffers, *prev = 0, *next; | 6355 | register struct buffer *buffer, **bprev = &all_buffers; |
| 6538 | 6356 | ||
| 6539 | total_buffers = 0; | 6357 | total_buffers = 0; |
| 6540 | while (buffer) | 6358 | for (buffer = all_buffers; buffer; buffer = *bprev) |
| 6541 | if (!VECTOR_MARKED_P (buffer)) | 6359 | if (!VECTOR_MARKED_P (buffer)) |
| 6542 | { | 6360 | { |
| 6543 | if (prev) | 6361 | *bprev = buffer->next; |
| 6544 | prev->header.next = buffer->header.next; | ||
| 6545 | else | ||
| 6546 | all_buffers = buffer->header.next.buffer; | ||
| 6547 | next = buffer->header.next.buffer; | ||
| 6548 | lisp_free (buffer); | 6362 | lisp_free (buffer); |
| 6549 | buffer = next; | ||
| 6550 | } | 6363 | } |
| 6551 | else | 6364 | else |
| 6552 | { | 6365 | { |
| @@ -6554,7 +6367,7 @@ gc_sweep (void) | |||
| 6554 | /* Do not use buffer_(set|get)_intervals here. */ | 6367 | /* Do not use buffer_(set|get)_intervals here. */ |
| 6555 | buffer->text->intervals = balance_intervals (buffer->text->intervals); | 6368 | buffer->text->intervals = balance_intervals (buffer->text->intervals); |
| 6556 | total_buffers++; | 6369 | total_buffers++; |
| 6557 | prev = buffer, buffer = buffer->header.next.buffer; | 6370 | bprev = &buffer->next; |
| 6558 | } | 6371 | } |
| 6559 | } | 6372 | } |
| 6560 | 6373 | ||
| @@ -6658,21 +6471,14 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) | |||
| 6658 | 6471 | ||
| 6659 | #ifdef ENABLE_CHECKING | 6472 | #ifdef ENABLE_CHECKING |
| 6660 | 6473 | ||
| 6661 | # include <execinfo.h> | ||
| 6662 | |||
| 6663 | bool suppress_checking; | 6474 | bool suppress_checking; |
| 6664 | 6475 | ||
| 6665 | void | 6476 | void |
| 6666 | die (const char *msg, const char *file, int line) | 6477 | die (const char *msg, const char *file, int line) |
| 6667 | { | 6478 | { |
| 6668 | enum { NPOINTERS_MAX = 500 }; | ||
| 6669 | void *buffer[NPOINTERS_MAX]; | ||
| 6670 | int npointers; | ||
| 6671 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", | 6479 | fprintf (stderr, "\r\n%s:%d: Emacs fatal error: %s\r\n", |
| 6672 | file, line, msg); | 6480 | file, line, msg); |
| 6673 | npointers = backtrace (buffer, NPOINTERS_MAX); | 6481 | terminate_due_to_signal (SIGABRT, INT_MAX); |
| 6674 | backtrace_symbols_fd (buffer, npointers, STDERR_FILENO); | ||
| 6675 | abort (); | ||
| 6676 | } | 6482 | } |
| 6677 | #endif | 6483 | #endif |
| 6678 | 6484 | ||
| @@ -6698,12 +6504,6 @@ init_alloc_once (void) | |||
| 6698 | init_strings (); | 6504 | init_strings (); |
| 6699 | init_vectors (); | 6505 | init_vectors (); |
| 6700 | 6506 | ||
| 6701 | #ifdef REL_ALLOC | ||
| 6702 | malloc_hysteresis = 32; | ||
| 6703 | #else | ||
| 6704 | malloc_hysteresis = 0; | ||
| 6705 | #endif | ||
| 6706 | |||
| 6707 | refill_memory_reserve (); | 6507 | refill_memory_reserve (); |
| 6708 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; | 6508 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; |
| 6709 | } | 6509 | } |
| @@ -6810,6 +6610,7 @@ do hash-consing of the objects allocated to pure space. */); | |||
| 6810 | DEFSYM (Qstring_bytes, "string-bytes"); | 6610 | DEFSYM (Qstring_bytes, "string-bytes"); |
| 6811 | DEFSYM (Qvector_slots, "vector-slots"); | 6611 | DEFSYM (Qvector_slots, "vector-slots"); |
| 6812 | DEFSYM (Qheap, "heap"); | 6612 | DEFSYM (Qheap, "heap"); |
| 6613 | DEFSYM (Qautomatic_gc, "Automatic GC"); | ||
| 6813 | 6614 | ||
| 6814 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); | 6615 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); |
| 6815 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); | 6616 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); |
| @@ -6843,7 +6644,8 @@ The time is in seconds as a floating point value. */); | |||
| 6843 | /* When compiled with GCC, GDB might say "No enum type named | 6644 | /* When compiled with GCC, GDB might say "No enum type named |
| 6844 | pvec_type" if we don't have at least one symbol with that type, and | 6645 | pvec_type" if we don't have at least one symbol with that type, and |
| 6845 | then xbacktrace could fail. Similarly for the other enums and | 6646 | then xbacktrace could fail. Similarly for the other enums and |
| 6846 | their values. */ | 6647 | their values. Some non-GCC compilers don't like these constructs. */ |
| 6648 | #ifdef __GNUC__ | ||
| 6847 | union | 6649 | union |
| 6848 | { | 6650 | { |
| 6849 | enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS; | 6651 | enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS; |
| @@ -6863,3 +6665,4 @@ union | |||
| 6863 | enum lsb_bits lsb_bits; | 6665 | enum lsb_bits lsb_bits; |
| 6864 | #endif | 6666 | #endif |
| 6865 | } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0}; | 6667 | } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0}; |
| 6668 | #endif /* __GNUC__ */ | ||