Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 380:8626e4521993 r21-2-5
Import from CVS: tag r21-2-5
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:07:10 +0200 |
parents | a300bb07d72d |
children | 064ab7fed2e0 |
comparison
equal
deleted
inserted
replaced
379:76b7d63099ad | 380:8626e4521993 |
---|---|
49 #include "elhash.h" | 49 #include "elhash.h" |
50 #include "events.h" | 50 #include "events.h" |
51 #include "extents.h" | 51 #include "extents.h" |
52 #include "frame.h" | 52 #include "frame.h" |
53 #include "glyphs.h" | 53 #include "glyphs.h" |
54 #include "opaque.h" | |
54 #include "redisplay.h" | 55 #include "redisplay.h" |
55 #include "specifier.h" | 56 #include "specifier.h" |
56 #include "sysfile.h" | 57 #include "sysfile.h" |
57 #include "window.h" | 58 #include "window.h" |
58 | 59 |
72 #endif | 73 #endif |
73 #endif | 74 #endif |
74 | 75 |
75 /* Define this to see where all that space is going... */ | 76 /* Define this to see where all that space is going... */ |
76 /* But the length of the printout is obnoxious, so limit it to testers */ | 77 /* But the length of the printout is obnoxious, so limit it to testers */ |
77 /* If somebody wants to see this they can ask for it. | 78 #ifdef MEMORY_USAGE_STATS |
78 #ifdef DEBUG_XEMACS | |
79 #define PURESTAT | 79 #define PURESTAT |
80 #endif | 80 #endif |
81 */ | |
82 | 81 |
83 /* Define this to use malloc/free with no freelist for all datatypes, | 82 /* Define this to use malloc/free with no freelist for all datatypes, |
84 the hope being that some debugging tools may help detect | 83 the hope being that some debugging tools may help detect |
85 freed memory references */ | 84 freed memory references */ |
86 #ifdef USE_DEBUG_MALLOC /* Taking the above comment at face value -slb */ | 85 #ifdef USE_DEBUG_MALLOC /* Taking the above comment at face value -slb */ |
89 #endif | 88 #endif |
90 | 89 |
91 #include "puresize.h" | 90 #include "puresize.h" |
92 | 91 |
93 #ifdef DEBUG_XEMACS | 92 #ifdef DEBUG_XEMACS |
94 int debug_allocation; | 93 static int debug_allocation; |
95 | 94 static int debug_allocation_backtrace_length; |
96 int debug_allocation_backtrace_length; | |
97 #endif | 95 #endif |
98 | 96 |
99 /* Number of bytes of consing done since the last gc */ | 97 /* Number of bytes of consing done since the last gc */ |
100 EMACS_INT consing_since_gc; | 98 EMACS_INT consing_since_gc; |
101 #ifdef EMACS_BTL | |
102 extern void cadillac_record_backtrace (); | |
103 #define INCREMENT_CONS_COUNTER_1(size) \ | |
104 do { \ | |
105 EMACS_INT __sz__ = ((EMACS_INT) (size)); \ | |
106 consing_since_gc += __sz__; \ | |
107 cadillac_record_backtrace (2, __sz__); \ | |
108 } while (0) | |
109 #else | |
110 #define INCREMENT_CONS_COUNTER_1(size) (consing_since_gc += (size)) | 99 #define INCREMENT_CONS_COUNTER_1(size) (consing_since_gc += (size)) |
111 #endif /* EMACS_BTL */ | |
112 | 100 |
113 #define debug_allocation_backtrace() \ | 101 #define debug_allocation_backtrace() \ |
114 do { \ | 102 do { \ |
115 if (debug_allocation_backtrace_length > 0) \ | 103 if (debug_allocation_backtrace_length > 0) \ |
116 debug_short_backtrace (debug_allocation_backtrace_length); \ | 104 debug_short_backtrace (debug_allocation_backtrace_length); \ |
139 #define INCREMENT_CONS_COUNTER(size, type) INCREMENT_CONS_COUNTER_1 (size) | 127 #define INCREMENT_CONS_COUNTER(size, type) INCREMENT_CONS_COUNTER_1 (size) |
140 #define NOSEEUM_INCREMENT_CONS_COUNTER(size, type) \ | 128 #define NOSEEUM_INCREMENT_CONS_COUNTER(size, type) \ |
141 INCREMENT_CONS_COUNTER_1 (size) | 129 INCREMENT_CONS_COUNTER_1 (size) |
142 #endif | 130 #endif |
143 | 131 |
144 #define DECREMENT_CONS_COUNTER(size) \ | 132 #define DECREMENT_CONS_COUNTER(size) do { \ |
145 do { \ | 133 consing_since_gc -= (size); \ |
146 EMACS_INT __sz__ = ((EMACS_INT) (size)); \ | 134 if (consing_since_gc < 0) \ |
147 if (consing_since_gc >= __sz__) \ | 135 consing_since_gc = 0; \ |
148 consing_since_gc -= __sz__; \ | 136 } while (0) |
149 else \ | |
150 consing_since_gc = 0; \ | |
151 } while (0) | |
152 | 137 |
153 /* Number of bytes of consing since gc before another gc should be done. */ | 138 /* Number of bytes of consing since gc before another gc should be done. */ |
154 EMACS_INT gc_cons_threshold; | 139 EMACS_INT gc_cons_threshold; |
155 | 140 |
156 /* Nonzero during gc */ | 141 /* Nonzero during gc */ |
193 | 178 |
194 #ifdef HEAP_IN_DATA | 179 #ifdef HEAP_IN_DATA |
195 extern void sheap_adjust_h(); | 180 extern void sheap_adjust_h(); |
196 #endif | 181 #endif |
197 | 182 |
183 /* Force linker to put it into data space! */ | |
184 EMACS_INT pure[PURESIZE / sizeof (EMACS_INT)] = { (EMACS_INT) 0}; | |
185 | |
198 #define PUREBEG ((char *) pure) | 186 #define PUREBEG ((char *) pure) |
199 | 187 |
200 #if 0 /* This is breathing_space in XEmacs */ | 188 #if 0 /* This is breathing_space in XEmacs */ |
201 /* Points to memory space allocated as "spare", | 189 /* Points to memory space allocated as "spare", |
202 to be freed if we run out of memory. */ | 190 to be freed if we run out of memory. */ |
211 | 199 |
212 #define PURIFIED(ptr) \ | 200 #define PURIFIED(ptr) \ |
213 ((char *) (ptr) >= PUREBEG && \ | 201 ((char *) (ptr) >= PUREBEG && \ |
214 (char *) (ptr) < PUREBEG + get_PURESIZE()) | 202 (char *) (ptr) < PUREBEG + get_PURESIZE()) |
215 | 203 |
216 /* Non-zero if pure_bytes_used > get_PURESIZE(); accounts for excess purespace needs. */ | 204 /* Non-zero if pure_bytes_used > get_PURESIZE(); |
205 accounts for excess purespace needs. */ | |
217 static size_t pure_lossage; | 206 static size_t pure_lossage; |
218 | 207 |
219 #ifdef ERROR_CHECK_TYPECHECK | 208 #ifdef ERROR_CHECK_TYPECHECK |
220 | 209 |
221 Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN; | 210 Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN; |
260 | 249 |
261 #define bump_purestat(p,b) DO_NOTHING | 250 #define bump_purestat(p,b) DO_NOTHING |
262 | 251 |
263 #else /* PURESTAT */ | 252 #else /* PURESTAT */ |
264 | 253 |
265 static int purecopying_for_bytecode; | 254 static int purecopying_function_constants; |
266 | 255 |
267 static size_t pure_sizeof (Lisp_Object /*, int recurse */); | 256 static size_t pure_sizeof (Lisp_Object); |
268 | 257 |
269 /* Keep statistics on how much of what is in purespace */ | 258 /* Keep statistics on how much of what is in purespace */ |
270 static struct purestat | 259 static struct purestat |
271 { | 260 { |
272 int nobjects; | 261 int nobjects; |
274 CONST char *name; | 263 CONST char *name; |
275 } | 264 } |
276 purestat_cons = {0, 0, "cons cells"}, | 265 purestat_cons = {0, 0, "cons cells"}, |
277 purestat_float = {0, 0, "float objects"}, | 266 purestat_float = {0, 0, "float objects"}, |
278 purestat_string_pname = {0, 0, "symbol-name strings"}, | 267 purestat_string_pname = {0, 0, "symbol-name strings"}, |
279 purestat_bytecode = {0, 0, "compiled-function objects"}, | 268 purestat_function = {0, 0, "compiled-function objects"}, |
280 purestat_string_bytecodes = {0, 0, "byte-code strings"}, | 269 purestat_opaque_instructions = {0, 0, "compiled-function instructions"}, |
281 purestat_vector_bytecode_constants = {0, 0, "byte-constant vectors"}, | 270 purestat_vector_constants = {0, 0, "compiled-function constants vectors"}, |
282 purestat_string_interactive = {0, 0, "interactive strings"}, | 271 purestat_string_interactive = {0, 0, "interactive strings"}, |
283 #ifdef I18N3 | 272 #ifdef I18N3 |
284 purestat_string_domain = {0, 0, "domain strings"}, | 273 purestat_string_domain = {0, 0, "domain strings"}, |
285 #endif | 274 #endif |
286 purestat_string_documentation = {0, 0, "documentation strings"}, | 275 purestat_string_documentation = {0, 0, "documentation strings"}, |
288 purestat_vector_other = {0, 0, "other vectors"}, | 277 purestat_vector_other = {0, 0, "other vectors"}, |
289 purestat_string_other = {0, 0, "other strings"}, | 278 purestat_string_other = {0, 0, "other strings"}, |
290 purestat_string_all = {0, 0, "all strings"}, | 279 purestat_string_all = {0, 0, "all strings"}, |
291 purestat_vector_all = {0, 0, "all vectors"}; | 280 purestat_vector_all = {0, 0, "all vectors"}; |
292 | 281 |
293 static struct purestat *purestats[] = | |
294 { | |
295 &purestat_cons, | |
296 &purestat_float, | |
297 &purestat_string_pname, | |
298 &purestat_bytecode, | |
299 &purestat_string_bytecodes, | |
300 &purestat_vector_bytecode_constants, | |
301 &purestat_string_interactive, | |
302 #ifdef I18N3 | |
303 &purestat_string_domain, | |
304 #endif | |
305 &purestat_string_documentation, | |
306 &purestat_string_other_function, | |
307 &purestat_vector_other, | |
308 &purestat_string_other, | |
309 0, | |
310 &purestat_string_all, | |
311 &purestat_vector_all | |
312 }; | |
313 | |
314 static void | 282 static void |
315 bump_purestat (struct purestat *purestat, size_t nbytes) | 283 bump_purestat (struct purestat *purestat, size_t nbytes) |
316 { | 284 { |
317 if (pure_lossage) return; | 285 if (pure_lossage) return; |
318 purestat->nobjects += 1; | 286 purestat->nobjects += 1; |
319 purestat->nbytes += nbytes; | 287 purestat->nbytes += nbytes; |
320 } | 288 } |
289 | |
290 static void | |
291 print_purestat (struct purestat *purestat) | |
292 { | |
293 char buf [100]; | |
294 sprintf(buf, "%s:", purestat->name); | |
295 message (" %-36s %5d %7d %2d%%", | |
296 buf, | |
297 purestat->nobjects, | |
298 purestat->nbytes, | |
299 (int) (purestat->nbytes / (pure_bytes_used / 100.0) + 0.5)); | |
300 } | |
321 #endif /* PURESTAT */ | 301 #endif /* PURESTAT */ |
322 | 302 |
323 | 303 |
324 /* Maximum amount of C stack to save when a GC happens. */ | 304 /* Maximum amount of C stack to save when a GC happens. */ |
325 | 305 |
326 #ifndef MAX_SAVE_STACK | 306 #ifndef MAX_SAVE_STACK |
327 #define MAX_SAVE_STACK 16000 | 307 #define MAX_SAVE_STACK 0 /* 16000 */ |
328 #endif | 308 #endif |
329 | 309 |
330 /* Non-zero means ignore malloc warnings. Set during initialization. */ | 310 /* Non-zero means ignore malloc warnings. Set during initialization. */ |
331 int ignore_malloc_warnings; | 311 int ignore_malloc_warnings; |
332 | 312 |
393 | 373 |
394 if (!val && (size != 0)) memory_full (); | 374 if (!val && (size != 0)) memory_full (); |
395 return val; | 375 return val; |
396 } | 376 } |
397 | 377 |
378 static void * | |
379 xcalloc (size_t nelem, size_t elsize) | |
380 { | |
381 void *val = (void *) calloc (nelem, elsize); | |
382 | |
383 if (!val && (nelem != 0)) memory_full (); | |
384 return val; | |
385 } | |
386 | |
398 void * | 387 void * |
399 xmalloc_and_zero (size_t size) | 388 xmalloc_and_zero (size_t size) |
400 { | 389 { |
401 void *val = xmalloc (size); | 390 return xcalloc (size, sizeof (char)); |
402 memset (val, 0, size); | |
403 return val; | |
404 } | 391 } |
405 | 392 |
406 #ifdef xrealloc | 393 #ifdef xrealloc |
407 #undef xrealloc | 394 #undef xrealloc |
408 #endif | 395 #endif |
517 void * | 504 void * |
518 alloc_lcrecord (size_t size, CONST struct lrecord_implementation *implementation) | 505 alloc_lcrecord (size_t size, CONST struct lrecord_implementation *implementation) |
519 { | 506 { |
520 struct lcrecord_header *lcheader; | 507 struct lcrecord_header *lcheader; |
521 | 508 |
522 if (size <= 0) abort (); | 509 #ifdef ERROR_CHECK_GC |
523 if (implementation->static_size == 0) | 510 if (implementation->static_size == 0) |
524 { | 511 assert (implementation->size_in_bytes_method); |
525 if (!implementation->size_in_bytes_method) | 512 else |
526 abort (); | 513 assert (implementation->static_size == size); |
527 } | 514 #endif |
528 else if (implementation->static_size != size) | |
529 abort (); | |
530 | 515 |
531 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); | 516 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); |
532 set_lheader_implementation(&(lcheader->lheader), implementation); | 517 set_lheader_implementation (&(lcheader->lheader), implementation); |
533 lcheader->next = all_lcrecords; | 518 lcheader->next = all_lcrecords; |
534 #if 1 /* mly prefers to see small ID numbers */ | 519 #if 1 /* mly prefers to see small ID numbers */ |
535 lcheader->uid = lrecord_uid_counter++; | 520 lcheader->uid = lrecord_uid_counter++; |
536 #else /* jwz prefers to see real addrs */ | 521 #else /* jwz prefers to see real addrs */ |
537 lcheader->uid = (int) &lcheader; | 522 lcheader->uid = (int) &lcheader; |
572 else | 557 else |
573 header = next; | 558 header = next; |
574 } | 559 } |
575 } | 560 } |
576 if (lrecord->implementation->finalizer) | 561 if (lrecord->implementation->finalizer) |
577 ((lrecord->implementation->finalizer) (lrecord, 0)); | 562 lrecord->implementation->finalizer (lrecord, 0); |
578 xfree (lrecord); | 563 xfree (lrecord); |
579 return; | 564 return; |
580 } | 565 } |
581 #endif /* Unused */ | 566 #endif /* Unused */ |
582 | 567 |
634 return imp == type || imp == type + 1; | 619 return imp == type || imp == type + 1; |
635 #endif | 620 #endif |
636 } | 621 } |
637 | 622 |
638 | 623 |
639 /**********************************************************************/ | 624 /************************************************************************/ |
640 /* Debugger support */ | 625 /* Debugger support */ |
641 /**********************************************************************/ | 626 /************************************************************************/ |
642 /* Give gdb/dbx enough information to decode Lisp Objects. | 627 /* Give gdb/dbx enough information to decode Lisp Objects. |
643 We make sure certain symbols are defined, so gdb doesn't complain | 628 We make sure certain symbols are defined, so gdb doesn't complain |
644 about expressions in src/gdbinit. Values are randomly chosen. | 629 about expressions in src/gdbinit. Values are randomly chosen. |
645 See src/gdbinit or src/dbxrc to see how this is used. */ | 630 See src/gdbinit or src/dbxrc to see how this is used. */ |
646 | 631 |
655 dbg_valmask = (EMACS_INT) ((1UL << VALBITS) - 1), | 640 dbg_valmask = (EMACS_INT) ((1UL << VALBITS) - 1), |
656 dbg_typemask = (EMACS_INT) (((1UL << GCTYPEBITS) - 1) << (VALBITS + GCMARKBITS)), | 641 dbg_typemask = (EMACS_INT) (((1UL << GCTYPEBITS) - 1) << (VALBITS + GCMARKBITS)), |
657 dbg_USE_MINIMAL_TAGBITS = 0, | 642 dbg_USE_MINIMAL_TAGBITS = 0, |
658 dbg_Lisp_Type_Int = Lisp_Type_Int, | 643 dbg_Lisp_Type_Int = Lisp_Type_Int, |
659 #endif /* ! USE_MIMIMAL_TAGBITS */ | 644 #endif /* ! USE_MIMIMAL_TAGBITS */ |
645 | |
646 #ifdef USE_UNION_TYPE | |
647 dbg_USE_UNION_TYPE = 1, | |
648 #else | |
649 dbg_USE_UNION_TYPE = 0, | |
650 #endif | |
651 | |
660 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION | 652 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION |
661 dbg_USE_INDEXED_LRECORD_IMPLEMENTATION = 1, | 653 dbg_USE_INDEXED_LRECORD_IMPLEMENTATION = 1, |
662 #else | 654 #else |
663 dbg_USE_INDEXED_LRECORD_IMPLEMENTATION = 0, | 655 dbg_USE_INDEXED_LRECORD_IMPLEMENTATION = 0, |
664 #endif | 656 #endif |
657 | |
665 dbg_Lisp_Type_Char = Lisp_Type_Char, | 658 dbg_Lisp_Type_Char = Lisp_Type_Char, |
666 dbg_Lisp_Type_Record = Lisp_Type_Record, | 659 dbg_Lisp_Type_Record = Lisp_Type_Record, |
667 #ifdef LRECORD_CONS | 660 #ifdef LRECORD_CONS |
668 dbg_Lisp_Type_Cons = 101, | 661 dbg_Lisp_Type_Cons = 101, |
669 #else | 662 #else |
707 dbg_gctypebits = GCTYPEBITS | 700 dbg_gctypebits = GCTYPEBITS |
708 /* If we don't have an actual object of this enum, pgcc (and perhaps | 701 /* If we don't have an actual object of this enum, pgcc (and perhaps |
709 other compilers) might optimize away the entire type declaration :-( */ | 702 other compilers) might optimize away the entire type declaration :-( */ |
710 } dbg_dummy; | 703 } dbg_dummy; |
711 | 704 |
705 /* A few macros turned into functions for ease of debugging. | |
706 Debuggers don't know about macros! */ | |
707 int dbg_eq (Lisp_Object obj1, Lisp_Object obj2); | |
708 int | |
709 dbg_eq (Lisp_Object obj1, Lisp_Object obj2) | |
710 { | |
711 return EQ (obj1, obj2); | |
712 } | |
713 | |
712 | 714 |
713 /**********************************************************************/ | 715 /************************************************************************/ |
714 /* Fixed-size type macros */ | 716 /* Fixed-size type macros */ |
715 /**********************************************************************/ | 717 /************************************************************************/ |
716 | 718 |
717 /* For fixed-size types that are commonly used, we malloc() large blocks | 719 /* For fixed-size types that are commonly used, we malloc() large blocks |
718 of memory at a time and subdivide them into chunks of the correct | 720 of memory at a time and subdivide them into chunks of the correct |
719 size for an object of that type. This is more efficient than | 721 size for an object of that type. This is more efficient than |
720 malloc()ing each object separately because we save on malloc() time | 722 malloc()ing each object separately because we save on malloc() time |
892 # define TYPE_ALLOC_SIZE(type, structtype) \ | 894 # define TYPE_ALLOC_SIZE(type, structtype) \ |
893 ((2048 - MALLOC_OVERHEAD - sizeof (struct type##_block *)) \ | 895 ((2048 - MALLOC_OVERHEAD - sizeof (struct type##_block *)) \ |
894 / sizeof (structtype)) | 896 / sizeof (structtype)) |
895 #endif /* ALLOC_NO_POOLS */ | 897 #endif /* ALLOC_NO_POOLS */ |
896 | 898 |
897 #define DECLARE_FIXED_TYPE_ALLOC(type, structtype) \ | 899 #define DECLARE_FIXED_TYPE_ALLOC(type, structtype) \ |
898 \ | 900 \ |
899 struct type##_block \ | 901 struct type##_block \ |
900 { \ | 902 { \ |
901 struct type##_block *prev; \ | 903 struct type##_block *prev; \ |
902 structtype block[TYPE_ALLOC_SIZE (type, structtype)]; \ | 904 structtype block[TYPE_ALLOC_SIZE (type, structtype)]; \ |
903 }; \ | 905 }; \ |
904 \ | 906 \ |
905 static struct type##_block *current_##type##_block; \ | 907 static struct type##_block *current_##type##_block; \ |
906 static int current_##type##_block_index; \ | 908 static int current_##type##_block_index; \ |
907 \ | 909 \ |
908 static structtype *type##_free_list; \ | 910 static structtype *type##_free_list; \ |
909 static structtype *type##_free_list_tail; \ | 911 static structtype *type##_free_list_tail; \ |
910 \ | 912 \ |
911 static void \ | 913 static void \ |
912 init_##type##_alloc (void) \ | 914 init_##type##_alloc (void) \ |
913 { \ | 915 { \ |
914 current_##type##_block = 0; \ | 916 current_##type##_block = 0; \ |
915 current_##type##_block_index = countof (current_##type##_block->block); \ | 917 current_##type##_block_index = \ |
916 type##_free_list = 0; \ | 918 countof (current_##type##_block->block); \ |
917 type##_free_list_tail = 0; \ | 919 type##_free_list = 0; \ |
918 } \ | 920 type##_free_list_tail = 0; \ |
919 \ | 921 } \ |
920 static int gc_count_num_##type##_in_use, gc_count_num_##type##_freelist | 922 \ |
921 | 923 static int gc_count_num_##type##_in_use; \ |
922 #define ALLOCATE_FIXED_TYPE_FROM_BLOCK(type, result) \ | 924 static int gc_count_num_##type##_freelist |
923 do { \ | 925 |
924 if (current_##type##_block_index \ | 926 #define ALLOCATE_FIXED_TYPE_FROM_BLOCK(type, result) do { \ |
925 == countof (current_##type##_block->block)) \ | 927 if (current_##type##_block_index \ |
928 == countof (current_##type##_block->block)) \ | |
926 { \ | 929 { \ |
927 struct type##_block *__new__ = (struct type##_block *) \ | 930 struct type##_block *AFTFB_new = (struct type##_block *) \ |
928 allocate_lisp_storage (sizeof (struct type##_block)); \ | 931 allocate_lisp_storage (sizeof (struct type##_block)); \ |
929 __new__->prev = current_##type##_block; \ | 932 AFTFB_new->prev = current_##type##_block; \ |
930 current_##type##_block = __new__; \ | 933 current_##type##_block = AFTFB_new; \ |
931 current_##type##_block_index = 0; \ | 934 current_##type##_block_index = 0; \ |
932 } \ | 935 } \ |
933 (result) = \ | 936 (result) = \ |
934 &(current_##type##_block->block[current_##type##_block_index++]); \ | 937 &(current_##type##_block->block[current_##type##_block_index++]); \ |
935 } while (0) | 938 } while (0) |
936 | 939 |
937 /* Allocate an instance of a type that is stored in blocks. | 940 /* Allocate an instance of a type that is stored in blocks. |
938 TYPE is the "name" of the type, STRUCTTYPE is the corresponding | 941 TYPE is the "name" of the type, STRUCTTYPE is the corresponding |
939 structure type. */ | 942 structure type. */ |
940 | 943 |
1046 } while (0) | 1049 } while (0) |
1047 | 1050 |
1048 #else /* !ERROR_CHECK_GC */ | 1051 #else /* !ERROR_CHECK_GC */ |
1049 | 1052 |
1050 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ | 1053 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ |
1051 do { * (structtype **) ((char *) ptr + sizeof (void *)) = \ | 1054 do { * (structtype **) ((char *) (ptr) + sizeof (void *)) = \ |
1052 type##_free_list; \ | 1055 type##_free_list; \ |
1053 type##_free_list = ptr; \ | 1056 type##_free_list = (ptr); \ |
1054 } while (0) | 1057 } while (0) |
1055 | 1058 |
1056 #endif /* !ERROR_CHECK_GC */ | 1059 #endif /* !ERROR_CHECK_GC */ |
1057 | 1060 |
1058 /* TYPE and STRUCTTYPE are the same as in ALLOCATE_FIXED_TYPE(). */ | 1061 /* TYPE and STRUCTTYPE are the same as in ALLOCATE_FIXED_TYPE(). */ |
1059 | 1062 |
1060 #define FREE_FIXED_TYPE(type, structtype, ptr) \ | 1063 #define FREE_FIXED_TYPE(type, structtype, ptr) do { \ |
1061 do { structtype *_weird_ = (ptr); \ | 1064 structtype *FFT_ptr = (ptr); \ |
1062 ADDITIONAL_FREE_##type (_weird_); \ | 1065 ADDITIONAL_FREE_##type (FFT_ptr); \ |
1063 deadbeef_memory (ptr, sizeof (structtype)); \ | 1066 deadbeef_memory (FFT_ptr, sizeof (structtype)); \ |
1064 PUT_FIXED_TYPE_ON_FREE_LIST (type, structtype, ptr); \ | 1067 PUT_FIXED_TYPE_ON_FREE_LIST (type, structtype, FFT_ptr); \ |
1065 MARK_STRUCT_AS_FREE (_weird_); \ | 1068 MARK_STRUCT_AS_FREE (FFT_ptr); \ |
1066 } while (0) | 1069 } while (0) |
1067 | 1070 |
1068 /* Like FREE_FIXED_TYPE() but used when we are explicitly | 1071 /* Like FREE_FIXED_TYPE() but used when we are explicitly |
1069 freeing a structure through free_cons(), free_marker(), etc. | 1072 freeing a structure through free_cons(), free_marker(), etc. |
1070 rather than through the normal process of sweeping. | 1073 rather than through the normal process of sweeping. |
1071 We attempt to undo the changes made to the allocation counters | 1074 We attempt to undo the changes made to the allocation counters |
1081 gc_count_num_##type##_freelist++; \ | 1084 gc_count_num_##type##_freelist++; \ |
1082 } while (0) | 1085 } while (0) |
1083 | 1086 |
1084 | 1087 |
1085 | 1088 |
1086 /**********************************************************************/ | 1089 /************************************************************************/ |
1087 /* Cons allocation */ | 1090 /* Cons allocation */ |
1088 /**********************************************************************/ | 1091 /************************************************************************/ |
1089 | 1092 |
1090 DECLARE_FIXED_TYPE_ALLOC (cons, struct Lisp_Cons); | 1093 DECLARE_FIXED_TYPE_ALLOC (cons, struct Lisp_Cons); |
1091 /* conses are used and freed so often that we set this really high */ | 1094 /* conses are used and freed so often that we set this really high */ |
1092 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */ | 1095 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */ |
1093 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 | 1096 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 |
1094 | 1097 |
1095 #ifdef LRECORD_CONS | 1098 #ifdef LRECORD_CONS |
1096 static Lisp_Object | 1099 static Lisp_Object |
1097 mark_cons (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 1100 mark_cons (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
1098 { | 1101 { |
1099 if (NILP (XCDR (obj))) | 1102 if (GC_NILP (XCDR (obj))) |
1100 return XCAR (obj); | 1103 return XCAR (obj); |
1101 | 1104 |
1102 (markobj) (XCAR (obj)); | 1105 markobj (XCAR (obj)); |
1103 return XCDR (obj); | 1106 return XCDR (obj); |
1104 } | 1107 } |
1105 | 1108 |
1106 static int | 1109 static int |
1107 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) | 1110 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) |
1173 (int nargs, Lisp_Object *args)) | 1176 (int nargs, Lisp_Object *args)) |
1174 { | 1177 { |
1175 Lisp_Object val = Qnil; | 1178 Lisp_Object val = Qnil; |
1176 Lisp_Object *argp = args + nargs; | 1179 Lisp_Object *argp = args + nargs; |
1177 | 1180 |
1178 while (nargs-- > 0) | 1181 while (argp > args) |
1179 val = Fcons (*--argp, val); | 1182 val = Fcons (*--argp, val); |
1180 return val; | 1183 return val; |
1181 } | 1184 } |
1182 | 1185 |
1183 Lisp_Object | 1186 Lisp_Object |
1253 return val; | 1256 return val; |
1254 } | 1257 } |
1255 } | 1258 } |
1256 | 1259 |
1257 | 1260 |
1258 /**********************************************************************/ | 1261 /************************************************************************/ |
1259 /* Float allocation */ | 1262 /* Float allocation */ |
1260 /**********************************************************************/ | 1263 /************************************************************************/ |
1261 | 1264 |
1262 #ifdef LISP_FLOAT_TYPE | 1265 #ifdef LISP_FLOAT_TYPE |
1263 | 1266 |
1264 DECLARE_FIXED_TYPE_ALLOC (float, struct Lisp_Float); | 1267 DECLARE_FIXED_TYPE_ALLOC (float, struct Lisp_Float); |
1265 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_float 1000 | 1268 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_float 1000 |
1278 } | 1281 } |
1279 | 1282 |
1280 #endif /* LISP_FLOAT_TYPE */ | 1283 #endif /* LISP_FLOAT_TYPE */ |
1281 | 1284 |
1282 | 1285 |
1283 /**********************************************************************/ | 1286 /************************************************************************/ |
1284 /* Vector allocation */ | 1287 /* Vector allocation */ |
1285 /**********************************************************************/ | 1288 /************************************************************************/ |
1286 | 1289 |
1287 #ifdef LRECORD_VECTOR | 1290 #ifdef LRECORD_VECTOR |
1288 static Lisp_Object | 1291 static Lisp_Object |
1289 mark_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) | 1292 mark_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
1290 { | 1293 { |
1291 struct Lisp_Vector *ptr = XVECTOR (obj); | 1294 Lisp_Vector *ptr = XVECTOR (obj); |
1292 int len = vector_length (ptr); | 1295 int len = vector_length (ptr); |
1293 int i; | 1296 int i; |
1294 | 1297 |
1295 for (i = 0; i < len - 1; i++) | 1298 for (i = 0; i < len - 1; i++) |
1296 (markobj) (ptr->contents[i]); | 1299 markobj (ptr->contents[i]); |
1297 return (len > 0) ? ptr->contents[len - 1] : Qnil; | 1300 return (len > 0) ? ptr->contents[len - 1] : Qnil; |
1298 } | 1301 } |
1299 | 1302 |
1300 static size_t | 1303 static size_t |
1301 size_vector (CONST void *lheader) | 1304 size_vector (CONST void *lheader) |
1302 { | 1305 { |
1303 /* * -1 because struct Lisp_Vector includes 1 slot */ | 1306 return offsetof (Lisp_Vector, contents[((Lisp_Vector *) lheader)->size]); |
1304 return sizeof (struct Lisp_Vector) + | |
1305 ((((struct Lisp_Vector *) lheader)->size - 1) * sizeof (Lisp_Object)); | |
1306 } | 1307 } |
1307 | 1308 |
1308 static int | 1309 static int |
1309 vector_equal (Lisp_Object o1, Lisp_Object o2, int depth) | 1310 vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
1310 { | 1311 { |
1311 int indice; | 1312 int indice; |
1312 int len = XVECTOR_LENGTH (o1); | 1313 int len = XVECTOR_LENGTH (obj1); |
1313 if (len != XVECTOR_LENGTH (o2)) | 1314 if (len != XVECTOR_LENGTH (obj2)) |
1314 return 0; | 1315 return 0; |
1315 for (indice = 0; indice < len; indice++) | 1316 for (indice = 0; indice < len; indice++) |
1316 { | 1317 { |
1317 if (!internal_equal (XVECTOR_DATA (o1) [indice], | 1318 if (!internal_equal (XVECTOR_DATA (obj1) [indice], |
1318 XVECTOR_DATA (o2) [indice], | 1319 XVECTOR_DATA (obj2) [indice], |
1319 depth + 1)) | 1320 depth + 1)) |
1320 return 0; | 1321 return 0; |
1321 } | 1322 } |
1322 return 1; | 1323 return 1; |
1323 } | 1324 } |
1329 * No `hash' method needed for | 1330 * No `hash' method needed for |
1330 * vectors. internal_hash | 1331 * vectors. internal_hash |
1331 * knows how to handle vectors. | 1332 * knows how to handle vectors. |
1332 */ | 1333 */ |
1333 0, | 1334 0, |
1334 size_vector, struct Lisp_Vector); | 1335 size_vector, Lisp_Vector); |
1335 | 1336 |
1336 /* #### should allocate `small' vectors from a frob-block */ | 1337 /* #### should allocate `small' vectors from a frob-block */ |
1337 static struct Lisp_Vector * | 1338 static Lisp_Vector * |
1338 make_vector_internal (size_t sizei) | 1339 make_vector_internal (size_t sizei) |
1339 { | 1340 { |
1340 size_t sizem = (sizeof (struct Lisp_Vector) | 1341 /* no vector_next */ |
1341 /* -1 because struct Lisp_Vector includes 1 slot */ | 1342 size_t sizem = offsetof (Lisp_Vector, contents[sizei]); |
1342 + (sizei - 1) * sizeof (Lisp_Object)); | 1343 Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord (sizem, lrecord_vector); |
1343 struct Lisp_Vector *p = | |
1344 (struct Lisp_Vector *) alloc_lcrecord (sizem, lrecord_vector); | |
1345 | 1344 |
1346 p->size = sizei; | 1345 p->size = sizei; |
1347 return p; | 1346 return p; |
1348 } | 1347 } |
1349 | 1348 |
1350 #else /* ! LRECORD_VECTOR */ | 1349 #else /* ! LRECORD_VECTOR */ |
1351 | 1350 |
1352 static Lisp_Object all_vectors; | 1351 static Lisp_Object all_vectors; |
1353 | 1352 |
1354 /* #### should allocate `small' vectors from a frob-block */ | 1353 /* #### should allocate `small' vectors from a frob-block */ |
1355 static struct Lisp_Vector * | 1354 static Lisp_Vector * |
1356 make_vector_internal (size_t sizei) | 1355 make_vector_internal (size_t sizei) |
1357 { | 1356 { |
1358 size_t sizem = (sizeof (struct Lisp_Vector) | 1357 /* + 1 to account for vector_next */ |
1359 /* -1 because struct Lisp_Vector includes 1 slot, | 1358 size_t sizem = offsetof (Lisp_Vector, contents[sizei+1]); |
1360 * +1 to account for vector_next */ | 1359 Lisp_Vector *p = (Lisp_Vector *) allocate_lisp_storage (sizem); |
1361 + (sizei - 1 + 1) * sizeof (Lisp_Object)); | |
1362 struct Lisp_Vector *p = (struct Lisp_Vector *) allocate_lisp_storage (sizem); | |
1363 | 1360 |
1364 INCREMENT_CONS_COUNTER (sizem, "vector"); | 1361 INCREMENT_CONS_COUNTER (sizem, "vector"); |
1365 | 1362 |
1366 p->size = sizei; | 1363 p->size = sizei; |
1367 vector_next (p) = all_vectors; | 1364 vector_next (p) = all_vectors; |
1374 Lisp_Object | 1371 Lisp_Object |
1375 make_vector (EMACS_INT length, Lisp_Object init) | 1372 make_vector (EMACS_INT length, Lisp_Object init) |
1376 { | 1373 { |
1377 int elt; | 1374 int elt; |
1378 Lisp_Object vector; | 1375 Lisp_Object vector; |
1379 struct Lisp_Vector *p; | 1376 Lisp_Vector *p; |
1380 | 1377 |
1381 if (length < 0) | 1378 if (length < 0) |
1382 length = XINT (wrong_type_argument (Qnatnump, make_int (length))); | 1379 length = XINT (wrong_type_argument (Qnatnump, make_int (length))); |
1383 | 1380 |
1384 p = make_vector_internal (length); | 1381 p = make_vector_internal (length); |
1420 */ | 1417 */ |
1421 (int nargs, Lisp_Object *args)) | 1418 (int nargs, Lisp_Object *args)) |
1422 { | 1419 { |
1423 Lisp_Object vector; | 1420 Lisp_Object vector; |
1424 int elt; | 1421 int elt; |
1425 struct Lisp_Vector *p = make_vector_internal (nargs); | 1422 Lisp_Vector *p = make_vector_internal (nargs); |
1426 | 1423 |
1427 for (elt = 0; elt < nargs; elt++) | 1424 for (elt = 0; elt < nargs; elt++) |
1428 vector_data(p)[elt] = args[elt]; | 1425 vector_data(p)[elt] = args[elt]; |
1429 | 1426 |
1430 XSETVECTOR (vector, p); | 1427 XSETVECTOR (vector, p); |
1529 args[7] = obj7; | 1526 args[7] = obj7; |
1530 return Fvector (8, args); | 1527 return Fvector (8, args); |
1531 } | 1528 } |
1532 #endif /* unused */ | 1529 #endif /* unused */ |
1533 | 1530 |
1534 /**********************************************************************/ | 1531 /************************************************************************/ |
1535 /* Bit Vector allocation */ | 1532 /* Bit Vector allocation */ |
1536 /**********************************************************************/ | 1533 /************************************************************************/ |
1537 | 1534 |
1538 static Lisp_Object all_bit_vectors; | 1535 static Lisp_Object all_bit_vectors; |
1539 | 1536 |
1540 /* #### should allocate `small' bit vectors from a frob-block */ | 1537 /* #### should allocate `small' bit vectors from a frob-block */ |
1541 static struct Lisp_Bit_Vector * | 1538 static struct Lisp_Bit_Vector * |
1542 make_bit_vector_internal (size_t sizei) | 1539 make_bit_vector_internal (size_t sizei) |
1543 { | 1540 { |
1544 size_t sizem = sizeof (struct Lisp_Bit_Vector) + | 1541 size_t sizem = |
1545 /* -1 because struct Lisp_Bit_Vector includes 1 slot */ | 1542 offsetof (Lisp_Bit_Vector, bits[BIT_VECTOR_LONG_STORAGE (sizei)]); |
1546 sizeof (long) * (BIT_VECTOR_LONG_STORAGE (sizei) - 1); | 1543 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem); |
1547 struct Lisp_Bit_Vector *p = | |
1548 (struct Lisp_Bit_Vector *) allocate_lisp_storage (sizem); | |
1549 set_lheader_implementation (&(p->lheader), lrecord_bit_vector); | 1544 set_lheader_implementation (&(p->lheader), lrecord_bit_vector); |
1550 | 1545 |
1551 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); | 1546 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); |
1552 | 1547 |
1553 bit_vector_length (p) = sizei; | 1548 bit_vector_length (p) = sizei; |
1554 bit_vector_next (p) = all_bit_vectors; | 1549 bit_vector_next (p) = all_bit_vectors; |
1555 /* make sure the extra bits in the last long are 0; the calling | 1550 /* make sure the extra bits in the last long are 0; the calling |
1556 functions might not set them. */ | 1551 functions might not set them. */ |
1557 p->bits[BIT_VECTOR_LONG_STORAGE (sizei) - 1] = 0; | 1552 p->bits[BIT_VECTOR_LONG_STORAGE (sizei) - 1] = 0; |
1558 XSETBIT_VECTOR (all_bit_vectors, p); | 1553 XSETBIT_VECTOR (all_bit_vectors, p); |
1559 return p; | 1554 return p; |
1638 XSETBIT_VECTOR (bit_vector, p); | 1633 XSETBIT_VECTOR (bit_vector, p); |
1639 return bit_vector; | 1634 return bit_vector; |
1640 } | 1635 } |
1641 | 1636 |
1642 | 1637 |
1643 /**********************************************************************/ | 1638 /************************************************************************/ |
1644 /* Compiled-function allocation */ | 1639 /* Compiled-function allocation */ |
1645 /**********************************************************************/ | 1640 /************************************************************************/ |
1646 | 1641 |
1647 DECLARE_FIXED_TYPE_ALLOC (compiled_function, struct Lisp_Compiled_Function); | 1642 DECLARE_FIXED_TYPE_ALLOC (compiled_function, Lisp_Compiled_Function); |
1648 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_compiled_function 1000 | 1643 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_compiled_function 1000 |
1649 | 1644 |
1650 static Lisp_Object | 1645 static Lisp_Object |
1651 make_compiled_function (int make_pure) | 1646 make_compiled_function (int make_pure) |
1652 { | 1647 { |
1653 struct Lisp_Compiled_Function *b; | 1648 Lisp_Compiled_Function *f; |
1654 Lisp_Object new; | 1649 Lisp_Object fun; |
1655 size_t size = sizeof (struct Lisp_Compiled_Function); | 1650 size_t size = sizeof (Lisp_Compiled_Function); |
1656 | 1651 |
1657 if (make_pure && check_purespace (size)) | 1652 if (make_pure && check_purespace (size)) |
1658 { | 1653 { |
1659 b = (struct Lisp_Compiled_Function *) (PUREBEG + pure_bytes_used); | 1654 f = (Lisp_Compiled_Function *) (PUREBEG + pure_bytes_used); |
1660 set_lheader_implementation (&(b->lheader), lrecord_compiled_function); | 1655 set_lheader_implementation (&(f->lheader), lrecord_compiled_function); |
1661 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION | 1656 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION |
1662 b->lheader.pure = 1; | 1657 f->lheader.pure = 1; |
1663 #endif | 1658 #endif |
1664 pure_bytes_used += size; | 1659 pure_bytes_used += size; |
1665 bump_purestat (&purestat_bytecode, size); | 1660 bump_purestat (&purestat_function, size); |
1666 } | 1661 } |
1667 else | 1662 else |
1668 { | 1663 { |
1669 ALLOCATE_FIXED_TYPE (compiled_function, struct Lisp_Compiled_Function, | 1664 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f); |
1670 b); | 1665 set_lheader_implementation (&(f->lheader), lrecord_compiled_function); |
1671 set_lheader_implementation (&(b->lheader), lrecord_compiled_function); | 1666 } |
1672 } | 1667 f->stack_depth = 0; |
1673 b->maxdepth = 0; | 1668 f->specpdl_depth = 0; |
1674 b->flags.documentationp = 0; | 1669 f->flags.documentationp = 0; |
1675 b->flags.interactivep = 0; | 1670 f->flags.interactivep = 0; |
1676 b->flags.domainp = 0; /* I18N3 */ | 1671 f->flags.domainp = 0; /* I18N3 */ |
1677 b->bytecodes = Qzero; | 1672 f->instructions = Qzero; |
1678 b->constants = Qzero; | 1673 f->constants = Qzero; |
1679 b->arglist = Qnil; | 1674 f->arglist = Qnil; |
1680 b->doc_and_interactive = Qnil; | 1675 f->doc_and_interactive = Qnil; |
1681 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | 1676 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK |
1682 b->annotated = Qnil; | 1677 f->annotated = Qnil; |
1683 #endif | 1678 #endif |
1684 XSETCOMPILED_FUNCTION (new, b); | 1679 XSETCOMPILED_FUNCTION (fun, f); |
1685 return new; | 1680 return fun; |
1686 } | 1681 } |
1687 | 1682 |
1688 DEFUN ("make-byte-code", Fmake_byte_code, 4, MANY, 0, /* | 1683 DEFUN ("make-byte-code", Fmake_byte_code, 4, MANY, 0, /* |
1689 Return a new compiled-function object. | 1684 Return a new compiled-function object. |
1690 Usage: (arglist instructions constants stack-size | 1685 Usage: (arglist instructions constants stack-depth |
1691 &optional doc-string interactive-spec) | 1686 &optional doc-string interactive) |
1692 Note that, unlike all other emacs-lisp functions, calling this with five | 1687 Note that, unlike all other emacs-lisp functions, calling this with five |
1693 arguments is NOT the same as calling it with six arguments, the last of | 1688 arguments is NOT the same as calling it with six arguments, the last of |
1694 which is nil. If the INTERACTIVE arg is specified as nil, then that means | 1689 which is nil. If the INTERACTIVE arg is specified as nil, then that means |
1695 that this function was defined with `(interactive)'. If the arg is not | 1690 that this function was defined with `(interactive)'. If the arg is not |
1696 specified, then that means the function is not interactive. | 1691 specified, then that means the function is not interactive. |
1697 This is terrible behavior which is retained for compatibility with old | 1692 This is terrible behavior which is retained for compatibility with old |
1698 `.elc' files which expected these semantics. | 1693 `.elc' files which expect these semantics. |
1699 */ | 1694 */ |
1700 (int nargs, Lisp_Object *args)) | 1695 (int nargs, Lisp_Object *args)) |
1701 { | 1696 { |
1702 /* In a non-insane world this function would have this arglist... | 1697 /* In a non-insane world this function would have this arglist... |
1703 (arglist, instructions, constants, stack_size, doc_string, interactive) | 1698 (arglist instructions constants stack_depth &optional doc_string interactive) |
1704 Lisp_Object arglist, instructions, constants, stack_size, doc_string, | |
1705 interactive; | |
1706 */ | 1699 */ |
1700 Lisp_Object fun = make_compiled_function (purify_flag); | |
1701 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun); | |
1702 | |
1707 Lisp_Object arglist = args[0]; | 1703 Lisp_Object arglist = args[0]; |
1708 Lisp_Object instructions = args[1]; | 1704 Lisp_Object instructions = args[1]; |
1709 Lisp_Object constants = args[2]; | 1705 Lisp_Object constants = args[2]; |
1710 Lisp_Object stack_size = args[3]; | 1706 Lisp_Object stack_depth = args[3]; |
1711 Lisp_Object doc_string = (nargs > 4) ? args[4] : Qnil; | 1707 Lisp_Object doc_string = (nargs > 4) ? args[4] : Qnil; |
1712 Lisp_Object interactive = (nargs > 5) ? args[5] : Qunbound; | 1708 Lisp_Object interactive = (nargs > 5) ? args[5] : Qunbound; |
1709 | |
1713 /* Don't purecopy the doc references in instructions because it's | 1710 /* Don't purecopy the doc references in instructions because it's |
1714 wasteful; they will get fixed up later. | 1711 wasteful; they will get fixed up later. |
1715 | 1712 |
1716 #### If something goes wrong and they don't get fixed up, | 1713 #### If something goes wrong and they don't get fixed up, |
1717 we're screwed, because pure stuff isn't marked and thus the | 1714 we're screwed, because pure stuff isn't marked and thus the |
1718 cons references won't be marked and will get reused. | 1715 cons references won't be marked and will get reused. |
1719 | 1716 |
1720 Note: there will be a window after the byte code is created and | 1717 Note: there will be a window after the byte code is created and |
1721 before the doc references are fixed up in which there will be | 1718 before the doc references are fixed up in which there will be |
1722 impure objects inside a pure object, which apparently won't | 1719 impure objects inside a pure object, which apparently won't |
1723 get marked, leading the trouble. But during that entire window, | 1720 get marked, leading to trouble. But during that entire window, |
1724 the objects are sitting on Vload_force_doc_string_list, which | 1721 the objects are sitting on Vload_force_doc_string_list, which |
1725 is staticpro'd, so we're OK. */ | 1722 is staticpro'd, so we're OK. */ |
1726 int purecopy_instructions = 1; | 1723 Lisp_Object (*cons) (Lisp_Object, Lisp_Object) |
1727 | 1724 = purify_flag ? pure_cons : Fcons; |
1728 if (nargs > 6) | 1725 |
1726 if (nargs < 4 || nargs > 6) | |
1729 return Fsignal (Qwrong_number_of_arguments, | 1727 return Fsignal (Qwrong_number_of_arguments, |
1730 list2 (intern ("make-byte-code"), make_int (nargs))); | 1728 list2 (intern ("make-byte-code"), make_int (nargs))); |
1731 | 1729 |
1732 CHECK_LIST (arglist); | 1730 /* Check for valid formal parameter list now, to allow us to use |
1733 /* instructions is a string or a cons (string . int) for a | 1731 SPECBIND_FAST_UNSAFE() later in funcall_compiled_function(). */ |
1732 { | |
1733 Lisp_Object symbol, tail; | |
1734 EXTERNAL_LIST_LOOP_3 (symbol, arglist, tail) | |
1735 { | |
1736 CHECK_SYMBOL (symbol); | |
1737 if (EQ (symbol, Qt) || | |
1738 EQ (symbol, Qnil) || | |
1739 SYMBOL_IS_KEYWORD (symbol)) | |
1740 signal_simple_error_2 | |
1741 ("Invalid constant symbol in formal parameter list", | |
1742 symbol, arglist); | |
1743 } | |
1744 } | |
1745 f->arglist = arglist; | |
1746 | |
1747 /* `instructions' is a string or a cons (string . int) for a | |
1734 lazy-loaded function. */ | 1748 lazy-loaded function. */ |
1735 if (CONSP (instructions)) | 1749 if (CONSP (instructions)) |
1736 { | 1750 { |
1737 CHECK_STRING (XCAR (instructions)); | 1751 CHECK_STRING (XCAR (instructions)); |
1738 CHECK_INT (XCDR (instructions)); | 1752 CHECK_INT (XCDR (instructions)); |
1739 if (!NILP (constants)) | |
1740 CHECK_VECTOR (constants); | |
1741 purecopy_instructions = 0; | |
1742 } | 1753 } |
1743 else | 1754 else |
1744 { | 1755 { |
1745 CHECK_STRING (instructions); | 1756 CHECK_STRING (instructions); |
1746 CHECK_VECTOR (constants); | 1757 } |
1747 } | 1758 f->instructions = instructions; |
1748 CHECK_NATNUM (stack_size); | 1759 |
1749 /* doc_string may be nil, string, int, or a cons (string . int). */ | 1760 if (!NILP (constants)) |
1750 | 1761 CHECK_VECTOR (constants); |
1751 /* interactive may be list or string (or unbound). */ | 1762 f->constants = constants; |
1763 | |
1764 CHECK_NATNUM (stack_depth); | |
1765 f->stack_depth = XINT (stack_depth); | |
1766 | |
1767 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | |
1768 if (!NILP (Vcurrent_compiled_function_annotation)) | |
1769 f->annotated = Fpurecopy (Vcurrent_compiled_function_annotation); | |
1770 else if (!NILP (Vload_file_name_internal_the_purecopy)) | |
1771 f->annotated = Vload_file_name_internal_the_purecopy; | |
1772 else if (!NILP (Vload_file_name_internal)) | |
1773 { | |
1774 struct gcpro gcpro1; | |
1775 GCPRO1 (fun); /* don't let fun get reaped */ | |
1776 Vload_file_name_internal_the_purecopy = | |
1777 Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); | |
1778 f->annotated = Vload_file_name_internal_the_purecopy; | |
1779 UNGCPRO; | |
1780 } | |
1781 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ | |
1782 | |
1783 /* doc_string may be nil, string, int, or a cons (string . int). | |
1784 interactive may be list or string (or unbound). */ | |
1785 f->doc_and_interactive = Qunbound; | |
1786 #ifdef I18N3 | |
1787 if ((f->flags.domainp = !NILP (Vfile_domain)) != 0) | |
1788 f->doc_and_interactive = Vfile_domain; | |
1789 #endif | |
1790 if ((f->flags.interactivep = !UNBOUNDP (interactive)) != 0) | |
1791 { | |
1792 if (purify_flag) | |
1793 { | |
1794 interactive = Fpurecopy (interactive); | |
1795 if (STRINGP (interactive)) | |
1796 bump_purestat (&purestat_string_interactive, | |
1797 pure_sizeof (interactive)); | |
1798 } | |
1799 f->doc_and_interactive | |
1800 = (UNBOUNDP (f->doc_and_interactive) ? interactive : | |
1801 cons (interactive, f->doc_and_interactive)); | |
1802 } | |
1803 if ((f->flags.documentationp = !NILP (doc_string)) != 0) | |
1804 { | |
1805 if (purify_flag) | |
1806 { | |
1807 doc_string = Fpurecopy (doc_string); | |
1808 if (STRINGP (doc_string)) | |
1809 /* These should have been snagged by make-docfile... */ | |
1810 bump_purestat (&purestat_string_documentation, | |
1811 pure_sizeof (doc_string)); | |
1812 } | |
1813 f->doc_and_interactive | |
1814 = (UNBOUNDP (f->doc_and_interactive) ? doc_string : | |
1815 cons (doc_string, f->doc_and_interactive)); | |
1816 } | |
1817 if (UNBOUNDP (f->doc_and_interactive)) | |
1818 f->doc_and_interactive = Qnil; | |
1752 | 1819 |
1753 if (purify_flag) | 1820 if (purify_flag) |
1754 { | 1821 { |
1755 if (!purified (arglist)) | 1822 |
1756 arglist = Fpurecopy (arglist); | 1823 if (!purified (f->arglist)) |
1757 if (purecopy_instructions && !purified (instructions)) | 1824 f->arglist = Fpurecopy (f->arglist); |
1758 instructions = Fpurecopy (instructions); | |
1759 if (!purified (doc_string)) | |
1760 doc_string = Fpurecopy (doc_string); | |
1761 if (!purified (interactive) && !UNBOUNDP (interactive)) | |
1762 interactive = Fpurecopy (interactive); | |
1763 | 1825 |
1764 /* Statistics are kept differently for the constants */ | 1826 /* Statistics are kept differently for the constants */ |
1765 if (!purified (constants)) | 1827 if (!purified (f->constants)) |
1828 { | |
1766 #ifdef PURESTAT | 1829 #ifdef PURESTAT |
1767 { | 1830 int old = purecopying_function_constants; |
1768 int old = purecopying_for_bytecode; | 1831 purecopying_function_constants = 1; |
1769 purecopying_for_bytecode = 1; | 1832 f->constants = Fpurecopy (f->constants); |
1770 constants = Fpurecopy (constants); | 1833 bump_purestat (&purestat_vector_constants, |
1771 purecopying_for_bytecode = old; | 1834 pure_sizeof (f->constants)); |
1835 purecopying_function_constants = old; | |
1836 #else | |
1837 f->constants = Fpurecopy (f->constants); | |
1838 #endif /* PURESTAT */ | |
1772 } | 1839 } |
1773 #else | 1840 |
1774 constants = Fpurecopy (constants); | 1841 optimize_compiled_function (fun); |
1775 #endif /* PURESTAT */ | 1842 |
1776 | 1843 bump_purestat (&purestat_opaque_instructions, |
1777 #ifdef PURESTAT | 1844 pure_sizeof (f->instructions)); |
1778 if (STRINGP (instructions)) | 1845 } |
1779 bump_purestat (&purestat_string_bytecodes, pure_sizeof (instructions)); | 1846 |
1780 if (VECTORP (constants)) | 1847 return fun; |
1781 bump_purestat (&purestat_vector_bytecode_constants, | |
1782 pure_sizeof (constants)); | |
1783 if (STRINGP (doc_string)) | |
1784 /* These should be have been snagged by make-docfile... */ | |
1785 bump_purestat (&purestat_string_documentation, | |
1786 pure_sizeof (doc_string)); | |
1787 if (STRINGP (interactive)) | |
1788 bump_purestat (&purestat_string_interactive, | |
1789 pure_sizeof (interactive)); | |
1790 #endif /* PURESTAT */ | |
1791 } | |
1792 | |
1793 { | |
1794 int docp = !NILP (doc_string); | |
1795 int intp = !UNBOUNDP (interactive); | |
1796 #ifdef I18N3 | |
1797 int domp = !NILP (Vfile_domain); | |
1798 #endif | |
1799 Lisp_Object val = make_compiled_function (purify_flag); | |
1800 struct Lisp_Compiled_Function *b = XCOMPILED_FUNCTION (val); | |
1801 b->flags.documentationp = docp; | |
1802 b->flags.interactivep = intp; | |
1803 #ifdef I18N3 | |
1804 b->flags.domainp = domp; | |
1805 #endif | |
1806 b->maxdepth = XINT (stack_size); | |
1807 b->bytecodes = instructions; | |
1808 b->constants = constants; | |
1809 b->arglist = arglist; | |
1810 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | |
1811 if (!NILP (Vcurrent_compiled_function_annotation)) | |
1812 b->annotated = Fpurecopy (Vcurrent_compiled_function_annotation); | |
1813 else if (!NILP (Vload_file_name_internal_the_purecopy)) | |
1814 b->annotated = Vload_file_name_internal_the_purecopy; | |
1815 else if (!NILP (Vload_file_name_internal)) | |
1816 { | |
1817 struct gcpro gcpro1; | |
1818 GCPRO1(val); /* don't let val or b get reaped */ | |
1819 Vload_file_name_internal_the_purecopy = | |
1820 Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); | |
1821 b->annotated = Vload_file_name_internal_the_purecopy; | |
1822 UNGCPRO; | |
1823 } | |
1824 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ | |
1825 | |
1826 #ifdef I18N3 | |
1827 if (docp && intp && domp) | |
1828 b->doc_and_interactive = (((purify_flag) ? pure_cons : Fcons) | |
1829 (doc_string, | |
1830 (((purify_flag) ? pure_cons : Fcons) | |
1831 (interactive, Vfile_domain)))); | |
1832 else if (docp && domp) | |
1833 b->doc_and_interactive = (((purify_flag) ? pure_cons : Fcons) | |
1834 (doc_string, Vfile_domain)); | |
1835 else if (intp && domp) | |
1836 b->doc_and_interactive = (((purify_flag) ? pure_cons : Fcons) | |
1837 (interactive, Vfile_domain)); | |
1838 else | |
1839 #endif | |
1840 if (docp && intp) | |
1841 b->doc_and_interactive = (((purify_flag) ? pure_cons : Fcons) | |
1842 (doc_string, interactive)); | |
1843 else if (intp) | |
1844 b->doc_and_interactive = interactive; | |
1845 #ifdef I18N3 | |
1846 else if (domp) | |
1847 b->doc_and_interactive = Vfile_domain; | |
1848 #endif | |
1849 else | |
1850 b->doc_and_interactive = doc_string; | |
1851 | |
1852 return val; | |
1853 } | |
1854 } | 1848 } |
1855 | 1849 |
1856 | 1850 |
1857 /**********************************************************************/ | 1851 /************************************************************************/ |
1858 /* Symbol allocation */ | 1852 /* Symbol allocation */ |
1859 /**********************************************************************/ | 1853 /************************************************************************/ |
1860 | 1854 |
1861 DECLARE_FIXED_TYPE_ALLOC (symbol, struct Lisp_Symbol); | 1855 DECLARE_FIXED_TYPE_ALLOC (symbol, struct Lisp_Symbol); |
1862 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_symbol 1000 | 1856 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_symbol 1000 |
1863 | 1857 |
1864 DEFUN ("make-symbol", Fmake_symbol, 1, 1, 0, /* | 1858 DEFUN ("make-symbol", Fmake_symbol, 1, 1, 0, /* |
1865 Return a newly allocated uninterned symbol whose name is NAME. | 1859 Return a newly allocated uninterned symbol whose name is NAME. |
1866 Its value and function definition are void, and its property list is nil. | 1860 Its value and function definition are void, and its property list is nil. |
1867 */ | 1861 */ |
1868 (str)) | 1862 (name)) |
1869 { | 1863 { |
1870 Lisp_Object val; | 1864 Lisp_Object val; |
1871 struct Lisp_Symbol *p; | 1865 struct Lisp_Symbol *p; |
1872 | 1866 |
1873 CHECK_STRING (str); | 1867 CHECK_STRING (name); |
1874 | 1868 |
1875 ALLOCATE_FIXED_TYPE (symbol, struct Lisp_Symbol, p); | 1869 ALLOCATE_FIXED_TYPE (symbol, struct Lisp_Symbol, p); |
1876 #ifdef LRECORD_SYMBOL | 1870 #ifdef LRECORD_SYMBOL |
1877 set_lheader_implementation (&(p->lheader), lrecord_symbol); | 1871 set_lheader_implementation (&(p->lheader), lrecord_symbol); |
1878 #endif | 1872 #endif |
1879 p->name = XSTRING (str); | 1873 p->name = XSTRING (name); |
1880 p->plist = Qnil; | 1874 p->plist = Qnil; |
1881 p->value = Qunbound; | 1875 p->value = Qunbound; |
1882 p->function = Qunbound; | 1876 p->function = Qunbound; |
1883 p->obarray = Qnil; | 1877 p->obarray = Qnil; |
1884 symbol_next (p) = 0; | 1878 symbol_next (p) = 0; |
1885 XSETSYMBOL (val, p); | 1879 XSETSYMBOL (val, p); |
1886 return val; | 1880 return val; |
1887 } | 1881 } |
1888 | 1882 |
1889 | 1883 |
1890 /**********************************************************************/ | 1884 /************************************************************************/ |
1891 /* Extent allocation */ | 1885 /* Extent allocation */ |
1892 /**********************************************************************/ | 1886 /************************************************************************/ |
1893 | 1887 |
1894 DECLARE_FIXED_TYPE_ALLOC (extent, struct extent); | 1888 DECLARE_FIXED_TYPE_ALLOC (extent, struct extent); |
1895 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_extent 1000 | 1889 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_extent 1000 |
1896 | 1890 |
1897 struct extent * | 1891 struct extent * |
1898 allocate_extent (void) | 1892 allocate_extent (void) |
1899 { | 1893 { |
1900 struct extent *e; | 1894 struct extent *e; |
1901 | 1895 |
1902 ALLOCATE_FIXED_TYPE (extent, struct extent, e); | 1896 ALLOCATE_FIXED_TYPE (extent, struct extent, e); |
1903 /* xzero (*e); */ | |
1904 set_lheader_implementation (&(e->lheader), lrecord_extent); | 1897 set_lheader_implementation (&(e->lheader), lrecord_extent); |
1905 extent_object (e) = Qnil; | 1898 extent_object (e) = Qnil; |
1906 set_extent_start (e, -1); | 1899 set_extent_start (e, -1); |
1907 set_extent_end (e, -1); | 1900 set_extent_end (e, -1); |
1908 e->plist = Qnil; | 1901 e->plist = Qnil; |
1915 | 1908 |
1916 return e; | 1909 return e; |
1917 } | 1910 } |
1918 | 1911 |
1919 | 1912 |
1920 /**********************************************************************/ | 1913 /************************************************************************/ |
1921 /* Event allocation */ | 1914 /* Event allocation */ |
1922 /**********************************************************************/ | 1915 /************************************************************************/ |
1923 | 1916 |
1924 DECLARE_FIXED_TYPE_ALLOC (event, struct Lisp_Event); | 1917 DECLARE_FIXED_TYPE_ALLOC (event, struct Lisp_Event); |
1925 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_event 1000 | 1918 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_event 1000 |
1926 | 1919 |
1927 Lisp_Object | 1920 Lisp_Object |
1936 XSETEVENT (val, e); | 1929 XSETEVENT (val, e); |
1937 return val; | 1930 return val; |
1938 } | 1931 } |
1939 | 1932 |
1940 | 1933 |
1941 /**********************************************************************/ | 1934 /************************************************************************/ |
1942 /* Marker allocation */ | 1935 /* Marker allocation */ |
1943 /**********************************************************************/ | 1936 /************************************************************************/ |
1944 | 1937 |
1945 DECLARE_FIXED_TYPE_ALLOC (marker, struct Lisp_Marker); | 1938 DECLARE_FIXED_TYPE_ALLOC (marker, struct Lisp_Marker); |
1946 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_marker 1000 | 1939 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_marker 1000 |
1947 | 1940 |
1948 DEFUN ("make-marker", Fmake_marker, 0, 0, 0, /* | 1941 DEFUN ("make-marker", Fmake_marker, 0, 0, 0, /* |
1980 XSETMARKER (val, p); | 1973 XSETMARKER (val, p); |
1981 return val; | 1974 return val; |
1982 } | 1975 } |
1983 | 1976 |
1984 | 1977 |
1985 /**********************************************************************/ | 1978 /************************************************************************/ |
1986 /* String allocation */ | 1979 /* String allocation */ |
1987 /**********************************************************************/ | 1980 /************************************************************************/ |
1988 | 1981 |
1989 /* The data for "short" strings generally resides inside of structs of type | 1982 /* The data for "short" strings generally resides inside of structs of type |
1990 string_chars_block. The Lisp_String structure is allocated just like any | 1983 string_chars_block. The Lisp_String structure is allocated just like any |
1991 other Lisp object (except for vectors), and these are freelisted when | 1984 other Lisp object (except for vectors), and these are freelisted when |
1992 they get garbage collected. The data for short strings get compacted, | 1985 they get garbage collected. The data for short strings get compacted, |
2014 flush_cached_extent_info (XCAR (ptr->plist)); | 2007 flush_cached_extent_info (XCAR (ptr->plist)); |
2015 return ptr->plist; | 2008 return ptr->plist; |
2016 } | 2009 } |
2017 | 2010 |
2018 static int | 2011 static int |
2019 string_equal (Lisp_Object o1, Lisp_Object o2, int depth) | 2012 string_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
2020 { | 2013 { |
2021 Bytecount len; | 2014 Bytecount len; |
2022 return (((len = XSTRING_LENGTH (o1)) == XSTRING_LENGTH (o2)) && | 2015 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && |
2023 !memcmp (XSTRING_DATA (o1), XSTRING_DATA (o2), len)); | 2016 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); |
2024 } | 2017 } |
2025 | 2018 |
2026 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string, | 2019 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string, |
2027 mark_string, print_string, | 2020 mark_string, print_string, |
2028 /* | 2021 /* |
2333 Return a new string of length LENGTH, with each character being INIT. | 2326 Return a new string of length LENGTH, with each character being INIT. |
2334 LENGTH must be an integer and INIT must be a character. | 2327 LENGTH must be an integer and INIT must be a character. |
2335 */ | 2328 */ |
2336 (length, init)) | 2329 (length, init)) |
2337 { | 2330 { |
2338 Lisp_Object val; | |
2339 | |
2340 CHECK_NATNUM (length); | 2331 CHECK_NATNUM (length); |
2341 CHECK_CHAR_COERCE_INT (init); | 2332 CHECK_CHAR_COERCE_INT (init); |
2342 { | 2333 { |
2343 Bufbyte str[MAX_EMCHAR_LEN]; | 2334 Bufbyte init_str[MAX_EMCHAR_LEN]; |
2344 int len = set_charptr_emchar (str, XCHAR (init)); | 2335 int len = set_charptr_emchar (init_str, XCHAR (init)); |
2345 | 2336 Lisp_Object val = make_uninit_string (len * XINT (length)); |
2346 val = make_uninit_string (len * XINT (length)); | 2337 |
2347 if (len == 1) | 2338 if (len == 1) |
2348 /* Optimize the single-byte case */ | 2339 /* Optimize the single-byte case */ |
2349 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); | 2340 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); |
2350 else | 2341 else |
2351 { | 2342 { |
2352 int i, j, k; | 2343 int i; |
2353 Bufbyte *ptr = XSTRING_DATA (val); | 2344 Bufbyte *ptr = XSTRING_DATA (val); |
2354 | 2345 |
2355 k = 0; | 2346 for (i = XINT (length); i; i--) |
2356 for (i = 0; i < XINT (length); i++) | 2347 { |
2357 for (j = 0; j < len; j++) | 2348 Bufbyte *init_ptr = init_str; |
2358 ptr[k++] = str[j]; | 2349 switch (len) |
2350 { | |
2351 case 4: *ptr++ = *init_ptr++; | |
2352 case 3: *ptr++ = *init_ptr++; | |
2353 case 2: *ptr++ = *init_ptr++; | |
2354 case 1: *ptr++ = *init_ptr++; | |
2355 } | |
2356 } | |
2359 } | 2357 } |
2358 return val; | |
2360 } | 2359 } |
2361 return val; | |
2362 } | 2360 } |
2363 | 2361 |
2364 DEFUN ("string", Fstring, 0, MANY, 0, /* | 2362 DEFUN ("string", Fstring, 0, MANY, 0, /* |
2365 Concatenate all the argument characters and make the result a string. | 2363 Concatenate all the argument characters and make the result a string. |
2366 */ | 2364 */ |
2570 | 2568 |
2571 #ifdef ERROR_CHECK_GC | 2569 #ifdef ERROR_CHECK_GC |
2572 /* Make sure the size is correct. This will catch, for example, | 2570 /* Make sure the size is correct. This will catch, for example, |
2573 putting a window configuration on the wrong free list. */ | 2571 putting a window configuration on the wrong free list. */ |
2574 if (implementation->size_in_bytes_method) | 2572 if (implementation->size_in_bytes_method) |
2575 assert (((implementation->size_in_bytes_method) (lheader)) | 2573 assert (implementation->size_in_bytes_method (lheader) == list->size); |
2576 == list->size); | |
2577 else | 2574 else |
2578 assert (implementation->static_size == list->size); | 2575 assert (implementation->static_size == list->size); |
2579 #endif /* ERROR_CHECK_GC */ | 2576 #endif /* ERROR_CHECK_GC */ |
2580 | 2577 |
2581 if (implementation->finalizer) | 2578 if (implementation->finalizer) |
2582 ((implementation->finalizer) (lheader, 0)); | 2579 implementation->finalizer (lheader, 0); |
2583 free_header->chain = list->free; | 2580 free_header->chain = list->free; |
2584 free_header->lcheader.free = 1; | 2581 free_header->lcheader.free = 1; |
2585 list->free = lcrecord; | 2582 list->free = lcrecord; |
2586 } | 2583 } |
2587 | 2584 |
2588 | 2585 |
2589 /**********************************************************************/ | 2586 /************************************************************************/ |
2590 /* Purity of essence, peace on earth */ | 2587 /* Purity of essence, peace on earth */ |
2591 /**********************************************************************/ | 2588 /************************************************************************/ |
2592 | 2589 |
2593 static int symbols_initialized; | 2590 static int symbols_initialized; |
2594 | 2591 |
2595 Lisp_Object | 2592 Lisp_Object |
2596 make_pure_string (CONST Bufbyte *data, Bytecount length, | 2593 make_pure_string (CONST Bufbyte *data, Bytecount length, |
2639 s->plist = Qnil; | 2636 s->plist = Qnil; |
2640 pure_bytes_used += size; | 2637 pure_bytes_used += size; |
2641 | 2638 |
2642 #ifdef PURESTAT | 2639 #ifdef PURESTAT |
2643 bump_purestat (&purestat_string_all, size); | 2640 bump_purestat (&purestat_string_all, size); |
2644 if (purecopying_for_bytecode) | 2641 if (purecopying_function_constants) |
2645 bump_purestat (&purestat_string_other_function, size); | 2642 bump_purestat (&purestat_string_other_function, size); |
2646 #endif /* PURESTAT */ | 2643 #endif /* PURESTAT */ |
2647 | 2644 |
2648 /* Do this after the official "completion" of the purecopying. */ | 2645 /* Do this after the official "completion" of the purecopying. */ |
2649 s->plist = Fpurecopy (plist); | 2646 s->plist = Fpurecopy (plist); |
2758 | 2755 |
2759 Lisp_Object | 2756 Lisp_Object |
2760 make_pure_vector (size_t len, Lisp_Object init) | 2757 make_pure_vector (size_t len, Lisp_Object init) |
2761 { | 2758 { |
2762 Lisp_Object new; | 2759 Lisp_Object new; |
2763 struct Lisp_Vector *v; | 2760 Lisp_Vector *v; |
2764 size_t size = (sizeof (struct Lisp_Vector) | 2761 size_t size = offsetof (Lisp_Vector, contents[len]); |
2765 + (len - 1) * sizeof (Lisp_Object)); | |
2766 | 2762 |
2767 init = Fpurecopy (init); | 2763 init = Fpurecopy (init); |
2768 | 2764 |
2769 if (!check_purespace (size)) | 2765 if (!check_purespace (size)) |
2770 return make_vector (len, init); | 2766 return make_vector (len, init); |
2771 | 2767 |
2772 v = (struct Lisp_Vector *) (PUREBEG + pure_bytes_used); | 2768 v = (Lisp_Vector *) (PUREBEG + pure_bytes_used); |
2773 #ifdef LRECORD_VECTOR | 2769 #ifdef LRECORD_VECTOR |
2774 set_lheader_implementation (&(v->header.lheader), lrecord_vector); | 2770 set_lheader_implementation (&(v->header.lheader), lrecord_vector); |
2775 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION | 2771 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION |
2776 v->header.lheader.pure = 1; | 2772 v->header.lheader.pure = 1; |
2777 #endif | 2773 #endif |
2811 Recursively copies contents of vectors and cons cells. | 2807 Recursively copies contents of vectors and cons cells. |
2812 Does not copy symbols. | 2808 Does not copy symbols. |
2813 */ | 2809 */ |
2814 (obj)) | 2810 (obj)) |
2815 { | 2811 { |
2816 int i; | |
2817 if (!purify_flag) | 2812 if (!purify_flag) |
2818 return obj; | 2813 { |
2819 | 2814 return obj; |
2820 if (!POINTER_TYPE_P (XTYPE (obj)) | 2815 } |
2821 || PURIFIED (XPNTR (obj)) | 2816 else if (!POINTER_TYPE_P (XTYPE (obj)) |
2822 /* happens when bootstrapping Qnil */ | 2817 || PURIFIED (XPNTR (obj)) |
2823 || EQ (obj, Qnull_pointer)) | 2818 /* happens when bootstrapping Qnil */ |
2824 return obj; | 2819 || EQ (obj, Qnull_pointer)) |
2825 | 2820 { |
2826 switch (XTYPE (obj)) | 2821 return obj; |
2827 { | 2822 } |
2828 #ifndef LRECORD_CONS | 2823 /* Order of subsequent tests determined via profiling. */ |
2829 case Lisp_Type_Cons: | 2824 else if (SYMBOLP (obj)) |
2825 { | |
2826 /* Symbols can't be made pure (and thus read-only), because | |
2827 assigning to their function, value or plist slots would | |
2828 produced a SEGV in the dumped XEmacs. So we previously would | |
2829 just return the symbol unchanged. | |
2830 | |
2831 But purified aggregate objects like lists and vectors can | |
2832 contain uninterned symbols. If there are no other non-pure | |
2833 references to the symbol, then the symbol is not protected | |
2834 from garbage collection because the collector does not mark | |
2835 the contents of purified objects. So to protect the symbols, | |
2836 an impure reference has to be kept for each uninterned symbol | |
2837 that is referenced by a pure object. All such symbols are | |
2838 stored in the hash table pointed to by | |
2839 Vpure_uninterned_symbol_table, which is itself | |
2840 staticpro'd. */ | |
2841 if (NILP (XSYMBOL (obj)->obarray)) | |
2842 Fputhash (obj, Qnil, Vpure_uninterned_symbol_table); | |
2843 return obj; | |
2844 } | |
2845 else if (CONSP (obj)) | |
2846 { | |
2830 return pure_cons (XCAR (obj), XCDR (obj)); | 2847 return pure_cons (XCAR (obj), XCDR (obj)); |
2831 #endif | 2848 } |
2832 | 2849 else if (STRINGP (obj)) |
2833 #ifndef LRECORD_STRING | 2850 { |
2834 case Lisp_Type_String: | |
2835 return make_pure_string (XSTRING_DATA (obj), | 2851 return make_pure_string (XSTRING_DATA (obj), |
2836 XSTRING_LENGTH (obj), | 2852 XSTRING_LENGTH (obj), |
2837 XSTRING (obj)->plist, | 2853 XSTRING (obj)->plist, |
2838 0); | 2854 0); |
2839 #endif /* ! LRECORD_STRING */ | 2855 } |
2840 | 2856 else if (VECTORP (obj)) |
2841 #ifndef LRECORD_VECTOR | 2857 { |
2842 case Lisp_Type_Vector: | 2858 int i; |
2843 { | 2859 Lisp_Vector *o = XVECTOR (obj); |
2844 struct Lisp_Vector *o = XVECTOR (obj); | 2860 Lisp_Object pure_obj = make_pure_vector (vector_length (o), Qnil); |
2845 Lisp_Object new = make_pure_vector (vector_length (o), Qnil); | 2861 for (i = 0; i < vector_length (o); i++) |
2846 for (i = 0; i < vector_length (o); i++) | 2862 XVECTOR_DATA (pure_obj)[i] = Fpurecopy (o->contents[i]); |
2847 XVECTOR_DATA (new)[i] = Fpurecopy (o->contents[i]); | 2863 return pure_obj; |
2848 return new; | 2864 } |
2849 } | |
2850 #endif /* !LRECORD_VECTOR */ | |
2851 | |
2852 default: | |
2853 { | |
2854 if (COMPILED_FUNCTIONP (obj)) | |
2855 { | |
2856 struct Lisp_Compiled_Function *o = XCOMPILED_FUNCTION (obj); | |
2857 Lisp_Object new = make_compiled_function (1); | |
2858 /* How on earth could this code have worked before? -sb */ | |
2859 struct Lisp_Compiled_Function *n = XCOMPILED_FUNCTION (new); | |
2860 n->flags = o->flags; | |
2861 n->bytecodes = Fpurecopy (o->bytecodes); | |
2862 n->constants = Fpurecopy (o->constants); | |
2863 n->arglist = Fpurecopy (o->arglist); | |
2864 n->doc_and_interactive = Fpurecopy (o->doc_and_interactive); | |
2865 n->maxdepth = o->maxdepth; | |
2866 return new; | |
2867 } | |
2868 #ifdef LRECORD_CONS | |
2869 else if (CONSP (obj)) | |
2870 return pure_cons (XCAR (obj), XCDR (obj)); | |
2871 #endif /* LRECORD_CONS */ | |
2872 #ifdef LRECORD_VECTOR | |
2873 else if (VECTORP (obj)) | |
2874 { | |
2875 struct Lisp_Vector *o = XVECTOR (obj); | |
2876 Lisp_Object new = make_pure_vector (vector_length (o), Qnil); | |
2877 for (i = 0; i < vector_length (o); i++) | |
2878 XVECTOR_DATA (new)[i] = Fpurecopy (o->contents[i]); | |
2879 return new; | |
2880 } | |
2881 #endif /* LRECORD_VECTOR */ | |
2882 #ifdef LRECORD_STRING | |
2883 else if (STRINGP (obj)) | |
2884 { | |
2885 return make_pure_string (XSTRING_DATA (obj), | |
2886 XSTRING_LENGTH (obj), | |
2887 XSTRING (obj)->plist, | |
2888 0); | |
2889 } | |
2890 #endif /* LRECORD_STRING */ | |
2891 #ifdef LISP_FLOAT_TYPE | 2865 #ifdef LISP_FLOAT_TYPE |
2892 else if (FLOATP (obj)) | 2866 else if (FLOATP (obj)) |
2893 return make_pure_float (float_data (XFLOAT (obj))); | 2867 { |
2894 #endif /* LISP_FLOAT_TYPE */ | 2868 return make_pure_float (XFLOAT_DATA (obj)); |
2895 else if (SYMBOLP (obj)) | 2869 } |
2896 { | 2870 #endif |
2897 /* | 2871 else if (COMPILED_FUNCTIONP (obj)) |
2898 * Symbols can't be made pure (and thus read-only), | 2872 { |
2899 * because assigning to their function, value or plist | 2873 Lisp_Object pure_obj = make_compiled_function (1); |
2900 * slots would produced a SEGV in the dumped XEmacs. So | 2874 Lisp_Compiled_Function *o = XCOMPILED_FUNCTION (obj); |
2901 * we previously would just return the symbol unchanged. | 2875 Lisp_Compiled_Function *n = XCOMPILED_FUNCTION (pure_obj); |
2902 * | 2876 n->flags = o->flags; |
2903 * But purified aggregate objects like lists and vectors | 2877 n->instructions = o->instructions; |
2904 * can contain uninterned symbols. If there are no | 2878 n->constants = Fpurecopy (o->constants); |
2905 * other non-pure references to the symbol, then the | 2879 n->arglist = Fpurecopy (o->arglist); |
2906 * symbol is not protected from garbage collection | 2880 n->doc_and_interactive = Fpurecopy (o->doc_and_interactive); |
2907 * because the collector does not mark the contents of | 2881 n->stack_depth = o->stack_depth; |
2908 * purified objects. So to protect the symbols, an impure | 2882 optimize_compiled_function (pure_obj); |
2909 * reference has to be kept for each uninterned symbol | 2883 return pure_obj; |
2910 * that is referenced by a pure object. All such | 2884 } |
2911 * symbols are stored in the hashtable pointed to by | 2885 else if (OPAQUEP (obj)) |
2912 * Vpure_uninterned_symbol_table, which is itself | 2886 { |
2913 * staticpro'd. | 2887 Lisp_Object pure_obj; |
2914 */ | 2888 Lisp_Opaque *old_opaque = XOPAQUE (obj); |
2915 if (!NILP (XSYMBOL (obj)->obarray)) | 2889 Lisp_Opaque *new_opaque = (Lisp_Opaque *) (PUREBEG + pure_bytes_used); |
2916 return obj; | 2890 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
2917 Fputhash (obj, Qnil, Vpure_uninterned_symbol_table); | 2891 CONST struct lrecord_implementation *implementation |
2918 return obj; | 2892 = LHEADER_IMPLEMENTATION (lheader); |
2919 } | 2893 size_t size = implementation->size_in_bytes_method (lheader); |
2920 else | 2894 size_t pure_size = ALIGN_SIZE (size, ALIGNOF (Lisp_Object)); |
2921 signal_simple_error ("Can't purecopy %S", obj); | 2895 if (!check_purespace (pure_size)) |
2922 } | 2896 return obj; |
2923 } | 2897 pure_bytes_used += pure_size; |
2924 return obj; | 2898 |
2899 memcpy (new_opaque, old_opaque, size); | |
2900 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION | |
2901 lheader->pure = 1; | |
2902 #endif | |
2903 new_opaque->header.next = 0; | |
2904 | |
2905 XSETOPAQUE (pure_obj, new_opaque); | |
2906 return pure_obj; | |
2907 } | |
2908 else | |
2909 { | |
2910 signal_simple_error ("Can't purecopy %S", obj); | |
2911 } | |
2912 return obj; /* Unreached */ | |
2925 } | 2913 } |
2926 | 2914 |
2927 | 2915 |
2928 | 2916 |
2929 static void | 2917 static void |
2997 | 2985 |
2998 #ifdef PURESTAT | 2986 #ifdef PURESTAT |
2999 | 2987 |
3000 purestat_vector_other.nbytes = | 2988 purestat_vector_other.nbytes = |
3001 purestat_vector_all.nbytes - | 2989 purestat_vector_all.nbytes - |
3002 purestat_vector_bytecode_constants.nbytes; | 2990 purestat_vector_constants.nbytes; |
3003 purestat_vector_other.nobjects = | 2991 purestat_vector_other.nobjects = |
3004 purestat_vector_all.nobjects - | 2992 purestat_vector_all.nobjects - |
3005 purestat_vector_bytecode_constants.nobjects; | 2993 purestat_vector_constants.nobjects; |
3006 | 2994 |
3007 purestat_string_other.nbytes = | 2995 purestat_string_other.nbytes = |
3008 purestat_string_all.nbytes - | 2996 purestat_string_all.nbytes - |
3009 (purestat_string_pname.nbytes + | 2997 (purestat_string_pname.nbytes + |
3010 purestat_string_bytecodes.nbytes + | |
3011 purestat_string_interactive.nbytes + | 2998 purestat_string_interactive.nbytes + |
3012 purestat_string_documentation.nbytes + | 2999 purestat_string_documentation.nbytes + |
3013 #ifdef I18N3 | 3000 #ifdef I18N3 |
3014 purestat_string_domain.nbytes + | 3001 purestat_string_domain.nbytes + |
3015 #endif | 3002 #endif |
3016 purestat_string_other_function.nbytes); | 3003 purestat_string_other_function.nbytes); |
3017 | 3004 |
3018 purestat_string_other.nobjects = | 3005 purestat_string_other.nobjects = |
3019 purestat_string_all.nobjects - | 3006 purestat_string_all.nobjects - |
3020 (purestat_string_pname.nobjects + | 3007 (purestat_string_pname.nobjects + |
3021 purestat_string_bytecodes.nobjects + | |
3022 purestat_string_interactive.nobjects + | 3008 purestat_string_interactive.nobjects + |
3023 purestat_string_documentation.nobjects + | 3009 purestat_string_documentation.nobjects + |
3024 #ifdef I18N3 | 3010 #ifdef I18N3 |
3025 purestat_string_domain.nobjects + | 3011 purestat_string_domain.nobjects + |
3026 #endif | 3012 #endif |
3027 purestat_string_other_function.nobjects); | 3013 purestat_string_other_function.nobjects); |
3028 | 3014 |
3029 message (" %-26s Total Bytes", ""); | 3015 message (" %-34s Objects Bytes", ""); |
3030 | 3016 |
3031 { | 3017 print_purestat (&purestat_cons); |
3032 int j; | 3018 print_purestat (&purestat_float); |
3033 | 3019 print_purestat (&purestat_string_pname); |
3034 for (j = 0; j < countof (purestats); j++) | 3020 print_purestat (&purestat_function); |
3035 if (!purestats[j]) | 3021 print_purestat (&purestat_opaque_instructions); |
3036 clear_message (); | 3022 print_purestat (&purestat_vector_constants); |
3037 else | 3023 print_purestat (&purestat_string_interactive); |
3024 #ifdef I18N3 | |
3025 print_purestat (&purestat_string_domain); | |
3026 #endif | |
3027 print_purestat (&purestat_string_documentation); | |
3028 print_purestat (&purestat_string_other_function); | |
3029 print_purestat (&purestat_vector_other); | |
3030 print_purestat (&purestat_string_other); | |
3031 print_purestat (&purestat_string_all); | |
3032 print_purestat (&purestat_vector_all); | |
3033 | |
3034 #endif /* PURESTAT */ | |
3035 | |
3036 | |
3037 if (report_impurities) | |
3038 { | |
3039 Lisp_Object plist; | |
3040 struct gcpro gcpro1; | |
3041 plist = XCAR (XCDR (XCDR (XCDR (XCDR (XCDR (Fgarbage_collect())))))); | |
3042 GCPRO1 (plist); | |
3043 message ("\nImpurities:"); | |
3044 for (; CONSP (plist); plist = XCDR (XCDR (plist))) | |
3038 { | 3045 { |
3039 char buf [100]; | 3046 Lisp_Object symbol = XCAR (plist); |
3040 sprintf(buf, "%s:", purestats[j]->name); | 3047 int size = XINT (XCAR (XCDR (plist))); |
3041 message (" %-26s %5d %7d %2d%%", | 3048 if (size > 0) |
3042 buf, | |
3043 purestats[j]->nobjects, | |
3044 purestats[j]->nbytes, | |
3045 (int) (purestats[j]->nbytes / (pure_bytes_used / 100.0) + 0.5)); | |
3046 } | |
3047 } | |
3048 #endif /* PURESTAT */ | |
3049 | |
3050 | |
3051 if (report_impurities) | |
3052 { | |
3053 Lisp_Object tem = Felt (Fgarbage_collect (), make_int (5)); | |
3054 struct gcpro gcpro1; | |
3055 GCPRO1 (tem); | |
3056 message ("\nImpurities:"); | |
3057 while (!NILP (tem)) | |
3058 { | |
3059 if (CONSP (tem) && SYMBOLP (Fcar (tem)) && CONSP (Fcdr (tem))) | |
3060 { | 3049 { |
3061 int total = XINT (Fcar (Fcdr (tem))); | 3050 char buf [100]; |
3062 if (total > 0) | 3051 char *s = buf; |
3063 { | 3052 memcpy (buf, |
3064 char buf [100]; | 3053 string_data (XSYMBOL (symbol)->name), |
3065 char *s = buf; | 3054 string_length (XSYMBOL (symbol)->name) + 1); |
3066 memcpy (buf, string_data (XSYMBOL (Fcar (tem))->name), | 3055 while (*s++) if (*s == '-') *s = ' '; |
3067 string_length (XSYMBOL (Fcar (tem))->name) + 1); | 3056 *(s-1) = ':'; *s = 0; |
3068 while (*s++) if (*s == '-') *s = ' '; | 3057 message (" %-34s %6d", buf, size); |
3069 s--; *s++ = ':'; *s = 0; | |
3070 message (" %-33s %6d", buf, total); | |
3071 } | |
3072 tem = Fcdr (Fcdr (tem)); | |
3073 } | |
3074 else /* WTF?! */ | |
3075 { | |
3076 Fprin1 (tem, Qexternal_debugging_output); | |
3077 tem = Qnil; | |
3078 } | 3058 } |
3079 } | 3059 } |
3080 UNGCPRO; | 3060 UNGCPRO; |
3081 garbage_collect_1 (); /* GC garbage_collect's garbage */ | 3061 garbage_collect_1 (); /* collect Fgarbage_collect()'s garbage */ |
3082 } | 3062 } |
3083 clear_message (); | 3063 clear_message (); |
3084 | 3064 |
3085 if (rc < 0) { | 3065 if (rc < 0) { |
3086 unlink("SATISFIED"); | 3066 unlink("SATISFIED"); |
3089 fatal ("Pure storage exhausted"); | 3069 fatal ("Pure storage exhausted"); |
3090 } | 3070 } |
3091 } | 3071 } |
3092 | 3072 |
3093 | 3073 |
3094 /**********************************************************************/ | 3074 /************************************************************************/ |
3095 /* staticpro */ | 3075 /* Garbage Collection */ |
3096 /**********************************************************************/ | 3076 /************************************************************************/ |
3077 | |
3078 /* This will be used more extensively In The Future */ | |
3079 static int last_lrecord_type_index_assigned; | |
3080 | |
3081 CONST struct lrecord_implementation *lrecord_implementations_table[128]; | |
3082 #define max_lrecord_type (countof (lrecord_implementations_table) - 1) | |
3097 | 3083 |
3098 struct gcpro *gcprolist; | 3084 struct gcpro *gcprolist; |
3099 | 3085 |
3100 /* 415 used Mly 29-Jun-93 */ | 3086 /* 415 used Mly 29-Jun-93 */ |
3101 /* 1327 used slb 28-Feb-98 */ | 3087 /* 1327 used slb 28-Feb-98 */ |
3129 static void | 3115 static void |
3130 mark_object (Lisp_Object obj) | 3116 mark_object (Lisp_Object obj) |
3131 { | 3117 { |
3132 tail_recurse: | 3118 tail_recurse: |
3133 | 3119 |
3134 if (EQ (obj, Qnull_pointer)) | 3120 #ifdef ERROR_CHECK_GC |
3135 return; | 3121 assert (! (GC_EQ (obj, Qnull_pointer))); |
3136 if (!POINTER_TYPE_P (XGCTYPE (obj))) | 3122 #endif |
3137 return; | 3123 /* Checks we used to perform */ |
3138 if (PURIFIED (XPNTR (obj))) | 3124 /* if (EQ (obj, Qnull_pointer)) return; */ |
3139 return; | 3125 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ |
3126 /* if (PURIFIED (XPNTR (obj))) return; */ | |
3127 | |
3140 switch (XGCTYPE (obj)) | 3128 switch (XGCTYPE (obj)) |
3141 { | 3129 { |
3142 #ifndef LRECORD_CONS | 3130 #ifndef LRECORD_CONS |
3143 case Lisp_Type_Cons: | 3131 case Lisp_Type_Cons: |
3144 { | 3132 { |
3145 struct Lisp_Cons *ptr = XCONS (obj); | 3133 struct Lisp_Cons *ptr = XCONS (obj); |
3134 if (PURIFIED (ptr)) | |
3135 break; | |
3146 if (CONS_MARKED_P (ptr)) | 3136 if (CONS_MARKED_P (ptr)) |
3147 break; | 3137 break; |
3148 MARK_CONS (ptr); | 3138 MARK_CONS (ptr); |
3149 /* If the cdr is nil, tail-recurse on the car. */ | 3139 /* If the cdr is nil, tail-recurse on the car. */ |
3150 if (NILP (ptr->cdr)) | 3140 if (GC_NILP (ptr->cdr)) |
3151 { | 3141 { |
3152 obj = ptr->car; | 3142 obj = ptr->car; |
3153 } | 3143 } |
3154 else | 3144 else |
3155 { | 3145 { |
3159 goto tail_recurse; | 3149 goto tail_recurse; |
3160 } | 3150 } |
3161 #endif | 3151 #endif |
3162 | 3152 |
3163 case Lisp_Type_Record: | 3153 case Lisp_Type_Record: |
3164 /* case Lisp_Symbol_Value_Magic: */ | |
3165 { | 3154 { |
3166 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | 3155 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
3167 CONST struct lrecord_implementation *implementation | 3156 #if defined (ERROR_CHECK_GC) && defined (USE_INDEXED_LRECORD_IMPLEMENTATION) |
3168 = LHEADER_IMPLEMENTATION (lheader); | 3157 assert (lheader->type <= last_lrecord_type_index_assigned); |
3158 #endif | |
3159 if (PURIFIED (lheader)) | |
3160 return; | |
3169 | 3161 |
3170 if (! MARKED_RECORD_HEADER_P (lheader) && | 3162 if (! MARKED_RECORD_HEADER_P (lheader) && |
3171 ! UNMARKABLE_RECORD_HEADER_P (lheader)) | 3163 ! UNMARKABLE_RECORD_HEADER_P (lheader)) |
3172 { | 3164 { |
3165 CONST struct lrecord_implementation *implementation = | |
3166 LHEADER_IMPLEMENTATION (lheader); | |
3173 MARK_RECORD_HEADER (lheader); | 3167 MARK_RECORD_HEADER (lheader); |
3174 #ifdef ERROR_CHECK_GC | 3168 #ifdef ERROR_CHECK_GC |
3175 if (!implementation->basic_p) | 3169 if (!implementation->basic_p) |
3176 assert (! ((struct lcrecord_header *) lheader)->free); | 3170 assert (! ((struct lcrecord_header *) lheader)->free); |
3177 #endif | 3171 #endif |
3178 if (implementation->marker != 0) | 3172 if (implementation->marker) |
3179 { | 3173 { |
3180 obj = ((implementation->marker) (obj, mark_object)); | 3174 obj = implementation->marker (obj, mark_object); |
3181 if (!NILP (obj)) goto tail_recurse; | 3175 if (!GC_NILP (obj)) goto tail_recurse; |
3182 } | 3176 } |
3183 } | 3177 } |
3184 } | 3178 } |
3185 break; | 3179 break; |
3186 | 3180 |
3187 #ifndef LRECORD_STRING | 3181 #ifndef LRECORD_STRING |
3188 case Lisp_Type_String: | 3182 case Lisp_Type_String: |
3189 { | 3183 { |
3190 struct Lisp_String *ptr = XSTRING (obj); | 3184 struct Lisp_String *ptr = XSTRING (obj); |
3185 if (PURIFIED (ptr)) | |
3186 return; | |
3191 | 3187 |
3192 if (!XMARKBIT (ptr->plist)) | 3188 if (!XMARKBIT (ptr->plist)) |
3193 { | 3189 { |
3194 if (CONSP (ptr->plist) && | 3190 if (CONSP (ptr->plist) && |
3195 EXTENT_INFOP (XCAR (ptr->plist))) | 3191 EXTENT_INFOP (XCAR (ptr->plist))) |
3204 | 3200 |
3205 #ifndef LRECORD_VECTOR | 3201 #ifndef LRECORD_VECTOR |
3206 case Lisp_Type_Vector: | 3202 case Lisp_Type_Vector: |
3207 { | 3203 { |
3208 struct Lisp_Vector *ptr = XVECTOR (obj); | 3204 struct Lisp_Vector *ptr = XVECTOR (obj); |
3209 int len = vector_length (ptr); | 3205 int len, i; |
3210 int i; | 3206 |
3207 if (PURIFIED (ptr)) | |
3208 return; | |
3209 | |
3210 len = vector_length (ptr); | |
3211 | 3211 |
3212 if (len < 0) | 3212 if (len < 0) |
3213 break; /* Already marked */ | 3213 break; /* Already marked */ |
3214 ptr->size = -1 - len; /* Else mark it */ | 3214 ptr->size = -1 - len; /* Else mark it */ |
3215 for (i = 0; i < len - 1; i++) /* and then mark its elements */ | 3215 for (i = 0; i < len - 1; i++) /* and then mark its elements */ |
3226 #ifndef LRECORD_SYMBOL | 3226 #ifndef LRECORD_SYMBOL |
3227 case Lisp_Type_Symbol: | 3227 case Lisp_Type_Symbol: |
3228 { | 3228 { |
3229 struct Lisp_Symbol *sym = XSYMBOL (obj); | 3229 struct Lisp_Symbol *sym = XSYMBOL (obj); |
3230 | 3230 |
3231 if (PURIFIED (sym)) | |
3232 return; | |
3233 | |
3231 while (!XMARKBIT (sym->plist)) | 3234 while (!XMARKBIT (sym->plist)) |
3232 { | 3235 { |
3233 XMARK (sym->plist); | 3236 XMARK (sym->plist); |
3234 mark_object (sym->value); | 3237 mark_object (sym->value); |
3235 mark_object (sym->function); | 3238 mark_object (sym->function); |
3237 /* | 3240 /* |
3238 * symbol->name is a struct Lisp_String *, not a | 3241 * symbol->name is a struct Lisp_String *, not a |
3239 * Lisp_Object. Fix it up and pass to mark_object. | 3242 * Lisp_Object. Fix it up and pass to mark_object. |
3240 */ | 3243 */ |
3241 Lisp_Object symname; | 3244 Lisp_Object symname; |
3242 XSETSTRING(symname, sym->name); | 3245 XSETSTRING (symname, sym->name); |
3243 mark_object(symname); | 3246 mark_object (symname); |
3244 } | 3247 } |
3245 if (!symbol_next (sym)) | 3248 if (!symbol_next (sym)) |
3246 { | 3249 { |
3247 obj = sym->plist; | 3250 obj = sym->plist; |
3248 goto tail_recurse; | 3251 goto tail_recurse; |
3253 } | 3256 } |
3254 } | 3257 } |
3255 break; | 3258 break; |
3256 #endif /* !LRECORD_SYMBOL */ | 3259 #endif /* !LRECORD_SYMBOL */ |
3257 | 3260 |
3261 /* Check for invalid Lisp_Object types */ | |
3262 #if defined (ERROR_CHECK_GC) && ! defined (USE_MINIMAL_TAGBITS) | |
3263 case Lisp_Type_Int: | |
3264 case Lisp_Type_Char: | |
3265 break; | |
3258 default: | 3266 default: |
3259 abort (); | 3267 abort(); |
3268 break; | |
3269 #endif /* ERROR_CHECK_GC && ! USE_MINIMAL_TAGBITS */ | |
3260 } | 3270 } |
3261 } | 3271 } |
3262 | 3272 |
3263 /* mark all of the conses in a list and mark the final cdr; but | 3273 /* mark all of the conses in a list and mark the final cdr; but |
3264 DO NOT mark the cars. | 3274 DO NOT mark the cars. |
3284 | 3294 |
3285 #ifdef PURESTAT | 3295 #ifdef PURESTAT |
3286 /* Simpler than mark-object, because pure structure can't | 3296 /* Simpler than mark-object, because pure structure can't |
3287 have any circularities */ | 3297 have any circularities */ |
3288 | 3298 |
3289 #if 0 /* unused */ | |
3290 static int idiot_c_doesnt_have_closures; | |
3291 static void | |
3292 idiot_c (Lisp_Object obj) | |
3293 { | |
3294 idiot_c_doesnt_have_closures += pure_sizeof (obj, 1); | |
3295 } | |
3296 #endif /* unused */ | |
3297 | |
3298 static size_t | 3299 static size_t |
3299 pure_string_sizeof (Lisp_Object obj) | 3300 pure_string_sizeof (Lisp_Object obj) |
3300 { | 3301 { |
3301 struct Lisp_String *ptr = XSTRING (obj); | 3302 struct Lisp_String *ptr = XSTRING (obj); |
3302 | 3303 |
3312 size = ALIGN_SIZE (size, sizeof (Lisp_Object)); | 3313 size = ALIGN_SIZE (size, sizeof (Lisp_Object)); |
3313 return size; | 3314 return size; |
3314 } | 3315 } |
3315 } | 3316 } |
3316 | 3317 |
3317 /* recurse arg isn't actually used */ | |
3318 static size_t | 3318 static size_t |
3319 pure_sizeof (Lisp_Object obj /*, int recurse */) | 3319 pure_sizeof (Lisp_Object obj) |
3320 { | 3320 { |
3321 size_t total = 0; | |
3322 | |
3323 /*tail_recurse: */ | |
3324 if (!POINTER_TYPE_P (XTYPE (obj)) | 3321 if (!POINTER_TYPE_P (XTYPE (obj)) |
3325 || !PURIFIED (XPNTR (obj))) | 3322 || !PURIFIED (XPNTR (obj))) |
3326 return total; | 3323 return 0; |
3327 | 3324 /* symbol sizes are accounted for separately */ |
3328 /* symbol's sizes are accounted for separately */ | 3325 else if (SYMBOLP (obj)) |
3329 if (SYMBOLP (obj)) | 3326 return 0; |
3330 return total; | 3327 else if (STRINGP (obj)) |
3331 | 3328 return pure_string_sizeof (obj); |
3332 switch (XTYPE (obj)) | 3329 else if (LRECORDP (obj)) |
3333 { | 3330 { |
3334 | 3331 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
3335 #ifndef LRECORD_STRING | 3332 CONST struct lrecord_implementation *implementation |
3336 case Lisp_Type_String: | 3333 = LHEADER_IMPLEMENTATION (lheader); |
3337 total += pure_string_sizeof (obj); | 3334 |
3338 break; | 3335 return implementation->size_in_bytes_method |
3339 #endif /* ! LRECORD_STRING */ | 3336 ? implementation->size_in_bytes_method (lheader) |
3340 | 3337 : implementation->static_size; |
3338 } | |
3341 #ifndef LRECORD_VECTOR | 3339 #ifndef LRECORD_VECTOR |
3342 case Lisp_Type_Vector: | 3340 else if (VECTORP (obj)) |
3343 { | 3341 return offsetof (Lisp_Vector, contents[XVECTOR_LENGTH (obj)]); |
3344 struct Lisp_Vector *ptr = XVECTOR (obj); | |
3345 int len = vector_length (ptr); | |
3346 | |
3347 total += (sizeof (struct Lisp_Vector) | |
3348 + (len - 1) * sizeof (Lisp_Object)); | |
3349 #if 0 /* unused */ | |
3350 if (!recurse) | |
3351 break; | |
3352 { | |
3353 int i; | |
3354 for (i = 0; i < len - 1; i++) | |
3355 total += pure_sizeof (ptr->contents[i], 1); | |
3356 } | |
3357 if (len > 0) | |
3358 { | |
3359 obj = ptr->contents[len - 1]; | |
3360 goto tail_recurse; | |
3361 } | |
3362 #endif /* unused */ | |
3363 } | |
3364 break; | |
3365 #endif /* !LRECORD_VECTOR */ | 3342 #endif /* !LRECORD_VECTOR */ |
3366 | 3343 |
3367 case Lisp_Type_Record: | |
3368 { | |
3369 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | |
3370 CONST struct lrecord_implementation *implementation | |
3371 = LHEADER_IMPLEMENTATION (lheader); | |
3372 | |
3373 #ifdef LRECORD_STRING | |
3374 if (STRINGP (obj)) | |
3375 total += pure_string_sizeof (obj); | |
3376 else | |
3377 #endif | |
3378 if (implementation->size_in_bytes_method) | |
3379 total += ((implementation->size_in_bytes_method) (lheader)); | |
3380 else | |
3381 total += implementation->static_size; | |
3382 | |
3383 #if 0 /* unused */ | |
3384 if (!recurse) | |
3385 break; | |
3386 | |
3387 if (implementation->marker != 0) | |
3388 { | |
3389 int old = idiot_c_doesnt_have_closures; | |
3390 | |
3391 idiot_c_doesnt_have_closures = 0; | |
3392 obj = ((implementation->marker) (obj, idiot_c)); | |
3393 total += idiot_c_doesnt_have_closures; | |
3394 idiot_c_doesnt_have_closures = old; | |
3395 | |
3396 if (!NILP (obj)) goto tail_recurse; | |
3397 } | |
3398 #endif /* unused */ | |
3399 } | |
3400 break; | |
3401 | |
3402 #ifndef LRECORD_CONS | 3344 #ifndef LRECORD_CONS |
3403 case Lisp_Type_Cons: | 3345 else if (CONSP (obj)) |
3404 { | 3346 return sizeof (struct Lisp_Cons); |
3405 struct Lisp_Cons *ptr = XCONS (obj); | 3347 #endif /* !LRECORD_CONS */ |
3406 total += sizeof (*ptr); | 3348 else |
3407 #if 0 /* unused */ | 3349 /* Others can't be purified */ |
3408 if (!recurse) | 3350 abort (); |
3409 break; | 3351 return 0; /* unreached */ |
3410 /* If the cdr is nil, tail-recurse on the car. */ | |
3411 if (NILP (ptr->cdr)) | |
3412 { | |
3413 obj = ptr->car; | |
3414 } | |
3415 else | |
3416 { | |
3417 total += pure_sizeof (ptr->car, 1); | |
3418 obj = ptr->cdr; | |
3419 } | |
3420 goto tail_recurse; | |
3421 #endif /* unused */ | |
3422 } | |
3423 break; | |
3424 #endif | |
3425 | |
3426 /* Others can't be purified */ | |
3427 default: | |
3428 abort (); | |
3429 } | |
3430 return total; | |
3431 } | 3352 } |
3432 #endif /* PURESTAT */ | 3353 #endif /* PURESTAT */ |
3433 | 3354 |
3434 | 3355 |
3435 | 3356 |
3447 static int gc_count_short_string_total_size; | 3368 static int gc_count_short_string_total_size; |
3448 | 3369 |
3449 /* static int gc_count_total_records_used, gc_count_records_total_size; */ | 3370 /* static int gc_count_total_records_used, gc_count_records_total_size; */ |
3450 | 3371 |
3451 | 3372 |
3452 /* This will be used more extensively In The Future */ | |
3453 static int last_lrecord_type_index_assigned; | |
3454 | |
3455 CONST struct lrecord_implementation *lrecord_implementations_table[128]; | |
3456 #define max_lrecord_type (countof (lrecord_implementations_table) - 1) | |
3457 | |
3458 int | 3373 int |
3459 lrecord_type_index (CONST struct lrecord_implementation *implementation) | 3374 lrecord_type_index (CONST struct lrecord_implementation *implementation) |
3460 { | 3375 { |
3461 int type_index = *(implementation->lrecord_type_index); | 3376 int type_index = *(implementation->lrecord_type_index); |
3462 /* Have to do this circuitous validation test because of problems | 3377 /* Have to do this circuitous validation test because of problems |
3513 lcrecord_stats[type_index].instances_on_free_list++; | 3428 lcrecord_stats[type_index].instances_on_free_list++; |
3514 } | 3429 } |
3515 else | 3430 else |
3516 { | 3431 { |
3517 size_t sz = (implementation->size_in_bytes_method | 3432 size_t sz = (implementation->size_in_bytes_method |
3518 ? ((implementation->size_in_bytes_method) (h)) | 3433 ? implementation->size_in_bytes_method (h) |
3519 : implementation->static_size); | 3434 : implementation->static_size); |
3520 | 3435 |
3521 if (free_p) | 3436 if (free_p) |
3522 { | 3437 { |
3523 lcrecord_stats[type_index].instances_freed++; | 3438 lcrecord_stats[type_index].instances_freed++; |
3555 { | 3470 { |
3556 struct lrecord_header *h = &(header->lheader); | 3471 struct lrecord_header *h = &(header->lheader); |
3557 if (!MARKED_RECORD_HEADER_P (h) && ! (header->free)) | 3472 if (!MARKED_RECORD_HEADER_P (h) && ! (header->free)) |
3558 { | 3473 { |
3559 if (LHEADER_IMPLEMENTATION (h)->finalizer) | 3474 if (LHEADER_IMPLEMENTATION (h)->finalizer) |
3560 ((LHEADER_IMPLEMENTATION (h)->finalizer) (h, 0)); | 3475 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0); |
3561 } | 3476 } |
3562 } | 3477 } |
3563 | 3478 |
3564 for (header = *prev; header; ) | 3479 for (header = *prev; header; ) |
3565 { | 3480 { |
3566 struct lrecord_header *h = &(header->lheader); | 3481 struct lrecord_header *h = &(header->lheader); |
3567 if (MARKED_RECORD_HEADER_P (h)) | 3482 if (MARKED_RECORD_HEADER_P (h)) |
3568 { | 3483 { |
3569 UNMARK_RECORD_HEADER (h); | 3484 UNMARK_RECORD_HEADER (h); |
3570 num_used++; | 3485 num_used++; |
3571 /* total_size += ((n->implementation->size_in_bytes) (h));*/ | 3486 /* total_size += n->implementation->size_in_bytes (h);*/ |
3572 prev = &(header->next); | 3487 prev = &(header->next); |
3573 header = *prev; | 3488 header = *prev; |
3574 tick_lcrecord_stats (h, 0); | 3489 tick_lcrecord_stats (h, 0); |
3575 } | 3490 } |
3576 else | 3491 else |
3598 int total_size = 0; | 3513 int total_size = 0; |
3599 int total_storage = 0; | 3514 int total_storage = 0; |
3600 | 3515 |
3601 for (vector = *prev; VECTORP (vector); ) | 3516 for (vector = *prev; VECTORP (vector); ) |
3602 { | 3517 { |
3603 struct Lisp_Vector *v = XVECTOR (vector); | 3518 Lisp_Vector *v = XVECTOR (vector); |
3604 int len = v->size; | 3519 int len = v->size; |
3605 if (len < 0) /* marked */ | 3520 if (len < 0) /* marked */ |
3606 { | 3521 { |
3607 len = - (len + 1); | 3522 len = - (len + 1); |
3608 v->size = len; | 3523 v->size = len; |
3609 total_size += len; | 3524 total_size += len; |
3610 total_storage += (MALLOC_OVERHEAD | 3525 total_storage += |
3611 + sizeof (struct Lisp_Vector) | 3526 MALLOC_OVERHEAD + offsetof (Lisp_Vector, contents[len + 1]); |
3612 + (len - 1 + 1) * sizeof (Lisp_Object)); | |
3613 num_used++; | 3527 num_used++; |
3614 prev = &(vector_next (v)); | 3528 prev = &(vector_next (v)); |
3615 vector = *prev; | 3529 vector = *prev; |
3616 } | 3530 } |
3617 else | 3531 else |
3640 | 3554 |
3641 /* BIT_VECTORP fails because the objects are marked, which changes | 3555 /* BIT_VECTORP fails because the objects are marked, which changes |
3642 their implementation */ | 3556 their implementation */ |
3643 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) | 3557 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) |
3644 { | 3558 { |
3645 struct Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); | 3559 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); |
3646 int len = v->size; | 3560 int len = v->size; |
3647 if (MARKED_RECORD_P (bit_vector)) | 3561 if (MARKED_RECORD_P (bit_vector)) |
3648 { | 3562 { |
3649 UNMARK_RECORD_HEADER (&(v->lheader)); | 3563 UNMARK_RECORD_HEADER (&(v->lheader)); |
3650 total_size += len; | 3564 total_size += len; |
3651 total_storage += (MALLOC_OVERHEAD | 3565 total_storage += |
3652 + sizeof (struct Lisp_Bit_Vector) | 3566 MALLOC_OVERHEAD |
3653 + (BIT_VECTOR_LONG_STORAGE (len) - 1) | 3567 + offsetof (Lisp_Bit_Vector, bits[BIT_VECTOR_LONG_STORAGE (len)]); |
3654 * sizeof (long)); | |
3655 num_used++; | 3568 num_used++; |
3656 prev = &(bit_vector_next (v)); | 3569 prev = &(bit_vector_next (v)); |
3657 bit_vector = *prev; | 3570 bit_vector = *prev; |
3658 } | 3571 } |
3659 else | 3572 else |
3674 | 3587 |
3675 #ifdef ERROR_CHECK_GC | 3588 #ifdef ERROR_CHECK_GC |
3676 | 3589 |
3677 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ | 3590 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ |
3678 do { \ | 3591 do { \ |
3679 struct typename##_block *_frob_current; \ | 3592 struct typename##_block *SFTB_current; \ |
3680 struct typename##_block **_frob_prev; \ | 3593 struct typename##_block **SFTB_prev; \ |
3681 int _frob_limit; \ | 3594 int SFTB_limit; \ |
3682 int num_free = 0, num_used = 0; \ | 3595 int num_free = 0, num_used = 0; \ |
3683 \ | 3596 \ |
3684 for (_frob_prev = ¤t_##typename##_block, \ | 3597 for (SFTB_prev = ¤t_##typename##_block, \ |
3685 _frob_current = current_##typename##_block, \ | 3598 SFTB_current = current_##typename##_block, \ |
3686 _frob_limit = current_##typename##_block_index; \ | 3599 SFTB_limit = current_##typename##_block_index; \ |
3687 _frob_current; \ | 3600 SFTB_current; \ |
3688 ) \ | 3601 ) \ |
3689 { \ | 3602 { \ |
3690 int _frob_iii; \ | 3603 int SFTB_iii; \ |
3691 \ | 3604 \ |
3692 for (_frob_iii = 0; _frob_iii < _frob_limit; _frob_iii++) \ | 3605 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ |
3693 { \ | 3606 { \ |
3694 obj_type *_frob_victim = &(_frob_current->block[_frob_iii]); \ | 3607 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ |
3695 \ | 3608 \ |
3696 if (FREE_STRUCT_P (_frob_victim)) \ | 3609 if (FREE_STRUCT_P (SFTB_victim)) \ |
3697 { \ | 3610 { \ |
3698 num_free++; \ | 3611 num_free++; \ |
3699 } \ | 3612 } \ |
3700 else if (!MARKED_##typename##_P (_frob_victim)) \ | 3613 else if (!MARKED_##typename##_P (SFTB_victim)) \ |
3701 { \ | 3614 { \ |
3702 num_free++; \ | 3615 num_free++; \ |
3703 FREE_FIXED_TYPE (typename, obj_type, _frob_victim); \ | 3616 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ |
3704 } \ | 3617 } \ |
3705 else \ | 3618 else \ |
3706 { \ | 3619 { \ |
3707 num_used++; \ | 3620 num_used++; \ |
3708 UNMARK_##typename (_frob_victim); \ | 3621 UNMARK_##typename (SFTB_victim); \ |
3709 } \ | 3622 } \ |
3710 } \ | 3623 } \ |
3711 _frob_prev = &(_frob_current->prev); \ | 3624 SFTB_prev = &(SFTB_current->prev); \ |
3712 _frob_current = _frob_current->prev; \ | 3625 SFTB_current = SFTB_current->prev; \ |
3713 _frob_limit = countof (current_##typename##_block->block); \ | 3626 SFTB_limit = countof (current_##typename##_block->block); \ |
3714 } \ | 3627 } \ |
3715 \ | 3628 \ |
3716 gc_count_num_##typename##_in_use = num_used; \ | 3629 gc_count_num_##typename##_in_use = num_used; \ |
3717 gc_count_num_##typename##_freelist = num_free; \ | 3630 gc_count_num_##typename##_freelist = num_free; \ |
3718 } while (0) | 3631 } while (0) |
3719 | 3632 |
3720 #else /* !ERROR_CHECK_GC */ | 3633 #else /* !ERROR_CHECK_GC */ |
3721 | 3634 |
3722 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ | 3635 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ |
3723 do { \ | 3636 do { \ |
3724 struct typename##_block *_frob_current; \ | 3637 struct typename##_block *SFTB_current; \ |
3725 struct typename##_block **_frob_prev; \ | 3638 struct typename##_block **SFTB_prev; \ |
3726 int _frob_limit; \ | 3639 int SFTB_limit; \ |
3727 int num_free = 0, num_used = 0; \ | 3640 int num_free = 0, num_used = 0; \ |
3728 \ | 3641 \ |
3729 typename##_free_list = 0; \ | 3642 typename##_free_list = 0; \ |
3730 \ | 3643 \ |
3731 for (_frob_prev = ¤t_##typename##_block, \ | 3644 for (SFTB_prev = ¤t_##typename##_block, \ |
3732 _frob_current = current_##typename##_block, \ | 3645 SFTB_current = current_##typename##_block, \ |
3733 _frob_limit = current_##typename##_block_index; \ | 3646 SFTB_limit = current_##typename##_block_index; \ |
3734 _frob_current; \ | 3647 SFTB_current; \ |
3735 ) \ | 3648 ) \ |
3736 { \ | 3649 { \ |
3737 int _frob_iii; \ | 3650 int SFTB_iii; \ |
3738 int _frob_empty = 1; \ | 3651 int SFTB_empty = 1; \ |
3739 obj_type *_frob_old_free_list = typename##_free_list; \ | 3652 obj_type *SFTB_old_free_list = typename##_free_list; \ |
3740 \ | 3653 \ |
3741 for (_frob_iii = 0; _frob_iii < _frob_limit; _frob_iii++) \ | 3654 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ |
3742 { \ | 3655 { \ |
3743 obj_type *_frob_victim = &(_frob_current->block[_frob_iii]); \ | 3656 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ |
3744 \ | 3657 \ |
3745 if (FREE_STRUCT_P (_frob_victim)) \ | 3658 if (FREE_STRUCT_P (SFTB_victim)) \ |
3746 { \ | 3659 { \ |
3747 num_free++; \ | 3660 num_free++; \ |
3748 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, _frob_victim); \ | 3661 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \ |
3749 } \ | 3662 } \ |
3750 else if (!MARKED_##typename##_P (_frob_victim)) \ | 3663 else if (!MARKED_##typename##_P (SFTB_victim)) \ |
3751 { \ | 3664 { \ |
3752 num_free++; \ | 3665 num_free++; \ |
3753 FREE_FIXED_TYPE (typename, obj_type, _frob_victim); \ | 3666 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ |
3754 } \ | 3667 } \ |
3755 else \ | 3668 else \ |
3756 { \ | 3669 { \ |
3757 _frob_empty = 0; \ | 3670 SFTB_empty = 0; \ |
3758 num_used++; \ | 3671 num_used++; \ |
3759 UNMARK_##typename (_frob_victim); \ | 3672 UNMARK_##typename (SFTB_victim); \ |
3760 } \ | 3673 } \ |
3761 } \ | 3674 } \ |
3762 if (!_frob_empty) \ | 3675 if (!SFTB_empty) \ |
3763 { \ | 3676 { \ |
3764 _frob_prev = &(_frob_current->prev); \ | 3677 SFTB_prev = &(SFTB_current->prev); \ |
3765 _frob_current = _frob_current->prev; \ | 3678 SFTB_current = SFTB_current->prev; \ |
3766 } \ | 3679 } \ |
3767 else if (_frob_current == current_##typename##_block \ | 3680 else if (SFTB_current == current_##typename##_block \ |
3768 && !_frob_current->prev) \ | 3681 && !SFTB_current->prev) \ |
3769 { \ | 3682 { \ |
3770 /* No real point in freeing sole allocation block */ \ | 3683 /* No real point in freeing sole allocation block */ \ |
3771 break; \ | 3684 break; \ |
3772 } \ | 3685 } \ |
3773 else \ | 3686 else \ |
3774 { \ | 3687 { \ |
3775 struct typename##_block *_frob_victim_block = _frob_current; \ | 3688 struct typename##_block *SFTB_victim_block = SFTB_current; \ |
3776 if (_frob_victim_block == current_##typename##_block) \ | 3689 if (SFTB_victim_block == current_##typename##_block) \ |
3777 current_##typename##_block_index \ | 3690 current_##typename##_block_index \ |
3778 = countof (current_##typename##_block->block); \ | 3691 = countof (current_##typename##_block->block); \ |
3779 _frob_current = _frob_current->prev; \ | 3692 SFTB_current = SFTB_current->prev; \ |
3780 { \ | 3693 { \ |
3781 *_frob_prev = _frob_current; \ | 3694 *SFTB_prev = SFTB_current; \ |
3782 xfree (_frob_victim_block); \ | 3695 xfree (SFTB_victim_block); \ |
3783 /* Restore free list to what it was before victim was swept */ \ | 3696 /* Restore free list to what it was before victim was swept */ \ |
3784 typename##_free_list = _frob_old_free_list; \ | 3697 typename##_free_list = SFTB_old_free_list; \ |
3785 num_free -= _frob_limit; \ | 3698 num_free -= SFTB_limit; \ |
3786 } \ | 3699 } \ |
3787 } \ | 3700 } \ |
3788 _frob_limit = countof (current_##typename##_block->block); \ | 3701 SFTB_limit = countof (current_##typename##_block->block); \ |
3789 } \ | 3702 } \ |
3790 \ | 3703 \ |
3791 gc_count_num_##typename##_in_use = num_used; \ | 3704 gc_count_num_##typename##_in_use = num_used; \ |
3792 gc_count_num_##typename##_freelist = num_free; \ | 3705 gc_count_num_##typename##_freelist = num_free; \ |
3793 } while (0) | 3706 } while (0) |
3794 | 3707 |
3795 #endif /* !ERROR_CHECK_GC */ | 3708 #endif /* !ERROR_CHECK_GC */ |
3796 | 3709 |
3797 | 3710 |
3873 #define MARKED_compiled_function_P(ptr) \ | 3786 #define MARKED_compiled_function_P(ptr) \ |
3874 MARKED_RECORD_HEADER_P (&((ptr)->lheader)) | 3787 MARKED_RECORD_HEADER_P (&((ptr)->lheader)) |
3875 #define UNMARK_compiled_function(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) | 3788 #define UNMARK_compiled_function(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) |
3876 #define ADDITIONAL_FREE_compiled_function(ptr) | 3789 #define ADDITIONAL_FREE_compiled_function(ptr) |
3877 | 3790 |
3878 SWEEP_FIXED_TYPE_BLOCK (compiled_function, struct Lisp_Compiled_Function); | 3791 SWEEP_FIXED_TYPE_BLOCK (compiled_function, Lisp_Compiled_Function); |
3879 } | 3792 } |
3880 | 3793 |
3881 | 3794 |
3882 #ifdef LISP_FLOAT_TYPE | 3795 #ifdef LISP_FLOAT_TYPE |
3883 static void | 3796 static void |
4191 | 4104 |
4192 /* I hate duplicating all this crap! */ | 4105 /* I hate duplicating all this crap! */ |
4193 static int | 4106 static int |
4194 marked_p (Lisp_Object obj) | 4107 marked_p (Lisp_Object obj) |
4195 { | 4108 { |
4196 if (EQ (obj, Qnull_pointer)) return 1; | 4109 #ifdef ERROR_CHECK_GC |
4197 if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; | 4110 assert (! (GC_EQ (obj, Qnull_pointer))); |
4198 if (PURIFIED (XPNTR (obj))) return 1; | 4111 #endif |
4112 /* Checks we used to perform. */ | |
4113 /* if (EQ (obj, Qnull_pointer)) return 1; */ | |
4114 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ | |
4115 /* if (PURIFIED (XPNTR (obj))) return 1; */ | |
4116 | |
4199 switch (XGCTYPE (obj)) | 4117 switch (XGCTYPE (obj)) |
4200 { | 4118 { |
4201 #ifndef LRECORD_CONS | 4119 #ifndef LRECORD_CONS |
4202 case Lisp_Type_Cons: | 4120 case Lisp_Type_Cons: |
4203 return XMARKBIT (XCAR (obj)); | 4121 { |
4122 struct Lisp_Cons *ptr = XCONS (obj); | |
4123 return PURIFIED (ptr) || XMARKBIT (ptr->car); | |
4124 } | |
4204 #endif | 4125 #endif |
4205 case Lisp_Type_Record: | 4126 case Lisp_Type_Record: |
4206 return MARKED_RECORD_HEADER_P (XRECORD_LHEADER (obj)); | 4127 { |
4128 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | |
4129 #if defined (ERROR_CHECK_GC) && defined (USE_INDEXED_LRECORD_IMPLEMENTATION) | |
4130 assert (lheader->type <= last_lrecord_type_index_assigned); | |
4131 #endif | |
4132 return PURIFIED (lheader) || MARKED_RECORD_HEADER_P (lheader); | |
4133 } | |
4207 #ifndef LRECORD_STRING | 4134 #ifndef LRECORD_STRING |
4208 case Lisp_Type_String: | 4135 case Lisp_Type_String: |
4209 return XMARKBIT (XSTRING (obj)->plist); | 4136 { |
4137 struct Lisp_String *ptr = XSTRING (obj); | |
4138 return PURIFIED (ptr) || XMARKBIT (ptr->plist); | |
4139 } | |
4210 #endif /* ! LRECORD_STRING */ | 4140 #endif /* ! LRECORD_STRING */ |
4211 #ifndef LRECORD_VECTOR | 4141 #ifndef LRECORD_VECTOR |
4212 case Lisp_Type_Vector: | 4142 case Lisp_Type_Vector: |
4213 return XVECTOR_LENGTH (obj) < 0; | 4143 { |
4144 struct Lisp_Vector *ptr = XVECTOR (obj); | |
4145 return PURIFIED (ptr) || vector_length (ptr) < 0; | |
4146 } | |
4214 #endif /* !LRECORD_VECTOR */ | 4147 #endif /* !LRECORD_VECTOR */ |
4215 #ifndef LRECORD_SYMBOL | 4148 #ifndef LRECORD_SYMBOL |
4216 case Lisp_Type_Symbol: | 4149 case Lisp_Type_Symbol: |
4217 return XMARKBIT (XSYMBOL (obj)->plist); | 4150 { |
4218 #endif | 4151 struct Lisp_Symbol *ptr = XSYMBOL (obj); |
4152 return PURIFIED (ptr) || XMARKBIT (ptr->plist); | |
4153 } | |
4154 #endif | |
4155 | |
4156 /* Ints and Chars don't need GC */ | |
4157 #if defined (USE_MINIMAL_TAGBITS) || ! defined (ERROR_CHECK_GC) | |
4219 default: | 4158 default: |
4220 abort (); | 4159 return 1; |
4221 } | 4160 #else |
4222 return 0; /* suppress compiler warning */ | 4161 default: |
4162 abort(); | |
4163 case Lisp_Type_Int: | |
4164 case Lisp_Type_Char: | |
4165 return 1; | |
4166 #endif | |
4167 } | |
4223 } | 4168 } |
4224 | 4169 |
4225 static void | 4170 static void |
4226 gc_sweep (void) | 4171 gc_sweep (void) |
4227 { | 4172 { |
4295 void | 4240 void |
4296 disksave_object_finalization (void) | 4241 disksave_object_finalization (void) |
4297 { | 4242 { |
4298 /* It's important that certain information from the environment not get | 4243 /* It's important that certain information from the environment not get |
4299 dumped with the executable (pathnames, environment variables, etc.). | 4244 dumped with the executable (pathnames, environment variables, etc.). |
4300 To make it easier to tell when this has happend with strings(1) we | 4245 To make it easier to tell when this has happened with strings(1) we |
4301 clear some known-to-be-garbage blocks of memory, so that leftover | 4246 clear some known-to-be-garbage blocks of memory, so that leftover |
4302 results of old evaluation don't look like potential problems. | 4247 results of old evaluation don't look like potential problems. |
4303 But first we set some notable variables to nil and do one more GC, | 4248 But first we set some notable variables to nil and do one more GC, |
4304 to turn those strings into garbage. | 4249 to turn those strings into garbage. |
4305 */ | 4250 */ |
4368 | 4313 |
4369 | 4314 |
4370 void | 4315 void |
4371 garbage_collect_1 (void) | 4316 garbage_collect_1 (void) |
4372 { | 4317 { |
4318 #if MAX_SAVE_STACK > 0 | |
4373 char stack_top_variable; | 4319 char stack_top_variable; |
4374 extern char *stack_bottom; | 4320 extern char *stack_bottom; |
4321 #endif | |
4375 int i; | 4322 int i; |
4376 struct frame *f; | 4323 struct frame *f; |
4377 int speccount; | 4324 int speccount; |
4378 int cursor_changed; | 4325 int cursor_changed; |
4379 Lisp_Object pre_gc_cursor; | 4326 Lisp_Object pre_gc_cursor; |
4383 || gc_currently_forbidden | 4330 || gc_currently_forbidden |
4384 || in_display | 4331 || in_display |
4385 || preparing_for_armageddon) | 4332 || preparing_for_armageddon) |
4386 return; | 4333 return; |
4387 | 4334 |
4335 /* We used to call selected_frame() here. | |
4336 | |
4337 The following functions cannot be called inside GC | |
4338 so we move to after the above tests. */ | |
4339 { | |
4340 Lisp_Object frame; | |
4341 Lisp_Object device = Fselected_device (Qnil); | |
4342 if (NILP (device)) /* Could happen during startup, eg. if always_gc */ | |
4343 return; | |
4344 frame = DEVICE_SELECTED_FRAME (XDEVICE (device)); | |
4345 if (NILP (frame)) | |
4346 signal_simple_error ("No frames exist on device", device); | |
4347 f = XFRAME (frame); | |
4348 } | |
4349 | |
4388 pre_gc_cursor = Qnil; | 4350 pre_gc_cursor = Qnil; |
4389 cursor_changed = 0; | 4351 cursor_changed = 0; |
4390 | |
4391 /* This function cannot be called inside GC so we move to after the */ | |
4392 /* above tests */ | |
4393 f = selected_frame (); | |
4394 | 4352 |
4395 GCPRO1 (pre_gc_cursor); | 4353 GCPRO1 (pre_gc_cursor); |
4396 | 4354 |
4397 /* Very important to prevent GC during any of the following | 4355 /* Very important to prevent GC during any of the following |
4398 stuff that might run Lisp code; otherwise, we'll likely | 4356 stuff that might run Lisp code; otherwise, we'll likely |
4484 struct backtrace *backlist; | 4442 struct backtrace *backlist; |
4485 struct specbinding *bind; | 4443 struct specbinding *bind; |
4486 | 4444 |
4487 for (i = 0; i < staticidx; i++) | 4445 for (i = 0; i < staticidx; i++) |
4488 { | 4446 { |
4489 #ifdef GDB_SUCKS | |
4490 printf ("%d\n", i); | |
4491 debug_print (*staticvec[i]); | |
4492 #endif | |
4493 mark_object (*(staticvec[i])); | 4447 mark_object (*(staticvec[i])); |
4494 } | 4448 } |
4495 | 4449 |
4496 for (tail = gcprolist; tail; tail = tail->next) | 4450 for (tail = gcprolist; tail; tail = tail->next) |
4497 { | 4451 { |
4526 mark_redisplay (mark_object); | 4480 mark_redisplay (mark_object); |
4527 mark_profiling_info (mark_object); | 4481 mark_profiling_info (mark_object); |
4528 } | 4482 } |
4529 | 4483 |
4530 /* OK, now do the after-mark stuff. This is for things that | 4484 /* OK, now do the after-mark stuff. This is for things that |
4531 are only marked when something else is marked (e.g. weak hashtables). | 4485 are only marked when something else is marked (e.g. weak hash tables). |
4532 There may be complex dependencies between such objects -- e.g. | 4486 There may be complex dependencies between such objects -- e.g. |
4533 a weak hashtable might be unmarked, but after processing a later | 4487 a weak hash table might be unmarked, but after processing a later |
4534 weak hashtable, the former one might get marked. So we have to | 4488 weak hash table, the former one might get marked. So we have to |
4535 iterate until nothing more gets marked. */ | 4489 iterate until nothing more gets marked. */ |
4536 { | 4490 |
4537 int did_mark; | 4491 while (finish_marking_weak_hash_tables (marked_p, mark_object) > 0 || |
4538 /* Need to iterate until there's nothing more to mark, in case | 4492 finish_marking_weak_lists (marked_p, mark_object) > 0) |
4539 of chains of mark dependencies. */ | 4493 ; |
4540 do | |
4541 { | |
4542 did_mark = 0; | |
4543 did_mark += !!finish_marking_weak_hashtables (marked_p, mark_object); | |
4544 did_mark += !!finish_marking_weak_lists (marked_p, mark_object); | |
4545 } | |
4546 while (did_mark); | |
4547 } | |
4548 | 4494 |
4549 /* And prune (this needs to be called after everything else has been | 4495 /* And prune (this needs to be called after everything else has been |
4550 marked and before we do any sweeping). */ | 4496 marked and before we do any sweeping). */ |
4551 /* #### this is somewhat ad-hoc and should probably be an object | 4497 /* #### this is somewhat ad-hoc and should probably be an object |
4552 method */ | 4498 method */ |
4553 prune_weak_hashtables (marked_p); | 4499 prune_weak_hash_tables (marked_p); |
4554 prune_weak_lists (marked_p); | 4500 prune_weak_lists (marked_p); |
4555 prune_specifiers (marked_p); | 4501 prune_specifiers (marked_p); |
4556 prune_syntax_tables (marked_p); | 4502 prune_syntax_tables (marked_p); |
4557 | 4503 |
4558 gc_sweep (); | 4504 gc_sweep (); |
4608 | 4554 |
4609 UNGCPRO; | 4555 UNGCPRO; |
4610 return; | 4556 return; |
4611 } | 4557 } |
4612 | 4558 |
4613 #ifdef EMACS_BTL | |
4614 /* This isn't actually called. BTL recognizes the stack frame of the top | |
4615 of the garbage collector by noting that PC is between &garbage_collect_1 | |
4616 and &BTL_after_garbage_collect_1_stub. So this fn must be right here. | |
4617 There's not any other way to know the address of the end of a function. | |
4618 */ | |
4619 void BTL_after_garbage_collect_1_stub () { abort (); } | |
4620 #endif /* EMACS_BTL */ | |
4621 | |
4622 /* Debugging aids. */ | 4559 /* Debugging aids. */ |
4623 | 4560 |
4624 static Lisp_Object | 4561 static Lisp_Object |
4625 gc_plist_hack (CONST char *name, int value, Lisp_Object tail) | 4562 gc_plist_hack (CONST char *name, int value, Lisp_Object tail) |
4626 { | 4563 { |
4628 or portable numeric datatypes, or bit-vectors, or characters, or | 4565 or portable numeric datatypes, or bit-vectors, or characters, or |
4629 arrays, or exceptions, or ...) */ | 4566 arrays, or exceptions, or ...) */ |
4630 return cons3 (intern (name), make_int (value), tail); | 4567 return cons3 (intern (name), make_int (value), tail); |
4631 } | 4568 } |
4632 | 4569 |
4633 #define HACK_O_MATIC(type, name, pl) \ | 4570 #define HACK_O_MATIC(type, name, pl) do { \ |
4634 { \ | 4571 int s = 0; \ |
4635 int s = 0; \ | 4572 struct type##_block *x = current_##type##_block; \ |
4636 struct type##_block *x = current_##type##_block; \ | 4573 while (x) { s += sizeof (*x) + MALLOC_OVERHEAD; x = x->prev; } \ |
4637 while (x) { s += sizeof (*x) + MALLOC_OVERHEAD; x = x->prev; } \ | 4574 (pl) = gc_plist_hack ((name), s, (pl)); \ |
4638 (pl) = gc_plist_hack ((name), s, (pl)); \ | 4575 } while (0) |
4639 } | |
4640 | 4576 |
4641 DEFUN ("garbage-collect", Fgarbage_collect, 0, 0, "", /* | 4577 DEFUN ("garbage-collect", Fgarbage_collect, 0, 0, "", /* |
4642 Reclaim storage for Lisp objects no longer needed. | 4578 Reclaim storage for Lisp objects no longer needed. |
4643 Return info on amount of space in use: | 4579 Return info on amount of space in use: |
4644 ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) | 4580 ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) |
4946 void | 4882 void |
4947 init_alloc_once_early (void) | 4883 init_alloc_once_early (void) |
4948 { | 4884 { |
4949 int iii; | 4885 int iii; |
4950 | 4886 |
4951 #ifdef PURESTAT | |
4952 for (iii = 0; iii < countof (purestats); iii++) | |
4953 { | |
4954 if (! purestats[iii]) continue; | |
4955 purestats[iii]->nobjects = 0; | |
4956 purestats[iii]->nbytes = 0; | |
4957 } | |
4958 purecopying_for_bytecode = 0; | |
4959 #endif /* PURESTAT */ | |
4960 | |
4961 last_lrecord_type_index_assigned = -1; | 4887 last_lrecord_type_index_assigned = -1; |
4962 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) | 4888 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) |
4963 { | 4889 { |
4964 lrecord_implementations_table[iii] = 0; | 4890 lrecord_implementations_table[iii] = 0; |
4965 } | 4891 } |