diff options
| author | Gerd Moellmann | 2000-02-17 15:21:21 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2000-02-17 15:21:21 +0000 |
| commit | 344000084d72f603d5953c65f1570841e01b98e4 (patch) | |
| tree | 7da26d7fa98e6b5a2833b4a9b790a34df89774d4 /src/alloc.c | |
| parent | 53c80cf65ea01af58e3f71654847d55dfa6f5416 (diff) | |
| download | emacs-344000084d72f603d5953c65f1570841e01b98e4.tar.gz emacs-344000084d72f603d5953c65f1570841e01b98e4.zip | |
(mark_object): Don't mark symbol names in pure space.
(gc_sweep): Don't unmark symbol names in pure space.
(toplevel): Include setjmp.h.
(PURE_POINTER_P): New define.
(enum mem_type) [GC_MARK_STACK]: New enumeration.
(Vdead) [GC_MARK_STACK]: New variable.
(lisp_malloc): Add parameter TYPE, call mem_insert if
GC_MARK_STACK is defined.
(allocate_buffer): New function.
(lisp_free) [GC_MARK_STACK]: Call mem_delete.
(free_float) [GC_MARK_STACK]: Set type to Vdead.
(free_cons) [GC_MARK_STACK]: Set car to Vdead.
(stack_base, mem_root, mem_z) [GC_MARK_STACK]: New variables.
(MEM_NIL) [GC_MARK_STACK]: New define.
(struct mem_node) [GC_MARK_STACK]: New structure.
(mem_init, mem_find, mem_insert, mem_delete, mem_insert_fixup)
(mem_delete_fixup, mem_rotate_left, mem_rotate_right)
(live_string_p, live_cons_p, live_symbol_p, live_float_p)
(live_misc_p, live_vector_p, live_buffer_p, mark_memory)
(mark_stack) [GC_MARK_STACK]: New functions.
(Fgarbage_collect) [GC_MARK_STACK]: Call mark_stack.
(clear_marks): Removed.
(gc_sweep): Set free conses' car, free floats' type, free
symbols' function to Vdead. Use lisp_free to free buffers.
(init_alloc_once): Initialize Vdead.
(survives_gc_p): Return non-zero for pure objects.
Add comments throughout the file.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 1298 |
1 files changed, 1169 insertions, 129 deletions
diff --git a/src/alloc.c b/src/alloc.c index 8152ad2bf1a..04c269deaf0 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -40,6 +40,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 40 | #include "keyboard.h" | 40 | #include "keyboard.h" |
| 41 | #include "charset.h" | 41 | #include "charset.h" |
| 42 | #include "syssignal.h" | 42 | #include "syssignal.h" |
| 43 | #include <setjmp.h> | ||
| 43 | 44 | ||
| 44 | extern char *sbrk (); | 45 | extern char *sbrk (); |
| 45 | 46 | ||
| @@ -149,9 +150,11 @@ int malloc_sbrk_unused; | |||
| 149 | int undo_limit; | 150 | int undo_limit; |
| 150 | int undo_strong_limit; | 151 | int undo_strong_limit; |
| 151 | 152 | ||
| 152 | int total_conses, total_markers, total_symbols, total_vector_size; | 153 | /* Number of live and free conses etc. */ |
| 153 | int total_free_conses, total_free_markers, total_free_symbols; | 154 | |
| 154 | int total_free_floats, total_floats; | 155 | static int total_conses, total_markers, total_symbols, total_vector_size; |
| 156 | static int total_free_conses, total_free_markers, total_free_symbols; | ||
| 157 | static int total_free_floats, total_floats; | ||
| 155 | 158 | ||
| 156 | /* Points to memory space allocated as "spare", to be freed if we run | 159 | /* Points to memory space allocated as "spare", to be freed if we run |
| 157 | out of memory. */ | 160 | out of memory. */ |
| @@ -198,6 +201,14 @@ EMACS_INT pure_size; | |||
| 198 | 201 | ||
| 199 | #endif /* not HAVE_SHM */ | 202 | #endif /* not HAVE_SHM */ |
| 200 | 203 | ||
| 204 | /* Value is non-zero if P points into pure space. */ | ||
| 205 | |||
| 206 | #define PURE_POINTER_P(P) \ | ||
| 207 | (((PNTR_COMPARISON_TYPE) (P) \ | ||
| 208 | < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE)) \ | ||
| 209 | && ((PNTR_COMPARISON_TYPE) (P) \ | ||
| 210 | >= (PNTR_COMPARISON_TYPE) pure)) | ||
| 211 | |||
| 201 | /* Index in pure at which next pure object will be allocated.. */ | 212 | /* Index in pure at which next pure object will be allocated.. */ |
| 202 | 213 | ||
| 203 | int pureptr; | 214 | int pureptr; |
| @@ -234,9 +245,6 @@ static void mark_kboards P_ ((void)); | |||
| 234 | static void gc_sweep P_ ((void)); | 245 | static void gc_sweep P_ ((void)); |
| 235 | static void mark_glyph_matrix P_ ((struct glyph_matrix *)); | 246 | static void mark_glyph_matrix P_ ((struct glyph_matrix *)); |
| 236 | static void mark_face_cache P_ ((struct face_cache *)); | 247 | static void mark_face_cache P_ ((struct face_cache *)); |
| 237 | #if 0 | ||
| 238 | static void clear_marks (); | ||
| 239 | #endif | ||
| 240 | 248 | ||
| 241 | #ifdef HAVE_WINDOW_SYSTEM | 249 | #ifdef HAVE_WINDOW_SYSTEM |
| 242 | static void mark_image P_ ((struct image *)); | 250 | static void mark_image P_ ((struct image *)); |
| @@ -249,9 +257,69 @@ static void free_large_strings P_ ((void)); | |||
| 249 | static void sweep_strings P_ ((void)); | 257 | static void sweep_strings P_ ((void)); |
| 250 | 258 | ||
| 251 | extern int message_enable_multibyte; | 259 | extern int message_enable_multibyte; |
| 260 | |||
| 261 | |||
| 262 | #if GC_MARK_STACK | ||
| 263 | |||
| 264 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 265 | #include <stdio.h> /* For fprintf. */ | ||
| 266 | #endif | ||
| 267 | |||
| 268 | /* A unique object in pure space used to make some Lisp objects | ||
| 269 | on free lists recognizable in O(1). */ | ||
| 270 | |||
| 271 | Lisp_Object Vdead; | ||
| 272 | |||
| 273 | /* When scanning the C stack for live Lisp objects, Emacs keeps track | ||
| 274 | of what memory allocated via lisp_malloc is intended for what | ||
| 275 | purpose. This enumeration specifies the type of memory. */ | ||
| 276 | |||
| 277 | enum mem_type | ||
| 278 | { | ||
| 279 | MEM_TYPE_NON_LISP, | ||
| 280 | MEM_TYPE_BUFFER, | ||
| 281 | MEM_TYPE_CONS, | ||
| 282 | MEM_TYPE_STRING, | ||
| 283 | MEM_TYPE_MISC, | ||
| 284 | MEM_TYPE_SYMBOL, | ||
| 285 | MEM_TYPE_FLOAT, | ||
| 286 | MEM_TYPE_VECTOR | ||
| 287 | }; | ||
| 288 | |||
| 289 | struct mem_node; | ||
| 290 | static void *lisp_malloc P_ ((int, enum mem_type)); | ||
| 291 | static void mark_stack P_ ((void)); | ||
| 292 | static void init_stack P_ ((Lisp_Object *)); | ||
| 293 | static int live_vector_p P_ ((struct mem_node *, void *)); | ||
| 294 | static int live_buffer_p P_ ((struct mem_node *, void *)); | ||
| 295 | static int live_string_p P_ ((struct mem_node *, void *)); | ||
| 296 | static int live_cons_p P_ ((struct mem_node *, void *)); | ||
| 297 | static int live_symbol_p P_ ((struct mem_node *, void *)); | ||
| 298 | static int live_float_p P_ ((struct mem_node *, void *)); | ||
| 299 | static int live_misc_p P_ ((struct mem_node *, void *)); | ||
| 300 | static void mark_memory P_ ((void *, void *)); | ||
| 301 | static void mem_init P_ ((void)); | ||
| 302 | static struct mem_node *mem_insert P_ ((void *, void *, enum mem_type)); | ||
| 303 | static void mem_insert_fixup P_ ((struct mem_node *)); | ||
| 304 | static void mem_rotate_left P_ ((struct mem_node *)); | ||
| 305 | static void mem_rotate_right P_ ((struct mem_node *)); | ||
| 306 | static void mem_delete P_ ((struct mem_node *)); | ||
| 307 | static void mem_delete_fixup P_ ((struct mem_node *)); | ||
| 308 | static INLINE struct mem_node *mem_find P_ ((void *)); | ||
| 309 | |||
| 310 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | ||
| 311 | static void check_gcpros P_ ((void)); | ||
| 312 | #endif | ||
| 313 | |||
| 314 | #endif /* GC_MARK_STACK != 0 */ | ||
| 315 | |||
| 252 | 316 | ||
| 253 | /* Versions of malloc and realloc that print warnings as memory gets | 317 | /************************************************************************ |
| 254 | full. */ | 318 | Malloc |
| 319 | ************************************************************************/ | ||
| 320 | |||
| 321 | /* Write STR to Vstandard_output plus some advice on how to free some | ||
| 322 | memory. Called when memory gets low. */ | ||
| 255 | 323 | ||
| 256 | Lisp_Object | 324 | Lisp_Object |
| 257 | malloc_warning_1 (str) | 325 | malloc_warning_1 (str) |
| @@ -264,7 +332,9 @@ malloc_warning_1 (str) | |||
| 264 | return Qnil; | 332 | return Qnil; |
| 265 | } | 333 | } |
| 266 | 334 | ||
| 267 | /* malloc calls this if it finds we are near exhausting storage. */ | 335 | |
| 336 | /* Function malloc calls this if it finds we are near exhausting | ||
| 337 | storage. */ | ||
| 268 | 338 | ||
| 269 | void | 339 | void |
| 270 | malloc_warning (str) | 340 | malloc_warning (str) |
| @@ -273,6 +343,9 @@ malloc_warning (str) | |||
| 273 | pending_malloc_warning = str; | 343 | pending_malloc_warning = str; |
| 274 | } | 344 | } |
| 275 | 345 | ||
| 346 | |||
| 347 | /* Display a malloc warning in buffer *Danger*. */ | ||
| 348 | |||
| 276 | void | 349 | void |
| 277 | display_malloc_warning () | 350 | display_malloc_warning () |
| 278 | { | 351 | { |
| @@ -283,12 +356,14 @@ display_malloc_warning () | |||
| 283 | internal_with_output_to_temp_buffer (" *Danger*", malloc_warning_1, val); | 356 | internal_with_output_to_temp_buffer (" *Danger*", malloc_warning_1, val); |
| 284 | } | 357 | } |
| 285 | 358 | ||
| 359 | |||
| 286 | #ifdef DOUG_LEA_MALLOC | 360 | #ifdef DOUG_LEA_MALLOC |
| 287 | # define BYTES_USED (mallinfo ().arena) | 361 | # define BYTES_USED (mallinfo ().arena) |
| 288 | #else | 362 | #else |
| 289 | # define BYTES_USED _bytes_used | 363 | # define BYTES_USED _bytes_used |
| 290 | #endif | 364 | #endif |
| 291 | 365 | ||
| 366 | |||
| 292 | /* Called if malloc returns zero. */ | 367 | /* Called if malloc returns zero. */ |
| 293 | 368 | ||
| 294 | void | 369 | void |
| @@ -311,6 +386,7 @@ memory_full () | |||
| 311 | Fsignal (Qnil, memory_signal_data); | 386 | Fsignal (Qnil, memory_signal_data); |
| 312 | } | 387 | } |
| 313 | 388 | ||
| 389 | |||
| 314 | /* Called if we can't allocate relocatable space for a buffer. */ | 390 | /* Called if we can't allocate relocatable space for a buffer. */ |
| 315 | 391 | ||
| 316 | void | 392 | void |
| @@ -333,8 +409,8 @@ buffer_memory_full () | |||
| 333 | Fsignal (Qerror, memory_signal_data); | 409 | Fsignal (Qerror, memory_signal_data); |
| 334 | } | 410 | } |
| 335 | 411 | ||
| 336 | /* Like malloc routines but check for no memory and block interrupt | 412 | |
| 337 | input.. */ | 413 | /* Like malloc but check for no memory and block interrupt input.. */ |
| 338 | 414 | ||
| 339 | long * | 415 | long * |
| 340 | xmalloc (size) | 416 | xmalloc (size) |
| @@ -351,6 +427,9 @@ xmalloc (size) | |||
| 351 | return val; | 427 | return val; |
| 352 | } | 428 | } |
| 353 | 429 | ||
| 430 | |||
| 431 | /* Like realloc but check for no memory and block interrupt input.. */ | ||
| 432 | |||
| 354 | long * | 433 | long * |
| 355 | xrealloc (block, size) | 434 | xrealloc (block, size) |
| 356 | long *block; | 435 | long *block; |
| @@ -371,6 +450,9 @@ xrealloc (block, size) | |||
| 371 | return val; | 450 | return val; |
| 372 | } | 451 | } |
| 373 | 452 | ||
| 453 | |||
| 454 | /* Like free but block interrupt input.. */ | ||
| 455 | |||
| 374 | void | 456 | void |
| 375 | xfree (block) | 457 | xfree (block) |
| 376 | long *block; | 458 | long *block; |
| @@ -380,24 +462,50 @@ xfree (block) | |||
| 380 | UNBLOCK_INPUT; | 462 | UNBLOCK_INPUT; |
| 381 | } | 463 | } |
| 382 | 464 | ||
| 383 | /* Like malloc but used for allocating Lisp data. */ | ||
| 384 | 465 | ||
| 385 | long * | 466 | /* Like malloc but used for allocating Lisp data. NBYTES is the |
| 386 | lisp_malloc (size) | 467 | number of bytes to allocate, TYPE describes the intended use of the |
| 387 | int size; | 468 | allcated memory block (for strings, for conses, ...). */ |
| 469 | |||
| 470 | static void * | ||
| 471 | lisp_malloc (nbytes, type) | ||
| 472 | int nbytes; | ||
| 473 | enum mem_type type; | ||
| 388 | { | 474 | { |
| 389 | register long *val; | 475 | register void *val; |
| 390 | 476 | ||
| 391 | BLOCK_INPUT; | 477 | BLOCK_INPUT; |
| 392 | allocating_for_lisp++; | 478 | allocating_for_lisp++; |
| 393 | val = (long *) malloc (size); | 479 | val = (void *) malloc (nbytes); |
| 394 | allocating_for_lisp--; | 480 | allocating_for_lisp--; |
| 395 | UNBLOCK_INPUT; | 481 | UNBLOCK_INPUT; |
| 396 | 482 | ||
| 397 | if (!val && size) memory_full (); | 483 | if (!val && nbytes) |
| 484 | memory_full (); | ||
| 485 | |||
| 486 | #if GC_MARK_STACK | ||
| 487 | if (type != MEM_TYPE_NON_LISP) | ||
| 488 | mem_insert (val, (char *) val + nbytes, type); | ||
| 489 | #endif | ||
| 490 | |||
| 398 | return val; | 491 | return val; |
| 399 | } | 492 | } |
| 400 | 493 | ||
| 494 | |||
| 495 | /* Return a new buffer structure allocated from the heap with | ||
| 496 | a call to lisp_malloc. */ | ||
| 497 | |||
| 498 | struct buffer * | ||
| 499 | allocate_buffer () | ||
| 500 | { | ||
| 501 | return (struct buffer *) lisp_malloc (sizeof (struct buffer), | ||
| 502 | MEM_TYPE_BUFFER); | ||
| 503 | } | ||
| 504 | |||
| 505 | |||
| 506 | /* Free BLOCK. This must be called to free memory allocated with a | ||
| 507 | call to lisp_malloc. */ | ||
| 508 | |||
| 401 | void | 509 | void |
| 402 | lisp_free (block) | 510 | lisp_free (block) |
| 403 | long *block; | 511 | long *block; |
| @@ -405,9 +513,13 @@ lisp_free (block) | |||
| 405 | BLOCK_INPUT; | 513 | BLOCK_INPUT; |
| 406 | allocating_for_lisp++; | 514 | allocating_for_lisp++; |
| 407 | free (block); | 515 | free (block); |
| 516 | #if GC_MARK_STACK | ||
| 517 | mem_delete (mem_find (block)); | ||
| 518 | #endif | ||
| 408 | allocating_for_lisp--; | 519 | allocating_for_lisp--; |
| 409 | UNBLOCK_INPUT; | 520 | UNBLOCK_INPUT; |
| 410 | } | 521 | } |
| 522 | |||
| 411 | 523 | ||
| 412 | /* Arranging to disable input signals while we're in malloc. | 524 | /* Arranging to disable input signals while we're in malloc. |
| 413 | 525 | ||
| @@ -453,6 +565,7 @@ emacs_blocked_free (ptr) | |||
| 453 | UNBLOCK_INPUT; | 565 | UNBLOCK_INPUT; |
| 454 | } | 566 | } |
| 455 | 567 | ||
| 568 | |||
| 456 | /* If we released our reserve (due to running out of memory), | 569 | /* If we released our reserve (due to running out of memory), |
| 457 | and we have a fair amount free once again, | 570 | and we have a fair amount free once again, |
| 458 | try to set aside another reserve in case we run out once more. | 571 | try to set aside another reserve in case we run out once more. |
| @@ -466,6 +579,7 @@ refill_memory_reserve () | |||
| 466 | spare_memory = (char *) malloc (SPARE_MEMORY); | 579 | spare_memory = (char *) malloc (SPARE_MEMORY); |
| 467 | } | 580 | } |
| 468 | 581 | ||
| 582 | |||
| 469 | /* This function is the malloc hook that Emacs uses. */ | 583 | /* This function is the malloc hook that Emacs uses. */ |
| 470 | 584 | ||
| 471 | static void * | 585 | static void * |
| @@ -488,6 +602,9 @@ emacs_blocked_malloc (size) | |||
| 488 | return value; | 602 | return value; |
| 489 | } | 603 | } |
| 490 | 604 | ||
| 605 | |||
| 606 | /* This function is the realloc hook that Emacs uses. */ | ||
| 607 | |||
| 491 | static void * | 608 | static void * |
| 492 | emacs_blocked_realloc (ptr, size) | 609 | emacs_blocked_realloc (ptr, size) |
| 493 | void *ptr; | 610 | void *ptr; |
| @@ -504,6 +621,9 @@ emacs_blocked_realloc (ptr, size) | |||
| 504 | return value; | 621 | return value; |
| 505 | } | 622 | } |
| 506 | 623 | ||
| 624 | |||
| 625 | /* Called from main to set up malloc to use our hooks. */ | ||
| 626 | |||
| 507 | void | 627 | void |
| 508 | uninterrupt_malloc () | 628 | uninterrupt_malloc () |
| 509 | { | 629 | { |
| @@ -528,30 +648,52 @@ uninterrupt_malloc () | |||
| 528 | Interval Allocation | 648 | Interval Allocation |
| 529 | ***********************************************************************/ | 649 | ***********************************************************************/ |
| 530 | 650 | ||
| 651 | /* Number of intervals allocated in an interval_block structure. | ||
| 652 | The 1020 is 1024 minus malloc overhead. */ | ||
| 653 | |||
| 531 | #define INTERVAL_BLOCK_SIZE \ | 654 | #define INTERVAL_BLOCK_SIZE \ |
| 532 | ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval)) | 655 | ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval)) |
| 533 | 656 | ||
| 657 | /* Intervals are allocated in chunks in form of an interval_block | ||
| 658 | structure. */ | ||
| 659 | |||
| 534 | struct interval_block | 660 | struct interval_block |
| 535 | { | 661 | { |
| 536 | struct interval_block *next; | 662 | struct interval_block *next; |
| 537 | struct interval intervals[INTERVAL_BLOCK_SIZE]; | 663 | struct interval intervals[INTERVAL_BLOCK_SIZE]; |
| 538 | }; | 664 | }; |
| 539 | 665 | ||
| 666 | /* Current interval block. Its `next' pointer points to older | ||
| 667 | blocks. */ | ||
| 668 | |||
| 540 | struct interval_block *interval_block; | 669 | struct interval_block *interval_block; |
| 670 | |||
| 671 | /* Index in interval_block above of the next unused interval | ||
| 672 | structure. */ | ||
| 673 | |||
| 541 | static int interval_block_index; | 674 | static int interval_block_index; |
| 675 | |||
| 676 | /* Number of free and live intervals. */ | ||
| 677 | |||
| 542 | static int total_free_intervals, total_intervals; | 678 | static int total_free_intervals, total_intervals; |
| 543 | 679 | ||
| 680 | /* List of free intervals. */ | ||
| 681 | |||
| 544 | INTERVAL interval_free_list; | 682 | INTERVAL interval_free_list; |
| 545 | 683 | ||
| 546 | /* Total number of interval blocks now in use. */ | 684 | /* Total number of interval blocks now in use. */ |
| 547 | 685 | ||
| 548 | int n_interval_blocks; | 686 | int n_interval_blocks; |
| 549 | 687 | ||
| 688 | |||
| 689 | /* Initialize interval allocation. */ | ||
| 690 | |||
| 550 | static void | 691 | static void |
| 551 | init_intervals () | 692 | init_intervals () |
| 552 | { | 693 | { |
| 553 | interval_block | 694 | interval_block |
| 554 | = (struct interval_block *) lisp_malloc (sizeof (struct interval_block)); | 695 | = (struct interval_block *) lisp_malloc (sizeof *interval_block, |
| 696 | MEM_TYPE_NON_LISP); | ||
| 555 | interval_block->next = 0; | 697 | interval_block->next = 0; |
| 556 | bzero ((char *) interval_block->intervals, sizeof interval_block->intervals); | 698 | bzero ((char *) interval_block->intervals, sizeof interval_block->intervals); |
| 557 | interval_block_index = 0; | 699 | interval_block_index = 0; |
| @@ -559,7 +701,8 @@ init_intervals () | |||
| 559 | n_interval_blocks = 1; | 701 | n_interval_blocks = 1; |
| 560 | } | 702 | } |
| 561 | 703 | ||
| 562 | #define INIT_INTERVALS init_intervals () | 704 | |
| 705 | /* Return a new interval. */ | ||
| 563 | 706 | ||
| 564 | INTERVAL | 707 | INTERVAL |
| 565 | make_interval () | 708 | make_interval () |
| @@ -577,7 +720,8 @@ make_interval () | |||
| 577 | { | 720 | { |
| 578 | register struct interval_block *newi; | 721 | register struct interval_block *newi; |
| 579 | 722 | ||
| 580 | newi = (struct interval_block *) lisp_malloc (sizeof (struct interval_block)); | 723 | newi = (struct interval_block *) lisp_malloc (sizeof *newi, |
| 724 | MEM_TYPE_NON_LISP); | ||
| 581 | 725 | ||
| 582 | VALIDATE_LISP_STORAGE (newi, sizeof *newi); | 726 | VALIDATE_LISP_STORAGE (newi, sizeof *newi); |
| 583 | newi->next = interval_block; | 727 | newi->next = interval_block; |
| @@ -593,7 +737,8 @@ make_interval () | |||
| 593 | return val; | 737 | return val; |
| 594 | } | 738 | } |
| 595 | 739 | ||
| 596 | /* Mark the pointers of one interval. */ | 740 | |
| 741 | /* Mark Lisp objects in interval I. */ | ||
| 597 | 742 | ||
| 598 | static void | 743 | static void |
| 599 | mark_interval (i, dummy) | 744 | mark_interval (i, dummy) |
| @@ -606,6 +751,10 @@ mark_interval (i, dummy) | |||
| 606 | XMARK (i->plist); | 751 | XMARK (i->plist); |
| 607 | } | 752 | } |
| 608 | 753 | ||
| 754 | |||
| 755 | /* Mark the interval tree rooted in TREE. Don't call this directly; | ||
| 756 | use the macro MARK_INTERVAL_TREE instead. */ | ||
| 757 | |||
| 609 | static void | 758 | static void |
| 610 | mark_interval_tree (tree) | 759 | mark_interval_tree (tree) |
| 611 | register INTERVAL tree; | 760 | register INTERVAL tree; |
| @@ -621,6 +770,9 @@ mark_interval_tree (tree) | |||
| 621 | traverse_intervals (tree, 1, 0, mark_interval, Qnil); | 770 | traverse_intervals (tree, 1, 0, mark_interval, Qnil); |
| 622 | } | 771 | } |
| 623 | 772 | ||
| 773 | |||
| 774 | /* Mark the interval tree rooted in I. */ | ||
| 775 | |||
| 624 | #define MARK_INTERVAL_TREE(i) \ | 776 | #define MARK_INTERVAL_TREE(i) \ |
| 625 | do { \ | 777 | do { \ |
| 626 | if (!NULL_INTERVAL_P (i) \ | 778 | if (!NULL_INTERVAL_P (i) \ |
| @@ -628,6 +780,7 @@ mark_interval_tree (tree) | |||
| 628 | mark_interval_tree (i); \ | 780 | mark_interval_tree (i); \ |
| 629 | } while (0) | 781 | } while (0) |
| 630 | 782 | ||
| 783 | |||
| 631 | /* The oddity in the call to XUNMARK is necessary because XUNMARK | 784 | /* The oddity in the call to XUNMARK is necessary because XUNMARK |
| 632 | expands to an assignment to its argument, and most C compilers | 785 | expands to an assignment to its argument, and most C compilers |
| 633 | don't support casts on the left operand of `='. */ | 786 | don't support casts on the left operand of `='. */ |
| @@ -641,6 +794,7 @@ mark_interval_tree (tree) | |||
| 641 | } \ | 794 | } \ |
| 642 | } while (0) | 795 | } while (0) |
| 643 | 796 | ||
| 797 | |||
| 644 | 798 | ||
| 645 | /*********************************************************************** | 799 | /*********************************************************************** |
| 646 | String Allocation | 800 | String Allocation |
| @@ -686,7 +840,7 @@ struct sdata | |||
| 686 | { | 840 | { |
| 687 | /* Back-pointer to the string this sdata belongs to. If null, this | 841 | /* Back-pointer to the string this sdata belongs to. If null, this |
| 688 | structure is free, and the NBYTES member of the union below | 842 | structure is free, and the NBYTES member of the union below |
| 689 | contains the string byte size (the same value that STRING_BYTES | 843 | contains the string's byte size (the same value that STRING_BYTES |
| 690 | would return if STRING were non-null). If non-null, STRING_BYTES | 844 | would return if STRING were non-null). If non-null, STRING_BYTES |
| 691 | (STRING) is the size of the data, and DATA contains the string's | 845 | (STRING) is the size of the data, and DATA contains the string's |
| 692 | contents. */ | 846 | contents. */ |
| @@ -814,7 +968,7 @@ allocate_string () | |||
| 814 | struct string_block *b; | 968 | struct string_block *b; |
| 815 | int i; | 969 | int i; |
| 816 | 970 | ||
| 817 | b = (struct string_block *) lisp_malloc (sizeof *b); | 971 | b = (struct string_block *) lisp_malloc (sizeof *b, MEM_TYPE_STRING); |
| 818 | VALIDATE_LISP_STORAGE (b, sizeof *b); | 972 | VALIDATE_LISP_STORAGE (b, sizeof *b); |
| 819 | bzero (b, sizeof *b); | 973 | bzero (b, sizeof *b); |
| 820 | b->next = string_blocks; | 974 | b->next = string_blocks; |
| @@ -875,7 +1029,7 @@ allocate_string_data (s, nchars, nbytes) | |||
| 875 | mallopt (M_MMAP_MAX, 0); | 1029 | mallopt (M_MMAP_MAX, 0); |
| 876 | #endif | 1030 | #endif |
| 877 | 1031 | ||
| 878 | b = (struct sblock *) lisp_malloc (size); | 1032 | b = (struct sblock *) lisp_malloc (size, MEM_TYPE_NON_LISP); |
| 879 | 1033 | ||
| 880 | #ifdef DOUG_LEA_MALLOC | 1034 | #ifdef DOUG_LEA_MALLOC |
| 881 | /* Back to a reasonable maximum of mmap'ed areas. */ | 1035 | /* Back to a reasonable maximum of mmap'ed areas. */ |
| @@ -893,7 +1047,7 @@ allocate_string_data (s, nchars, nbytes) | |||
| 893 | < needed)) | 1047 | < needed)) |
| 894 | { | 1048 | { |
| 895 | /* Not enough room in the current sblock. */ | 1049 | /* Not enough room in the current sblock. */ |
| 896 | b = (struct sblock *) lisp_malloc (SBLOCK_SIZE); | 1050 | b = (struct sblock *) lisp_malloc (SBLOCK_SIZE, MEM_TYPE_NON_LISP); |
| 897 | b->next_free = &b->first_data; | 1051 | b->next_free = &b->first_data; |
| 898 | b->first_data.string = NULL; | 1052 | b->first_data.string = NULL; |
| 899 | b->next = NULL; | 1053 | b->next = NULL; |
| @@ -997,7 +1151,7 @@ sweep_strings () | |||
| 997 | } | 1151 | } |
| 998 | } | 1152 | } |
| 999 | 1153 | ||
| 1000 | /* Free blocks that are contain free Lisp_Strings only, except | 1154 | /* Free blocks that contain free Lisp_Strings only, except |
| 1001 | the first two of them. */ | 1155 | the first two of them. */ |
| 1002 | if (nfree == STRINGS_IN_STRING_BLOCK | 1156 | if (nfree == STRINGS_IN_STRING_BLOCK |
| 1003 | && total_free_strings > STRINGS_IN_STRING_BLOCK) | 1157 | && total_free_strings > STRINGS_IN_STRING_BLOCK) |
| @@ -1190,6 +1344,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil.") | |||
| 1190 | slot `size' of the struct Lisp_Bool_Vector. */ | 1344 | slot `size' of the struct Lisp_Bool_Vector. */ |
| 1191 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); | 1345 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); |
| 1192 | p = XBOOL_VECTOR (val); | 1346 | p = XBOOL_VECTOR (val); |
| 1347 | |||
| 1193 | /* Get rid of any bits that would cause confusion. */ | 1348 | /* Get rid of any bits that would cause confusion. */ |
| 1194 | p->vector_size = 0; | 1349 | p->vector_size = 0; |
| 1195 | XSETBOOL_VECTOR (val, p); | 1350 | XSETBOOL_VECTOR (val, p); |
| @@ -1198,6 +1353,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil.") | |||
| 1198 | real_init = (NILP (init) ? 0 : -1); | 1353 | real_init = (NILP (init) ? 0 : -1); |
| 1199 | for (i = 0; i < length_in_chars ; i++) | 1354 | for (i = 0; i < length_in_chars ; i++) |
| 1200 | p->data[i] = real_init; | 1355 | p->data[i] = real_init; |
| 1356 | |||
| 1201 | /* Clear the extraneous bits in the last byte. */ | 1357 | /* Clear the extraneous bits in the last byte. */ |
| 1202 | if (XINT (length) != length_in_chars * BITS_PER_CHAR) | 1358 | if (XINT (length) != length_in_chars * BITS_PER_CHAR) |
| 1203 | XBOOL_VECTOR (val)->data[length_in_chars - 1] | 1359 | XBOOL_VECTOR (val)->data[length_in_chars - 1] |
| @@ -1361,19 +1517,30 @@ struct float_block | |||
| 1361 | struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; | 1517 | struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; |
| 1362 | }; | 1518 | }; |
| 1363 | 1519 | ||
| 1520 | /* Current float_block. */ | ||
| 1521 | |||
| 1364 | struct float_block *float_block; | 1522 | struct float_block *float_block; |
| 1523 | |||
| 1524 | /* Index of first unused Lisp_Float in the current float_block. */ | ||
| 1525 | |||
| 1365 | int float_block_index; | 1526 | int float_block_index; |
| 1366 | 1527 | ||
| 1367 | /* Total number of float blocks now in use. */ | 1528 | /* Total number of float blocks now in use. */ |
| 1368 | 1529 | ||
| 1369 | int n_float_blocks; | 1530 | int n_float_blocks; |
| 1370 | 1531 | ||
| 1532 | /* Free-list of Lisp_Floats. */ | ||
| 1533 | |||
| 1371 | struct Lisp_Float *float_free_list; | 1534 | struct Lisp_Float *float_free_list; |
| 1372 | 1535 | ||
| 1536 | |||
| 1537 | /* Initialze float allocation. */ | ||
| 1538 | |||
| 1373 | void | 1539 | void |
| 1374 | init_float () | 1540 | init_float () |
| 1375 | { | 1541 | { |
| 1376 | float_block = (struct float_block *) lisp_malloc (sizeof (struct float_block)); | 1542 | float_block = (struct float_block *) lisp_malloc (sizeof *float_block, |
| 1543 | MEM_TYPE_FLOAT); | ||
| 1377 | float_block->next = 0; | 1544 | float_block->next = 0; |
| 1378 | bzero ((char *) float_block->floats, sizeof float_block->floats); | 1545 | bzero ((char *) float_block->floats, sizeof float_block->floats); |
| 1379 | float_block_index = 0; | 1546 | float_block_index = 0; |
| @@ -1381,16 +1548,23 @@ init_float () | |||
| 1381 | n_float_blocks = 1; | 1548 | n_float_blocks = 1; |
| 1382 | } | 1549 | } |
| 1383 | 1550 | ||
| 1384 | /* Explicitly free a float cell. */ | 1551 | |
| 1552 | /* Explicitly free a float cell by putting it on the free-list. */ | ||
| 1385 | 1553 | ||
| 1386 | void | 1554 | void |
| 1387 | free_float (ptr) | 1555 | free_float (ptr) |
| 1388 | struct Lisp_Float *ptr; | 1556 | struct Lisp_Float *ptr; |
| 1389 | { | 1557 | { |
| 1390 | *(struct Lisp_Float **)&ptr->data = float_free_list; | 1558 | *(struct Lisp_Float **)&ptr->data = float_free_list; |
| 1559 | #if GC_MARK_STACK | ||
| 1560 | ptr->type = Vdead; | ||
| 1561 | #endif | ||
| 1391 | float_free_list = ptr; | 1562 | float_free_list = ptr; |
| 1392 | } | 1563 | } |
| 1393 | 1564 | ||
| 1565 | |||
| 1566 | /* Return a new float object with value FLOAT_VALUE. */ | ||
| 1567 | |||
| 1394 | Lisp_Object | 1568 | Lisp_Object |
| 1395 | make_float (float_value) | 1569 | make_float (float_value) |
| 1396 | double float_value; | 1570 | double float_value; |
| @@ -1410,7 +1584,8 @@ make_float (float_value) | |||
| 1410 | { | 1584 | { |
| 1411 | register struct float_block *new; | 1585 | register struct float_block *new; |
| 1412 | 1586 | ||
| 1413 | new = (struct float_block *) lisp_malloc (sizeof (struct float_block)); | 1587 | new = (struct float_block *) lisp_malloc (sizeof *new, |
| 1588 | MEM_TYPE_FLOAT); | ||
| 1414 | VALIDATE_LISP_STORAGE (new, sizeof *new); | 1589 | VALIDATE_LISP_STORAGE (new, sizeof *new); |
| 1415 | new->next = float_block; | 1590 | new->next = float_block; |
| 1416 | float_block = new; | 1591 | float_block = new; |
| @@ -1451,19 +1626,30 @@ struct cons_block | |||
| 1451 | struct Lisp_Cons conses[CONS_BLOCK_SIZE]; | 1626 | struct Lisp_Cons conses[CONS_BLOCK_SIZE]; |
| 1452 | }; | 1627 | }; |
| 1453 | 1628 | ||
| 1629 | /* Current cons_block. */ | ||
| 1630 | |||
| 1454 | struct cons_block *cons_block; | 1631 | struct cons_block *cons_block; |
| 1632 | |||
| 1633 | /* Index of first unused Lisp_Cons in the current block. */ | ||
| 1634 | |||
| 1455 | int cons_block_index; | 1635 | int cons_block_index; |
| 1456 | 1636 | ||
| 1637 | /* Free-list of Lisp_Cons structures. */ | ||
| 1638 | |||
| 1457 | struct Lisp_Cons *cons_free_list; | 1639 | struct Lisp_Cons *cons_free_list; |
| 1458 | 1640 | ||
| 1459 | /* Total number of cons blocks now in use. */ | 1641 | /* Total number of cons blocks now in use. */ |
| 1460 | 1642 | ||
| 1461 | int n_cons_blocks; | 1643 | int n_cons_blocks; |
| 1462 | 1644 | ||
| 1645 | |||
| 1646 | /* Initialize cons allocation. */ | ||
| 1647 | |||
| 1463 | void | 1648 | void |
| 1464 | init_cons () | 1649 | init_cons () |
| 1465 | { | 1650 | { |
| 1466 | cons_block = (struct cons_block *) lisp_malloc (sizeof (struct cons_block)); | 1651 | cons_block = (struct cons_block *) lisp_malloc (sizeof *cons_block, |
| 1652 | MEM_TYPE_CONS); | ||
| 1467 | cons_block->next = 0; | 1653 | cons_block->next = 0; |
| 1468 | bzero ((char *) cons_block->conses, sizeof cons_block->conses); | 1654 | bzero ((char *) cons_block->conses, sizeof cons_block->conses); |
| 1469 | cons_block_index = 0; | 1655 | cons_block_index = 0; |
| @@ -1471,16 +1657,21 @@ init_cons () | |||
| 1471 | n_cons_blocks = 1; | 1657 | n_cons_blocks = 1; |
| 1472 | } | 1658 | } |
| 1473 | 1659 | ||
| 1474 | /* Explicitly free a cons cell. */ | 1660 | |
| 1661 | /* Explicitly free a cons cell by putting it on the free-list. */ | ||
| 1475 | 1662 | ||
| 1476 | void | 1663 | void |
| 1477 | free_cons (ptr) | 1664 | free_cons (ptr) |
| 1478 | struct Lisp_Cons *ptr; | 1665 | struct Lisp_Cons *ptr; |
| 1479 | { | 1666 | { |
| 1480 | *(struct Lisp_Cons **)&ptr->cdr = cons_free_list; | 1667 | *(struct Lisp_Cons **)&ptr->cdr = cons_free_list; |
| 1668 | #if GC_MARK_STACK | ||
| 1669 | ptr->car = Vdead; | ||
| 1670 | #endif | ||
| 1481 | cons_free_list = ptr; | 1671 | cons_free_list = ptr; |
| 1482 | } | 1672 | } |
| 1483 | 1673 | ||
| 1674 | |||
| 1484 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 1675 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, |
| 1485 | "Create a new cons, give it CAR and CDR as components, and return it.") | 1676 | "Create a new cons, give it CAR and CDR as components, and return it.") |
| 1486 | (car, cdr) | 1677 | (car, cdr) |
| @@ -1500,7 +1691,8 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 1500 | if (cons_block_index == CONS_BLOCK_SIZE) | 1691 | if (cons_block_index == CONS_BLOCK_SIZE) |
| 1501 | { | 1692 | { |
| 1502 | register struct cons_block *new; | 1693 | register struct cons_block *new; |
| 1503 | new = (struct cons_block *) lisp_malloc (sizeof (struct cons_block)); | 1694 | new = (struct cons_block *) lisp_malloc (sizeof *new, |
| 1695 | MEM_TYPE_CONS); | ||
| 1504 | VALIDATE_LISP_STORAGE (new, sizeof *new); | 1696 | VALIDATE_LISP_STORAGE (new, sizeof *new); |
| 1505 | new->next = cons_block; | 1697 | new->next = cons_block; |
| 1506 | cons_block = new; | 1698 | cons_block = new; |
| @@ -1517,7 +1709,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 1517 | return val; | 1709 | return val; |
| 1518 | } | 1710 | } |
| 1519 | 1711 | ||
| 1520 | 1712 | ||
| 1521 | /* Make a list of 2, 3, 4 or 5 specified objects. */ | 1713 | /* Make a list of 2, 3, 4 or 5 specified objects. */ |
| 1522 | 1714 | ||
| 1523 | Lisp_Object | 1715 | Lisp_Object |
| @@ -1527,6 +1719,7 @@ list2 (arg1, arg2) | |||
| 1527 | return Fcons (arg1, Fcons (arg2, Qnil)); | 1719 | return Fcons (arg1, Fcons (arg2, Qnil)); |
| 1528 | } | 1720 | } |
| 1529 | 1721 | ||
| 1722 | |||
| 1530 | Lisp_Object | 1723 | Lisp_Object |
| 1531 | list3 (arg1, arg2, arg3) | 1724 | list3 (arg1, arg2, arg3) |
| 1532 | Lisp_Object arg1, arg2, arg3; | 1725 | Lisp_Object arg1, arg2, arg3; |
| @@ -1534,6 +1727,7 @@ list3 (arg1, arg2, arg3) | |||
| 1534 | return Fcons (arg1, Fcons (arg2, Fcons (arg3, Qnil))); | 1727 | return Fcons (arg1, Fcons (arg2, Fcons (arg3, Qnil))); |
| 1535 | } | 1728 | } |
| 1536 | 1729 | ||
| 1730 | |||
| 1537 | Lisp_Object | 1731 | Lisp_Object |
| 1538 | list4 (arg1, arg2, arg3, arg4) | 1732 | list4 (arg1, arg2, arg3, arg4) |
| 1539 | Lisp_Object arg1, arg2, arg3, arg4; | 1733 | Lisp_Object arg1, arg2, arg3, arg4; |
| @@ -1541,6 +1735,7 @@ list4 (arg1, arg2, arg3, arg4) | |||
| 1541 | return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4, Qnil)))); | 1735 | return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4, Qnil)))); |
| 1542 | } | 1736 | } |
| 1543 | 1737 | ||
| 1738 | |||
| 1544 | Lisp_Object | 1739 | Lisp_Object |
| 1545 | list5 (arg1, arg2, arg3, arg4, arg5) | 1740 | list5 (arg1, arg2, arg3, arg4, arg5) |
| 1546 | Lisp_Object arg1, arg2, arg3, arg4, arg5; | 1741 | Lisp_Object arg1, arg2, arg3, arg4, arg5; |
| @@ -1549,6 +1744,7 @@ list5 (arg1, arg2, arg3, arg4, arg5) | |||
| 1549 | Fcons (arg5, Qnil))))); | 1744 | Fcons (arg5, Qnil))))); |
| 1550 | } | 1745 | } |
| 1551 | 1746 | ||
| 1747 | |||
| 1552 | DEFUN ("list", Flist, Slist, 0, MANY, 0, | 1748 | DEFUN ("list", Flist, Slist, 0, MANY, 0, |
| 1553 | "Return a newly created list with specified arguments as elements.\n\ | 1749 | "Return a newly created list with specified arguments as elements.\n\ |
| 1554 | Any number of arguments, even zero arguments, are allowed.") | 1750 | Any number of arguments, even zero arguments, are allowed.") |
| @@ -1567,6 +1763,7 @@ Any number of arguments, even zero arguments, are allowed.") | |||
| 1567 | return val; | 1763 | return val; |
| 1568 | } | 1764 | } |
| 1569 | 1765 | ||
| 1766 | |||
| 1570 | DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | 1767 | DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, |
| 1571 | "Return a newly created list of length LENGTH, with each element being INIT.") | 1768 | "Return a newly created list of length LENGTH, with each element being INIT.") |
| 1572 | (length, init) | 1769 | (length, init) |
| @@ -1590,39 +1787,49 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | |||
| 1590 | Vector Allocation | 1787 | Vector Allocation |
| 1591 | ***********************************************************************/ | 1788 | ***********************************************************************/ |
| 1592 | 1789 | ||
| 1790 | /* Singly-linked list of all vectors. */ | ||
| 1791 | |||
| 1593 | struct Lisp_Vector *all_vectors; | 1792 | struct Lisp_Vector *all_vectors; |
| 1594 | 1793 | ||
| 1595 | /* Total number of vector-like objects now in use. */ | 1794 | /* Total number of vector-like objects now in use. */ |
| 1596 | 1795 | ||
| 1597 | int n_vectors; | 1796 | int n_vectors; |
| 1598 | 1797 | ||
| 1798 | |||
| 1799 | /* Value is a pointer to a newly allocated Lisp_Vector structure | ||
| 1800 | with room for LEN Lisp_Objects. */ | ||
| 1801 | |||
| 1599 | struct Lisp_Vector * | 1802 | struct Lisp_Vector * |
| 1600 | allocate_vectorlike (len) | 1803 | allocate_vectorlike (len) |
| 1601 | EMACS_INT len; | 1804 | EMACS_INT len; |
| 1602 | { | 1805 | { |
| 1603 | struct Lisp_Vector *p; | 1806 | struct Lisp_Vector *p; |
| 1807 | int nbytes; | ||
| 1604 | 1808 | ||
| 1605 | #ifdef DOUG_LEA_MALLOC | 1809 | #ifdef DOUG_LEA_MALLOC |
| 1606 | /* Prevent mmap'ing the chunk (which is potentially very large).. */ | 1810 | /* Prevent mmap'ing the chunk (which is potentially very large).. */ |
| 1607 | mallopt (M_MMAP_MAX, 0); | 1811 | mallopt (M_MMAP_MAX, 0); |
| 1608 | #endif | 1812 | #endif |
| 1609 | p = (struct Lisp_Vector *)lisp_malloc (sizeof (struct Lisp_Vector) | 1813 | |
| 1610 | + (len - 1) * sizeof (Lisp_Object)); | 1814 | nbytes = sizeof *p + (len - 1) * sizeof p->contents[0]; |
| 1815 | p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTOR); | ||
| 1816 | |||
| 1611 | #ifdef DOUG_LEA_MALLOC | 1817 | #ifdef DOUG_LEA_MALLOC |
| 1612 | /* Back to a reasonable maximum of mmap'ed areas. */ | 1818 | /* Back to a reasonable maximum of mmap'ed areas. */ |
| 1613 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | 1819 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); |
| 1614 | #endif | 1820 | #endif |
| 1821 | |||
| 1615 | VALIDATE_LISP_STORAGE (p, 0); | 1822 | VALIDATE_LISP_STORAGE (p, 0); |
| 1616 | consing_since_gc += (sizeof (struct Lisp_Vector) | 1823 | consing_since_gc += nbytes; |
| 1617 | + (len - 1) * sizeof (Lisp_Object)); | ||
| 1618 | vector_cells_consed += len; | 1824 | vector_cells_consed += len; |
| 1619 | n_vectors++; | ||
| 1620 | 1825 | ||
| 1621 | p->next = all_vectors; | 1826 | p->next = all_vectors; |
| 1622 | all_vectors = p; | 1827 | all_vectors = p; |
| 1828 | ++n_vectors; | ||
| 1623 | return p; | 1829 | return p; |
| 1624 | } | 1830 | } |
| 1625 | 1831 | ||
| 1832 | |||
| 1626 | DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, | 1833 | DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, |
| 1627 | "Return a newly created vector of length LENGTH, with each element being INIT.\n\ | 1834 | "Return a newly created vector of length LENGTH, with each element being INIT.\n\ |
| 1628 | See also the function `vector'.") | 1835 | See also the function `vector'.") |
| @@ -1646,6 +1853,7 @@ See also the function `vector'.") | |||
| 1646 | return vector; | 1853 | return vector; |
| 1647 | } | 1854 | } |
| 1648 | 1855 | ||
| 1856 | |||
| 1649 | DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0, | 1857 | DEFUN ("make-char-table", Fmake_char_table, Smake_char_table, 1, 2, 0, |
| 1650 | "Return a newly created char-table, with purpose PURPOSE.\n\ | 1858 | "Return a newly created char-table, with purpose PURPOSE.\n\ |
| 1651 | Each element is initialized to INIT, which defaults to nil.\n\ | 1859 | Each element is initialized to INIT, which defaults to nil.\n\ |
| @@ -1671,6 +1879,7 @@ The property's value should be an integer between 0 and 10.") | |||
| 1671 | return vector; | 1879 | return vector; |
| 1672 | } | 1880 | } |
| 1673 | 1881 | ||
| 1882 | |||
| 1674 | /* Return a newly created sub char table with default value DEFALT. | 1883 | /* Return a newly created sub char table with default value DEFALT. |
| 1675 | Since a sub char table does not appear as a top level Emacs Lisp | 1884 | Since a sub char table does not appear as a top level Emacs Lisp |
| 1676 | object, we don't need a Lisp interface to make it. */ | 1885 | object, we don't need a Lisp interface to make it. */ |
| @@ -1687,6 +1896,7 @@ make_sub_char_table (defalt) | |||
| 1687 | return vector; | 1896 | return vector; |
| 1688 | } | 1897 | } |
| 1689 | 1898 | ||
| 1899 | |||
| 1690 | DEFUN ("vector", Fvector, Svector, 0, MANY, 0, | 1900 | DEFUN ("vector", Fvector, Svector, 0, MANY, 0, |
| 1691 | "Return a newly created vector with specified arguments as elements.\n\ | 1901 | "Return a newly created vector with specified arguments as elements.\n\ |
| 1692 | Any number of arguments, even zero arguments, are allowed.") | 1902 | Any number of arguments, even zero arguments, are allowed.") |
| @@ -1706,6 +1916,7 @@ Any number of arguments, even zero arguments, are allowed.") | |||
| 1706 | return val; | 1916 | return val; |
| 1707 | } | 1917 | } |
| 1708 | 1918 | ||
| 1919 | |||
| 1709 | DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, | 1920 | DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, |
| 1710 | "Create a byte-code object with specified arguments as elements.\n\ | 1921 | "Create a byte-code object with specified arguments as elements.\n\ |
| 1711 | The arguments should be the arglist, bytecode-string, constant vector,\n\ | 1922 | The arguments should be the arglist, bytecode-string, constant vector,\n\ |
| @@ -1736,6 +1947,7 @@ significance.") | |||
| 1736 | return val; | 1947 | return val; |
| 1737 | } | 1948 | } |
| 1738 | 1949 | ||
| 1950 | |||
| 1739 | 1951 | ||
| 1740 | /*********************************************************************** | 1952 | /*********************************************************************** |
| 1741 | Symbol Allocation | 1953 | Symbol Allocation |
| @@ -1754,19 +1966,28 @@ struct symbol_block | |||
| 1754 | struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; | 1966 | struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; |
| 1755 | }; | 1967 | }; |
| 1756 | 1968 | ||
| 1969 | /* Current symbol block and index of first unused Lisp_Symbol | ||
| 1970 | structure in it. */ | ||
| 1971 | |||
| 1757 | struct symbol_block *symbol_block; | 1972 | struct symbol_block *symbol_block; |
| 1758 | int symbol_block_index; | 1973 | int symbol_block_index; |
| 1759 | 1974 | ||
| 1975 | /* List of free symbols. */ | ||
| 1976 | |||
| 1760 | struct Lisp_Symbol *symbol_free_list; | 1977 | struct Lisp_Symbol *symbol_free_list; |
| 1761 | 1978 | ||
| 1762 | /* Total number of symbol blocks now in use. */ | 1979 | /* Total number of symbol blocks now in use. */ |
| 1763 | 1980 | ||
| 1764 | int n_symbol_blocks; | 1981 | int n_symbol_blocks; |
| 1765 | 1982 | ||
| 1983 | |||
| 1984 | /* Initialize symbol allocation. */ | ||
| 1985 | |||
| 1766 | void | 1986 | void |
| 1767 | init_symbol () | 1987 | init_symbol () |
| 1768 | { | 1988 | { |
| 1769 | symbol_block = (struct symbol_block *) lisp_malloc (sizeof (struct symbol_block)); | 1989 | symbol_block = (struct symbol_block *) lisp_malloc (sizeof *symbol_block, |
| 1990 | MEM_TYPE_SYMBOL); | ||
| 1770 | symbol_block->next = 0; | 1991 | symbol_block->next = 0; |
| 1771 | bzero ((char *) symbol_block->symbols, sizeof symbol_block->symbols); | 1992 | bzero ((char *) symbol_block->symbols, sizeof symbol_block->symbols); |
| 1772 | symbol_block_index = 0; | 1993 | symbol_block_index = 0; |
| @@ -1774,6 +1995,7 @@ init_symbol () | |||
| 1774 | n_symbol_blocks = 1; | 1995 | n_symbol_blocks = 1; |
| 1775 | } | 1996 | } |
| 1776 | 1997 | ||
| 1998 | |||
| 1777 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, | 1999 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, |
| 1778 | "Return a newly allocated uninterned symbol whose name is NAME.\n\ | 2000 | "Return a newly allocated uninterned symbol whose name is NAME.\n\ |
| 1779 | Its value and function definition are void, and its property list is nil.") | 2001 | Its value and function definition are void, and its property list is nil.") |
| @@ -1795,7 +2017,8 @@ Its value and function definition are void, and its property list is nil.") | |||
| 1795 | if (symbol_block_index == SYMBOL_BLOCK_SIZE) | 2017 | if (symbol_block_index == SYMBOL_BLOCK_SIZE) |
| 1796 | { | 2018 | { |
| 1797 | struct symbol_block *new; | 2019 | struct symbol_block *new; |
| 1798 | new = (struct symbol_block *) lisp_malloc (sizeof (struct symbol_block)); | 2020 | new = (struct symbol_block *) lisp_malloc (sizeof *new, |
| 2021 | MEM_TYPE_SYMBOL); | ||
| 1799 | VALIDATE_LISP_STORAGE (new, sizeof *new); | 2022 | VALIDATE_LISP_STORAGE (new, sizeof *new); |
| 1800 | new->next = symbol_block; | 2023 | new->next = symbol_block; |
| 1801 | symbol_block = new; | 2024 | symbol_block = new; |
| @@ -1820,7 +2043,7 @@ Its value and function definition are void, and its property list is nil.") | |||
| 1820 | 2043 | ||
| 1821 | 2044 | ||
| 1822 | /*********************************************************************** | 2045 | /*********************************************************************** |
| 1823 | Marker Allocation | 2046 | Marker (Misc) Allocation |
| 1824 | ***********************************************************************/ | 2047 | ***********************************************************************/ |
| 1825 | 2048 | ||
| 1826 | /* Allocation of markers and other objects that share that structure. | 2049 | /* Allocation of markers and other objects that share that structure. |
| @@ -1847,7 +2070,8 @@ int n_marker_blocks; | |||
| 1847 | void | 2070 | void |
| 1848 | init_marker () | 2071 | init_marker () |
| 1849 | { | 2072 | { |
| 1850 | marker_block = (struct marker_block *) lisp_malloc (sizeof (struct marker_block)); | 2073 | marker_block = (struct marker_block *) lisp_malloc (sizeof *marker_block, |
| 2074 | MEM_TYPE_MISC); | ||
| 1851 | marker_block->next = 0; | 2075 | marker_block->next = 0; |
| 1852 | bzero ((char *) marker_block->markers, sizeof marker_block->markers); | 2076 | bzero ((char *) marker_block->markers, sizeof marker_block->markers); |
| 1853 | marker_block_index = 0; | 2077 | marker_block_index = 0; |
| @@ -1872,7 +2096,8 @@ allocate_misc () | |||
| 1872 | if (marker_block_index == MARKER_BLOCK_SIZE) | 2096 | if (marker_block_index == MARKER_BLOCK_SIZE) |
| 1873 | { | 2097 | { |
| 1874 | struct marker_block *new; | 2098 | struct marker_block *new; |
| 1875 | new = (struct marker_block *) lisp_malloc (sizeof (struct marker_block)); | 2099 | new = (struct marker_block *) lisp_malloc (sizeof *new, |
| 2100 | MEM_TYPE_MISC); | ||
| 1876 | VALIDATE_LISP_STORAGE (new, sizeof *new); | 2101 | VALIDATE_LISP_STORAGE (new, sizeof *new); |
| 1877 | new->next = marker_block; | 2102 | new->next = marker_block; |
| 1878 | marker_block = new; | 2103 | marker_block = new; |
| @@ -1962,6 +2187,816 @@ make_event_array (nargs, args) | |||
| 1962 | 2187 | ||
| 1963 | 2188 | ||
| 1964 | 2189 | ||
| 2190 | /************************************************************************ | ||
| 2191 | C Stack Marking | ||
| 2192 | ************************************************************************/ | ||
| 2193 | |||
| 2194 | #if GC_MARK_STACK | ||
| 2195 | |||
| 2196 | |||
| 2197 | /* Base address of stack. Set in main. */ | ||
| 2198 | |||
| 2199 | Lisp_Object *stack_base; | ||
| 2200 | |||
| 2201 | /* A node in the red-black tree describing allocated memory containing | ||
| 2202 | Lisp data. Each such block is recorded with its start and end | ||
| 2203 | address when it is allocated, and removed from the tree when it | ||
| 2204 | is freed. | ||
| 2205 | |||
| 2206 | A red-black tree is a balanced binary tree with the following | ||
| 2207 | properties: | ||
| 2208 | |||
| 2209 | 1. Every node is either red or black. | ||
| 2210 | 2. Every leaf is black. | ||
| 2211 | 3. If a node is red, then both of its children are black. | ||
| 2212 | 4. Every simple path from a node to a descendant leaf contains | ||
| 2213 | the same number of black nodes. | ||
| 2214 | 5. The root is always black. | ||
| 2215 | |||
| 2216 | When nodes are inserted into the tree, or deleted from the tree, | ||
| 2217 | the tree is "fixed" so that these properties are always true. | ||
| 2218 | |||
| 2219 | A red-black tree with N internal nodes has height at most 2 | ||
| 2220 | log(N+1). Searches, insertions and deletions are done in O(log N). | ||
| 2221 | Please see a text book about data structures for a detailed | ||
| 2222 | description of red-black trees. Any book worth its salt should | ||
| 2223 | describe them. */ | ||
| 2224 | |||
| 2225 | struct mem_node | ||
| 2226 | { | ||
| 2227 | struct mem_node *left, *right, *parent; | ||
| 2228 | |||
| 2229 | /* Start and end of allocated region. */ | ||
| 2230 | void *start, *end; | ||
| 2231 | |||
| 2232 | /* Node color. */ | ||
| 2233 | enum {MEM_BLACK, MEM_RED} color; | ||
| 2234 | |||
| 2235 | /* Memory type. */ | ||
| 2236 | enum mem_type type; | ||
| 2237 | }; | ||
| 2238 | |||
| 2239 | /* Root of the tree describing allocated Lisp memory. */ | ||
| 2240 | |||
| 2241 | static struct mem_node *mem_root; | ||
| 2242 | |||
| 2243 | /* Sentinel node of the tree. */ | ||
| 2244 | |||
| 2245 | static struct mem_node mem_z; | ||
| 2246 | #define MEM_NIL &mem_z | ||
| 2247 | |||
| 2248 | |||
| 2249 | /* Initialize this part of alloc.c. */ | ||
| 2250 | |||
| 2251 | static void | ||
| 2252 | mem_init () | ||
| 2253 | { | ||
| 2254 | mem_z.left = mem_z.right = MEM_NIL; | ||
| 2255 | mem_z.parent = NULL; | ||
| 2256 | mem_z.color = MEM_BLACK; | ||
| 2257 | mem_z.start = mem_z.end = NULL; | ||
| 2258 | mem_root = MEM_NIL; | ||
| 2259 | } | ||
| 2260 | |||
| 2261 | |||
| 2262 | /* Value is a pointer to the mem_node containing START. Value is | ||
| 2263 | MEM_NIL if there is no node in the tree containing START. */ | ||
| 2264 | |||
| 2265 | static INLINE struct mem_node * | ||
| 2266 | mem_find (start) | ||
| 2267 | void *start; | ||
| 2268 | { | ||
| 2269 | struct mem_node *p; | ||
| 2270 | |||
| 2271 | /* Make the search always successful to speed up the loop below. */ | ||
| 2272 | mem_z.start = start; | ||
| 2273 | mem_z.end = (char *) start + 1; | ||
| 2274 | |||
| 2275 | p = mem_root; | ||
| 2276 | while (start < p->start || start >= p->end) | ||
| 2277 | p = start < p->start ? p->left : p->right; | ||
| 2278 | return p; | ||
| 2279 | } | ||
| 2280 | |||
| 2281 | |||
| 2282 | /* Insert a new node into the tree for a block of memory with start | ||
| 2283 | address START, end address END, and type TYPE. Value is a | ||
| 2284 | pointer to the node that was inserted. */ | ||
| 2285 | |||
| 2286 | static struct mem_node * | ||
| 2287 | mem_insert (start, end, type) | ||
| 2288 | void *start, *end; | ||
| 2289 | enum mem_type type; | ||
| 2290 | { | ||
| 2291 | struct mem_node *c, *parent, *x; | ||
| 2292 | |||
| 2293 | /* See where in the tree a node for START belongs. In this | ||
| 2294 | particular application, it shouldn't happen that a node is already | ||
| 2295 | present. For debugging purposes, let's check that. */ | ||
| 2296 | c = mem_root; | ||
| 2297 | parent = NULL; | ||
| 2298 | |||
| 2299 | #if GC_MARK_STACK != GC_MAKE_GCPROS_NOOPS | ||
| 2300 | |||
| 2301 | while (c != MEM_NIL) | ||
| 2302 | { | ||
| 2303 | if (start >= c->start && start < c->end) | ||
| 2304 | abort (); | ||
| 2305 | parent = c; | ||
| 2306 | c = start < c->start ? c->left : c->right; | ||
| 2307 | } | ||
| 2308 | |||
| 2309 | #else /* GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS */ | ||
| 2310 | |||
| 2311 | while (c != MEM_NIL) | ||
| 2312 | { | ||
| 2313 | parent = c; | ||
| 2314 | c = start < c->start ? c->left : c->right; | ||
| 2315 | } | ||
| 2316 | |||
| 2317 | #endif /* GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS */ | ||
| 2318 | |||
| 2319 | /* Create a new node. */ | ||
| 2320 | x = (struct mem_node *) xmalloc (sizeof *x); | ||
| 2321 | x->start = start; | ||
| 2322 | x->end = end; | ||
| 2323 | x->type = type; | ||
| 2324 | x->parent = parent; | ||
| 2325 | x->left = x->right = MEM_NIL; | ||
| 2326 | x->color = MEM_RED; | ||
| 2327 | |||
| 2328 | /* Insert it as child of PARENT or install it as root. */ | ||
| 2329 | if (parent) | ||
| 2330 | { | ||
| 2331 | if (start < parent->start) | ||
| 2332 | parent->left = x; | ||
| 2333 | else | ||
| 2334 | parent->right = x; | ||
| 2335 | } | ||
| 2336 | else | ||
| 2337 | mem_root = x; | ||
| 2338 | |||
| 2339 | /* Re-establish red-black tree properties. */ | ||
| 2340 | mem_insert_fixup (x); | ||
| 2341 | return x; | ||
| 2342 | } | ||
| 2343 | |||
| 2344 | |||
| 2345 | /* Re-establish the red-black properties of the tree, and thereby | ||
| 2346 | balance the tree, after node X has been inserted; X is always red. */ | ||
| 2347 | |||
| 2348 | static void | ||
| 2349 | mem_insert_fixup (x) | ||
| 2350 | struct mem_node *x; | ||
| 2351 | { | ||
| 2352 | while (x != mem_root && x->parent->color == MEM_RED) | ||
| 2353 | { | ||
| 2354 | /* X is red and its parent is red. This is a violation of | ||
| 2355 | red-black tree property #3. */ | ||
| 2356 | |||
| 2357 | if (x->parent == x->parent->parent->left) | ||
| 2358 | { | ||
| 2359 | /* We're on the left side of our grandparent, and Y is our | ||
| 2360 | "uncle". */ | ||
| 2361 | struct mem_node *y = x->parent->parent->right; | ||
| 2362 | |||
| 2363 | if (y->color == MEM_RED) | ||
| 2364 | { | ||
| 2365 | /* Uncle and parent are red but should be black because | ||
| 2366 | X is red. Change the colors accordingly and proceed | ||
| 2367 | with the grandparent. */ | ||
| 2368 | x->parent->color = MEM_BLACK; | ||
| 2369 | y->color = MEM_BLACK; | ||
| 2370 | x->parent->parent->color = MEM_RED; | ||
| 2371 | x = x->parent->parent; | ||
| 2372 | } | ||
| 2373 | else | ||
| 2374 | { | ||
| 2375 | /* Parent and uncle have different colors; parent is | ||
| 2376 | red, uncle is black. */ | ||
| 2377 | if (x == x->parent->right) | ||
| 2378 | { | ||
| 2379 | x = x->parent; | ||
| 2380 | mem_rotate_left (x); | ||
| 2381 | } | ||
| 2382 | |||
| 2383 | x->parent->color = MEM_BLACK; | ||
| 2384 | x->parent->parent->color = MEM_RED; | ||
| 2385 | mem_rotate_right (x->parent->parent); | ||
| 2386 | } | ||
| 2387 | } | ||
| 2388 | else | ||
| 2389 | { | ||
| 2390 | /* This is the symmetrical case of above. */ | ||
| 2391 | struct mem_node *y = x->parent->parent->left; | ||
| 2392 | |||
| 2393 | if (y->color == MEM_RED) | ||
| 2394 | { | ||
| 2395 | x->parent->color = MEM_BLACK; | ||
| 2396 | y->color = MEM_BLACK; | ||
| 2397 | x->parent->parent->color = MEM_RED; | ||
| 2398 | x = x->parent->parent; | ||
| 2399 | } | ||
| 2400 | else | ||
| 2401 | { | ||
| 2402 | if (x == x->parent->left) | ||
| 2403 | { | ||
| 2404 | x = x->parent; | ||
| 2405 | mem_rotate_right (x); | ||
| 2406 | } | ||
| 2407 | |||
| 2408 | x->parent->color = MEM_BLACK; | ||
| 2409 | x->parent->parent->color = MEM_RED; | ||
| 2410 | mem_rotate_left (x->parent->parent); | ||
| 2411 | } | ||
| 2412 | } | ||
| 2413 | } | ||
| 2414 | |||
| 2415 | /* The root may have been changed to red due to the algorithm. Set | ||
| 2416 | it to black so that property #5 is satisfied. */ | ||
| 2417 | mem_root->color = MEM_BLACK; | ||
| 2418 | } | ||
| 2419 | |||
| 2420 | |||
| 2421 | /* (x) (y) | ||
| 2422 | / \ / \ | ||
| 2423 | a (y) ===> (x) c | ||
| 2424 | / \ / \ | ||
| 2425 | b c a b */ | ||
| 2426 | |||
| 2427 | static void | ||
| 2428 | mem_rotate_left (x) | ||
| 2429 | struct mem_node *x; | ||
| 2430 | { | ||
| 2431 | struct mem_node *y; | ||
| 2432 | |||
| 2433 | /* Turn y's left sub-tree into x's right sub-tree. */ | ||
| 2434 | y = x->right; | ||
| 2435 | x->right = y->left; | ||
| 2436 | if (y->left != MEM_NIL) | ||
| 2437 | y->left->parent = x; | ||
| 2438 | |||
| 2439 | /* Y's parent was x's parent. */ | ||
| 2440 | if (y != MEM_NIL) | ||
| 2441 | y->parent = x->parent; | ||
| 2442 | |||
| 2443 | /* Get the parent to point to y instead of x. */ | ||
| 2444 | if (x->parent) | ||
| 2445 | { | ||
| 2446 | if (x == x->parent->left) | ||
| 2447 | x->parent->left = y; | ||
| 2448 | else | ||
| 2449 | x->parent->right = y; | ||
| 2450 | } | ||
| 2451 | else | ||
| 2452 | mem_root = y; | ||
| 2453 | |||
| 2454 | /* Put x on y's left. */ | ||
| 2455 | y->left = x; | ||
| 2456 | if (x != MEM_NIL) | ||
| 2457 | x->parent = y; | ||
| 2458 | } | ||
| 2459 | |||
| 2460 | |||
| 2461 | /* (x) (Y) | ||
| 2462 | / \ / \ | ||
| 2463 | (y) c ===> a (x) | ||
| 2464 | / \ / \ | ||
| 2465 | a b b c */ | ||
| 2466 | |||
| 2467 | static void | ||
| 2468 | mem_rotate_right (x) | ||
| 2469 | struct mem_node *x; | ||
| 2470 | { | ||
| 2471 | struct mem_node *y = x->left; | ||
| 2472 | |||
| 2473 | x->left = y->right; | ||
| 2474 | if (y->right != MEM_NIL) | ||
| 2475 | y->right->parent = x; | ||
| 2476 | |||
| 2477 | if (y != MEM_NIL) | ||
| 2478 | y->parent = x->parent; | ||
| 2479 | if (x->parent) | ||
| 2480 | { | ||
| 2481 | if (x == x->parent->right) | ||
| 2482 | x->parent->right = y; | ||
| 2483 | else | ||
| 2484 | x->parent->left = y; | ||
| 2485 | } | ||
| 2486 | else | ||
| 2487 | mem_root = y; | ||
| 2488 | |||
| 2489 | y->right = x; | ||
| 2490 | if (x != MEM_NIL) | ||
| 2491 | x->parent = y; | ||
| 2492 | } | ||
| 2493 | |||
| 2494 | |||
| 2495 | /* Delete node Z from the tree. If Z is null or MEM_NIL, do nothing. */ | ||
| 2496 | |||
| 2497 | static void | ||
| 2498 | mem_delete (z) | ||
| 2499 | struct mem_node *z; | ||
| 2500 | { | ||
| 2501 | struct mem_node *x, *y; | ||
| 2502 | |||
| 2503 | if (!z || z == MEM_NIL) | ||
| 2504 | return; | ||
| 2505 | |||
| 2506 | if (z->left == MEM_NIL || z->right == MEM_NIL) | ||
| 2507 | y = z; | ||
| 2508 | else | ||
| 2509 | { | ||
| 2510 | y = z->right; | ||
| 2511 | while (y->left != MEM_NIL) | ||
| 2512 | y = y->left; | ||
| 2513 | } | ||
| 2514 | |||
| 2515 | if (y->left != MEM_NIL) | ||
| 2516 | x = y->left; | ||
| 2517 | else | ||
| 2518 | x = y->right; | ||
| 2519 | |||
| 2520 | x->parent = y->parent; | ||
| 2521 | if (y->parent) | ||
| 2522 | { | ||
| 2523 | if (y == y->parent->left) | ||
| 2524 | y->parent->left = x; | ||
| 2525 | else | ||
| 2526 | y->parent->right = x; | ||
| 2527 | } | ||
| 2528 | else | ||
| 2529 | mem_root = x; | ||
| 2530 | |||
| 2531 | if (y != z) | ||
| 2532 | { | ||
| 2533 | z->start = y->start; | ||
| 2534 | z->end = y->end; | ||
| 2535 | z->type = y->type; | ||
| 2536 | } | ||
| 2537 | |||
| 2538 | if (y->color == MEM_BLACK) | ||
| 2539 | mem_delete_fixup (x); | ||
| 2540 | xfree (y); | ||
| 2541 | } | ||
| 2542 | |||
| 2543 | |||
| 2544 | /* Re-establish the red-black properties of the tree, after a | ||
| 2545 | deletion. */ | ||
| 2546 | |||
| 2547 | static void | ||
| 2548 | mem_delete_fixup (x) | ||
| 2549 | struct mem_node *x; | ||
| 2550 | { | ||
| 2551 | while (x != mem_root && x->color == MEM_BLACK) | ||
| 2552 | { | ||
| 2553 | if (x == x->parent->left) | ||
| 2554 | { | ||
| 2555 | struct mem_node *w = x->parent->right; | ||
| 2556 | |||
| 2557 | if (w->color == MEM_RED) | ||
| 2558 | { | ||
| 2559 | w->color = MEM_BLACK; | ||
| 2560 | x->parent->color = MEM_RED; | ||
| 2561 | mem_rotate_left (x->parent); | ||
| 2562 | w = x->parent->right; | ||
| 2563 | } | ||
| 2564 | |||
| 2565 | if (w->left->color == MEM_BLACK && w->right->color == MEM_BLACK) | ||
| 2566 | { | ||
| 2567 | w->color = MEM_RED; | ||
| 2568 | x = x->parent; | ||
| 2569 | } | ||
| 2570 | else | ||
| 2571 | { | ||
| 2572 | if (w->right->color == MEM_BLACK) | ||
| 2573 | { | ||
| 2574 | w->left->color = MEM_BLACK; | ||
| 2575 | w->color = MEM_RED; | ||
| 2576 | mem_rotate_right (w); | ||
| 2577 | w = x->parent->right; | ||
| 2578 | } | ||
| 2579 | w->color = x->parent->color; | ||
| 2580 | x->parent->color = MEM_BLACK; | ||
| 2581 | w->right->color = MEM_BLACK; | ||
| 2582 | mem_rotate_left (x->parent); | ||
| 2583 | x = mem_root; | ||
| 2584 | } | ||
| 2585 | } | ||
| 2586 | else | ||
| 2587 | { | ||
| 2588 | struct mem_node *w = x->parent->left; | ||
| 2589 | |||
| 2590 | if (w->color == MEM_RED) | ||
| 2591 | { | ||
| 2592 | w->color = MEM_BLACK; | ||
| 2593 | x->parent->color = MEM_RED; | ||
| 2594 | mem_rotate_right (x->parent); | ||
| 2595 | w = x->parent->left; | ||
| 2596 | } | ||
| 2597 | |||
| 2598 | if (w->right->color == MEM_BLACK && w->left->color == MEM_BLACK) | ||
| 2599 | { | ||
| 2600 | w->color = MEM_RED; | ||
| 2601 | x = x->parent; | ||
| 2602 | } | ||
| 2603 | else | ||
| 2604 | { | ||
| 2605 | if (w->left->color == MEM_BLACK) | ||
| 2606 | { | ||
| 2607 | w->right->color = MEM_BLACK; | ||
| 2608 | w->color = MEM_RED; | ||
| 2609 | mem_rotate_left (w); | ||
| 2610 | w = x->parent->left; | ||
| 2611 | } | ||
| 2612 | |||
| 2613 | w->color = x->parent->color; | ||
| 2614 | x->parent->color = MEM_BLACK; | ||
| 2615 | w->left->color = MEM_BLACK; | ||
| 2616 | mem_rotate_right (x->parent); | ||
| 2617 | x = mem_root; | ||
| 2618 | } | ||
| 2619 | } | ||
| 2620 | } | ||
| 2621 | |||
| 2622 | x->color = MEM_BLACK; | ||
| 2623 | } | ||
| 2624 | |||
| 2625 | |||
| 2626 | /* Value is non-zero if P is a pointer to a live Lisp string on | ||
| 2627 | the heap. M is a pointer to the mem_block for P. */ | ||
| 2628 | |||
| 2629 | static INLINE int | ||
| 2630 | live_string_p (m, p) | ||
| 2631 | struct mem_node *m; | ||
| 2632 | void *p; | ||
| 2633 | { | ||
| 2634 | if (m->type == MEM_TYPE_STRING) | ||
| 2635 | { | ||
| 2636 | struct string_block *b = (struct string_block *) m->start; | ||
| 2637 | int offset = (char *) p - (char *) &b->strings[0]; | ||
| 2638 | |||
| 2639 | /* P must point to the start of a Lisp_String structure, and it | ||
| 2640 | must not be on the free-list. */ | ||
| 2641 | return (offset % sizeof b->strings[0] == 0 | ||
| 2642 | && ((struct Lisp_String *) p)->data != NULL); | ||
| 2643 | } | ||
| 2644 | else | ||
| 2645 | return 0; | ||
| 2646 | } | ||
| 2647 | |||
| 2648 | |||
| 2649 | /* Value is non-zero if P is a pointer to a live Lisp cons on | ||
| 2650 | the heap. M is a pointer to the mem_block for P. */ | ||
| 2651 | |||
| 2652 | static INLINE int | ||
| 2653 | live_cons_p (m, p) | ||
| 2654 | struct mem_node *m; | ||
| 2655 | void *p; | ||
| 2656 | { | ||
| 2657 | if (m->type == MEM_TYPE_CONS) | ||
| 2658 | { | ||
| 2659 | struct cons_block *b = (struct cons_block *) m->start; | ||
| 2660 | int offset = (char *) p - (char *) &b->conses[0]; | ||
| 2661 | |||
| 2662 | /* P must point to the start of a Lisp_Cons, not be | ||
| 2663 | one of the unused cells in the current cons block, | ||
| 2664 | and not be on the free-list. */ | ||
| 2665 | return (offset % sizeof b->conses[0] == 0 | ||
| 2666 | && (b != cons_block | ||
| 2667 | || offset / sizeof b->conses[0] < cons_block_index) | ||
| 2668 | && !EQ (((struct Lisp_Cons *) p)->car, Vdead)); | ||
| 2669 | } | ||
| 2670 | else | ||
| 2671 | return 0; | ||
| 2672 | } | ||
| 2673 | |||
| 2674 | |||
| 2675 | /* Value is non-zero if P is a pointer to a live Lisp symbol on | ||
| 2676 | the heap. M is a pointer to the mem_block for P. */ | ||
| 2677 | |||
| 2678 | static INLINE int | ||
| 2679 | live_symbol_p (m, p) | ||
| 2680 | struct mem_node *m; | ||
| 2681 | void *p; | ||
| 2682 | { | ||
| 2683 | if (m->type == MEM_TYPE_SYMBOL) | ||
| 2684 | { | ||
| 2685 | struct symbol_block *b = (struct symbol_block *) m->start; | ||
| 2686 | int offset = (char *) p - (char *) &b->symbols[0]; | ||
| 2687 | |||
| 2688 | /* P must point to the start of a Lisp_Symbol, not be | ||
| 2689 | one of the unused cells in the current symbol block, | ||
| 2690 | and not be on the free-list. */ | ||
| 2691 | return (offset % sizeof b->symbols[0] == 0 | ||
| 2692 | && (b != symbol_block | ||
| 2693 | || offset / sizeof b->symbols[0] < symbol_block_index) | ||
| 2694 | && !EQ (((struct Lisp_Symbol *) p)->function, Vdead)); | ||
| 2695 | } | ||
| 2696 | else | ||
| 2697 | return 0; | ||
| 2698 | } | ||
| 2699 | |||
| 2700 | |||
| 2701 | /* Value is non-zero if P is a pointer to a live Lisp float on | ||
| 2702 | the heap. M is a pointer to the mem_block for P. */ | ||
| 2703 | |||
| 2704 | static INLINE int | ||
| 2705 | live_float_p (m, p) | ||
| 2706 | struct mem_node *m; | ||
| 2707 | void *p; | ||
| 2708 | { | ||
| 2709 | if (m->type == MEM_TYPE_FLOAT) | ||
| 2710 | { | ||
| 2711 | struct float_block *b = (struct float_block *) m->start; | ||
| 2712 | int offset = (char *) p - (char *) &b->floats[0]; | ||
| 2713 | |||
| 2714 | /* P must point to the start of a Lisp_Float, not be | ||
| 2715 | one of the unused cells in the current float block, | ||
| 2716 | and not be on the free-list. */ | ||
| 2717 | return (offset % sizeof b->floats[0] == 0 | ||
| 2718 | && (b != float_block | ||
| 2719 | || offset / sizeof b->floats[0] < float_block_index) | ||
| 2720 | && !EQ (((struct Lisp_Float *) p)->type, Vdead)); | ||
| 2721 | } | ||
| 2722 | else | ||
| 2723 | return 0; | ||
| 2724 | } | ||
| 2725 | |||
| 2726 | |||
| 2727 | /* Value is non-zero if P is a pointer to a live Lisp Misc on | ||
| 2728 | the heap. M is a pointer to the mem_block for P. */ | ||
| 2729 | |||
| 2730 | static INLINE int | ||
| 2731 | live_misc_p (m, p) | ||
| 2732 | struct mem_node *m; | ||
| 2733 | void *p; | ||
| 2734 | { | ||
| 2735 | if (m->type == MEM_TYPE_MISC) | ||
| 2736 | { | ||
| 2737 | struct marker_block *b = (struct marker_block *) m->start; | ||
| 2738 | int offset = (char *) p - (char *) &b->markers[0]; | ||
| 2739 | |||
| 2740 | /* P must point to the start of a Lisp_Misc, not be | ||
| 2741 | one of the unused cells in the current misc block, | ||
| 2742 | and not be on the free-list. */ | ||
| 2743 | return (offset % sizeof b->markers[0] == 0 | ||
| 2744 | && (b != marker_block | ||
| 2745 | || offset / sizeof b->markers[0] < marker_block_index) | ||
| 2746 | && ((union Lisp_Misc *) p)->u_marker.type != Lisp_Misc_Free); | ||
| 2747 | } | ||
| 2748 | else | ||
| 2749 | return 0; | ||
| 2750 | } | ||
| 2751 | |||
| 2752 | |||
| 2753 | /* Value is non-zero if P is a pointer to a live vector-like object. | ||
| 2754 | M is a pointer to the mem_block for P. */ | ||
| 2755 | |||
| 2756 | static INLINE int | ||
| 2757 | live_vector_p (m, p) | ||
| 2758 | struct mem_node *m; | ||
| 2759 | void *p; | ||
| 2760 | { | ||
| 2761 | return m->type == MEM_TYPE_VECTOR && p == m->start; | ||
| 2762 | } | ||
| 2763 | |||
| 2764 | |||
| 2765 | /* Value is non-zero of P is a pointer to a live buffer. M is a | ||
| 2766 | pointer to the mem_block for P. */ | ||
| 2767 | |||
| 2768 | static INLINE int | ||
| 2769 | live_buffer_p (m, p) | ||
| 2770 | struct mem_node *m; | ||
| 2771 | void *p; | ||
| 2772 | { | ||
| 2773 | /* P must point to the start of the block, and the buffer | ||
| 2774 | must not have been killed. */ | ||
| 2775 | return (m->type == MEM_TYPE_BUFFER | ||
| 2776 | && p == m->start | ||
| 2777 | && !NILP (((struct buffer *) p)->name)); | ||
| 2778 | } | ||
| 2779 | |||
| 2780 | |||
| 2781 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 2782 | |||
| 2783 | /* Array of objects that are kept alive because the C stack contains | ||
| 2784 | a pattern that looks like a reference to them . */ | ||
| 2785 | |||
| 2786 | #define MAX_ZOMBIES 10 | ||
| 2787 | static Lisp_Object zombies[MAX_ZOMBIES]; | ||
| 2788 | |||
| 2789 | /* Number of zombie objects. */ | ||
| 2790 | |||
| 2791 | static int nzombies; | ||
| 2792 | |||
| 2793 | /* Number of garbage collections. */ | ||
| 2794 | |||
| 2795 | static int ngcs; | ||
| 2796 | |||
| 2797 | /* Average percentage of zombies per collection. */ | ||
| 2798 | |||
| 2799 | static double avg_zombies; | ||
| 2800 | |||
| 2801 | /* Max. number of live and zombie objects. */ | ||
| 2802 | |||
| 2803 | static int max_live, max_zombies; | ||
| 2804 | |||
| 2805 | /* Average number of live objects per GC. */ | ||
| 2806 | |||
| 2807 | static double avg_live; | ||
| 2808 | |||
| 2809 | DEFUN ("gc-status", Fgc_status, Sgc_status, 0, 0, "", | ||
| 2810 | "Show information about live and zombie objects.") | ||
| 2811 | () | ||
| 2812 | { | ||
| 2813 | Lisp_Object args[7]; | ||
| 2814 | args[0] = build_string ("%d GCs, avg live/zombies = %.2f/%.2f (%f%%), max %d/%d"); | ||
| 2815 | args[1] = make_number (ngcs); | ||
| 2816 | args[2] = make_float (avg_live); | ||
| 2817 | args[3] = make_float (avg_zombies); | ||
| 2818 | args[4] = make_float (avg_zombies / avg_live / 100); | ||
| 2819 | args[5] = make_number (max_live); | ||
| 2820 | args[6] = make_number (max_zombies); | ||
| 2821 | return Fmessage (7, args); | ||
| 2822 | } | ||
| 2823 | |||
| 2824 | #endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */ | ||
| 2825 | |||
| 2826 | |||
| 2827 | /* Mark Lisp objects in the address range START..END. */ | ||
| 2828 | |||
| 2829 | static void | ||
| 2830 | mark_memory (start, end) | ||
| 2831 | void *start, *end; | ||
| 2832 | { | ||
| 2833 | Lisp_Object *p; | ||
| 2834 | |||
| 2835 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 2836 | nzombies = 0; | ||
| 2837 | #endif | ||
| 2838 | |||
| 2839 | /* Make START the pointer to the start of the memory region, | ||
| 2840 | if it isn't already. */ | ||
| 2841 | if (end < start) | ||
| 2842 | { | ||
| 2843 | void *tem = start; | ||
| 2844 | start = end; | ||
| 2845 | end = tem; | ||
| 2846 | } | ||
| 2847 | |||
| 2848 | for (p = (Lisp_Object *) start; (void *) p < end; ++p) | ||
| 2849 | { | ||
| 2850 | void *po = (void *) XPNTR (*p); | ||
| 2851 | struct mem_node *m = mem_find (po); | ||
| 2852 | |||
| 2853 | if (m != MEM_NIL) | ||
| 2854 | { | ||
| 2855 | int mark_p = 0; | ||
| 2856 | |||
| 2857 | switch (XGCTYPE (*p)) | ||
| 2858 | { | ||
| 2859 | case Lisp_String: | ||
| 2860 | mark_p = (live_string_p (m, po) | ||
| 2861 | && !STRING_MARKED_P ((struct Lisp_String *) po)); | ||
| 2862 | break; | ||
| 2863 | |||
| 2864 | case Lisp_Cons: | ||
| 2865 | mark_p = (live_cons_p (m, po) | ||
| 2866 | && !XMARKBIT (XCONS (*p)->car)); | ||
| 2867 | break; | ||
| 2868 | |||
| 2869 | case Lisp_Symbol: | ||
| 2870 | mark_p = (live_symbol_p (m, po) | ||
| 2871 | && !XMARKBIT (XSYMBOL (*p)->plist)); | ||
| 2872 | break; | ||
| 2873 | |||
| 2874 | case Lisp_Float: | ||
| 2875 | mark_p = (live_float_p (m, po) | ||
| 2876 | && !XMARKBIT (XFLOAT (*p)->type)); | ||
| 2877 | break; | ||
| 2878 | |||
| 2879 | case Lisp_Vectorlike: | ||
| 2880 | /* Note: can't check GC_BUFFERP before we know it's a | ||
| 2881 | buffer because checking that dereferences the pointer | ||
| 2882 | PO which might point anywhere. */ | ||
| 2883 | if (live_vector_p (m, po)) | ||
| 2884 | mark_p = (!GC_SUBRP (*p) | ||
| 2885 | && !(XVECTOR (*p)->size & ARRAY_MARK_FLAG)); | ||
| 2886 | else if (live_buffer_p (m, po)) | ||
| 2887 | mark_p = GC_BUFFERP (*p) && !XMARKBIT (XBUFFER (*p)->name); | ||
| 2888 | break; | ||
| 2889 | |||
| 2890 | case Lisp_Misc: | ||
| 2891 | if (live_misc_p (m, po)) | ||
| 2892 | { | ||
| 2893 | switch (XMISCTYPE (*p)) | ||
| 2894 | { | ||
| 2895 | case Lisp_Misc_Marker: | ||
| 2896 | mark_p = !XMARKBIT (XMARKER (*p)->chain); | ||
| 2897 | break; | ||
| 2898 | |||
| 2899 | case Lisp_Misc_Buffer_Local_Value: | ||
| 2900 | case Lisp_Misc_Some_Buffer_Local_Value: | ||
| 2901 | mark_p = !XMARKBIT (XBUFFER_LOCAL_VALUE (*p)->realvalue); | ||
| 2902 | break; | ||
| 2903 | |||
| 2904 | case Lisp_Misc_Overlay: | ||
| 2905 | mark_p = !XMARKBIT (XOVERLAY (*p)->plist); | ||
| 2906 | break; | ||
| 2907 | } | ||
| 2908 | } | ||
| 2909 | break; | ||
| 2910 | } | ||
| 2911 | |||
| 2912 | if (mark_p) | ||
| 2913 | { | ||
| 2914 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 2915 | if (nzombies < MAX_ZOMBIES) | ||
| 2916 | zombies[nzombies] = *p; | ||
| 2917 | ++nzombies; | ||
| 2918 | #endif | ||
| 2919 | mark_object (p); | ||
| 2920 | } | ||
| 2921 | } | ||
| 2922 | } | ||
| 2923 | } | ||
| 2924 | |||
| 2925 | |||
| 2926 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | ||
| 2927 | |||
| 2928 | /* Abort if anything GCPRO'd doesn't survive the GC. */ | ||
| 2929 | |||
| 2930 | static void | ||
| 2931 | check_gcpros () | ||
| 2932 | { | ||
| 2933 | struct gcpro *p; | ||
| 2934 | int i; | ||
| 2935 | |||
| 2936 | for (p = gcprolist; p; p = p->next) | ||
| 2937 | for (i = 0; i < p->nvars; ++i) | ||
| 2938 | if (!survives_gc_p (p->var[i])) | ||
| 2939 | abort (); | ||
| 2940 | } | ||
| 2941 | |||
| 2942 | #elif GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 2943 | |||
| 2944 | static void | ||
| 2945 | dump_zombies () | ||
| 2946 | { | ||
| 2947 | int i; | ||
| 2948 | |||
| 2949 | fprintf (stderr, "\nZombies kept alive = %d:\n", nzombies); | ||
| 2950 | for (i = 0; i < min (MAX_ZOMBIES, nzombies); ++i) | ||
| 2951 | { | ||
| 2952 | fprintf (stderr, " %d = ", i); | ||
| 2953 | debug_print (zombies[i]); | ||
| 2954 | } | ||
| 2955 | } | ||
| 2956 | |||
| 2957 | #endif /* GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES */ | ||
| 2958 | |||
| 2959 | |||
| 2960 | /* Mark live Lisp objects on the C stack. */ | ||
| 2961 | |||
| 2962 | static void | ||
| 2963 | mark_stack () | ||
| 2964 | { | ||
| 2965 | jmp_buf j; | ||
| 2966 | int stack_grows_down_p = (char *) &j > (char *) stack_base; | ||
| 2967 | void *end; | ||
| 2968 | |||
| 2969 | /* This trick flushes the register windows so that all the state of | ||
| 2970 | the process is contained in the stack. */ | ||
| 2971 | #ifdef sparc | ||
| 2972 | asm ("ta 3"); | ||
| 2973 | #endif | ||
| 2974 | |||
| 2975 | /* Save registers that we need to see on the stack. We need to see | ||
| 2976 | registers used to hold register variables and registers used to | ||
| 2977 | pass parameters. */ | ||
| 2978 | #ifdef GC_SAVE_REGISTERS_ON_STACK | ||
| 2979 | GC_SAVE_REGISTERS_ON_STACK (end); | ||
| 2980 | #else | ||
| 2981 | setjmp (j); | ||
| 2982 | end = stack_grows_down_p ? (char *) &j + sizeof j : (char *) &j; | ||
| 2983 | #endif | ||
| 2984 | |||
| 2985 | /* This assumes that the stack is a contiguous region in memory. If | ||
| 2986 | that's not the case, something has to be done here to iterate over | ||
| 2987 | the stack segments. */ | ||
| 2988 | mark_memory (stack_base, end); | ||
| 2989 | |||
| 2990 | #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | ||
| 2991 | check_gcpros (); | ||
| 2992 | #endif | ||
| 2993 | } | ||
| 2994 | |||
| 2995 | |||
| 2996 | #endif /* GC_MARK_STACK != 0 */ | ||
| 2997 | |||
| 2998 | |||
| 2999 | |||
| 1965 | /*********************************************************************** | 3000 | /*********************************************************************** |
| 1966 | Pure Storage Management | 3001 | Pure Storage Management |
| 1967 | ***********************************************************************/ | 3002 | ***********************************************************************/ |
| @@ -2010,6 +3045,9 @@ make_pure_string (data, nchars, nbytes, multibyte) | |||
| 2010 | } | 3045 | } |
| 2011 | 3046 | ||
| 2012 | 3047 | ||
| 3048 | /* Return a cons allocated from pure space. Give it pure copies | ||
| 3049 | of CAR as car and CDR as cdr. */ | ||
| 3050 | |||
| 2013 | Lisp_Object | 3051 | Lisp_Object |
| 2014 | pure_cons (car, cdr) | 3052 | pure_cons (car, cdr) |
| 2015 | Lisp_Object car, cdr; | 3053 | Lisp_Object car, cdr; |
| @@ -2026,6 +3064,8 @@ pure_cons (car, cdr) | |||
| 2026 | } | 3064 | } |
| 2027 | 3065 | ||
| 2028 | 3066 | ||
| 3067 | /* Value is a float object with value NUM allocated from pure space. */ | ||
| 3068 | |||
| 2029 | Lisp_Object | 3069 | Lisp_Object |
| 2030 | make_pure_float (num) | 3070 | make_pure_float (num) |
| 2031 | double num; | 3071 | double num; |
| @@ -2062,12 +3102,17 @@ make_pure_float (num) | |||
| 2062 | return new; | 3102 | return new; |
| 2063 | } | 3103 | } |
| 2064 | 3104 | ||
| 3105 | |||
| 3106 | /* Return a vector with room for LEN Lisp_Objects allocated from | ||
| 3107 | pure space. */ | ||
| 3108 | |||
| 2065 | Lisp_Object | 3109 | Lisp_Object |
| 2066 | make_pure_vector (len) | 3110 | make_pure_vector (len) |
| 2067 | EMACS_INT len; | 3111 | EMACS_INT len; |
| 2068 | { | 3112 | { |
| 2069 | register Lisp_Object new; | 3113 | register Lisp_Object new; |
| 2070 | register EMACS_INT size = sizeof (struct Lisp_Vector) + (len - 1) * sizeof (Lisp_Object); | 3114 | register EMACS_INT size = (sizeof (struct Lisp_Vector) |
| 3115 | + (len - 1) * sizeof (Lisp_Object)); | ||
| 2071 | 3116 | ||
| 2072 | if (pureptr + size > PURESIZE) | 3117 | if (pureptr + size > PURESIZE) |
| 2073 | error ("Pure Lisp storage exhausted"); | 3118 | error ("Pure Lisp storage exhausted"); |
| @@ -2078,6 +3123,7 @@ make_pure_vector (len) | |||
| 2078 | return new; | 3123 | return new; |
| 2079 | } | 3124 | } |
| 2080 | 3125 | ||
| 3126 | |||
| 2081 | DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, | 3127 | DEFUN ("purecopy", Fpurecopy, Spurecopy, 1, 1, 0, |
| 2082 | "Make a copy of OBJECT in pure storage.\n\ | 3128 | "Make a copy of OBJECT in pure storage.\n\ |
| 2083 | Recursively copies contents of vectors and cons cells.\n\ | 3129 | Recursively copies contents of vectors and cons cells.\n\ |
| @@ -2123,17 +3169,26 @@ Does not copy symbols. Copies strings without text properties.") | |||
| 2123 | return obj; | 3169 | return obj; |
| 2124 | } | 3170 | } |
| 2125 | 3171 | ||
| 3172 | |||
| 2126 | 3173 | ||
| 3174 | /*********************************************************************** | ||
| 3175 | Protection from GC | ||
| 3176 | ***********************************************************************/ | ||
| 3177 | |||
| 2127 | /* Recording what needs to be marked for gc. */ | 3178 | /* Recording what needs to be marked for gc. */ |
| 2128 | 3179 | ||
| 2129 | struct gcpro *gcprolist; | 3180 | struct gcpro *gcprolist; |
| 2130 | 3181 | ||
| 2131 | #define NSTATICS 1024 | 3182 | /* Addresses of staticpro'd variables. */ |
| 2132 | 3183 | ||
| 3184 | #define NSTATICS 1024 | ||
| 2133 | Lisp_Object *staticvec[NSTATICS] = {0}; | 3185 | Lisp_Object *staticvec[NSTATICS] = {0}; |
| 2134 | 3186 | ||
| 3187 | /* Index of next unused slot in staticvec. */ | ||
| 3188 | |||
| 2135 | int staticidx = 0; | 3189 | int staticidx = 0; |
| 2136 | 3190 | ||
| 3191 | |||
| 2137 | /* Put an entry in staticvec, pointing at the variable with address | 3192 | /* Put an entry in staticvec, pointing at the variable with address |
| 2138 | VARADDRESS. */ | 3193 | VARADDRESS. */ |
| 2139 | 3194 | ||
| @@ -2151,9 +3206,6 @@ struct catchtag | |||
| 2151 | Lisp_Object tag; | 3206 | Lisp_Object tag; |
| 2152 | Lisp_Object val; | 3207 | Lisp_Object val; |
| 2153 | struct catchtag *next; | 3208 | struct catchtag *next; |
| 2154 | #if 0 /* We don't need this for GC purposes */ | ||
| 2155 | jmp_buf jmp; | ||
| 2156 | #endif | ||
| 2157 | }; | 3209 | }; |
| 2158 | 3210 | ||
| 2159 | struct backtrace | 3211 | struct backtrace |
| @@ -2167,8 +3219,11 @@ struct backtrace | |||
| 2167 | char evalargs; | 3219 | char evalargs; |
| 2168 | }; | 3220 | }; |
| 2169 | 3221 | ||
| 3222 | |||
| 2170 | 3223 | ||
| 2171 | /* Garbage collection! */ | 3224 | /*********************************************************************** |
| 3225 | Protection from GC | ||
| 3226 | ***********************************************************************/ | ||
| 2172 | 3227 | ||
| 2173 | /* Temporarily prevent garbage collection. */ | 3228 | /* Temporarily prevent garbage collection. */ |
| 2174 | 3229 | ||
| @@ -2186,6 +3241,7 @@ inhibit_garbage_collection () | |||
| 2186 | return count; | 3241 | return count; |
| 2187 | } | 3242 | } |
| 2188 | 3243 | ||
| 3244 | |||
| 2189 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 3245 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 2190 | "Reclaim storage for Lisp objects no longer needed.\n\ | 3246 | "Reclaim storage for Lisp objects no longer needed.\n\ |
| 2191 | Returns info on amount of space in use:\n\ | 3247 | Returns info on amount of space in use:\n\ |
| @@ -2275,6 +3331,11 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 2275 | 3331 | ||
| 2276 | for (i = 0; i < staticidx; i++) | 3332 | for (i = 0; i < staticidx; i++) |
| 2277 | mark_object (staticvec[i]); | 3333 | mark_object (staticvec[i]); |
| 3334 | |||
| 3335 | #if (GC_MARK_STACK == GC_MAKE_GCPROS_NOOPS \ | ||
| 3336 | || GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS) | ||
| 3337 | mark_stack (); | ||
| 3338 | #else | ||
| 2278 | for (tail = gcprolist; tail; tail = tail->next) | 3339 | for (tail = gcprolist; tail; tail = tail->next) |
| 2279 | for (i = 0; i < tail->nvars; i++) | 3340 | for (i = 0; i < tail->nvars; i++) |
| 2280 | if (!XMARKBIT (tail->var[i])) | 3341 | if (!XMARKBIT (tail->var[i])) |
| @@ -2282,6 +3343,8 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 2282 | mark_object (&tail->var[i]); | 3343 | mark_object (&tail->var[i]); |
| 2283 | XMARK (tail->var[i]); | 3344 | XMARK (tail->var[i]); |
| 2284 | } | 3345 | } |
| 3346 | #endif | ||
| 3347 | |||
| 2285 | mark_byte_stack (); | 3348 | mark_byte_stack (); |
| 2286 | for (bind = specpdl; bind != specpdl_ptr; bind++) | 3349 | for (bind = specpdl; bind != specpdl_ptr; bind++) |
| 2287 | { | 3350 | { |
| @@ -2358,13 +3421,21 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 2358 | } | 3421 | } |
| 2359 | } | 3422 | } |
| 2360 | 3423 | ||
| 3424 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 3425 | mark_stack (); | ||
| 3426 | #endif | ||
| 3427 | |||
| 2361 | gc_sweep (); | 3428 | gc_sweep (); |
| 2362 | 3429 | ||
| 2363 | /* Clear the mark bits that we set in certain root slots. */ | 3430 | /* Clear the mark bits that we set in certain root slots. */ |
| 2364 | 3431 | ||
| 3432 | #if (GC_MARK_STACK == GC_USE_GCPROS_AS_BEFORE \ | ||
| 3433 | || GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES) | ||
| 2365 | for (tail = gcprolist; tail; tail = tail->next) | 3434 | for (tail = gcprolist; tail; tail = tail->next) |
| 2366 | for (i = 0; i < tail->nvars; i++) | 3435 | for (i = 0; i < tail->nvars; i++) |
| 2367 | XUNMARK (tail->var[i]); | 3436 | XUNMARK (tail->var[i]); |
| 3437 | #endif | ||
| 3438 | |||
| 2368 | unmark_byte_stack (); | 3439 | unmark_byte_stack (); |
| 2369 | for (backlist = backtrace_list; backlist; backlist = backlist->next) | 3440 | for (backlist = backtrace_list; backlist; backlist = backlist->next) |
| 2370 | { | 3441 | { |
| @@ -2379,6 +3450,10 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 2379 | XUNMARK (buffer_defaults.name); | 3450 | XUNMARK (buffer_defaults.name); |
| 2380 | XUNMARK (buffer_local_symbols.name); | 3451 | XUNMARK (buffer_local_symbols.name); |
| 2381 | 3452 | ||
| 3453 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES && 0 | ||
| 3454 | dump_zombies (); | ||
| 3455 | #endif | ||
| 3456 | |||
| 2382 | UNBLOCK_INPUT; | 3457 | UNBLOCK_INPUT; |
| 2383 | 3458 | ||
| 2384 | /* clear_marks (); */ | 3459 | /* clear_marks (); */ |
| @@ -2413,67 +3488,25 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 2413 | total[6] = Fcons (make_number (total_strings), | 3488 | total[6] = Fcons (make_number (total_strings), |
| 2414 | make_number (total_free_strings)); | 3489 | make_number (total_free_strings)); |
| 2415 | 3490 | ||
| 2416 | return Flist (7, total); | 3491 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 2417 | } | ||
| 2418 | |||
| 2419 | #if 0 | ||
| 2420 | static void | ||
| 2421 | clear_marks () | ||
| 2422 | { | ||
| 2423 | /* Clear marks on all conses */ | ||
| 2424 | { | ||
| 2425 | register struct cons_block *cblk; | ||
| 2426 | register int lim = cons_block_index; | ||
| 2427 | |||
| 2428 | for (cblk = cons_block; cblk; cblk = cblk->next) | ||
| 2429 | { | ||
| 2430 | register int i; | ||
| 2431 | for (i = 0; i < lim; i++) | ||
| 2432 | XUNMARK (cblk->conses[i].car); | ||
| 2433 | lim = CONS_BLOCK_SIZE; | ||
| 2434 | } | ||
| 2435 | } | ||
| 2436 | /* Clear marks on all symbols */ | ||
| 2437 | { | 3492 | { |
| 2438 | register struct symbol_block *sblk; | 3493 | /* Compute average percentage of zombies. */ |
| 2439 | register int lim = symbol_block_index; | 3494 | double nlive = 0; |
| 2440 | 3495 | ||
| 2441 | for (sblk = symbol_block; sblk; sblk = sblk->next) | 3496 | for (i = 0; i < 7; ++i) |
| 2442 | { | 3497 | nlive += XFASTINT (XCAR (total[i])); |
| 2443 | register int i; | 3498 | |
| 2444 | for (i = 0; i < lim; i++) | 3499 | avg_live = (avg_live * ngcs + nlive) / (ngcs + 1); |
| 2445 | { | 3500 | max_live = max (nlive, max_live); |
| 2446 | XUNMARK (sblk->symbols[i].plist); | 3501 | avg_zombies = (avg_zombies * ngcs + nzombies) / (ngcs + 1); |
| 2447 | } | 3502 | max_zombies = max (nzombies, max_zombies); |
| 2448 | lim = SYMBOL_BLOCK_SIZE; | 3503 | ++ngcs; |
| 2449 | } | 3504 | } |
| 2450 | } | 3505 | #endif |
| 2451 | /* Clear marks on all markers */ | ||
| 2452 | { | ||
| 2453 | register struct marker_block *sblk; | ||
| 2454 | register int lim = marker_block_index; | ||
| 2455 | |||
| 2456 | for (sblk = marker_block; sblk; sblk = sblk->next) | ||
| 2457 | { | ||
| 2458 | register int i; | ||
| 2459 | for (i = 0; i < lim; i++) | ||
| 2460 | if (sblk->markers[i].u_marker.type == Lisp_Misc_Marker) | ||
| 2461 | XUNMARK (sblk->markers[i].u_marker.chain); | ||
| 2462 | lim = MARKER_BLOCK_SIZE; | ||
| 2463 | } | ||
| 2464 | } | ||
| 2465 | /* Clear mark bits on all buffers */ | ||
| 2466 | { | ||
| 2467 | register struct buffer *nextb = all_buffers; | ||
| 2468 | 3506 | ||
| 2469 | while (nextb) | 3507 | return Flist (7, total); |
| 2470 | { | ||
| 2471 | XUNMARK (nextb->name); | ||
| 2472 | nextb = nextb->next; | ||
| 2473 | } | ||
| 2474 | } | ||
| 2475 | } | 3508 | } |
| 2476 | #endif | 3509 | |
| 2477 | 3510 | ||
| 2478 | /* Mark Lisp objects in glyph matrix MATRIX. Currently the | 3511 | /* Mark Lisp objects in glyph matrix MATRIX. Currently the |
| 2479 | only interesting objects referenced from glyphs are strings. */ | 3512 | only interesting objects referenced from glyphs are strings. */ |
| @@ -2502,6 +3535,7 @@ mark_glyph_matrix (matrix) | |||
| 2502 | } | 3535 | } |
| 2503 | } | 3536 | } |
| 2504 | 3537 | ||
| 3538 | |||
| 2505 | /* Mark Lisp faces in the face cache C. */ | 3539 | /* Mark Lisp faces in the face cache C. */ |
| 2506 | 3540 | ||
| 2507 | static void | 3541 | static void |
| @@ -2575,8 +3609,7 @@ mark_object (argptr) | |||
| 2575 | loop2: | 3609 | loop2: |
| 2576 | XUNMARK (obj); | 3610 | XUNMARK (obj); |
| 2577 | 3611 | ||
| 2578 | if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE) | 3612 | if (PURE_POINTER_P ((PNTR_COMPARISON_TYPE) XPNTR (obj))) |
| 2579 | && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure) | ||
| 2580 | return; | 3613 | return; |
| 2581 | 3614 | ||
| 2582 | last_marked[last_marked_index++] = objptr; | 3615 | last_marked[last_marked_index++] = objptr; |
| @@ -2772,8 +3805,10 @@ mark_object (argptr) | |||
| 2772 | mark_object ((Lisp_Object *) &ptr->value); | 3805 | mark_object ((Lisp_Object *) &ptr->value); |
| 2773 | mark_object (&ptr->function); | 3806 | mark_object (&ptr->function); |
| 2774 | mark_object (&ptr->plist); | 3807 | mark_object (&ptr->plist); |
| 3808 | |||
| 3809 | if (!PURE_POINTER_P (ptr->name)) | ||
| 3810 | MARK_STRING (ptr->name); | ||
| 2775 | MARK_INTERVAL_TREE (ptr->name->intervals); | 3811 | MARK_INTERVAL_TREE (ptr->name->intervals); |
| 2776 | MARK_STRING (ptr->name); | ||
| 2777 | 3812 | ||
| 2778 | /* Note that we do not mark the obarray of the symbol. | 3813 | /* Note that we do not mark the obarray of the symbol. |
| 2779 | It is safe not to do so because nothing accesses that | 3814 | It is safe not to do so because nothing accesses that |
| @@ -3048,7 +4083,7 @@ survives_gc_p (obj) | |||
| 3048 | abort (); | 4083 | abort (); |
| 3049 | } | 4084 | } |
| 3050 | 4085 | ||
| 3051 | return survives_p; | 4086 | return survives_p || PURE_POINTER_P ((void *) XPNTR (obj)); |
| 3052 | } | 4087 | } |
| 3053 | 4088 | ||
| 3054 | 4089 | ||
| @@ -3083,6 +4118,9 @@ gc_sweep () | |||
| 3083 | this_free++; | 4118 | this_free++; |
| 3084 | *(struct Lisp_Cons **)&cblk->conses[i].cdr = cons_free_list; | 4119 | *(struct Lisp_Cons **)&cblk->conses[i].cdr = cons_free_list; |
| 3085 | cons_free_list = &cblk->conses[i]; | 4120 | cons_free_list = &cblk->conses[i]; |
| 4121 | #if GC_MARK_STACK | ||
| 4122 | cons_free_list->car = Vdead; | ||
| 4123 | #endif | ||
| 3086 | } | 4124 | } |
| 3087 | else | 4125 | else |
| 3088 | { | 4126 | { |
| @@ -3130,6 +4168,9 @@ gc_sweep () | |||
| 3130 | this_free++; | 4168 | this_free++; |
| 3131 | *(struct Lisp_Float **)&fblk->floats[i].data = float_free_list; | 4169 | *(struct Lisp_Float **)&fblk->floats[i].data = float_free_list; |
| 3132 | float_free_list = &fblk->floats[i]; | 4170 | float_free_list = &fblk->floats[i]; |
| 4171 | #if GC_MARK_STACK | ||
| 4172 | float_free_list->type = Vdead; | ||
| 4173 | #endif | ||
| 3133 | } | 4174 | } |
| 3134 | else | 4175 | else |
| 3135 | { | 4176 | { |
| @@ -3226,12 +4267,16 @@ gc_sweep () | |||
| 3226 | { | 4267 | { |
| 3227 | *(struct Lisp_Symbol **)&sblk->symbols[i].value = symbol_free_list; | 4268 | *(struct Lisp_Symbol **)&sblk->symbols[i].value = symbol_free_list; |
| 3228 | symbol_free_list = &sblk->symbols[i]; | 4269 | symbol_free_list = &sblk->symbols[i]; |
| 4270 | #if GC_MARK_STACK | ||
| 4271 | symbol_free_list->function = Vdead; | ||
| 4272 | #endif | ||
| 3229 | this_free++; | 4273 | this_free++; |
| 3230 | } | 4274 | } |
| 3231 | else | 4275 | else |
| 3232 | { | 4276 | { |
| 3233 | num_used++; | 4277 | num_used++; |
| 3234 | UNMARK_STRING (sblk->symbols[i].name); | 4278 | if (!PURE_POINTER_P (sblk->symbols[i].name)) |
| 4279 | UNMARK_STRING (sblk->symbols[i].name); | ||
| 3235 | XUNMARK (sblk->symbols[i].plist); | 4280 | XUNMARK (sblk->symbols[i].plist); |
| 3236 | } | 4281 | } |
| 3237 | lim = SYMBOL_BLOCK_SIZE; | 4282 | lim = SYMBOL_BLOCK_SIZE; |
| @@ -3356,7 +4401,7 @@ gc_sweep () | |||
| 3356 | else | 4401 | else |
| 3357 | all_buffers = buffer->next; | 4402 | all_buffers = buffer->next; |
| 3358 | next = buffer->next; | 4403 | next = buffer->next; |
| 3359 | xfree (buffer); | 4404 | lisp_free (buffer); |
| 3360 | buffer = next; | 4405 | buffer = next; |
| 3361 | } | 4406 | } |
| 3362 | else | 4407 | else |
| @@ -3375,11 +4420,6 @@ gc_sweep () | |||
| 3375 | while (vector) | 4420 | while (vector) |
| 3376 | if (!(vector->size & ARRAY_MARK_FLAG)) | 4421 | if (!(vector->size & ARRAY_MARK_FLAG)) |
| 3377 | { | 4422 | { |
| 3378 | #if 0 | ||
| 3379 | if ((vector->size & (PSEUDOVECTOR_FLAG | PVEC_HASH_TABLE)) | ||
| 3380 | == (PSEUDOVECTOR_FLAG | PVEC_HASH_TABLE)) | ||
| 3381 | fprintf (stderr, "Freeing hash table %p\n", vector); | ||
| 3382 | #endif | ||
| 3383 | if (prev) | 4423 | if (prev) |
| 3384 | prev->next = vector->next; | 4424 | prev->next = vector->next; |
| 3385 | else | 4425 | else |
| @@ -3464,6 +4504,10 @@ init_alloc_once () | |||
| 3464 | { | 4504 | { |
| 3465 | /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ | 4505 | /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ |
| 3466 | pureptr = 0; | 4506 | pureptr = 0; |
| 4507 | #if GC_MARK_STACK | ||
| 4508 | mem_init (); | ||
| 4509 | Vdead = make_pure_string ("DEAD", 4, 4, 0); | ||
| 4510 | #endif | ||
| 3467 | #ifdef HAVE_SHM | 4511 | #ifdef HAVE_SHM |
| 3468 | pure_size = PURESIZE; | 4512 | pure_size = PURESIZE; |
| 3469 | #endif | 4513 | #endif |
| @@ -3479,7 +4523,7 @@ init_alloc_once () | |||
| 3479 | init_symbol (); | 4523 | init_symbol (); |
| 3480 | init_marker (); | 4524 | init_marker (); |
| 3481 | init_float (); | 4525 | init_float (); |
| 3482 | INIT_INTERVALS; | 4526 | init_intervals (); |
| 3483 | 4527 | ||
| 3484 | #ifdef REL_ALLOC | 4528 | #ifdef REL_ALLOC |
| 3485 | malloc_hysteresis = 32; | 4529 | malloc_hysteresis = 32; |
| @@ -3546,14 +4590,6 @@ prevent garbage collection during a part of the program."); | |||
| 3546 | DEFVAR_INT ("strings-consed", &strings_consed, | 4590 | DEFVAR_INT ("strings-consed", &strings_consed, |
| 3547 | "Number of strings that have been consed so far."); | 4591 | "Number of strings that have been consed so far."); |
| 3548 | 4592 | ||
| 3549 | #if 0 | ||
| 3550 | DEFVAR_INT ("data-bytes-used", &malloc_sbrk_used, | ||
| 3551 | "Number of bytes of unshared memory allocated in this session."); | ||
| 3552 | |||
| 3553 | DEFVAR_INT ("data-bytes-free", &malloc_sbrk_unused, | ||
| 3554 | "Number of bytes of unshared memory remaining available in this session."); | ||
| 3555 | #endif | ||
| 3556 | |||
| 3557 | DEFVAR_LISP ("purify-flag", &Vpurify_flag, | 4593 | DEFVAR_LISP ("purify-flag", &Vpurify_flag, |
| 3558 | "Non-nil means loading Lisp code in order to dump an executable.\n\ | 4594 | "Non-nil means loading Lisp code in order to dump an executable.\n\ |
| 3559 | This means that certain objects should be allocated in shared (pure) space."); | 4595 | This means that certain objects should be allocated in shared (pure) space."); |
| @@ -3604,4 +4640,8 @@ which includes both saved text and other data."); | |||
| 3604 | defsubr (&Sgarbage_collect); | 4640 | defsubr (&Sgarbage_collect); |
| 3605 | defsubr (&Smemory_limit); | 4641 | defsubr (&Smemory_limit); |
| 3606 | defsubr (&Smemory_use_counts); | 4642 | defsubr (&Smemory_use_counts); |
| 4643 | |||
| 4644 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | ||
| 4645 | defsubr (&Sgc_status); | ||
| 4646 | #endif | ||
| 3607 | } | 4647 | } |