Mercurial > emacs
comparison src/alloc.c @ 27738:581c76c41ca4
(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.
| author | Gerd Moellmann <gerd@gnu.org> |
|---|---|
| date | Thu, 17 Feb 2000 15:21:21 +0000 |
| parents | 9400865ec7cf |
| children | 2556e20596b8 |
comparison
equal
deleted
inserted
replaced
| 27737:861c19525f53 | 27738:581c76c41ca4 |
|---|---|
| 38 #include "frame.h" | 38 #include "frame.h" |
| 39 #include "blockinput.h" | 39 #include "blockinput.h" |
| 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 |
| 46 #ifdef DOUG_LEA_MALLOC | 47 #ifdef DOUG_LEA_MALLOC |
| 47 | 48 |
| 147 /* Two limits controlling how much undo information to keep. */ | 148 /* Two limits controlling how much undo information to keep. */ |
| 148 | 149 |
| 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. */ |
| 158 | 161 |
| 159 static char *spare_memory; | 162 static char *spare_memory; |
| 196 | 199 |
| 197 EMACS_INT pure_size; | 200 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; |
| 204 | 215 |
| 205 /* If nonzero, this is a warning delivered by malloc and not yet | 216 /* If nonzero, this is a warning delivered by malloc and not yet |
| 232 static void mark_buffer P_ ((Lisp_Object)); | 243 static void mark_buffer P_ ((Lisp_Object)); |
| 233 static void mark_kboards P_ ((void)); | 244 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 *)); |
| 243 static void mark_image_cache P_ ((struct frame *)); | 251 static void mark_image_cache P_ ((struct frame *)); |
| 244 #endif /* HAVE_WINDOW_SYSTEM */ | 252 #endif /* HAVE_WINDOW_SYSTEM */ |
| 247 static void compact_small_strings P_ ((void)); | 255 static void compact_small_strings P_ ((void)); |
| 248 static void free_large_strings P_ ((void)); | 256 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) |
| 258 Lisp_Object str; | 326 Lisp_Object str; |
| 259 { | 327 { |
| 262 write_string ("However, certainly by the time you receive the 95% warning,\n", -1); | 330 write_string ("However, certainly by the time you receive the 95% warning,\n", -1); |
| 263 write_string ("you should clean up, kill this Emacs, and start a new one.", -1); | 331 write_string ("you should clean up, kill this Emacs, and start a new one.", -1); |
| 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) |
| 271 char *str; | 341 char *str; |
| 272 { | 342 { |
| 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 { |
| 279 register Lisp_Object val; | 352 register Lisp_Object val; |
| 280 | 353 |
| 281 val = build_string (pending_malloc_warning); | 354 val = build_string (pending_malloc_warning); |
| 282 pending_malloc_warning = 0; | 355 pending_malloc_warning = 0; |
| 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 } |
| 358 | |
| 285 | 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 |
| 295 memory_full () | 370 memory_full () |
| 296 { | 371 { |
| 308 /* This used to call error, but if we've run out of memory, we could | 383 /* This used to call error, but if we've run out of memory, we could |
| 309 get infinite recursion trying to build the string. */ | 384 get infinite recursion trying to build the string. */ |
| 310 while (1) | 385 while (1) |
| 311 Fsignal (Qnil, memory_signal_data); | 386 Fsignal (Qnil, memory_signal_data); |
| 312 } | 387 } |
| 388 | |
| 313 | 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 |
| 317 buffer_memory_full () | 393 buffer_memory_full () |
| 331 get infinite recursion trying to build the string. */ | 407 get infinite recursion trying to build the string. */ |
| 332 while (1) | 408 while (1) |
| 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) |
| 341 int size; | 417 int size; |
| 342 { | 418 { |
| 348 | 424 |
| 349 if (!val && size) | 425 if (!val && size) |
| 350 memory_full (); | 426 memory_full (); |
| 351 return val; | 427 return val; |
| 352 } | 428 } |
| 429 | |
| 430 | |
| 431 /* Like realloc but check for no memory and block interrupt input.. */ | |
| 353 | 432 |
| 354 long * | 433 long * |
| 355 xrealloc (block, size) | 434 xrealloc (block, size) |
| 356 long *block; | 435 long *block; |
| 357 int size; | 436 int size; |
| 369 | 448 |
| 370 if (!val && size) memory_full (); | 449 if (!val && size) memory_full (); |
| 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; |
| 377 { | 459 { |
| 378 BLOCK_INPUT; | 460 BLOCK_INPUT; |
| 379 free (block); | 461 free (block); |
| 380 UNBLOCK_INPUT; | 462 UNBLOCK_INPUT; |
| 381 } | 463 } |
| 382 | 464 |
| 383 /* Like malloc but used for allocating Lisp data. */ | 465 |
| 384 | 466 /* Like malloc but used for allocating Lisp data. NBYTES is the |
| 385 long * | 467 number of bytes to allocate, TYPE describes the intended use of the |
| 386 lisp_malloc (size) | 468 allcated memory block (for strings, for conses, ...). */ |
| 387 int size; | 469 |
| 388 { | 470 static void * |
| 389 register long *val; | 471 lisp_malloc (nbytes, type) |
| 472 int nbytes; | |
| 473 enum mem_type type; | |
| 474 { | |
| 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 } |
| 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. */ | |
| 400 | 508 |
| 401 void | 509 void |
| 402 lisp_free (block) | 510 lisp_free (block) |
| 403 long *block; | 511 long *block; |
| 404 { | 512 { |
| 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 |
| 414 This only works with GNU malloc. To help out systems which can't | 526 This only works with GNU malloc. To help out systems which can't |
| 415 use GNU malloc, all the calls to malloc, realloc, and free | 527 use GNU malloc, all the calls to malloc, realloc, and free |
| 451 | 563 |
| 452 __free_hook = emacs_blocked_free; | 564 __free_hook = emacs_blocked_free; |
| 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. |
| 459 | 572 |
| 460 This is called when a relocatable block is freed in ralloc.c. */ | 573 This is called when a relocatable block is freed in ralloc.c. */ |
| 463 refill_memory_reserve () | 576 refill_memory_reserve () |
| 464 { | 577 { |
| 465 if (spare_memory == 0) | 578 if (spare_memory == 0) |
| 466 spare_memory = (char *) malloc (SPARE_MEMORY); | 579 spare_memory = (char *) malloc (SPARE_MEMORY); |
| 467 } | 580 } |
| 581 | |
| 468 | 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 * |
| 472 emacs_blocked_malloc (size) | 586 emacs_blocked_malloc (size) |
| 486 UNBLOCK_INPUT; | 600 UNBLOCK_INPUT; |
| 487 | 601 |
| 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; |
| 494 unsigned size; | 611 unsigned size; |
| 495 { | 612 { |
| 502 UNBLOCK_INPUT; | 619 UNBLOCK_INPUT; |
| 503 | 620 |
| 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 { |
| 510 if (__free_hook != emacs_blocked_free) | 630 if (__free_hook != emacs_blocked_free) |
| 511 old_free_hook = __free_hook; | 631 old_free_hook = __free_hook; |
| 526 | 646 |
| 527 /*********************************************************************** | 647 /*********************************************************************** |
| 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)) |
| 656 | |
| 657 /* Intervals are allocated in chunks in form of an interval_block | |
| 658 structure. */ | |
| 533 | 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; |
| 687 | |
| 688 | |
| 689 /* Initialize interval allocation. */ | |
| 549 | 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; |
| 558 interval_free_list = 0; | 700 interval_free_list = 0; |
| 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 () |
| 566 { | 709 { |
| 567 INTERVAL val; | 710 INTERVAL val; |
| 575 { | 718 { |
| 576 if (interval_block_index == INTERVAL_BLOCK_SIZE) | 719 if (interval_block_index == INTERVAL_BLOCK_SIZE) |
| 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; |
| 584 interval_block = newi; | 728 interval_block = newi; |
| 585 interval_block_index = 0; | 729 interval_block_index = 0; |
| 591 intervals_consed++; | 735 intervals_consed++; |
| 592 RESET_INTERVAL (val); | 736 RESET_INTERVAL (val); |
| 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) |
| 600 register INTERVAL i; | 745 register INTERVAL i; |
| 601 Lisp_Object dummy; | 746 Lisp_Object dummy; |
| 604 abort (); | 749 abort (); |
| 605 mark_object (&i->plist); | 750 mark_object (&i->plist); |
| 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; |
| 612 { | 761 { |
| 613 /* No need to test if this tree has been marked already; this | 762 /* No need to test if this tree has been marked already; this |
| 618 a cast. */ | 767 a cast. */ |
| 619 XMARK (* (Lisp_Object *) &tree->parent); | 768 XMARK (* (Lisp_Object *) &tree->parent); |
| 620 | 769 |
| 621 traverse_intervals (tree, 1, 0, mark_interval, Qnil); | 770 traverse_intervals (tree, 1, 0, mark_interval, Qnil); |
| 622 } | 771 } |
| 772 | |
| 773 | |
| 774 /* Mark the interval tree rooted in I. */ | |
| 623 | 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) \ |
| 627 && ! XMARKBIT (*(Lisp_Object *) &i->parent)) \ | 779 && ! XMARKBIT (*(Lisp_Object *) &i->parent)) \ |
| 628 mark_interval_tree (i); \ | 780 mark_interval_tree (i); \ |
| 629 } while (0) | 781 } while (0) |
| 782 | |
| 630 | 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 `='. */ |
| 634 | 787 |
| 639 XUNMARK (* (Lisp_Object *) (&(i)->parent)); \ | 792 XUNMARK (* (Lisp_Object *) (&(i)->parent)); \ |
| 640 (i) = balance_intervals (i); \ | 793 (i) = balance_intervals (i); \ |
| 641 } \ | 794 } \ |
| 642 } while (0) | 795 } while (0) |
| 643 | 796 |
| 797 | |
| 644 | 798 |
| 645 /*********************************************************************** | 799 /*********************************************************************** |
| 646 String Allocation | 800 String Allocation |
| 647 ***********************************************************************/ | 801 ***********************************************************************/ |
| 648 | 802 |
| 684 | 838 |
| 685 struct sdata | 839 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. */ |
| 693 struct Lisp_String *string; | 847 struct Lisp_String *string; |
| 694 | 848 |
| 812 if (string_free_list == NULL) | 966 if (string_free_list == NULL) |
| 813 { | 967 { |
| 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; |
| 821 string_blocks = b; | 975 string_blocks = b; |
| 822 ++n_string_blocks; | 976 ++n_string_blocks; |
| 873 #ifdef DOUG_LEA_MALLOC | 1027 #ifdef DOUG_LEA_MALLOC |
| 874 /* Prevent mmap'ing the chunk (which is potentially very large). */ | 1028 /* Prevent mmap'ing the chunk (which is potentially very large). */ |
| 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. */ |
| 882 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | 1036 mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); |
| 883 #endif | 1037 #endif |
| 891 || (((char *) current_sblock + SBLOCK_SIZE | 1045 || (((char *) current_sblock + SBLOCK_SIZE |
| 892 - (char *) current_sblock->next_free) | 1046 - (char *) current_sblock->next_free) |
| 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; |
| 900 | 1054 |
| 901 if (current_sblock) | 1055 if (current_sblock) |
| 995 string_free_list = s; | 1149 string_free_list = s; |
| 996 ++nfree; | 1150 ++nfree; |
| 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) |
| 1004 { | 1158 { |
| 1005 lisp_free (b); | 1159 lisp_free (b); |
| 1188 | 1342 |
| 1189 /* We must allocate one more elements than LENGTH_IN_ELTS for the | 1343 /* We must allocate one more elements than LENGTH_IN_ELTS for the |
| 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); |
| 1196 p->size = XFASTINT (length); | 1351 p->size = XFASTINT (length); |
| 1197 | 1352 |
| 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] |
| 1204 &= (1 << (XINT (length) % BITS_PER_CHAR)) - 1; | 1360 &= (1 << (XINT (length) % BITS_PER_CHAR)) - 1; |
| 1205 | 1361 |
| 1359 { | 1515 { |
| 1360 struct float_block *next; | 1516 struct float_block *next; |
| 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; |
| 1535 | |
| 1536 | |
| 1537 /* Initialze float allocation. */ | |
| 1372 | 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; |
| 1380 float_free_list = 0; | 1547 float_free_list = 0; |
| 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 } |
| 1564 | |
| 1565 | |
| 1566 /* Return a new float object with value FLOAT_VALUE. */ | |
| 1393 | 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; |
| 1397 { | 1571 { |
| 1408 { | 1582 { |
| 1409 if (float_block_index == FLOAT_BLOCK_SIZE) | 1583 if (float_block_index == FLOAT_BLOCK_SIZE) |
| 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; |
| 1417 float_block_index = 0; | 1592 float_block_index = 0; |
| 1418 n_float_blocks++; | 1593 n_float_blocks++; |
| 1449 { | 1624 { |
| 1450 struct cons_block *next; | 1625 struct cons_block *next; |
| 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; |
| 1644 | |
| 1645 | |
| 1646 /* Initialize cons allocation. */ | |
| 1462 | 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; |
| 1470 cons_free_list = 0; | 1656 cons_free_list = 0; |
| 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 } |
| 1673 | |
| 1483 | 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) |
| 1487 Lisp_Object car, cdr; | 1678 Lisp_Object car, cdr; |
| 1498 else | 1689 else |
| 1499 { | 1690 { |
| 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; |
| 1507 cons_block_index = 0; | 1699 cons_block_index = 0; |
| 1508 n_cons_blocks++; | 1700 n_cons_blocks++; |
| 1515 consing_since_gc += sizeof (struct Lisp_Cons); | 1707 consing_since_gc += sizeof (struct Lisp_Cons); |
| 1516 cons_cells_consed++; | 1708 cons_cells_consed++; |
| 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 |
| 1524 list2 (arg1, arg2) | 1716 list2 (arg1, arg2) |
| 1525 Lisp_Object arg1, arg2; | 1717 Lisp_Object arg1, arg2; |
| 1526 { | 1718 { |
| 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; |
| 1533 { | 1726 { |
| 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; |
| 1540 { | 1734 { |
| 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; |
| 1547 { | 1742 { |
| 1548 return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4, | 1743 return Fcons (arg1, Fcons (arg2, Fcons (arg3, Fcons (arg4, |
| 1549 Fcons (arg5, Qnil))))); | 1744 Fcons (arg5, Qnil))))); |
| 1550 } | 1745 } |
| 1746 | |
| 1551 | 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.") |
| 1555 (nargs, args) | 1751 (nargs, args) |
| 1565 val = Fcons (args[nargs], val); | 1761 val = Fcons (args[nargs], val); |
| 1566 } | 1762 } |
| 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) |
| 1573 register Lisp_Object length, init; | 1770 register Lisp_Object length, init; |
| 1574 { | 1771 { |
| 1588 | 1785 |
| 1589 /*********************************************************************** | 1786 /*********************************************************************** |
| 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; |
| 1797 | |
| 1798 | |
| 1799 /* Value is a pointer to a newly allocated Lisp_Vector structure | |
| 1800 with room for LEN Lisp_Objects. */ | |
| 1598 | 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 } |
| 1831 | |
| 1625 | 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'.") |
| 1629 (length, init) | 1836 (length, init) |
| 1643 p->contents[index] = init; | 1850 p->contents[index] = init; |
| 1644 | 1851 |
| 1645 XSETVECTOR (vector, p); | 1852 XSETVECTOR (vector, p); |
| 1646 return vector; | 1853 return vector; |
| 1647 } | 1854 } |
| 1855 | |
| 1648 | 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\ |
| 1652 PURPOSE should be a symbol which has a `char-table-extra-slots' property.\n\ | 1860 PURPOSE should be a symbol which has a `char-table-extra-slots' property.\n\ |
| 1669 XCHAR_TABLE (vector)->purpose = purpose; | 1877 XCHAR_TABLE (vector)->purpose = purpose; |
| 1670 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); | 1878 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); |
| 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. */ |
| 1677 | 1886 |
| 1678 Lisp_Object | 1887 Lisp_Object |
| 1685 XCHAR_TABLE (vector)->defalt = defalt; | 1894 XCHAR_TABLE (vector)->defalt = defalt; |
| 1686 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); | 1895 XSETCHAR_TABLE (vector, XCHAR_TABLE (vector)); |
| 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.") |
| 1693 (nargs, args) | 1903 (nargs, args) |
| 1694 register int nargs; | 1904 register int nargs; |
| 1703 p = XVECTOR (val); | 1913 p = XVECTOR (val); |
| 1704 for (index = 0; index < nargs; index++) | 1914 for (index = 0; index < nargs; index++) |
| 1705 p->contents[index] = args[index]; | 1915 p->contents[index] = args[index]; |
| 1706 return val; | 1916 return val; |
| 1707 } | 1917 } |
| 1918 | |
| 1708 | 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\ |
| 1712 stack size, (optional) doc string, and (optional) interactive spec.\n\ | 1923 stack size, (optional) doc string, and (optional) interactive spec.\n\ |
| 1734 } | 1945 } |
| 1735 XSETCOMPILED (val, p); | 1946 XSETCOMPILED (val, p); |
| 1736 return val; | 1947 return val; |
| 1737 } | 1948 } |
| 1738 | 1949 |
| 1950 | |
| 1739 | 1951 |
| 1740 /*********************************************************************** | 1952 /*********************************************************************** |
| 1741 Symbol Allocation | 1953 Symbol Allocation |
| 1742 ***********************************************************************/ | 1954 ***********************************************************************/ |
| 1743 | 1955 |
| 1752 { | 1964 { |
| 1753 struct symbol_block *next; | 1965 struct symbol_block *next; |
| 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; |
| 1982 | |
| 1983 | |
| 1984 /* Initialize symbol allocation. */ | |
| 1765 | 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; |
| 1773 symbol_free_list = 0; | 1994 symbol_free_list = 0; |
| 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.") |
| 1780 (name) | 2002 (name) |
| 1781 Lisp_Object name; | 2003 Lisp_Object name; |
| 1793 else | 2015 else |
| 1794 { | 2016 { |
| 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; |
| 1802 symbol_block_index = 0; | 2025 symbol_block_index = 0; |
| 1803 n_symbol_blocks++; | 2026 n_symbol_blocks++; |
| 1818 } | 2041 } |
| 1819 | 2042 |
| 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. |
| 1827 Works like allocation of conses. */ | 2050 Works like allocation of conses. */ |
| 1828 | 2051 |
| 1845 int n_marker_blocks; | 2068 int n_marker_blocks; |
| 1846 | 2069 |
| 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; |
| 1854 marker_free_list = 0; | 2078 marker_free_list = 0; |
| 1855 n_marker_blocks = 1; | 2079 n_marker_blocks = 1; |
| 1870 else | 2094 else |
| 1871 { | 2095 { |
| 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; |
| 1879 marker_block_index = 0; | 2104 marker_block_index = 0; |
| 1880 n_marker_blocks++; | 2105 n_marker_blocks++; |
| 1960 } | 2185 } |
| 1961 } | 2186 } |
| 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 ***********************************************************************/ |
| 1968 | 3003 |
| 1969 /* Return a string allocated in pure space. DATA is a buffer holding | 3004 /* Return a string allocated in pure space. DATA is a buffer holding |
| 2008 XSETSTRING (string, s); | 3043 XSETSTRING (string, s); |
| 2009 return string; | 3044 return string; |
| 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; |
| 2016 { | 3054 { |
| 2017 register Lisp_Object new; | 3055 register Lisp_Object new; |
| 2023 XCAR (new) = Fpurecopy (car); | 3061 XCAR (new) = Fpurecopy (car); |
| 2024 XCDR (new) = Fpurecopy (cdr); | 3062 XCDR (new) = Fpurecopy (cdr); |
| 2025 return new; | 3063 return new; |
| 2026 } | 3064 } |
| 2027 | 3065 |
| 3066 | |
| 3067 /* Value is a float object with value NUM allocated from pure space. */ | |
| 2028 | 3068 |
| 2029 Lisp_Object | 3069 Lisp_Object |
| 2030 make_pure_float (num) | 3070 make_pure_float (num) |
| 2031 double num; | 3071 double num; |
| 2032 { | 3072 { |
| 2060 XFLOAT_DATA (new) = num; | 3100 XFLOAT_DATA (new) = num; |
| 2061 XSETFASTINT (XFLOAT (new)->type, 0); /* bug chasing -wsr */ | 3101 XSETFASTINT (XFLOAT (new)->type, 0); /* bug chasing -wsr */ |
| 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"); |
| 2074 | 3119 |
| 2075 XSETVECTOR (new, PUREBEG + pureptr); | 3120 XSETVECTOR (new, PUREBEG + pureptr); |
| 2076 pureptr += size; | 3121 pureptr += size; |
| 2077 XVECTOR (new)->size = len; | 3122 XVECTOR (new)->size = len; |
| 2078 return new; | 3123 return new; |
| 2079 } | 3124 } |
| 3125 | |
| 2080 | 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\ |
| 2084 Does not copy symbols. Copies strings without text properties.") | 3130 Does not copy symbols. Copies strings without text properties.") |
| 2121 error ("Attempt to copy a marker to pure storage"); | 3167 error ("Attempt to copy a marker to pure storage"); |
| 2122 else | 3168 else |
| 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 |
| 3182 /* Addresses of staticpro'd variables. */ | |
| 3183 | |
| 2131 #define NSTATICS 1024 | 3184 #define NSTATICS 1024 |
| 2132 | |
| 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; |
| 3190 | |
| 2136 | 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 |
| 2140 void | 3195 void |
| 2149 struct catchtag | 3204 struct catchtag |
| 2150 { | 3205 { |
| 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 |
| 2160 { | 3212 { |
| 2161 struct backtrace *next; | 3213 struct backtrace *next; |
| 2165 /* If nargs is UNEVALLED, args points to slot holding list of | 3217 /* If nargs is UNEVALLED, args points to slot holding list of |
| 2166 unevalled args. */ | 3218 unevalled args. */ |
| 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 |
| 2175 int | 3230 int |
| 2176 inhibit_garbage_collection () | 3231 inhibit_garbage_collection () |
| 2183 | 3238 |
| 2184 specbind (Qgc_cons_threshold, number); | 3239 specbind (Qgc_cons_threshold, number); |
| 2185 | 3240 |
| 2186 return count; | 3241 return count; |
| 2187 } | 3242 } |
| 3243 | |
| 2188 | 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\ |
| 2192 ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\ | 3248 ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\ |
| 2273 In some cases, the structures point to the slots to be marked. | 3329 In some cases, the structures point to the slots to be marked. |
| 2274 For these, we use MARKBIT to avoid double marking of the slot. */ | 3330 For these, we use MARKBIT to avoid double marking of the slot. */ |
| 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])) |
| 2281 { | 3342 { |
| 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 { |
| 2288 mark_object (&bind->symbol); | 3351 mark_object (&bind->symbol); |
| 2289 mark_object (&bind->old_value); | 3352 mark_object (&bind->old_value); |
| 2356 | 3419 |
| 2357 nextb = nextb->next; | 3420 nextb = nextb->next; |
| 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 { |
| 2371 XUNMARK (*backlist->function); | 3442 XUNMARK (*backlist->function); |
| 2372 if (backlist->nargs == UNEVALLED || backlist->nargs == MANY) | 3443 if (backlist->nargs == UNEVALLED || backlist->nargs == MANY) |
| 2376 for (; i >= 0; i--) | 3447 for (; i >= 0; i--) |
| 2377 XUNMARK (backlist->args[i]); | 3448 XUNMARK (backlist->args[i]); |
| 2378 } | 3449 } |
| 2379 XUNMARK (buffer_defaults.name); | 3450 XUNMARK (buffer_defaults.name); |
| 2380 XUNMARK (buffer_local_symbols.name); | 3451 XUNMARK (buffer_local_symbols.name); |
| 3452 | |
| 3453 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES && 0 | |
| 3454 dump_zombies (); | |
| 3455 #endif | |
| 2381 | 3456 |
| 2382 UNBLOCK_INPUT; | 3457 UNBLOCK_INPUT; |
| 2383 | 3458 |
| 2384 /* clear_marks (); */ | 3459 /* clear_marks (); */ |
| 2385 gc_in_progress = 0; | 3460 gc_in_progress = 0; |
| 2411 total[5] = Fcons (make_number (total_intervals), | 3486 total[5] = Fcons (make_number (total_intervals), |
| 2412 make_number (total_free_intervals)); | 3487 make_number (total_free_intervals)); |
| 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 |
| 3491 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | |
| 3492 { | |
| 3493 /* Compute average percentage of zombies. */ | |
| 3494 double nlive = 0; | |
| 3495 | |
| 3496 for (i = 0; i < 7; ++i) | |
| 3497 nlive += XFASTINT (XCAR (total[i])); | |
| 3498 | |
| 3499 avg_live = (avg_live * ngcs + nlive) / (ngcs + 1); | |
| 3500 max_live = max (nlive, max_live); | |
| 3501 avg_zombies = (avg_zombies * ngcs + nzombies) / (ngcs + 1); | |
| 3502 max_zombies = max (nzombies, max_zombies); | |
| 3503 ++ngcs; | |
| 3504 } | |
| 3505 #endif | |
| 3506 | |
| 2416 return Flist (7, total); | 3507 return Flist (7, total); |
| 2417 } | 3508 } |
| 2418 | 3509 |
| 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 { | |
| 2438 register struct symbol_block *sblk; | |
| 2439 register int lim = symbol_block_index; | |
| 2440 | |
| 2441 for (sblk = symbol_block; sblk; sblk = sblk->next) | |
| 2442 { | |
| 2443 register int i; | |
| 2444 for (i = 0; i < lim; i++) | |
| 2445 { | |
| 2446 XUNMARK (sblk->symbols[i].plist); | |
| 2447 } | |
| 2448 lim = SYMBOL_BLOCK_SIZE; | |
| 2449 } | |
| 2450 } | |
| 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 | |
| 2469 while (nextb) | |
| 2470 { | |
| 2471 XUNMARK (nextb->name); | |
| 2472 nextb = nextb->next; | |
| 2473 } | |
| 2474 } | |
| 2475 } | |
| 2476 #endif | |
| 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. */ |
| 2480 | 3513 |
| 2481 static void | 3514 static void |
| 2500 mark_object (&glyph->object); | 3533 mark_object (&glyph->object); |
| 2501 } | 3534 } |
| 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 |
| 2508 mark_face_cache (c) | 3542 mark_face_cache (c) |
| 2509 struct face_cache *c; | 3543 struct face_cache *c; |
| 2573 loop: | 3607 loop: |
| 2574 obj = *objptr; | 3608 obj = *objptr; |
| 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; |
| 2583 if (last_marked_index == LAST_MARKED_SIZE) | 3616 if (last_marked_index == LAST_MARKED_SIZE) |
| 2584 last_marked_index = 0; | 3617 last_marked_index = 0; |
| 2770 if (XMARKBIT (ptr->plist)) break; | 3803 if (XMARKBIT (ptr->plist)) break; |
| 2771 XMARK (ptr->plist); | 3804 XMARK (ptr->plist); |
| 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 |
| 2780 slot except to check whether it is nil. */ | 3815 slot except to check whether it is nil. */ |
| 2781 ptr = ptr->next; | 3816 ptr = ptr->next; |
| 3046 | 4081 |
| 3047 default: | 4082 default: |
| 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 |
| 3055 | 4090 |
| 3056 /* Sweep: find all structures not marked, and free them. */ | 4091 /* Sweep: find all structures not marked, and free them. */ |
| 3081 if (!XMARKBIT (cblk->conses[i].car)) | 4116 if (!XMARKBIT (cblk->conses[i].car)) |
| 3082 { | 4117 { |
| 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 { |
| 3089 num_used++; | 4127 num_used++; |
| 3090 XUNMARK (cblk->conses[i].car); | 4128 XUNMARK (cblk->conses[i].car); |
| 3128 if (!XMARKBIT (fblk->floats[i].type)) | 4166 if (!XMARKBIT (fblk->floats[i].type)) |
| 3129 { | 4167 { |
| 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 { |
| 3136 num_used++; | 4177 num_used++; |
| 3137 XUNMARK (fblk->floats[i].type); | 4178 XUNMARK (fblk->floats[i].type); |
| 3224 for (i = 0; i < lim; i++) | 4265 for (i = 0; i < lim; i++) |
| 3225 if (!XMARKBIT (sblk->symbols[i].plist)) | 4266 if (!XMARKBIT (sblk->symbols[i].plist)) |
| 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; |
| 3238 /* If this block contains only free symbols and we have already | 4283 /* If this block contains only free symbols and we have already |
| 3239 seen more than two blocks worth of free symbols then deallocate | 4284 seen more than two blocks worth of free symbols then deallocate |
| 3354 if (prev) | 4399 if (prev) |
| 3355 prev->next = buffer->next; | 4400 prev->next = buffer->next; |
| 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 |
| 3363 { | 4408 { |
| 3364 XUNMARK (buffer->name); | 4409 XUNMARK (buffer->name); |
| 3373 total_vector_size = 0; | 4418 total_vector_size = 0; |
| 3374 | 4419 |
| 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 |
| 3386 all_vectors = vector->next; | 4426 all_vectors = vector->next; |
| 3387 next = vector->next; | 4427 next = vector->next; |
| 3462 void | 4502 void |
| 3463 init_alloc_once () | 4503 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 |
| 3470 all_vectors = 0; | 4514 all_vectors = 0; |
| 3471 ignore_warnings = 1; | 4515 ignore_warnings = 1; |
| 3477 init_strings (); | 4521 init_strings (); |
| 3478 init_cons (); | 4522 init_cons (); |
| 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; |
| 3486 #else | 4530 #else |
| 3487 malloc_hysteresis = 0; | 4531 malloc_hysteresis = 0; |
| 3543 DEFVAR_INT ("intervals-consed", &intervals_consed, | 4587 DEFVAR_INT ("intervals-consed", &intervals_consed, |
| 3544 "Number of intervals that have been consed so far."); | 4588 "Number of intervals that have been consed so far."); |
| 3545 | 4589 |
| 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 | |
| 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 | 4592 |
| 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."); |
| 3560 | 4596 |
| 3602 defsubr (&Smake_marker); | 4638 defsubr (&Smake_marker); |
| 3603 defsubr (&Spurecopy); | 4639 defsubr (&Spurecopy); |
| 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); |
| 3607 } | 4643 |
| 4644 #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | |
| 4645 defsubr (&Sgc_status); | |
| 4646 #endif | |
| 4647 } |
