Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 412:697ef44129c6 r21-2-14
Import from CVS: tag r21-2-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:20:41 +0200 |
parents | b8cc9ab3f761 |
children | da8ed4261e83 |
comparison
equal
deleted
inserted
replaced
411:12e008d41344 | 412:697ef44129c6 |
---|---|
34 and various changes for Mule, for 19.12. | 34 and various changes for Mule, for 19.12. |
35 Added bit vectors for 19.13. | 35 Added bit vectors for 19.13. |
36 Added lcrecord lists for 19.14. | 36 Added lcrecord lists for 19.14. |
37 slb: Lots of work on the purification and dump time code. | 37 slb: Lots of work on the purification and dump time code. |
38 Synched Doug Lea malloc support from Emacs 20.2. | 38 Synched Doug Lea malloc support from Emacs 20.2. |
39 og: Killed the purespace. Portable dumper (moved to dumper.c) | 39 og: Killed the purespace. |
40 */ | 40 */ |
41 | 41 |
42 #include <config.h> | 42 #include <config.h> |
43 #include "lisp.h" | 43 #include "lisp.h" |
44 | 44 |
45 #include "alloc.h" | |
46 #include "backtrace.h" | 45 #include "backtrace.h" |
47 #include "buffer.h" | 46 #include "buffer.h" |
48 #include "bytecode.h" | 47 #include "bytecode.h" |
49 #include "chartab.h" | 48 #include "chartab.h" |
50 #include "device.h" | 49 #include "device.h" |
55 #include "glyphs.h" | 54 #include "glyphs.h" |
56 #include "opaque.h" | 55 #include "opaque.h" |
57 #include "redisplay.h" | 56 #include "redisplay.h" |
58 #include "specifier.h" | 57 #include "specifier.h" |
59 #include "sysfile.h" | 58 #include "sysfile.h" |
60 #include "sysdep.h" | |
61 #include "window.h" | 59 #include "window.h" |
62 #include "console-stream.h" | 60 |
61 #include <stddef.h> | |
63 | 62 |
64 #ifdef DOUG_LEA_MALLOC | 63 #ifdef DOUG_LEA_MALLOC |
65 #include <malloc.h> | 64 #include <malloc.h> |
66 #endif | 65 #endif |
67 | 66 |
68 #ifdef PDUMP | |
69 #include "dumper.h" | |
70 #endif | |
71 | |
72 EXFUN (Fgarbage_collect, 0); | 67 EXFUN (Fgarbage_collect, 0); |
68 | |
69 /* Return the true size of a struct with a variable-length array field. */ | |
70 #define STRETCHY_STRUCT_SIZEOF(stretchy_struct_type, \ | |
71 stretchy_array_field, \ | |
72 stretchy_array_length) \ | |
73 (offsetof (stretchy_struct_type, stretchy_array_field) + \ | |
74 (offsetof (stretchy_struct_type, stretchy_array_field[1]) - \ | |
75 offsetof (stretchy_struct_type, stretchy_array_field[0])) * \ | |
76 (stretchy_array_length)) | |
73 | 77 |
74 #if 0 /* this is _way_ too slow to be part of the standard debug options */ | 78 #if 0 /* this is _way_ too slow to be part of the standard debug options */ |
75 #if defined(DEBUG_XEMACS) && defined(MULE) | 79 #if defined(DEBUG_XEMACS) && defined(MULE) |
76 #define VERIFY_STRING_CHARS_INTEGRITY | 80 #define VERIFY_STRING_CHARS_INTEGRITY |
77 #endif | 81 #endif |
154 Lisp_Object Vpost_gc_hook, Qpost_gc_hook; | 158 Lisp_Object Vpost_gc_hook, Qpost_gc_hook; |
155 | 159 |
156 /* "Garbage collecting" */ | 160 /* "Garbage collecting" */ |
157 Lisp_Object Vgc_message; | 161 Lisp_Object Vgc_message; |
158 Lisp_Object Vgc_pointer_glyph; | 162 Lisp_Object Vgc_pointer_glyph; |
159 static const char gc_default_message[] = "Garbage collecting"; | 163 static CONST char gc_default_message[] = "Garbage collecting"; |
160 Lisp_Object Qgarbage_collecting; | 164 Lisp_Object Qgarbage_collecting; |
161 | 165 |
162 #ifndef VIRT_ADDR_VARIES | 166 #ifndef VIRT_ADDR_VARIES |
163 extern | 167 extern |
164 #endif /* VIRT_ADDR_VARIES */ | 168 #endif /* VIRT_ADDR_VARIES */ |
170 EMACS_INT malloc_sbrk_unused; | 174 EMACS_INT malloc_sbrk_unused; |
171 | 175 |
172 /* Non-zero means we're in the process of doing the dump */ | 176 /* Non-zero means we're in the process of doing the dump */ |
173 int purify_flag; | 177 int purify_flag; |
174 | 178 |
179 #ifdef HEAP_IN_DATA | |
180 extern void sheap_adjust_h(); | |
181 #endif | |
182 | |
175 #ifdef ERROR_CHECK_TYPECHECK | 183 #ifdef ERROR_CHECK_TYPECHECK |
176 | 184 |
177 Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN; | 185 Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN; |
178 | 186 |
179 #endif | 187 #endif |
180 | 188 |
181 int | 189 int |
182 c_readonly (Lisp_Object obj) | 190 c_readonly (Lisp_Object obj) |
183 { | 191 { |
184 return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj); | 192 return POINTER_TYPE_P (XGCTYPE (obj)) && C_READONLY (obj); |
185 } | 193 } |
186 | 194 |
187 int | 195 int |
188 lisp_readonly (Lisp_Object obj) | 196 lisp_readonly (Lisp_Object obj) |
189 { | 197 { |
190 return POINTER_TYPE_P (XTYPE (obj)) && LISP_READONLY (obj); | 198 return POINTER_TYPE_P (XGCTYPE (obj)) && LISP_READONLY (obj); |
191 } | 199 } |
192 | 200 |
193 | 201 |
194 /* Maximum amount of C stack to save when a GC happens. */ | 202 /* Maximum amount of C stack to save when a GC happens. */ |
195 | 203 |
214 } | 222 } |
215 } | 223 } |
216 | 224 |
217 /* malloc calls this if it finds we are near exhausting storage */ | 225 /* malloc calls this if it finds we are near exhausting storage */ |
218 void | 226 void |
219 malloc_warning (const char *str) | 227 malloc_warning (CONST char *str) |
220 { | 228 { |
221 if (ignore_malloc_warnings) | 229 if (ignore_malloc_warnings) |
222 return; | 230 return; |
223 | 231 |
224 warn_when_safe | 232 warn_when_safe |
250 error ("Memory exhausted"); | 258 error ("Memory exhausted"); |
251 } | 259 } |
252 | 260 |
253 /* like malloc and realloc but check for no memory left, and block input. */ | 261 /* like malloc and realloc but check for no memory left, and block input. */ |
254 | 262 |
263 #ifdef xmalloc | |
255 #undef xmalloc | 264 #undef xmalloc |
265 #endif | |
266 | |
256 void * | 267 void * |
257 xmalloc (size_t size) | 268 xmalloc (size_t size) |
258 { | 269 { |
259 void *val = malloc (size); | 270 void *val = malloc (size); |
260 | 271 |
261 if (!val && (size != 0)) memory_full (); | 272 if (!val && (size != 0)) memory_full (); |
262 return val; | 273 return val; |
263 } | 274 } |
264 | 275 |
276 #ifdef xcalloc | |
265 #undef xcalloc | 277 #undef xcalloc |
278 #endif | |
279 | |
266 static void * | 280 static void * |
267 xcalloc (size_t nelem, size_t elsize) | 281 xcalloc (size_t nelem, size_t elsize) |
268 { | 282 { |
269 void *val = calloc (nelem, elsize); | 283 void *val = calloc (nelem, elsize); |
270 | 284 |
276 xmalloc_and_zero (size_t size) | 290 xmalloc_and_zero (size_t size) |
277 { | 291 { |
278 return xcalloc (size, sizeof (char)); | 292 return xcalloc (size, sizeof (char)); |
279 } | 293 } |
280 | 294 |
295 #ifdef xrealloc | |
281 #undef xrealloc | 296 #undef xrealloc |
297 #endif | |
298 | |
282 void * | 299 void * |
283 xrealloc (void *block, size_t size) | 300 xrealloc (void *block, size_t size) |
284 { | 301 { |
285 /* We must call malloc explicitly when BLOCK is 0, since some | 302 /* We must call malloc explicitly when BLOCK is 0, since some |
286 reallocs don't do this. */ | 303 reallocs don't do this. */ |
335 | 352 |
336 #define deadbeef_memory(ptr, size) | 353 #define deadbeef_memory(ptr, size) |
337 | 354 |
338 #endif /* !ERROR_CHECK_GC */ | 355 #endif /* !ERROR_CHECK_GC */ |
339 | 356 |
357 #ifdef xstrdup | |
340 #undef xstrdup | 358 #undef xstrdup |
359 #endif | |
360 | |
341 char * | 361 char * |
342 xstrdup (const char *str) | 362 xstrdup (CONST char *str) |
343 { | 363 { |
344 int len = strlen (str) + 1; /* for stupid terminating 0 */ | 364 int len = strlen (str) + 1; /* for stupid terminating 0 */ |
345 | 365 |
346 void *val = xmalloc (len); | 366 void *val = xmalloc (len); |
347 if (val == 0) return 0; | 367 if (val == 0) return 0; |
348 return (char *) memcpy (val, str, len); | 368 memcpy (val, str, len); |
369 return (char *) val; | |
349 } | 370 } |
350 | 371 |
351 #ifdef NEED_STRDUP | 372 #ifdef NEED_STRDUP |
352 char * | 373 char * |
353 strdup (const char *s) | 374 strdup (CONST char *s) |
354 { | 375 { |
355 return xstrdup (s); | 376 return xstrdup (s); |
356 } | 377 } |
357 #endif /* NEED_STRDUP */ | 378 #endif /* NEED_STRDUP */ |
358 | 379 |
359 | 380 |
360 static void * | 381 static void * |
361 allocate_lisp_storage (size_t size) | 382 allocate_lisp_storage (size_t size) |
362 { | 383 { |
363 return xmalloc (size); | 384 void *p = xmalloc (size); |
364 } | 385 return p; |
365 | 386 } |
366 | 387 |
367 /* lcrecords are chained together through their "next" field. | 388 |
368 After doing the mark phase, GC will walk this linked list | 389 /* lrecords are chained together through their "next.v" field. |
369 and free any lcrecord which hasn't been marked. */ | 390 * After doing the mark phase, the GC will walk this linked |
391 * list and free any record which hasn't been marked. | |
392 */ | |
370 static struct lcrecord_header *all_lcrecords; | 393 static struct lcrecord_header *all_lcrecords; |
371 | 394 |
372 void * | 395 void * |
373 alloc_lcrecord (size_t size, const struct lrecord_implementation *implementation) | 396 alloc_lcrecord (size_t size, CONST struct lrecord_implementation *implementation) |
374 { | 397 { |
375 struct lcrecord_header *lcheader; | 398 struct lcrecord_header *lcheader; |
376 | 399 |
377 type_checking_assert | 400 #ifdef ERROR_CHECK_GC |
378 ((implementation->static_size == 0 ? | 401 if (implementation->static_size == 0) |
379 implementation->size_in_bytes_method != NULL : | 402 assert (implementation->size_in_bytes_method); |
380 implementation->static_size == size) | 403 else |
381 && | 404 assert (implementation->static_size == size); |
382 (! implementation->basic_p) | 405 #endif |
383 && | |
384 (! (implementation->hash == NULL && implementation->equal != NULL))); | |
385 | 406 |
386 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); | 407 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); |
387 set_lheader_implementation (&lcheader->lheader, implementation); | 408 set_lheader_implementation (&(lcheader->lheader), implementation); |
388 lcheader->next = all_lcrecords; | 409 lcheader->next = all_lcrecords; |
389 #if 1 /* mly prefers to see small ID numbers */ | 410 #if 1 /* mly prefers to see small ID numbers */ |
390 lcheader->uid = lrecord_uid_counter++; | 411 lcheader->uid = lrecord_uid_counter++; |
391 #else /* jwz prefers to see real addrs */ | 412 #else /* jwz prefers to see real addrs */ |
392 lcheader->uid = (int) &lcheader; | 413 lcheader->uid = (int) &lcheader; |
441 { | 462 { |
442 struct lcrecord_header *header; | 463 struct lcrecord_header *header; |
443 | 464 |
444 for (header = all_lcrecords; header; header = header->next) | 465 for (header = all_lcrecords; header; header = header->next) |
445 { | 466 { |
446 if (LHEADER_IMPLEMENTATION (&header->lheader)->finalizer && | 467 if (LHEADER_IMPLEMENTATION(&header->lheader)->finalizer && |
447 !header->free) | 468 !header->free) |
448 LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1); | 469 ((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer) |
449 } | 470 (header, 1)); |
471 } | |
472 } | |
473 | |
474 | |
475 /* This must not be called -- it just serves as for EQ test | |
476 * If lheader->implementation->finalizer is this_marks_a_marked_record, | |
477 * then lrecord has been marked by the GC sweeper | |
478 * header->implementation is put back to its correct value by | |
479 * sweep_records */ | |
480 void | |
481 this_marks_a_marked_record (void *dummy0, int dummy1) | |
482 { | |
483 abort (); | |
484 } | |
485 | |
486 /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck | |
487 in CONST space and you get SEGV's if you attempt to mark them. | |
488 This sits in lheader->implementation->marker. */ | |
489 | |
490 Lisp_Object | |
491 this_one_is_unmarkable (Lisp_Object obj, void (*markobj) (Lisp_Object)) | |
492 { | |
493 abort (); | |
494 return Qnil; | |
495 } | |
496 | |
497 /* XGCTYPE for records */ | |
498 int | |
499 gc_record_type_p (Lisp_Object frob, CONST struct lrecord_implementation *type) | |
500 { | |
501 CONST struct lrecord_implementation *imp; | |
502 | |
503 if (XGCTYPE (frob) != Lisp_Type_Record) | |
504 return 0; | |
505 | |
506 imp = XRECORD_LHEADER_IMPLEMENTATION (frob); | |
507 return imp == type; | |
450 } | 508 } |
451 | 509 |
452 | 510 |
453 /************************************************************************/ | 511 /************************************************************************/ |
454 /* Debugger support */ | 512 /* Debugger support */ |
455 /************************************************************************/ | 513 /************************************************************************/ |
456 /* Give gdb/dbx enough information to decode Lisp Objects. We make | 514 /* Give gdb/dbx enough information to decode Lisp Objects. We make |
457 sure certain symbols are always defined, so gdb doesn't complain | 515 sure certain symbols are always defined, so gdb doesn't complain |
458 about expressions in src/.gdbinit. See src/.gdbinit or src/.dbxrc | 516 about expressions in src/gdbinit. See src/gdbinit or src/dbxrc to |
459 to see how this is used. */ | 517 see how this is used. */ |
460 | 518 |
461 EMACS_UINT dbg_valmask = ((1UL << VALBITS) - 1) << GCBITS; | 519 EMACS_UINT dbg_valmask = ((1UL << VALBITS) - 1) << GCBITS; |
462 EMACS_UINT dbg_typemask = (1UL << GCTYPEBITS) - 1; | 520 EMACS_UINT dbg_typemask = (1UL << GCTYPEBITS) - 1; |
463 | 521 |
464 #ifdef USE_UNION_TYPE | 522 #ifdef USE_UNION_TYPE |
465 unsigned char dbg_USE_UNION_TYPE = 1; | 523 unsigned char dbg_USE_UNION_TYPE = 1; |
466 #else | 524 #else |
467 unsigned char dbg_USE_UNION_TYPE = 0; | 525 unsigned char dbg_USE_UNION_TYPE = 0; |
526 #endif | |
527 | |
528 unsigned char Lisp_Type_Int = 100; | |
529 unsigned char Lisp_Type_Cons = 101; | |
530 unsigned char Lisp_Type_String = 102; | |
531 unsigned char Lisp_Type_Vector = 103; | |
532 unsigned char Lisp_Type_Symbol = 104; | |
533 | |
534 #ifndef MULE | |
535 unsigned char lrecord_char_table_entry; | |
536 unsigned char lrecord_charset; | |
537 #ifndef FILE_CODING | |
538 unsigned char lrecord_coding_system; | |
539 #endif | |
540 #endif | |
541 | |
542 #ifndef HAVE_TOOLBARS | |
543 unsigned char lrecord_toolbar_button; | |
544 #endif | |
545 | |
546 #ifndef TOOLTALK | |
547 unsigned char lrecord_tooltalk_message; | |
548 unsigned char lrecord_tooltalk_pattern; | |
549 #endif | |
550 | |
551 #ifndef HAVE_DATABASE | |
552 unsigned char lrecord_database; | |
468 #endif | 553 #endif |
469 | 554 |
470 unsigned char dbg_valbits = VALBITS; | 555 unsigned char dbg_valbits = VALBITS; |
471 unsigned char dbg_gctypebits = GCTYPEBITS; | 556 unsigned char dbg_gctypebits = GCTYPEBITS; |
472 | 557 |
510 (a struct Lisp_String) is a fixed-size structure and is managed the | 595 (a struct Lisp_String) is a fixed-size structure and is managed the |
511 same way as all the other such types. This structure contains a | 596 same way as all the other such types. This structure contains a |
512 pointer to the actual string data, which is stored in structures of | 597 pointer to the actual string data, which is stored in structures of |
513 type struct string_chars_block. Each string_chars_block consists | 598 type struct string_chars_block. Each string_chars_block consists |
514 of a pointer to a struct Lisp_String, followed by the data for that | 599 of a pointer to a struct Lisp_String, followed by the data for that |
515 string, followed by another pointer to a Lisp_String, followed by | 600 string, followed by another pointer to a struct Lisp_String, |
516 the data for that string, etc. At GC time, the data in these | 601 followed by the data for that string, etc. At GC time, the data in |
517 blocks is compacted by searching sequentially through all the | 602 these blocks is compacted by searching sequentially through all the |
518 blocks and compressing out any holes created by unmarked strings. | 603 blocks and compressing out any holes created by unmarked strings. |
519 Strings that are more than a certain size (bigger than the size of | 604 Strings that are more than a certain size (bigger than the size of |
520 a string_chars_block, although something like half as big might | 605 a string_chars_block, although something like half as big might |
521 make more sense) are malloc()ed separately and not stored in | 606 make more sense) are malloc()ed separately and not stored in |
522 string_chars_blocks. Furthermore, no one string stretches across | 607 string_chars_blocks. Furthermore, no one string stretches across |
626 Furthermore, we never take objects off the free list | 711 Furthermore, we never take objects off the free list |
627 unless there's a large number (usually 1000, but | 712 unless there's a large number (usually 1000, but |
628 varies depending on type) of them already on the list. | 713 varies depending on type) of them already on the list. |
629 This way, we ensure that an object that gets freed will | 714 This way, we ensure that an object that gets freed will |
630 remain free for the next 1000 (or whatever) times that | 715 remain free for the next 1000 (or whatever) times that |
631 an object of that type is allocated. */ | 716 an object of that type is allocated. |
717 */ | |
632 | 718 |
633 #ifndef MALLOC_OVERHEAD | 719 #ifndef MALLOC_OVERHEAD |
634 #ifdef GNU_MALLOC | 720 #ifdef GNU_MALLOC |
635 #define MALLOC_OVERHEAD 0 | 721 #define MALLOC_OVERHEAD 0 |
636 #elif defined (rcheck) | 722 #elif defined (rcheck) |
646 try to set aside another reserve in case we run out once more. | 732 try to set aside another reserve in case we run out once more. |
647 | 733 |
648 This is called when a relocatable block is freed in ralloc.c. */ | 734 This is called when a relocatable block is freed in ralloc.c. */ |
649 void refill_memory_reserve (void); | 735 void refill_memory_reserve (void); |
650 void | 736 void |
651 refill_memory_reserve (void) | 737 refill_memory_reserve () |
652 { | 738 { |
653 if (breathing_space == 0) | 739 if (breathing_space == 0) |
654 breathing_space = (char *) malloc (4096 - MALLOC_OVERHEAD); | 740 breathing_space = (char *) malloc (4096 - MALLOC_OVERHEAD); |
655 } | 741 } |
656 #endif | 742 #endif |
785 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFFFFFF | 871 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFFFFFF |
786 #else | 872 #else |
787 You have some weird system and need to supply a reasonable value here. | 873 You have some weird system and need to supply a reasonable value here. |
788 #endif | 874 #endif |
789 | 875 |
790 /* The construct (* (void **) (ptr)) would cause aliasing problems | |
791 with modern optimizing compilers like `gcc -O3 -fstrict-aliasing'. | |
792 But `char *' can legally alias any pointer. Hence this union trick. */ | |
793 typedef union { char c; void *p; } *aliasing_voidpp; | |
794 #define ALIASING_VOIDPP_DEREFERENCE(ptr) \ | |
795 (((aliasing_voidpp) (ptr))->p) | |
796 #define FREE_STRUCT_P(ptr) \ | 876 #define FREE_STRUCT_P(ptr) \ |
797 (ALIASING_VOIDPP_DEREFERENCE (ptr) == (void *) INVALID_POINTER_VALUE) | 877 (* (void **) ptr == (void *) INVALID_POINTER_VALUE) |
798 #define MARK_STRUCT_AS_FREE(ptr) \ | 878 #define MARK_STRUCT_AS_FREE(ptr) \ |
799 (ALIASING_VOIDPP_DEREFERENCE (ptr) = (void *) INVALID_POINTER_VALUE) | 879 (* (void **) ptr = (void *) INVALID_POINTER_VALUE) |
800 #define MARK_STRUCT_AS_NOT_FREE(ptr) \ | 880 #define MARK_STRUCT_AS_NOT_FREE(ptr) \ |
801 (ALIASING_VOIDPP_DEREFERENCE (ptr) = 0) | 881 (* (void **) ptr = 0) |
802 | 882 |
803 #ifdef ERROR_CHECK_GC | 883 #ifdef ERROR_CHECK_GC |
804 | 884 |
805 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ | 885 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ |
806 do { if (type##_free_list_tail) \ | 886 do { if (type##_free_list_tail) \ |
861 | 941 |
862 /************************************************************************/ | 942 /************************************************************************/ |
863 /* Cons allocation */ | 943 /* Cons allocation */ |
864 /************************************************************************/ | 944 /************************************************************************/ |
865 | 945 |
866 DECLARE_FIXED_TYPE_ALLOC (cons, Lisp_Cons); | 946 DECLARE_FIXED_TYPE_ALLOC (cons, struct Lisp_Cons); |
867 /* conses are used and freed so often that we set this really high */ | 947 /* conses are used and freed so often that we set this really high */ |
868 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */ | 948 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */ |
869 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 | 949 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 |
870 | 950 |
871 static Lisp_Object | 951 static Lisp_Object |
872 mark_cons (Lisp_Object obj) | 952 mark_cons (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
873 { | 953 { |
874 if (NILP (XCDR (obj))) | 954 if (GC_NILP (XCDR (obj))) |
875 return XCAR (obj); | 955 return XCAR (obj); |
876 | 956 |
877 mark_object (XCAR (obj)); | 957 markobj (XCAR (obj)); |
878 return XCDR (obj); | 958 return XCDR (obj); |
879 } | 959 } |
880 | 960 |
881 static int | 961 static int |
882 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) | 962 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) |
883 { | 963 { |
884 depth++; | 964 while (internal_equal (XCAR (ob1), XCAR (ob2), depth + 1)) |
885 while (internal_equal (XCAR (ob1), XCAR (ob2), depth)) | |
886 { | 965 { |
887 ob1 = XCDR (ob1); | 966 ob1 = XCDR (ob1); |
888 ob2 = XCDR (ob2); | 967 ob2 = XCDR (ob2); |
889 if (! CONSP (ob1) || ! CONSP (ob2)) | 968 if (! CONSP (ob1) || ! CONSP (ob2)) |
890 return internal_equal (ob1, ob2, depth); | 969 return internal_equal (ob1, ob2, depth + 1); |
891 } | 970 } |
892 return 0; | 971 return 0; |
893 } | 972 } |
894 | |
895 static const struct lrecord_description cons_description[] = { | |
896 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car) }, | |
897 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr) }, | |
898 { XD_END } | |
899 }; | |
900 | 973 |
901 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("cons", cons, | 974 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("cons", cons, |
902 mark_cons, print_cons, 0, | 975 mark_cons, print_cons, 0, |
903 cons_equal, | 976 cons_equal, |
904 /* | 977 /* |
905 * No `hash' method needed. | 978 * No `hash' method needed. |
906 * internal_hash knows how to | 979 * internal_hash knows how to |
907 * handle conses. | 980 * handle conses. |
908 */ | 981 */ |
909 0, | 982 0, |
910 cons_description, | 983 struct Lisp_Cons); |
911 Lisp_Cons); | |
912 | 984 |
913 DEFUN ("cons", Fcons, 2, 2, 0, /* | 985 DEFUN ("cons", Fcons, 2, 2, 0, /* |
914 Create a new cons, give it CAR and CDR as components, and return it. | 986 Create a new cons, give it CAR and CDR as components, and return it. |
915 */ | 987 */ |
916 (car, cdr)) | 988 (car, cdr)) |
917 { | 989 { |
918 /* This cannot GC. */ | 990 /* This cannot GC. */ |
919 Lisp_Object val; | 991 Lisp_Object val; |
920 Lisp_Cons *c; | 992 struct Lisp_Cons *c; |
921 | 993 |
922 ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); | 994 ALLOCATE_FIXED_TYPE (cons, struct Lisp_Cons, c); |
923 set_lheader_implementation (&c->lheader, &lrecord_cons); | 995 set_lheader_implementation (&(c->lheader), &lrecord_cons); |
924 XSETCONS (val, c); | 996 XSETCONS (val, c); |
925 c->car = car; | 997 c->car = car; |
926 c->cdr = cdr; | 998 c->cdr = cdr; |
927 return val; | 999 return val; |
928 } | 1000 } |
932 "real" consing. */ | 1004 "real" consing. */ |
933 Lisp_Object | 1005 Lisp_Object |
934 noseeum_cons (Lisp_Object car, Lisp_Object cdr) | 1006 noseeum_cons (Lisp_Object car, Lisp_Object cdr) |
935 { | 1007 { |
936 Lisp_Object val; | 1008 Lisp_Object val; |
937 Lisp_Cons *c; | 1009 struct Lisp_Cons *c; |
938 | 1010 |
939 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); | 1011 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, struct Lisp_Cons, c); |
940 set_lheader_implementation (&c->lheader, &lrecord_cons); | 1012 set_lheader_implementation (&(c->lheader), &lrecord_cons); |
941 XSETCONS (val, c); | 1013 XSETCONS (val, c); |
942 XCAR (val) = car; | 1014 XCAR (val) = car; |
943 XCDR (val) = cdr; | 1015 XCDR (val) = cdr; |
944 return val; | 1016 return val; |
945 } | 1017 } |
1022 { | 1094 { |
1023 CHECK_NATNUM (length); | 1095 CHECK_NATNUM (length); |
1024 | 1096 |
1025 { | 1097 { |
1026 Lisp_Object val = Qnil; | 1098 Lisp_Object val = Qnil; |
1027 size_t size = XINT (length); | 1099 int size = XINT (length); |
1028 | 1100 |
1029 while (size--) | 1101 while (size-- > 0) |
1030 val = Fcons (init, val); | 1102 val = Fcons (init, val); |
1031 return val; | 1103 return val; |
1032 } | 1104 } |
1033 } | 1105 } |
1034 | 1106 |
1037 /* Float allocation */ | 1109 /* Float allocation */ |
1038 /************************************************************************/ | 1110 /************************************************************************/ |
1039 | 1111 |
1040 #ifdef LISP_FLOAT_TYPE | 1112 #ifdef LISP_FLOAT_TYPE |
1041 | 1113 |
1042 DECLARE_FIXED_TYPE_ALLOC (float, Lisp_Float); | 1114 DECLARE_FIXED_TYPE_ALLOC (float, struct Lisp_Float); |
1043 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_float 1000 | 1115 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_float 1000 |
1044 | 1116 |
1045 Lisp_Object | 1117 Lisp_Object |
1046 make_float (double float_value) | 1118 make_float (double float_value) |
1047 { | 1119 { |
1048 Lisp_Object val; | 1120 Lisp_Object val; |
1049 Lisp_Float *f; | 1121 struct Lisp_Float *f; |
1050 | 1122 |
1051 ALLOCATE_FIXED_TYPE (float, Lisp_Float, f); | 1123 ALLOCATE_FIXED_TYPE (float, struct Lisp_Float, f); |
1052 | 1124 set_lheader_implementation (&(f->lheader), &lrecord_float); |
1053 /* Avoid dump-time `uninitialized memory read' purify warnings. */ | |
1054 if (sizeof (struct lrecord_header) + sizeof (double) != sizeof (*f)) | |
1055 xzero (*f); | |
1056 | |
1057 set_lheader_implementation (&f->lheader, &lrecord_float); | |
1058 float_data (f) = float_value; | 1125 float_data (f) = float_value; |
1059 XSETFLOAT (val, f); | 1126 XSETFLOAT (val, f); |
1060 return val; | 1127 return val; |
1061 } | 1128 } |
1062 | 1129 |
1066 /************************************************************************/ | 1133 /************************************************************************/ |
1067 /* Vector allocation */ | 1134 /* Vector allocation */ |
1068 /************************************************************************/ | 1135 /************************************************************************/ |
1069 | 1136 |
1070 static Lisp_Object | 1137 static Lisp_Object |
1071 mark_vector (Lisp_Object obj) | 1138 mark_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
1072 { | 1139 { |
1073 Lisp_Vector *ptr = XVECTOR (obj); | 1140 Lisp_Vector *ptr = XVECTOR (obj); |
1074 int len = vector_length (ptr); | 1141 int len = vector_length (ptr); |
1075 int i; | 1142 int i; |
1076 | 1143 |
1077 for (i = 0; i < len - 1; i++) | 1144 for (i = 0; i < len - 1; i++) |
1078 mark_object (ptr->contents[i]); | 1145 markobj (ptr->contents[i]); |
1079 return (len > 0) ? ptr->contents[len - 1] : Qnil; | 1146 return (len > 0) ? ptr->contents[len - 1] : Qnil; |
1080 } | 1147 } |
1081 | 1148 |
1082 static size_t | 1149 static size_t |
1083 size_vector (const void *lheader) | 1150 size_vector (CONST void *lheader) |
1084 { | 1151 { |
1085 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Vector, contents, | 1152 return STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, |
1086 ((Lisp_Vector *) lheader)->size); | 1153 ((Lisp_Vector *) lheader)->size); |
1087 } | 1154 } |
1088 | 1155 |
1089 static int | 1156 static int |
1090 vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) | 1157 vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) |
1091 { | 1158 { |
1101 return 0; | 1168 return 0; |
1102 } | 1169 } |
1103 return 1; | 1170 return 1; |
1104 } | 1171 } |
1105 | 1172 |
1106 static hashcode_t | |
1107 vector_hash (Lisp_Object obj, int depth) | |
1108 { | |
1109 return HASH2 (XVECTOR_LENGTH (obj), | |
1110 internal_array_hash (XVECTOR_DATA (obj), | |
1111 XVECTOR_LENGTH (obj), | |
1112 depth + 1)); | |
1113 } | |
1114 | |
1115 static const struct lrecord_description vector_description[] = { | |
1116 { XD_LONG, offsetof (Lisp_Vector, size) }, | |
1117 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Vector, contents), XD_INDIRECT(0, 0) }, | |
1118 { XD_END } | |
1119 }; | |
1120 | |
1121 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector, | 1173 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector, |
1122 mark_vector, print_vector, 0, | 1174 mark_vector, print_vector, 0, |
1123 vector_equal, | 1175 vector_equal, |
1124 vector_hash, | 1176 /* |
1125 vector_description, | 1177 * No `hash' method needed for |
1178 * vectors. internal_hash | |
1179 * knows how to handle vectors. | |
1180 */ | |
1181 0, | |
1126 size_vector, Lisp_Vector); | 1182 size_vector, Lisp_Vector); |
1127 | 1183 |
1128 /* #### should allocate `small' vectors from a frob-block */ | 1184 /* #### should allocate `small' vectors from a frob-block */ |
1129 static Lisp_Vector * | 1185 static Lisp_Vector * |
1130 make_vector_internal (size_t sizei) | 1186 make_vector_internal (size_t sizei) |
1131 { | 1187 { |
1132 /* no vector_next */ | 1188 /* no vector_next */ |
1133 size_t sizem = FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Vector, contents, sizei); | 1189 size_t sizem = STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, sizei); |
1134 Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord (sizem, &lrecord_vector); | 1190 Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord (sizem, &lrecord_vector); |
1135 | 1191 |
1136 p->size = sizei; | 1192 p->size = sizei; |
1137 return p; | 1193 return p; |
1138 } | 1194 } |
1287 /************************************************************************/ | 1343 /************************************************************************/ |
1288 | 1344 |
1289 static Lisp_Object all_bit_vectors; | 1345 static Lisp_Object all_bit_vectors; |
1290 | 1346 |
1291 /* #### should allocate `small' bit vectors from a frob-block */ | 1347 /* #### should allocate `small' bit vectors from a frob-block */ |
1292 static Lisp_Bit_Vector * | 1348 static struct Lisp_Bit_Vector * |
1293 make_bit_vector_internal (size_t sizei) | 1349 make_bit_vector_internal (size_t sizei) |
1294 { | 1350 { |
1295 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei); | 1351 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei); |
1296 size_t sizem = FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, num_longs); | 1352 size_t sizem = STRETCHY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, num_longs); |
1297 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem); | 1353 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem); |
1298 set_lheader_implementation (&p->lheader, &lrecord_bit_vector); | 1354 set_lheader_implementation (&(p->lheader), &lrecord_bit_vector); |
1299 | 1355 |
1300 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); | 1356 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); |
1301 | 1357 |
1302 bit_vector_length (p) = sizei; | 1358 bit_vector_length (p) = sizei; |
1303 bit_vector_next (p) = all_bit_vectors; | 1359 bit_vector_next (p) = all_bit_vectors; |
1309 } | 1365 } |
1310 | 1366 |
1311 Lisp_Object | 1367 Lisp_Object |
1312 make_bit_vector (size_t length, Lisp_Object init) | 1368 make_bit_vector (size_t length, Lisp_Object init) |
1313 { | 1369 { |
1314 Lisp_Bit_Vector *p = make_bit_vector_internal (length); | 1370 struct Lisp_Bit_Vector *p = make_bit_vector_internal (length); |
1315 size_t num_longs = BIT_VECTOR_LONG_STORAGE (length); | 1371 size_t num_longs = BIT_VECTOR_LONG_STORAGE (length); |
1316 | 1372 |
1317 CHECK_BIT (init); | 1373 CHECK_BIT (init); |
1318 | 1374 |
1319 if (ZEROP (init)) | 1375 if (ZEROP (init)) |
1397 { | 1453 { |
1398 Lisp_Compiled_Function *f; | 1454 Lisp_Compiled_Function *f; |
1399 Lisp_Object fun; | 1455 Lisp_Object fun; |
1400 | 1456 |
1401 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f); | 1457 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f); |
1402 set_lheader_implementation (&f->lheader, &lrecord_compiled_function); | 1458 set_lheader_implementation (&(f->lheader), &lrecord_compiled_function); |
1403 | 1459 |
1404 f->stack_depth = 0; | 1460 f->stack_depth = 0; |
1405 f->specpdl_depth = 0; | 1461 f->specpdl_depth = 0; |
1406 f->flags.documentationp = 0; | 1462 f->flags.documentationp = 0; |
1407 f->flags.interactivep = 0; | 1463 f->flags.interactivep = 0; |
1481 if (!NILP (constants)) | 1537 if (!NILP (constants)) |
1482 CHECK_VECTOR (constants); | 1538 CHECK_VECTOR (constants); |
1483 f->constants = constants; | 1539 f->constants = constants; |
1484 | 1540 |
1485 CHECK_NATNUM (stack_depth); | 1541 CHECK_NATNUM (stack_depth); |
1486 f->stack_depth = (unsigned short) XINT (stack_depth); | 1542 f->stack_depth = XINT (stack_depth); |
1487 | 1543 |
1488 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK | 1544 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK |
1489 if (!NILP (Vcurrent_compiled_function_annotation)) | 1545 if (!NILP (Vcurrent_compiled_function_annotation)) |
1490 f->annotated = Fcopy (Vcurrent_compiled_function_annotation); | 1546 f->annotated = Fcopy (Vcurrent_compiled_function_annotation); |
1491 else if (!NILP (Vload_file_name_internal_the_purecopy)) | 1547 else if (!NILP (Vload_file_name_internal_the_purecopy)) |
1493 else if (!NILP (Vload_file_name_internal)) | 1549 else if (!NILP (Vload_file_name_internal)) |
1494 { | 1550 { |
1495 struct gcpro gcpro1; | 1551 struct gcpro gcpro1; |
1496 GCPRO1 (fun); /* don't let fun get reaped */ | 1552 GCPRO1 (fun); /* don't let fun get reaped */ |
1497 Vload_file_name_internal_the_purecopy = | 1553 Vload_file_name_internal_the_purecopy = |
1498 Ffile_name_nondirectory (Vload_file_name_internal); | 1554 Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); |
1499 f->annotated = Vload_file_name_internal_the_purecopy; | 1555 f->annotated = Vload_file_name_internal_the_purecopy; |
1500 UNGCPRO; | 1556 UNGCPRO; |
1501 } | 1557 } |
1502 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ | 1558 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ |
1503 | 1559 |
1529 | 1585 |
1530 /************************************************************************/ | 1586 /************************************************************************/ |
1531 /* Symbol allocation */ | 1587 /* Symbol allocation */ |
1532 /************************************************************************/ | 1588 /************************************************************************/ |
1533 | 1589 |
1534 DECLARE_FIXED_TYPE_ALLOC (symbol, Lisp_Symbol); | 1590 DECLARE_FIXED_TYPE_ALLOC (symbol, struct Lisp_Symbol); |
1535 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_symbol 1000 | 1591 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_symbol 1000 |
1536 | 1592 |
1537 DEFUN ("make-symbol", Fmake_symbol, 1, 1, 0, /* | 1593 DEFUN ("make-symbol", Fmake_symbol, 1, 1, 0, /* |
1538 Return a newly allocated uninterned symbol whose name is NAME. | 1594 Return a newly allocated uninterned symbol whose name is NAME. |
1539 Its value and function definition are void, and its property list is nil. | 1595 Its value and function definition are void, and its property list is nil. |
1540 */ | 1596 */ |
1541 (name)) | 1597 (name)) |
1542 { | 1598 { |
1543 Lisp_Object val; | 1599 Lisp_Object val; |
1544 Lisp_Symbol *p; | 1600 struct Lisp_Symbol *p; |
1545 | 1601 |
1546 CHECK_STRING (name); | 1602 CHECK_STRING (name); |
1547 | 1603 |
1548 ALLOCATE_FIXED_TYPE (symbol, Lisp_Symbol, p); | 1604 ALLOCATE_FIXED_TYPE (symbol, struct Lisp_Symbol, p); |
1549 set_lheader_implementation (&p->lheader, &lrecord_symbol); | 1605 set_lheader_implementation (&(p->lheader), &lrecord_symbol); |
1550 p->name = XSTRING (name); | 1606 p->name = XSTRING (name); |
1551 p->plist = Qnil; | 1607 p->plist = Qnil; |
1552 p->value = Qunbound; | 1608 p->value = Qunbound; |
1553 p->function = Qunbound; | 1609 p->function = Qunbound; |
1554 symbol_next (p) = 0; | 1610 symbol_next (p) = 0; |
1568 allocate_extent (void) | 1624 allocate_extent (void) |
1569 { | 1625 { |
1570 struct extent *e; | 1626 struct extent *e; |
1571 | 1627 |
1572 ALLOCATE_FIXED_TYPE (extent, struct extent, e); | 1628 ALLOCATE_FIXED_TYPE (extent, struct extent, e); |
1573 set_lheader_implementation (&e->lheader, &lrecord_extent); | 1629 set_lheader_implementation (&(e->lheader), &lrecord_extent); |
1574 extent_object (e) = Qnil; | 1630 extent_object (e) = Qnil; |
1575 set_extent_start (e, -1); | 1631 set_extent_start (e, -1); |
1576 set_extent_end (e, -1); | 1632 set_extent_end (e, -1); |
1577 e->plist = Qnil; | 1633 e->plist = Qnil; |
1578 | 1634 |
1588 | 1644 |
1589 /************************************************************************/ | 1645 /************************************************************************/ |
1590 /* Event allocation */ | 1646 /* Event allocation */ |
1591 /************************************************************************/ | 1647 /************************************************************************/ |
1592 | 1648 |
1593 DECLARE_FIXED_TYPE_ALLOC (event, Lisp_Event); | 1649 DECLARE_FIXED_TYPE_ALLOC (event, struct Lisp_Event); |
1594 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_event 1000 | 1650 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_event 1000 |
1595 | 1651 |
1596 Lisp_Object | 1652 Lisp_Object |
1597 allocate_event (void) | 1653 allocate_event (void) |
1598 { | 1654 { |
1599 Lisp_Object val; | 1655 Lisp_Object val; |
1600 Lisp_Event *e; | 1656 struct Lisp_Event *e; |
1601 | 1657 |
1602 ALLOCATE_FIXED_TYPE (event, Lisp_Event, e); | 1658 ALLOCATE_FIXED_TYPE (event, struct Lisp_Event, e); |
1603 set_lheader_implementation (&e->lheader, &lrecord_event); | 1659 set_lheader_implementation (&(e->lheader), &lrecord_event); |
1604 | 1660 |
1605 XSETEVENT (val, e); | 1661 XSETEVENT (val, e); |
1606 return val; | 1662 return val; |
1607 } | 1663 } |
1608 | 1664 |
1609 | 1665 |
1610 /************************************************************************/ | 1666 /************************************************************************/ |
1611 /* Marker allocation */ | 1667 /* Marker allocation */ |
1612 /************************************************************************/ | 1668 /************************************************************************/ |
1613 | 1669 |
1614 DECLARE_FIXED_TYPE_ALLOC (marker, Lisp_Marker); | 1670 DECLARE_FIXED_TYPE_ALLOC (marker, struct Lisp_Marker); |
1615 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_marker 1000 | 1671 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_marker 1000 |
1616 | 1672 |
1617 DEFUN ("make-marker", Fmake_marker, 0, 0, 0, /* | 1673 DEFUN ("make-marker", Fmake_marker, 0, 0, 0, /* |
1618 Return a new marker which does not point at any place. | 1674 Return a new marker which does not point at any place. |
1619 */ | 1675 */ |
1620 ()) | 1676 ()) |
1621 { | 1677 { |
1622 Lisp_Object val; | 1678 Lisp_Object val; |
1623 Lisp_Marker *p; | 1679 struct Lisp_Marker *p; |
1624 | 1680 |
1625 ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); | 1681 ALLOCATE_FIXED_TYPE (marker, struct Lisp_Marker, p); |
1626 set_lheader_implementation (&p->lheader, &lrecord_marker); | 1682 set_lheader_implementation (&(p->lheader), &lrecord_marker); |
1627 p->buffer = 0; | 1683 p->buffer = 0; |
1628 p->memind = 0; | 1684 p->memind = 0; |
1629 marker_next (p) = 0; | 1685 marker_next (p) = 0; |
1630 marker_prev (p) = 0; | 1686 marker_prev (p) = 0; |
1631 p->insertion_type = 0; | 1687 p->insertion_type = 0; |
1635 | 1691 |
1636 Lisp_Object | 1692 Lisp_Object |
1637 noseeum_make_marker (void) | 1693 noseeum_make_marker (void) |
1638 { | 1694 { |
1639 Lisp_Object val; | 1695 Lisp_Object val; |
1640 Lisp_Marker *p; | 1696 struct Lisp_Marker *p; |
1641 | 1697 |
1642 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); | 1698 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, struct Lisp_Marker, p); |
1643 set_lheader_implementation (&p->lheader, &lrecord_marker); | 1699 set_lheader_implementation (&(p->lheader), &lrecord_marker); |
1644 p->buffer = 0; | 1700 p->buffer = 0; |
1645 p->memind = 0; | 1701 p->memind = 0; |
1646 marker_next (p) = 0; | 1702 marker_next (p) = 0; |
1647 marker_prev (p) = 0; | 1703 marker_prev (p) = 0; |
1648 p->insertion_type = 0; | 1704 p->insertion_type = 0; |
1666 strings (since EVERY REFERENCE to a short string needed to be GCPRO'd so | 1722 strings (since EVERY REFERENCE to a short string needed to be GCPRO'd so |
1667 that the reference would get relocated). | 1723 that the reference would get relocated). |
1668 | 1724 |
1669 This new method makes things somewhat bigger, but it is MUCH safer. */ | 1725 This new method makes things somewhat bigger, but it is MUCH safer. */ |
1670 | 1726 |
1671 DECLARE_FIXED_TYPE_ALLOC (string, Lisp_String); | 1727 DECLARE_FIXED_TYPE_ALLOC (string, struct Lisp_String); |
1672 /* strings are used and freed quite often */ | 1728 /* strings are used and freed quite often */ |
1673 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */ | 1729 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */ |
1674 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000 | 1730 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000 |
1675 | 1731 |
1676 static Lisp_Object | 1732 static Lisp_Object |
1677 mark_string (Lisp_Object obj) | 1733 mark_string (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
1678 { | 1734 { |
1679 Lisp_String *ptr = XSTRING (obj); | 1735 struct Lisp_String *ptr = XSTRING (obj); |
1680 | 1736 |
1681 if (CONSP (ptr->plist) && EXTENT_INFOP (XCAR (ptr->plist))) | 1737 if (GC_CONSP (ptr->plist) && GC_EXTENT_INFOP (XCAR (ptr->plist))) |
1682 flush_cached_extent_info (XCAR (ptr->plist)); | 1738 flush_cached_extent_info (XCAR (ptr->plist)); |
1683 return ptr->plist; | 1739 return ptr->plist; |
1684 } | 1740 } |
1685 | 1741 |
1686 static int | 1742 static int |
1689 Bytecount len; | 1745 Bytecount len; |
1690 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && | 1746 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && |
1691 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); | 1747 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); |
1692 } | 1748 } |
1693 | 1749 |
1694 static const struct lrecord_description string_description[] = { | 1750 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string, |
1695 { XD_BYTECOUNT, offsetof (Lisp_String, size) }, | 1751 mark_string, print_string, |
1696 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT(0, 1) }, | 1752 /* |
1697 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, | 1753 * No `finalize', or `hash' methods. |
1698 { XD_END } | 1754 * internal_hash already knows how |
1699 }; | 1755 * to hash strings and finalization |
1700 | 1756 * is done with the |
1701 /* We store the string's extent info as the first element of the string's | 1757 * ADDITIONAL_FREE_string macro, |
1702 property list; and the string's MODIFF as the first or second element | 1758 * which is the standard way to do |
1703 of the string's property list (depending on whether the extent info | 1759 * finalization when using |
1704 is present), but only if the string has been modified. This is ugly | 1760 * SWEEP_FIXED_TYPE_BLOCK(). |
1705 but it reduces the memory allocated for the string in the vast | 1761 */ |
1706 majority of cases, where the string is never modified and has no | 1762 0, string_equal, 0, |
1707 extent info. | 1763 struct Lisp_String); |
1708 | |
1709 #### This means you can't use an int as a key in a string's plist. */ | |
1710 | |
1711 static Lisp_Object * | |
1712 string_plist_ptr (Lisp_Object string) | |
1713 { | |
1714 Lisp_Object *ptr = &XSTRING (string)->plist; | |
1715 | |
1716 if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr))) | |
1717 ptr = &XCDR (*ptr); | |
1718 if (CONSP (*ptr) && INTP (XCAR (*ptr))) | |
1719 ptr = &XCDR (*ptr); | |
1720 return ptr; | |
1721 } | |
1722 | |
1723 static Lisp_Object | |
1724 string_getprop (Lisp_Object string, Lisp_Object property) | |
1725 { | |
1726 return external_plist_get (string_plist_ptr (string), property, 0, ERROR_ME); | |
1727 } | |
1728 | |
1729 static int | |
1730 string_putprop (Lisp_Object string, Lisp_Object property, Lisp_Object value) | |
1731 { | |
1732 external_plist_put (string_plist_ptr (string), property, value, 0, ERROR_ME); | |
1733 return 1; | |
1734 } | |
1735 | |
1736 static int | |
1737 string_remprop (Lisp_Object string, Lisp_Object property) | |
1738 { | |
1739 return external_remprop (string_plist_ptr (string), property, 0, ERROR_ME); | |
1740 } | |
1741 | |
1742 static Lisp_Object | |
1743 string_plist (Lisp_Object string) | |
1744 { | |
1745 return *string_plist_ptr (string); | |
1746 } | |
1747 | |
1748 /* No `finalize', or `hash' methods. | |
1749 internal_hash() already knows how to hash strings and finalization | |
1750 is done with the ADDITIONAL_FREE_string macro, which is the | |
1751 standard way to do finalization when using | |
1752 SWEEP_FIXED_TYPE_BLOCK(). */ | |
1753 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS ("string", string, | |
1754 mark_string, print_string, | |
1755 0, string_equal, 0, | |
1756 string_description, | |
1757 string_getprop, | |
1758 string_putprop, | |
1759 string_remprop, | |
1760 string_plist, | |
1761 Lisp_String); | |
1762 | 1764 |
1763 /* String blocks contain this many useful bytes. */ | 1765 /* String blocks contain this many useful bytes. */ |
1764 #define STRING_CHARS_BLOCK_SIZE \ | 1766 #define STRING_CHARS_BLOCK_SIZE \ |
1765 ((Bytecount) (8192 - MALLOC_OVERHEAD - \ | 1767 ((Bytecount) (8192 - MALLOC_OVERHEAD - \ |
1766 ((2 * sizeof (struct string_chars_block *)) \ | 1768 ((2 * sizeof (struct string_chars_block *)) \ |
1774 /* Contents of string_chars_block->string_chars are interleaved | 1776 /* Contents of string_chars_block->string_chars are interleaved |
1775 string_chars structures (see below) and the actual string data */ | 1777 string_chars structures (see below) and the actual string data */ |
1776 unsigned char string_chars[STRING_CHARS_BLOCK_SIZE]; | 1778 unsigned char string_chars[STRING_CHARS_BLOCK_SIZE]; |
1777 }; | 1779 }; |
1778 | 1780 |
1779 static struct string_chars_block *first_string_chars_block; | 1781 struct string_chars_block *first_string_chars_block; |
1780 static struct string_chars_block *current_string_chars_block; | 1782 struct string_chars_block *current_string_chars_block; |
1781 | 1783 |
1782 /* If SIZE is the length of a string, this returns how many bytes | 1784 /* If SIZE is the length of a string, this returns how many bytes |
1783 * the string occupies in string_chars_block->string_chars | 1785 * the string occupies in string_chars_block->string_chars |
1784 * (including alignment padding). | 1786 * (including alignment padding). |
1785 */ | 1787 */ |
1786 #define STRING_FULLSIZE(size) \ | 1788 #define STRING_FULLSIZE(s) \ |
1787 ALIGN_SIZE (((size) + 1 + sizeof (Lisp_String *)),\ | 1789 ALIGN_SIZE (((s) + 1 + sizeof (struct Lisp_String *)),\ |
1788 ALIGNOF (Lisp_String *)) | 1790 ALIGNOF (struct Lisp_String *)) |
1789 | 1791 |
1790 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) | 1792 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) |
1791 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) | 1793 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) |
1792 | 1794 |
1795 #define CHARS_TO_STRING_CHAR(x) \ | |
1796 ((struct string_chars *) \ | |
1797 (((char *) (x)) - (slot_offset (struct string_chars, chars[0])))) | |
1798 | |
1799 | |
1793 struct string_chars | 1800 struct string_chars |
1794 { | 1801 { |
1795 Lisp_String *string; | 1802 struct Lisp_String *string; |
1796 unsigned char chars[1]; | 1803 unsigned char chars[1]; |
1797 }; | 1804 }; |
1798 | 1805 |
1799 struct unused_string_chars | 1806 struct unused_string_chars |
1800 { | 1807 { |
1801 Lisp_String *string; | 1808 struct Lisp_String *string; |
1802 EMACS_INT fullsize; | 1809 EMACS_INT fullsize; |
1803 }; | 1810 }; |
1804 | 1811 |
1805 static void | 1812 static void |
1806 init_string_chars_alloc (void) | 1813 init_string_chars_alloc (void) |
1811 first_string_chars_block->pos = 0; | 1818 first_string_chars_block->pos = 0; |
1812 current_string_chars_block = first_string_chars_block; | 1819 current_string_chars_block = first_string_chars_block; |
1813 } | 1820 } |
1814 | 1821 |
1815 static struct string_chars * | 1822 static struct string_chars * |
1816 allocate_string_chars_struct (Lisp_String *string_it_goes_with, | 1823 allocate_string_chars_struct (struct Lisp_String *string_it_goes_with, |
1817 EMACS_INT fullsize) | 1824 EMACS_INT fullsize) |
1818 { | 1825 { |
1819 struct string_chars *s_chars; | 1826 struct string_chars *s_chars; |
1820 | 1827 |
1821 if (fullsize <= | 1828 /* Allocate the string's actual data */ |
1822 (countof (current_string_chars_block->string_chars) | 1829 if (BIG_STRING_FULLSIZE_P (fullsize)) |
1823 - current_string_chars_block->pos)) | 1830 { |
1831 s_chars = (struct string_chars *) xmalloc (fullsize); | |
1832 } | |
1833 else if (fullsize <= | |
1834 (countof (current_string_chars_block->string_chars) | |
1835 - current_string_chars_block->pos)) | |
1824 { | 1836 { |
1825 /* This string can fit in the current string chars block */ | 1837 /* This string can fit in the current string chars block */ |
1826 s_chars = (struct string_chars *) | 1838 s_chars = (struct string_chars *) |
1827 (current_string_chars_block->string_chars | 1839 (current_string_chars_block->string_chars |
1828 + current_string_chars_block->pos); | 1840 + current_string_chars_block->pos); |
1850 } | 1862 } |
1851 | 1863 |
1852 Lisp_Object | 1864 Lisp_Object |
1853 make_uninit_string (Bytecount length) | 1865 make_uninit_string (Bytecount length) |
1854 { | 1866 { |
1855 Lisp_String *s; | 1867 struct Lisp_String *s; |
1868 struct string_chars *s_chars; | |
1856 EMACS_INT fullsize = STRING_FULLSIZE (length); | 1869 EMACS_INT fullsize = STRING_FULLSIZE (length); |
1857 Lisp_Object val; | 1870 Lisp_Object val; |
1858 | 1871 |
1859 assert (length >= 0 && fullsize > 0); | 1872 if ((length < 0) || (fullsize <= 0)) |
1873 abort (); | |
1860 | 1874 |
1861 /* Allocate the string header */ | 1875 /* Allocate the string header */ |
1862 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); | 1876 ALLOCATE_FIXED_TYPE (string, struct Lisp_String, s); |
1863 set_lheader_implementation (&s->lheader, &lrecord_string); | 1877 set_lheader_implementation (&(s->lheader), &lrecord_string); |
1864 | 1878 |
1865 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize) | 1879 s_chars = allocate_string_chars_struct (s, fullsize); |
1866 ? xnew_array (Bufbyte, length + 1) | 1880 |
1867 : allocate_string_chars_struct (s, fullsize)->chars); | 1881 set_string_data (s, &(s_chars->chars[0])); |
1868 | |
1869 set_string_length (s, length); | 1882 set_string_length (s, length); |
1870 s->plist = Qnil; | 1883 s->plist = Qnil; |
1871 | 1884 |
1872 set_string_byte (s, length, 0); | 1885 set_string_byte (s, length, 0); |
1873 | 1886 |
1884 POS < 0, resize the string but don't copy any characters. Use | 1897 POS < 0, resize the string but don't copy any characters. Use |
1885 this if you're planning on completely overwriting the string. | 1898 this if you're planning on completely overwriting the string. |
1886 */ | 1899 */ |
1887 | 1900 |
1888 void | 1901 void |
1889 resize_string (Lisp_String *s, Bytecount pos, Bytecount delta) | 1902 resize_string (struct Lisp_String *s, Bytecount pos, Bytecount delta) |
1890 { | 1903 { |
1891 Bytecount oldfullsize, newfullsize; | |
1892 #ifdef VERIFY_STRING_CHARS_INTEGRITY | 1904 #ifdef VERIFY_STRING_CHARS_INTEGRITY |
1893 verify_string_chars_integrity (); | 1905 verify_string_chars_integrity (); |
1894 #endif | 1906 #endif |
1895 | 1907 |
1896 #ifdef ERROR_CHECK_BUFPOS | 1908 #ifdef ERROR_CHECK_BUFPOS |
1905 if (delta < 0) | 1917 if (delta < 0) |
1906 assert ((-delta) <= string_length (s)); | 1918 assert ((-delta) <= string_length (s)); |
1907 } | 1919 } |
1908 #endif /* ERROR_CHECK_BUFPOS */ | 1920 #endif /* ERROR_CHECK_BUFPOS */ |
1909 | 1921 |
1922 if (pos >= 0 && delta < 0) | |
1923 /* If DELTA < 0, the functions below will delete the characters | |
1924 before POS. We want to delete characters *after* POS, however, | |
1925 so convert this to the appropriate form. */ | |
1926 pos += -delta; | |
1927 | |
1910 if (delta == 0) | 1928 if (delta == 0) |
1911 /* simplest case: no size change. */ | 1929 /* simplest case: no size change. */ |
1912 return; | 1930 return; |
1913 | 1931 else |
1914 if (pos >= 0 && delta < 0) | 1932 { |
1915 /* If DELTA < 0, the functions below will delete the characters | 1933 Bytecount oldfullsize = STRING_FULLSIZE (string_length (s)); |
1916 before POS. We want to delete characters *after* POS, however, | 1934 Bytecount newfullsize = STRING_FULLSIZE (string_length (s) + delta); |
1917 so convert this to the appropriate form. */ | 1935 |
1918 pos += -delta; | 1936 if (oldfullsize == newfullsize) |
1919 | |
1920 oldfullsize = STRING_FULLSIZE (string_length (s)); | |
1921 newfullsize = STRING_FULLSIZE (string_length (s) + delta); | |
1922 | |
1923 if (BIG_STRING_FULLSIZE_P (oldfullsize)) | |
1924 { | |
1925 if (BIG_STRING_FULLSIZE_P (newfullsize)) | |
1926 { | 1937 { |
1927 /* Both strings are big. We can just realloc(). | 1938 /* next simplest case; size change but the necessary |
1928 But careful! If the string is shrinking, we have to | 1939 allocation size won't change (up or down; code somewhere |
1929 memmove() _before_ realloc(), and if growing, we have to | 1940 depends on there not being any unused allocation space, |
1930 memmove() _after_ realloc() - otherwise the access is | 1941 modulo any alignment constraints). */ |
1931 illegal, and we might crash. */ | |
1932 Bytecount len = string_length (s) + 1 - pos; | |
1933 | |
1934 if (delta < 0 && pos >= 0) | |
1935 memmove (string_data (s) + pos + delta, string_data (s) + pos, len); | |
1936 set_string_data (s, (Bufbyte *) xrealloc (string_data (s), | |
1937 string_length (s) + delta + 1)); | |
1938 if (delta > 0 && pos >= 0) | |
1939 memmove (string_data (s) + pos + delta, string_data (s) + pos, len); | |
1940 } | |
1941 else /* String has been demoted from BIG_STRING. */ | |
1942 { | |
1943 Bufbyte *new_data = | |
1944 allocate_string_chars_struct (s, newfullsize)->chars; | |
1945 Bufbyte *old_data = string_data (s); | |
1946 | |
1947 if (pos >= 0) | 1942 if (pos >= 0) |
1948 { | 1943 { |
1949 memcpy (new_data, old_data, pos); | 1944 Bufbyte *addroff = pos + string_data (s); |
1950 memcpy (new_data + pos + delta, old_data + pos, | 1945 |
1951 string_length (s) + 1 - pos); | 1946 memmove (addroff + delta, addroff, |
1947 /* +1 due to zero-termination. */ | |
1948 string_length (s) + 1 - pos); | |
1952 } | 1949 } |
1953 set_string_data (s, new_data); | |
1954 xfree (old_data); | |
1955 } | 1950 } |
1956 } | 1951 else if (BIG_STRING_FULLSIZE_P (oldfullsize) && |
1957 else /* old string is small */ | 1952 BIG_STRING_FULLSIZE_P (newfullsize)) |
1958 { | |
1959 if (oldfullsize == newfullsize) | |
1960 { | 1953 { |
1961 /* special case; size change but the necessary | 1954 /* next simplest case; the string is big enough to be malloc()ed |
1962 allocation size won't change (up or down; code | 1955 itself, so we just realloc. |
1963 somewhere depends on there not being any unused | 1956 |
1964 allocation space, modulo any alignment | 1957 It's important not to let the string get below the threshold |
1965 constraints). */ | 1958 for making big strings and still remain malloc()ed; if that |
1959 were the case, repeated calls to this function on the same | |
1960 string could result in memory leakage. */ | |
1961 set_string_data (s, (Bufbyte *) xrealloc (string_data (s), | |
1962 newfullsize)); | |
1966 if (pos >= 0) | 1963 if (pos >= 0) |
1967 { | 1964 { |
1968 Bufbyte *addroff = pos + string_data (s); | 1965 Bufbyte *addroff = pos + string_data (s); |
1969 | 1966 |
1970 memmove (addroff + delta, addroff, | 1967 memmove (addroff + delta, addroff, |
1972 string_length (s) + 1 - pos); | 1969 string_length (s) + 1 - pos); |
1973 } | 1970 } |
1974 } | 1971 } |
1975 else | 1972 else |
1976 { | 1973 { |
1977 Bufbyte *old_data = string_data (s); | 1974 /* worst case. We make a new string_chars struct and copy |
1978 Bufbyte *new_data = | 1975 the string's data into it, inserting/deleting the delta |
1979 BIG_STRING_FULLSIZE_P (newfullsize) | 1976 in the process. The old string data will either get |
1980 ? xnew_array (Bufbyte, string_length (s) + delta + 1) | 1977 freed by us (if it was malloc()ed) or will be reclaimed |
1981 : allocate_string_chars_struct (s, newfullsize)->chars; | 1978 in the normal course of garbage collection. */ |
1982 | 1979 struct string_chars *s_chars = |
1980 allocate_string_chars_struct (s, newfullsize); | |
1981 Bufbyte *new_addr = &(s_chars->chars[0]); | |
1982 Bufbyte *old_addr = string_data (s); | |
1983 if (pos >= 0) | 1983 if (pos >= 0) |
1984 { | 1984 { |
1985 memcpy (new_data, old_data, pos); | 1985 memcpy (new_addr, old_addr, pos); |
1986 memcpy (new_data + pos + delta, old_data + pos, | 1986 memcpy (new_addr + pos + delta, old_addr + pos, |
1987 string_length (s) + 1 - pos); | 1987 string_length (s) + 1 - pos); |
1988 } | 1988 } |
1989 set_string_data (s, new_data); | 1989 set_string_data (s, new_addr); |
1990 | 1990 if (BIG_STRING_FULLSIZE_P (oldfullsize)) |
1991 { | 1991 xfree (old_addr); |
1992 /* We need to mark this chunk of the string_chars_block | 1992 else |
1993 as unused so that compact_string_chars() doesn't | 1993 { |
1994 freak. */ | 1994 /* We need to mark this chunk of the string_chars_block |
1995 struct string_chars *old_s_chars = (struct string_chars *) | 1995 as unused so that compact_string_chars() doesn't |
1996 ((char *) old_data - offsetof (struct string_chars, chars)); | 1996 freak. */ |
1997 /* Sanity check to make sure we aren't hosed by strange | 1997 struct string_chars *old_s_chars = |
1998 alignment/padding. */ | 1998 (struct string_chars *) ((char *) old_addr - |
1999 assert (old_s_chars->string == s); | 1999 sizeof (struct Lisp_String *)); |
2000 MARK_STRUCT_AS_FREE (old_s_chars); | 2000 /* Sanity check to make sure we aren't hosed by strange |
2001 ((struct unused_string_chars *) old_s_chars)->fullsize = | 2001 alignment/padding. */ |
2002 oldfullsize; | 2002 assert (old_s_chars->string == s); |
2003 } | 2003 MARK_STRUCT_AS_FREE (old_s_chars); |
2004 ((struct unused_string_chars *) old_s_chars)->fullsize = | |
2005 oldfullsize; | |
2006 } | |
2004 } | 2007 } |
2005 } | 2008 |
2006 | 2009 set_string_length (s, string_length (s) + delta); |
2007 set_string_length (s, string_length (s) + delta); | 2010 /* If pos < 0, the string won't be zero-terminated. |
2008 /* If pos < 0, the string won't be zero-terminated. | 2011 Terminate now just to make sure. */ |
2009 Terminate now just to make sure. */ | 2012 string_data (s)[string_length (s)] = '\0'; |
2010 string_data (s)[string_length (s)] = '\0'; | 2013 |
2011 | 2014 if (pos >= 0) |
2012 if (pos >= 0) | 2015 { |
2013 { | 2016 Lisp_Object string; |
2014 Lisp_Object string; | 2017 |
2015 | 2018 XSETSTRING (string, s); |
2016 XSETSTRING (string, s); | 2019 /* We also have to adjust all of the extent indices after the |
2017 /* We also have to adjust all of the extent indices after the | 2020 place we did the change. We say "pos - 1" because |
2018 place we did the change. We say "pos - 1" because | 2021 adjust_extents() is exclusive of the starting position |
2019 adjust_extents() is exclusive of the starting position | 2022 passed to it. */ |
2020 passed to it. */ | 2023 adjust_extents (string, pos - 1, string_length (s), |
2021 adjust_extents (string, pos - 1, string_length (s), | 2024 delta); |
2022 delta); | 2025 } |
2023 } | 2026 } |
2024 | 2027 |
2025 #ifdef VERIFY_STRING_CHARS_INTEGRITY | 2028 #ifdef VERIFY_STRING_CHARS_INTEGRITY |
2026 verify_string_chars_integrity (); | 2029 verify_string_chars_integrity (); |
2027 #endif | 2030 #endif |
2028 } | 2031 } |
2029 | 2032 |
2030 #ifdef MULE | 2033 #ifdef MULE |
2031 | 2034 |
2032 void | 2035 void |
2033 set_string_char (Lisp_String *s, Charcount i, Emchar c) | 2036 set_string_char (struct Lisp_String *s, Charcount i, Emchar c) |
2034 { | 2037 { |
2035 Bufbyte newstr[MAX_EMCHAR_LEN]; | 2038 Bufbyte newstr[MAX_EMCHAR_LEN]; |
2036 Bytecount bytoff = charcount_to_bytecount (string_data (s), i); | 2039 Bytecount bytoff = charcount_to_bytecount (string_data (s), i); |
2037 Bytecount oldlen = charcount_to_bytecount (string_data (s) + bytoff, 1); | 2040 Bytecount oldlen = charcount_to_bytecount (string_data (s) + bytoff, 1); |
2038 Bytecount newlen = set_charptr_emchar (newstr, c); | 2041 Bytecount newlen = set_charptr_emchar (newstr, c); |
2061 if (len == 1) | 2064 if (len == 1) |
2062 /* Optimize the single-byte case */ | 2065 /* Optimize the single-byte case */ |
2063 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); | 2066 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); |
2064 else | 2067 else |
2065 { | 2068 { |
2066 size_t i; | 2069 int i; |
2067 Bufbyte *ptr = XSTRING_DATA (val); | 2070 Bufbyte *ptr = XSTRING_DATA (val); |
2068 | 2071 |
2069 for (i = XINT (length); i; i--) | 2072 for (i = XINT (length); i; i--) |
2070 { | 2073 { |
2071 Bufbyte *init_ptr = init_str; | 2074 Bufbyte *init_ptr = init_str; |
2101 | 2104 |
2102 | 2105 |
2103 /* Take some raw memory, which MUST already be in internal format, | 2106 /* Take some raw memory, which MUST already be in internal format, |
2104 and package it up into a Lisp string. */ | 2107 and package it up into a Lisp string. */ |
2105 Lisp_Object | 2108 Lisp_Object |
2106 make_string (const Bufbyte *contents, Bytecount length) | 2109 make_string (CONST Bufbyte *contents, Bytecount length) |
2107 { | 2110 { |
2108 Lisp_Object val; | 2111 Lisp_Object val; |
2109 | 2112 |
2110 /* Make sure we find out about bad make_string's when they happen */ | 2113 /* Make sure we find out about bad make_string's when they happen */ |
2111 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) | 2114 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) |
2118 } | 2121 } |
2119 | 2122 |
2120 /* Take some raw memory, encoded in some external data format, | 2123 /* Take some raw memory, encoded in some external data format, |
2121 and convert it into a Lisp string. */ | 2124 and convert it into a Lisp string. */ |
2122 Lisp_Object | 2125 Lisp_Object |
2123 make_ext_string (const Extbyte *contents, EMACS_INT length, | 2126 make_ext_string (CONST Extbyte *contents, EMACS_INT length, |
2124 Lisp_Object coding_system) | 2127 enum external_data_format fmt) |
2125 { | 2128 { |
2126 Lisp_Object string; | 2129 Bufbyte *intstr; |
2127 TO_INTERNAL_FORMAT (DATA, (contents, length), | 2130 Bytecount intlen; |
2128 LISP_STRING, string, | 2131 |
2129 coding_system); | 2132 GET_CHARPTR_INT_DATA_ALLOCA (contents, length, fmt, intstr, intlen); |
2130 return string; | 2133 return make_string (intstr, intlen); |
2131 } | 2134 } |
2132 | 2135 |
2133 Lisp_Object | 2136 Lisp_Object |
2134 build_string (const char *str) | 2137 build_string (CONST char *str) |
2135 { | 2138 { |
2136 /* Some strlen's crash and burn if passed null. */ | 2139 /* Some strlen's crash and burn if passed null. */ |
2137 return make_string ((const Bufbyte *) str, (str ? strlen(str) : 0)); | 2140 return make_string ((CONST Bufbyte *) str, (str ? strlen(str) : 0)); |
2138 } | 2141 } |
2139 | 2142 |
2140 Lisp_Object | 2143 Lisp_Object |
2141 build_ext_string (const char *str, Lisp_Object coding_system) | 2144 build_ext_string (CONST char *str, enum external_data_format fmt) |
2142 { | 2145 { |
2143 /* Some strlen's crash and burn if passed null. */ | 2146 /* Some strlen's crash and burn if passed null. */ |
2144 return make_ext_string ((const Extbyte *) str, (str ? strlen(str) : 0), | 2147 return make_ext_string ((CONST Extbyte *) str, (str ? strlen(str) : 0), fmt); |
2145 coding_system); | |
2146 } | 2148 } |
2147 | 2149 |
2148 Lisp_Object | 2150 Lisp_Object |
2149 build_translated_string (const char *str) | 2151 build_translated_string (CONST char *str) |
2150 { | 2152 { |
2151 return build_string (GETTEXT (str)); | 2153 return build_string (GETTEXT (str)); |
2152 } | 2154 } |
2153 | 2155 |
2154 Lisp_Object | 2156 Lisp_Object |
2155 make_string_nocopy (const Bufbyte *contents, Bytecount length) | 2157 make_string_nocopy (CONST Bufbyte *contents, Bytecount length) |
2156 { | 2158 { |
2157 Lisp_String *s; | 2159 struct Lisp_String *s; |
2158 Lisp_Object val; | 2160 Lisp_Object val; |
2159 | 2161 |
2160 /* Make sure we find out about bad make_string_nocopy's when they happen */ | 2162 /* Make sure we find out about bad make_string_nocopy's when they happen */ |
2161 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) | 2163 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) |
2162 bytecount_to_charcount (contents, length); /* Just for the assertions */ | 2164 bytecount_to_charcount (contents, length); /* Just for the assertions */ |
2163 #endif | 2165 #endif |
2164 | 2166 |
2165 /* Allocate the string header */ | 2167 /* Allocate the string header */ |
2166 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); | 2168 ALLOCATE_FIXED_TYPE (string, struct Lisp_String, s); |
2167 set_lheader_implementation (&s->lheader, &lrecord_string); | 2169 set_lheader_implementation (&(s->lheader), &lrecord_string); |
2168 SET_C_READONLY_RECORD_HEADER (&s->lheader); | 2170 SET_C_READONLY_RECORD_HEADER (&s->lheader); |
2169 s->plist = Qnil; | 2171 s->plist = Qnil; |
2170 set_string_data (s, (Bufbyte *)contents); | 2172 set_string_data (s, (Bufbyte *)contents); |
2171 set_string_length (s, length); | 2173 set_string_length (s, length); |
2172 | 2174 |
2185 It is similar to the Blocktype class. | 2187 It is similar to the Blocktype class. |
2186 | 2188 |
2187 It works like this: | 2189 It works like this: |
2188 | 2190 |
2189 1) Create an lcrecord-list object using make_lcrecord_list(). | 2191 1) Create an lcrecord-list object using make_lcrecord_list(). |
2190 This is often done at initialization. Remember to staticpro_nodump | 2192 This is often done at initialization. Remember to staticpro |
2191 this object! The arguments to make_lcrecord_list() are the | 2193 this object! The arguments to make_lcrecord_list() are the |
2192 same as would be passed to alloc_lcrecord(). | 2194 same as would be passed to alloc_lcrecord(). |
2193 2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord() | 2195 2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord() |
2194 and pass the lcrecord-list earlier created. | 2196 and pass the lcrecord-list earlier created. |
2195 3) When done with the lcrecord, call free_managed_lcrecord(). | 2197 3) When done with the lcrecord, call free_managed_lcrecord(). |
2206 at the time that free_managed_lcrecord() is called. | 2208 at the time that free_managed_lcrecord() is called. |
2207 | 2209 |
2208 */ | 2210 */ |
2209 | 2211 |
2210 static Lisp_Object | 2212 static Lisp_Object |
2211 mark_lcrecord_list (Lisp_Object obj) | 2213 mark_lcrecord_list (Lisp_Object obj, void (*markobj) (Lisp_Object)) |
2212 { | 2214 { |
2213 struct lcrecord_list *list = XLCRECORD_LIST (obj); | 2215 struct lcrecord_list *list = XLCRECORD_LIST (obj); |
2214 Lisp_Object chain = list->free; | 2216 Lisp_Object chain = list->free; |
2215 | 2217 |
2216 while (!NILP (chain)) | 2218 while (!NILP (chain)) |
2217 { | 2219 { |
2218 struct lrecord_header *lheader = XRECORD_LHEADER (chain); | 2220 struct lrecord_header *lheader = XRECORD_LHEADER (chain); |
2219 struct free_lcrecord_header *free_header = | 2221 struct free_lcrecord_header *free_header = |
2220 (struct free_lcrecord_header *) lheader; | 2222 (struct free_lcrecord_header *) lheader; |
2221 | 2223 |
2222 gc_checking_assert | 2224 #ifdef ERROR_CHECK_GC |
2223 (/* There should be no other pointers to the free list. */ | 2225 CONST struct lrecord_implementation *implementation |
2224 ! MARKED_RECORD_HEADER_P (lheader) | 2226 = LHEADER_IMPLEMENTATION(lheader); |
2225 && | 2227 |
2226 /* Only lcrecords should be here. */ | 2228 /* There should be no other pointers to the free list. */ |
2227 ! LHEADER_IMPLEMENTATION (lheader)->basic_p | 2229 assert (!MARKED_RECORD_HEADER_P (lheader)); |
2228 && | 2230 /* Only lcrecords should be here. */ |
2229 /* Only free lcrecords should be here. */ | 2231 assert (!implementation->basic_p); |
2230 free_header->lcheader.free | 2232 /* Only free lcrecords should be here. */ |
2231 && | 2233 assert (free_header->lcheader.free); |
2232 /* The type of the lcrecord must be right. */ | 2234 /* The type of the lcrecord must be right. */ |
2233 LHEADER_IMPLEMENTATION (lheader) == list->implementation | 2235 assert (implementation == list->implementation); |
2234 && | 2236 /* So must the size. */ |
2235 /* So must the size. */ | 2237 assert (implementation->static_size == 0 |
2236 (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 || | 2238 || implementation->static_size == list->size); |
2237 LHEADER_IMPLEMENTATION (lheader)->static_size == list->size) | 2239 #endif /* ERROR_CHECK_GC */ |
2238 ); | |
2239 | 2240 |
2240 MARK_RECORD_HEADER (lheader); | 2241 MARK_RECORD_HEADER (lheader); |
2241 chain = free_header->chain; | 2242 chain = free_header->chain; |
2242 } | 2243 } |
2243 | 2244 |
2244 return Qnil; | 2245 return Qnil; |
2245 } | 2246 } |
2246 | 2247 |
2247 DEFINE_LRECORD_IMPLEMENTATION ("lcrecord-list", lcrecord_list, | 2248 DEFINE_LRECORD_IMPLEMENTATION ("lcrecord-list", lcrecord_list, |
2248 mark_lcrecord_list, internal_object_printer, | 2249 mark_lcrecord_list, internal_object_printer, |
2249 0, 0, 0, 0, struct lcrecord_list); | 2250 0, 0, 0, struct lcrecord_list); |
2250 Lisp_Object | 2251 Lisp_Object |
2251 make_lcrecord_list (size_t size, | 2252 make_lcrecord_list (size_t size, |
2252 const struct lrecord_implementation *implementation) | 2253 CONST struct lrecord_implementation *implementation) |
2253 { | 2254 { |
2254 struct lcrecord_list *p = alloc_lcrecord_type (struct lcrecord_list, | 2255 struct lcrecord_list *p = alloc_lcrecord_type (struct lcrecord_list, |
2255 &lrecord_lcrecord_list); | 2256 &lrecord_lcrecord_list); |
2256 Lisp_Object val; | 2257 Lisp_Object val; |
2257 | 2258 |
2271 Lisp_Object val = list->free; | 2272 Lisp_Object val = list->free; |
2272 struct free_lcrecord_header *free_header = | 2273 struct free_lcrecord_header *free_header = |
2273 (struct free_lcrecord_header *) XPNTR (val); | 2274 (struct free_lcrecord_header *) XPNTR (val); |
2274 | 2275 |
2275 #ifdef ERROR_CHECK_GC | 2276 #ifdef ERROR_CHECK_GC |
2276 struct lrecord_header *lheader = &free_header->lcheader.lheader; | 2277 struct lrecord_header *lheader = |
2278 (struct lrecord_header *) free_header; | |
2279 CONST struct lrecord_implementation *implementation | |
2280 = LHEADER_IMPLEMENTATION (lheader); | |
2277 | 2281 |
2278 /* There should be no other pointers to the free list. */ | 2282 /* There should be no other pointers to the free list. */ |
2279 assert (! MARKED_RECORD_HEADER_P (lheader)); | 2283 assert (!MARKED_RECORD_HEADER_P (lheader)); |
2280 /* Only lcrecords should be here. */ | 2284 /* Only lcrecords should be here. */ |
2281 assert (! LHEADER_IMPLEMENTATION (lheader)->basic_p); | 2285 assert (!implementation->basic_p); |
2282 /* Only free lcrecords should be here. */ | 2286 /* Only free lcrecords should be here. */ |
2283 assert (free_header->lcheader.free); | 2287 assert (free_header->lcheader.free); |
2284 /* The type of the lcrecord must be right. */ | 2288 /* The type of the lcrecord must be right. */ |
2285 assert (LHEADER_IMPLEMENTATION (lheader) == list->implementation); | 2289 assert (implementation == list->implementation); |
2286 /* So must the size. */ | 2290 /* So must the size. */ |
2287 assert (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 || | 2291 assert (implementation->static_size == 0 |
2288 LHEADER_IMPLEMENTATION (lheader)->static_size == list->size); | 2292 || implementation->static_size == list->size); |
2289 #endif /* ERROR_CHECK_GC */ | 2293 #endif /* ERROR_CHECK_GC */ |
2290 | |
2291 list->free = free_header->chain; | 2294 list->free = free_header->chain; |
2292 free_header->lcheader.free = 0; | 2295 free_header->lcheader.free = 0; |
2293 return val; | 2296 return val; |
2294 } | 2297 } |
2295 else | 2298 else |
2306 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord) | 2309 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord) |
2307 { | 2310 { |
2308 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list); | 2311 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list); |
2309 struct free_lcrecord_header *free_header = | 2312 struct free_lcrecord_header *free_header = |
2310 (struct free_lcrecord_header *) XPNTR (lcrecord); | 2313 (struct free_lcrecord_header *) XPNTR (lcrecord); |
2311 struct lrecord_header *lheader = &free_header->lcheader.lheader; | 2314 struct lrecord_header *lheader = |
2312 const struct lrecord_implementation *implementation | 2315 (struct lrecord_header *) free_header; |
2316 CONST struct lrecord_implementation *implementation | |
2313 = LHEADER_IMPLEMENTATION (lheader); | 2317 = LHEADER_IMPLEMENTATION (lheader); |
2314 | 2318 |
2319 #ifdef ERROR_CHECK_GC | |
2315 /* Make sure the size is correct. This will catch, for example, | 2320 /* Make sure the size is correct. This will catch, for example, |
2316 putting a window configuration on the wrong free list. */ | 2321 putting a window configuration on the wrong free list. */ |
2317 gc_checking_assert ((implementation->size_in_bytes_method ? | 2322 if (implementation->size_in_bytes_method) |
2318 implementation->size_in_bytes_method (lheader) : | 2323 assert (implementation->size_in_bytes_method (lheader) == list->size); |
2319 implementation->static_size) | 2324 else |
2320 == list->size); | 2325 assert (implementation->static_size == list->size); |
2326 #endif /* ERROR_CHECK_GC */ | |
2321 | 2327 |
2322 if (implementation->finalizer) | 2328 if (implementation->finalizer) |
2323 implementation->finalizer (lheader, 0); | 2329 implementation->finalizer (lheader, 0); |
2324 free_header->chain = list->free; | 2330 free_header->chain = list->free; |
2325 free_header->lcheader.free = 1; | 2331 free_header->lcheader.free = 1; |
2339 (obj)) | 2345 (obj)) |
2340 { | 2346 { |
2341 return obj; | 2347 return obj; |
2342 } | 2348 } |
2343 | 2349 |
2350 | |
2344 | 2351 |
2345 /************************************************************************/ | 2352 /************************************************************************/ |
2346 /* Garbage Collection */ | 2353 /* Garbage Collection */ |
2347 /************************************************************************/ | 2354 /************************************************************************/ |
2348 | 2355 |
2349 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. | 2356 /* This will be used more extensively In The Future */ |
2350 Additional ones may be defined by a module (none yet). We leave some | 2357 static int last_lrecord_type_index_assigned; |
2351 room in `lrecord_implementations_table' for such new lisp object types. */ | 2358 |
2352 #define MODULE_DEFINABLE_TYPE_COUNT 32 | 2359 CONST struct lrecord_implementation *lrecord_implementations_table[128]; |
2353 const struct lrecord_implementation *lrecord_implementations_table[lrecord_type_count + MODULE_DEFINABLE_TYPE_COUNT]; | 2360 #define max_lrecord_type (countof (lrecord_implementations_table) - 1) |
2354 | |
2355 /* Object marker functions are in the lrecord_implementation structure. | |
2356 But copying them to a parallel array is much more cache-friendly. | |
2357 This hack speeds up (garbage-collect) by about 5%. */ | |
2358 Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object); | |
2359 | 2361 |
2360 struct gcpro *gcprolist; | 2362 struct gcpro *gcprolist; |
2361 | 2363 |
2362 /* 415 used Mly 29-Jun-93 */ | 2364 /* 415 used Mly 29-Jun-93 */ |
2363 /* 1327 used slb 28-Feb-98 */ | 2365 /* 1327 used slb 28-Feb-98 */ |
2364 /* 1328 used og 03-Oct-99 (moving slowly, heh?) */ | |
2365 #ifdef HAVE_SHLIB | 2366 #ifdef HAVE_SHLIB |
2366 #define NSTATICS 4000 | 2367 #define NSTATICS 4000 |
2367 #else | 2368 #else |
2368 #define NSTATICS 2000 | 2369 #define NSTATICS 2000 |
2369 #endif | 2370 #endif |
2370 | 2371 /* Not "static" because of linker lossage on some systems */ |
2371 /* Not "static" because used by dumper.c */ | 2372 Lisp_Object *staticvec[NSTATICS] |
2372 Lisp_Object *staticvec[NSTATICS]; | 2373 /* Force it into data space! */ |
2373 int staticidx; | 2374 = {0}; |
2375 static int staticidx; | |
2374 | 2376 |
2375 /* Put an entry in staticvec, pointing at the variable whose address is given | 2377 /* Put an entry in staticvec, pointing at the variable whose address is given |
2376 */ | 2378 */ |
2377 void | 2379 void |
2378 staticpro (Lisp_Object *varaddress) | 2380 staticpro (Lisp_Object *varaddress) |
2379 { | 2381 { |
2380 /* #### This is now a dubious assert() since this routine may be called */ | 2382 if (staticidx >= countof (staticvec)) |
2381 /* by Lisp attempting to load a DLL. */ | 2383 /* #### This is now a dubious abort() since this routine may be called */ |
2382 assert (staticidx < countof (staticvec)); | 2384 /* by Lisp attempting to load a DLL. */ |
2385 abort (); | |
2383 staticvec[staticidx++] = varaddress; | 2386 staticvec[staticidx++] = varaddress; |
2384 } | 2387 } |
2385 | |
2386 | |
2387 Lisp_Object *staticvec_nodump[200]; | |
2388 int staticidx_nodump; | |
2389 | |
2390 /* Put an entry in staticvec_nodump, pointing at the variable whose address is given | |
2391 */ | |
2392 void | |
2393 staticpro_nodump (Lisp_Object *varaddress) | |
2394 { | |
2395 /* #### This is now a dubious assert() since this routine may be called */ | |
2396 /* by Lisp attempting to load a DLL. */ | |
2397 assert (staticidx_nodump < countof (staticvec_nodump)); | |
2398 staticvec_nodump[staticidx_nodump++] = varaddress; | |
2399 } | |
2400 | |
2401 | |
2402 struct pdump_dumpstructinfo dumpstructvec[200]; | |
2403 int dumpstructidx; | |
2404 | |
2405 /* Put an entry in dumpstructvec, pointing at the variable whose address is given | |
2406 */ | |
2407 void | |
2408 dumpstruct (void *varaddress, const struct struct_description *desc) | |
2409 { | |
2410 assert (dumpstructidx < countof (dumpstructvec)); | |
2411 dumpstructvec[dumpstructidx].data = varaddress; | |
2412 dumpstructvec[dumpstructidx].desc = desc; | |
2413 dumpstructidx++; | |
2414 } | |
2415 | |
2416 struct pdump_dumpopaqueinfo dumpopaquevec[250]; | |
2417 int dumpopaqueidx; | |
2418 | |
2419 /* Put an entry in dumpopaquevec, pointing at the variable whose address is given | |
2420 */ | |
2421 void | |
2422 dumpopaque (void *varaddress, size_t size) | |
2423 { | |
2424 assert (dumpopaqueidx < countof (dumpopaquevec)); | |
2425 | |
2426 dumpopaquevec[dumpopaqueidx].data = varaddress; | |
2427 dumpopaquevec[dumpopaqueidx].size = size; | |
2428 dumpopaqueidx++; | |
2429 } | |
2430 | |
2431 Lisp_Object *pdump_wirevec[50]; | |
2432 int pdump_wireidx; | |
2433 | |
2434 /* Put an entry in pdump_wirevec, pointing at the variable whose address is given | |
2435 */ | |
2436 void | |
2437 pdump_wire (Lisp_Object *varaddress) | |
2438 { | |
2439 assert (pdump_wireidx < countof (pdump_wirevec)); | |
2440 pdump_wirevec[pdump_wireidx++] = varaddress; | |
2441 } | |
2442 | |
2443 | |
2444 Lisp_Object *pdump_wirevec_list[50]; | |
2445 int pdump_wireidx_list; | |
2446 | |
2447 /* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given | |
2448 */ | |
2449 void | |
2450 pdump_wire_list (Lisp_Object *varaddress) | |
2451 { | |
2452 assert (pdump_wireidx_list < countof (pdump_wirevec_list)); | |
2453 pdump_wirevec_list[pdump_wireidx_list++] = varaddress; | |
2454 } | |
2455 | |
2456 #ifdef ERROR_CHECK_GC | |
2457 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \ | |
2458 struct lrecord_header * GCLI_lh = (lheader); \ | |
2459 assert (GCLI_lh != 0); \ | |
2460 assert (GCLI_lh->type < lrecord_type_count); \ | |
2461 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) || \ | |
2462 (MARKED_RECORD_HEADER_P (GCLI_lh) && \ | |
2463 LISP_READONLY_RECORD_HEADER_P (GCLI_lh))); \ | |
2464 } while (0) | |
2465 #else | |
2466 #define GC_CHECK_LHEADER_INVARIANTS(lheader) | |
2467 #endif | |
2468 | 2388 |
2469 | 2389 |
2470 /* Mark reference to a Lisp_Object. If the object referred to has not been | 2390 /* Mark reference to a Lisp_Object. If the object referred to has not been |
2471 seen yet, recursively mark all the references contained in it. */ | 2391 seen yet, recursively mark all the references contained in it. */ |
2472 | 2392 |
2473 void | 2393 static void |
2474 mark_object (Lisp_Object obj) | 2394 mark_object (Lisp_Object obj) |
2475 { | 2395 { |
2476 tail_recurse: | 2396 tail_recurse: |
2477 | 2397 |
2398 #ifdef ERROR_CHECK_GC | |
2399 assert (! (GC_EQ (obj, Qnull_pointer))); | |
2400 #endif | |
2478 /* Checks we used to perform */ | 2401 /* Checks we used to perform */ |
2479 /* if (EQ (obj, Qnull_pointer)) return; */ | 2402 /* if (EQ (obj, Qnull_pointer)) return; */ |
2480 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ | 2403 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ |
2481 /* if (PURIFIED (XPNTR (obj))) return; */ | 2404 /* if (PURIFIED (XPNTR (obj))) return; */ |
2482 | 2405 |
2483 if (XTYPE (obj) == Lisp_Type_Record) | 2406 if (XGCTYPE (obj) == Lisp_Type_Record) |
2484 { | 2407 { |
2485 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | 2408 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
2486 | 2409 #if defined (ERROR_CHECK_GC) |
2487 GC_CHECK_LHEADER_INVARIANTS (lheader); | 2410 assert (lheader->type <= last_lrecord_type_index_assigned); |
2488 | 2411 #endif |
2489 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || | 2412 if (C_READONLY_RECORD_HEADER_P (lheader)) |
2490 ! ((struct lcrecord_header *) lheader)->free); | 2413 return; |
2491 | 2414 |
2492 /* All c_readonly objects have their mark bit set, | 2415 if (! MARKED_RECORD_HEADER_P (lheader) && |
2493 so that we only need to check the mark bit here. */ | 2416 ! UNMARKABLE_RECORD_HEADER_P (lheader)) |
2494 if (! MARKED_RECORD_HEADER_P (lheader)) | |
2495 { | 2417 { |
2418 CONST struct lrecord_implementation *implementation = | |
2419 LHEADER_IMPLEMENTATION (lheader); | |
2496 MARK_RECORD_HEADER (lheader); | 2420 MARK_RECORD_HEADER (lheader); |
2497 | 2421 #ifdef ERROR_CHECK_GC |
2498 if (RECORD_MARKER (lheader)) | 2422 if (!implementation->basic_p) |
2423 assert (! ((struct lcrecord_header *) lheader)->free); | |
2424 #endif | |
2425 if (implementation->marker) | |
2499 { | 2426 { |
2500 obj = RECORD_MARKER (lheader) (obj); | 2427 obj = implementation->marker (obj, mark_object); |
2501 if (!NILP (obj)) goto tail_recurse; | 2428 if (!GC_NILP (obj)) goto tail_recurse; |
2502 } | 2429 } |
2503 } | 2430 } |
2504 } | 2431 } |
2505 } | 2432 } |
2506 | 2433 |
2535 static int gc_count_short_string_total_size; | 2462 static int gc_count_short_string_total_size; |
2536 | 2463 |
2537 /* static int gc_count_total_records_used, gc_count_records_total_size; */ | 2464 /* static int gc_count_total_records_used, gc_count_records_total_size; */ |
2538 | 2465 |
2539 | 2466 |
2467 int | |
2468 lrecord_type_index (CONST struct lrecord_implementation *implementation) | |
2469 { | |
2470 int type_index = *(implementation->lrecord_type_index); | |
2471 /* Have to do this circuitous validation test because of problems | |
2472 dumping out initialized variables (ie can't set xxx_type_index to -1 | |
2473 because that would make xxx_type_index read-only in a dumped emacs. */ | |
2474 if (type_index < 0 || type_index > max_lrecord_type | |
2475 || lrecord_implementations_table[type_index] != implementation) | |
2476 { | |
2477 assert (last_lrecord_type_index_assigned < max_lrecord_type); | |
2478 type_index = ++last_lrecord_type_index_assigned; | |
2479 lrecord_implementations_table[type_index] = implementation; | |
2480 *(implementation->lrecord_type_index) = type_index; | |
2481 } | |
2482 return type_index; | |
2483 } | |
2484 | |
2540 /* stats on lcrecords in use - kinda kludgy */ | 2485 /* stats on lcrecords in use - kinda kludgy */ |
2541 | 2486 |
2542 static struct | 2487 static struct |
2543 { | 2488 { |
2544 int instances_in_use; | 2489 int instances_in_use; |
2547 int bytes_freed; | 2492 int bytes_freed; |
2548 int instances_on_free_list; | 2493 int instances_on_free_list; |
2549 } lcrecord_stats [countof (lrecord_implementations_table)]; | 2494 } lcrecord_stats [countof (lrecord_implementations_table)]; |
2550 | 2495 |
2551 static void | 2496 static void |
2552 tick_lcrecord_stats (const struct lrecord_header *h, int free_p) | 2497 tick_lcrecord_stats (CONST struct lrecord_header *h, int free_p) |
2553 { | 2498 { |
2554 unsigned int type_index = h->type; | 2499 CONST struct lrecord_implementation *implementation = |
2500 LHEADER_IMPLEMENTATION (h); | |
2501 int type_index = lrecord_type_index (implementation); | |
2555 | 2502 |
2556 if (((struct lcrecord_header *) h)->free) | 2503 if (((struct lcrecord_header *) h)->free) |
2557 { | 2504 { |
2558 gc_checking_assert (!free_p); | 2505 assert (!free_p); |
2559 lcrecord_stats[type_index].instances_on_free_list++; | 2506 lcrecord_stats[type_index].instances_on_free_list++; |
2560 } | 2507 } |
2561 else | 2508 else |
2562 { | 2509 { |
2563 const struct lrecord_implementation *implementation = | 2510 size_t sz = (implementation->size_in_bytes_method |
2564 LHEADER_IMPLEMENTATION (h); | 2511 ? implementation->size_in_bytes_method (h) |
2565 | 2512 : implementation->static_size); |
2566 size_t sz = (implementation->size_in_bytes_method ? | 2513 |
2567 implementation->size_in_bytes_method (h) : | |
2568 implementation->static_size); | |
2569 if (free_p) | 2514 if (free_p) |
2570 { | 2515 { |
2571 lcrecord_stats[type_index].instances_freed++; | 2516 lcrecord_stats[type_index].instances_freed++; |
2572 lcrecord_stats[type_index].bytes_freed += sz; | 2517 lcrecord_stats[type_index].bytes_freed += sz; |
2573 } | 2518 } |
2601 other object. */ | 2546 other object. */ |
2602 | 2547 |
2603 for (header = *prev; header; header = header->next) | 2548 for (header = *prev; header; header = header->next) |
2604 { | 2549 { |
2605 struct lrecord_header *h = &(header->lheader); | 2550 struct lrecord_header *h = &(header->lheader); |
2606 | 2551 if (!C_READONLY_RECORD_HEADER_P(h) |
2607 GC_CHECK_LHEADER_INVARIANTS (h); | 2552 && !MARKED_RECORD_HEADER_P (h) |
2608 | 2553 && ! (header->free)) |
2609 if (! MARKED_RECORD_HEADER_P (h) && ! header->free) | |
2610 { | 2554 { |
2611 if (LHEADER_IMPLEMENTATION (h)->finalizer) | 2555 if (LHEADER_IMPLEMENTATION (h)->finalizer) |
2612 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0); | 2556 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0); |
2613 } | 2557 } |
2614 } | 2558 } |
2615 | 2559 |
2616 for (header = *prev; header; ) | 2560 for (header = *prev; header; ) |
2617 { | 2561 { |
2618 struct lrecord_header *h = &(header->lheader); | 2562 struct lrecord_header *h = &(header->lheader); |
2619 if (MARKED_RECORD_HEADER_P (h)) | 2563 if (C_READONLY_RECORD_HEADER_P(h) || MARKED_RECORD_HEADER_P (h)) |
2620 { | 2564 { |
2621 if (! C_READONLY_RECORD_HEADER_P (h)) | 2565 if (MARKED_RECORD_HEADER_P (h)) |
2622 UNMARK_RECORD_HEADER (h); | 2566 UNMARK_RECORD_HEADER (h); |
2623 num_used++; | 2567 num_used++; |
2624 /* total_size += n->implementation->size_in_bytes (h);*/ | 2568 /* total_size += n->implementation->size_in_bytes (h);*/ |
2625 /* #### May modify header->next on a C_READONLY lcrecord */ | 2569 /* ### May modify header->next on a C_READONLY lcrecord */ |
2626 prev = &(header->next); | 2570 prev = &(header->next); |
2627 header = *prev; | 2571 header = *prev; |
2628 tick_lcrecord_stats (h, 0); | 2572 tick_lcrecord_stats (h, 0); |
2629 } | 2573 } |
2630 else | 2574 else |
2655 their implementation */ | 2599 their implementation */ |
2656 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) | 2600 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) |
2657 { | 2601 { |
2658 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); | 2602 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); |
2659 int len = v->size; | 2603 int len = v->size; |
2660 if (MARKED_RECORD_P (bit_vector)) | 2604 if (C_READONLY_RECORD_HEADER_P(&(v->lheader)) || MARKED_RECORD_P (bit_vector)) |
2661 { | 2605 { |
2662 if (! C_READONLY_RECORD_HEADER_P(&(v->lheader))) | 2606 if (MARKED_RECORD_P (bit_vector)) |
2663 UNMARK_RECORD_HEADER (&(v->lheader)); | 2607 UNMARK_RECORD_HEADER (&(v->lheader)); |
2664 total_size += len; | 2608 total_size += len; |
2665 total_storage += | 2609 total_storage += |
2666 MALLOC_OVERHEAD + | 2610 MALLOC_OVERHEAD + |
2667 FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, | 2611 STRETCHY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, |
2668 BIT_VECTOR_LONG_STORAGE (len)); | 2612 BIT_VECTOR_LONG_STORAGE (len)); |
2669 num_used++; | 2613 num_used++; |
2670 /* #### May modify next on a C_READONLY bitvector */ | 2614 /* ### May modify next on a C_READONLY bitvector */ |
2671 prev = &(bit_vector_next (v)); | 2615 prev = &(bit_vector_next (v)); |
2672 bit_vector = *prev; | 2616 bit_vector = *prev; |
2673 } | 2617 } |
2674 else | 2618 else |
2675 { | 2619 { |
2714 } \ | 2658 } \ |
2715 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2659 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2716 { \ | 2660 { \ |
2717 num_used++; \ | 2661 num_used++; \ |
2718 } \ | 2662 } \ |
2719 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2663 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2720 { \ | 2664 { \ |
2721 num_free++; \ | 2665 num_free++; \ |
2722 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ | 2666 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ |
2723 } \ | 2667 } \ |
2724 else \ | 2668 else \ |
2769 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2713 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2770 { \ | 2714 { \ |
2771 SFTB_empty = 0; \ | 2715 SFTB_empty = 0; \ |
2772 num_used++; \ | 2716 num_used++; \ |
2773 } \ | 2717 } \ |
2774 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2718 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2775 { \ | 2719 { \ |
2776 num_free++; \ | 2720 num_free++; \ |
2777 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ | 2721 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ |
2778 } \ | 2722 } \ |
2779 else \ | 2723 else \ |
2825 sweep_conses (void) | 2769 sweep_conses (void) |
2826 { | 2770 { |
2827 #define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) | 2771 #define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) |
2828 #define ADDITIONAL_FREE_cons(ptr) | 2772 #define ADDITIONAL_FREE_cons(ptr) |
2829 | 2773 |
2830 SWEEP_FIXED_TYPE_BLOCK (cons, Lisp_Cons); | 2774 SWEEP_FIXED_TYPE_BLOCK (cons, struct Lisp_Cons); |
2831 } | 2775 } |
2832 | 2776 |
2833 /* Explicitly free a cons cell. */ | 2777 /* Explicitly free a cons cell. */ |
2834 void | 2778 void |
2835 free_cons (Lisp_Cons *ptr) | 2779 free_cons (struct Lisp_Cons *ptr) |
2836 { | 2780 { |
2837 #ifdef ERROR_CHECK_GC | 2781 #ifdef ERROR_CHECK_GC |
2838 /* If the CAR is not an int, then it will be a pointer, which will | 2782 /* If the CAR is not an int, then it will be a pointer, which will |
2839 always be four-byte aligned. If this cons cell has already been | 2783 always be four-byte aligned. If this cons cell has already been |
2840 placed on the free list, however, its car will probably contain | 2784 placed on the free list, however, its car will probably contain |
2844 if (POINTER_TYPE_P (XTYPE (ptr->car))) | 2788 if (POINTER_TYPE_P (XTYPE (ptr->car))) |
2845 ASSERT_VALID_POINTER (XPNTR (ptr->car)); | 2789 ASSERT_VALID_POINTER (XPNTR (ptr->car)); |
2846 #endif /* ERROR_CHECK_GC */ | 2790 #endif /* ERROR_CHECK_GC */ |
2847 | 2791 |
2848 #ifndef ALLOC_NO_POOLS | 2792 #ifndef ALLOC_NO_POOLS |
2849 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, Lisp_Cons, ptr); | 2793 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, struct Lisp_Cons, ptr); |
2850 #endif /* ALLOC_NO_POOLS */ | 2794 #endif /* ALLOC_NO_POOLS */ |
2851 } | 2795 } |
2852 | 2796 |
2853 /* explicitly free a list. You **must make sure** that you have | 2797 /* explicitly free a list. You **must make sure** that you have |
2854 created all the cons cells that make up this list and that there | 2798 created all the cons cells that make up this list and that there |
2900 sweep_floats (void) | 2844 sweep_floats (void) |
2901 { | 2845 { |
2902 #define UNMARK_float(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) | 2846 #define UNMARK_float(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) |
2903 #define ADDITIONAL_FREE_float(ptr) | 2847 #define ADDITIONAL_FREE_float(ptr) |
2904 | 2848 |
2905 SWEEP_FIXED_TYPE_BLOCK (float, Lisp_Float); | 2849 SWEEP_FIXED_TYPE_BLOCK (float, struct Lisp_Float); |
2906 } | 2850 } |
2907 #endif /* LISP_FLOAT_TYPE */ | 2851 #endif /* LISP_FLOAT_TYPE */ |
2908 | 2852 |
2909 static void | 2853 static void |
2910 sweep_symbols (void) | 2854 sweep_symbols (void) |
2911 { | 2855 { |
2912 #define UNMARK_symbol(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) | 2856 #define UNMARK_symbol(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) |
2913 #define ADDITIONAL_FREE_symbol(ptr) | 2857 #define ADDITIONAL_FREE_symbol(ptr) |
2914 | 2858 |
2915 SWEEP_FIXED_TYPE_BLOCK (symbol, Lisp_Symbol); | 2859 SWEEP_FIXED_TYPE_BLOCK (symbol, struct Lisp_Symbol); |
2916 } | 2860 } |
2917 | 2861 |
2918 static void | 2862 static void |
2919 sweep_extents (void) | 2863 sweep_extents (void) |
2920 { | 2864 { |
2928 sweep_events (void) | 2872 sweep_events (void) |
2929 { | 2873 { |
2930 #define UNMARK_event(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) | 2874 #define UNMARK_event(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) |
2931 #define ADDITIONAL_FREE_event(ptr) | 2875 #define ADDITIONAL_FREE_event(ptr) |
2932 | 2876 |
2933 SWEEP_FIXED_TYPE_BLOCK (event, Lisp_Event); | 2877 SWEEP_FIXED_TYPE_BLOCK (event, struct Lisp_Event); |
2934 } | 2878 } |
2935 | 2879 |
2936 static void | 2880 static void |
2937 sweep_markers (void) | 2881 sweep_markers (void) |
2938 { | 2882 { |
2941 do { Lisp_Object tem; \ | 2885 do { Lisp_Object tem; \ |
2942 XSETMARKER (tem, ptr); \ | 2886 XSETMARKER (tem, ptr); \ |
2943 unchain_marker (tem); \ | 2887 unchain_marker (tem); \ |
2944 } while (0) | 2888 } while (0) |
2945 | 2889 |
2946 SWEEP_FIXED_TYPE_BLOCK (marker, Lisp_Marker); | 2890 SWEEP_FIXED_TYPE_BLOCK (marker, struct Lisp_Marker); |
2947 } | 2891 } |
2948 | 2892 |
2949 /* Explicitly free a marker. */ | 2893 /* Explicitly free a marker. */ |
2950 void | 2894 void |
2951 free_marker (Lisp_Marker *ptr) | 2895 free_marker (struct Lisp_Marker *ptr) |
2952 { | 2896 { |
2897 #ifdef ERROR_CHECK_GC | |
2953 /* Perhaps this will catch freeing an already-freed marker. */ | 2898 /* Perhaps this will catch freeing an already-freed marker. */ |
2954 gc_checking_assert (ptr->lheader.type = lrecord_type_marker); | 2899 Lisp_Object temmy; |
2900 XSETMARKER (temmy, ptr); | |
2901 assert (GC_MARKERP (temmy)); | |
2902 #endif /* ERROR_CHECK_GC */ | |
2955 | 2903 |
2956 #ifndef ALLOC_NO_POOLS | 2904 #ifndef ALLOC_NO_POOLS |
2957 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, ptr); | 2905 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, struct Lisp_Marker, ptr); |
2958 #endif /* ALLOC_NO_POOLS */ | 2906 #endif /* ALLOC_NO_POOLS */ |
2959 } | 2907 } |
2960 | 2908 |
2961 | 2909 |
2962 #if defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) | 2910 #if defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) |
2973 /* POS is the index of the next string in the block. */ | 2921 /* POS is the index of the next string in the block. */ |
2974 while (pos < sb->pos) | 2922 while (pos < sb->pos) |
2975 { | 2923 { |
2976 struct string_chars *s_chars = | 2924 struct string_chars *s_chars = |
2977 (struct string_chars *) &(sb->string_chars[pos]); | 2925 (struct string_chars *) &(sb->string_chars[pos]); |
2978 Lisp_String *string; | 2926 struct Lisp_String *string; |
2979 int size; | 2927 int size; |
2980 int fullsize; | 2928 int fullsize; |
2981 | 2929 |
2982 /* If the string_chars struct is marked as free (i.e. the STRING | 2930 /* If the string_chars struct is marked as free (i.e. the STRING |
2983 pointer is 0xFFFFFFFF) then this is an unused chunk of string | 2931 pointer is 0xFFFFFFFF) then this is an unused chunk of string |
3024 while (from_pos < from_sb->pos) | 2972 while (from_pos < from_sb->pos) |
3025 { | 2973 { |
3026 struct string_chars *from_s_chars = | 2974 struct string_chars *from_s_chars = |
3027 (struct string_chars *) &(from_sb->string_chars[from_pos]); | 2975 (struct string_chars *) &(from_sb->string_chars[from_pos]); |
3028 struct string_chars *to_s_chars; | 2976 struct string_chars *to_s_chars; |
3029 Lisp_String *string; | 2977 struct Lisp_String *string; |
3030 int size; | 2978 int size; |
3031 int fullsize; | 2979 int fullsize; |
3032 | 2980 |
3033 /* If the string_chars struct is marked as free (i.e. the STRING | 2981 /* If the string_chars struct is marked as free (i.e. the STRING |
3034 pointer is 0xFFFFFFFF) then this is an unused chunk of string | 2982 pointer is 0xFFFFFFFF) then this is an unused chunk of string |
3050 assert (!(FREE_STRUCT_P (string))); | 2998 assert (!(FREE_STRUCT_P (string))); |
3051 | 2999 |
3052 size = string_length (string); | 3000 size = string_length (string); |
3053 fullsize = STRING_FULLSIZE (size); | 3001 fullsize = STRING_FULLSIZE (size); |
3054 | 3002 |
3055 gc_checking_assert (! BIG_STRING_FULLSIZE_P (fullsize)); | 3003 if (BIG_STRING_FULLSIZE_P (fullsize)) |
3004 abort (); | |
3056 | 3005 |
3057 /* Just skip it if it isn't marked. */ | 3006 /* Just skip it if it isn't marked. */ |
3058 if (! MARKED_RECORD_HEADER_P (&(string->lheader))) | 3007 if (! MARKED_RECORD_HEADER_P (&(string->lheader))) |
3059 { | 3008 { |
3060 from_pos += fullsize; | 3009 from_pos += fullsize; |
3108 | 3057 |
3109 #if 1 /* Hack to debug missing purecopy's */ | 3058 #if 1 /* Hack to debug missing purecopy's */ |
3110 static int debug_string_purity; | 3059 static int debug_string_purity; |
3111 | 3060 |
3112 static void | 3061 static void |
3113 debug_string_purity_print (Lisp_String *p) | 3062 debug_string_purity_print (struct Lisp_String *p) |
3114 { | 3063 { |
3115 Charcount i; | 3064 Charcount i; |
3116 Charcount s = string_char_length (p); | 3065 Charcount s = string_char_length (p); |
3117 stderr_out ("\""); | 3066 putc ('\"', stderr); |
3118 for (i = 0; i < s; i++) | 3067 for (i = 0; i < s; i++) |
3119 { | 3068 { |
3120 Emchar ch = string_char (p, i); | 3069 Emchar ch = string_char (p, i); |
3121 if (ch < 32 || ch >= 126) | 3070 if (ch < 32 || ch >= 126) |
3122 stderr_out ("\\%03o", ch); | 3071 stderr_out ("\\%03o", ch); |
3134 sweep_strings (void) | 3083 sweep_strings (void) |
3135 { | 3084 { |
3136 int num_small_used = 0, num_small_bytes = 0, num_bytes = 0; | 3085 int num_small_used = 0, num_small_bytes = 0, num_bytes = 0; |
3137 int debug = debug_string_purity; | 3086 int debug = debug_string_purity; |
3138 | 3087 |
3139 #define UNMARK_string(ptr) do { \ | 3088 #define UNMARK_string(ptr) \ |
3140 Lisp_String *p = (ptr); \ | 3089 do { struct Lisp_String *p = (ptr); \ |
3141 size_t size = string_length (p); \ | 3090 int size = string_length (p); \ |
3142 UNMARK_RECORD_HEADER (&(p->lheader)); \ | 3091 UNMARK_RECORD_HEADER (&(p->lheader)); \ |
3143 num_bytes += size; \ | 3092 num_bytes += size; \ |
3144 if (!BIG_STRING_SIZE_P (size)) \ | 3093 if (!BIG_STRING_SIZE_P (size)) \ |
3145 { \ | 3094 { num_small_bytes += size; \ |
3146 num_small_bytes += size; \ | 3095 num_small_used++; \ |
3147 num_small_used++; \ | 3096 } \ |
3148 } \ | 3097 if (debug) debug_string_purity_print (p); \ |
3149 if (debug) \ | 3098 } while (0) |
3150 debug_string_purity_print (p); \ | 3099 #define ADDITIONAL_FREE_string(p) \ |
3151 } while (0) | 3100 do { int size = string_length (p); \ |
3152 #define ADDITIONAL_FREE_string(ptr) do { \ | 3101 if (BIG_STRING_SIZE_P (size)) \ |
3153 size_t size = string_length (ptr); \ | 3102 xfree_1 (CHARS_TO_STRING_CHAR (string_data (p))); \ |
3154 if (BIG_STRING_SIZE_P (size)) \ | 3103 } while (0) |
3155 xfree (ptr->data); \ | 3104 |
3156 } while (0) | 3105 SWEEP_FIXED_TYPE_BLOCK (string, struct Lisp_String); |
3157 | |
3158 SWEEP_FIXED_TYPE_BLOCK (string, Lisp_String); | |
3159 | 3106 |
3160 gc_count_num_short_string_in_use = num_small_used; | 3107 gc_count_num_short_string_in_use = num_small_used; |
3161 gc_count_string_total_size = num_bytes; | 3108 gc_count_string_total_size = num_bytes; |
3162 gc_count_short_string_total_size = num_small_bytes; | 3109 gc_count_short_string_total_size = num_small_bytes; |
3163 } | 3110 } |
3164 | 3111 |
3165 | 3112 |
3166 /* I hate duplicating all this crap! */ | 3113 /* I hate duplicating all this crap! */ |
3167 int | 3114 static int |
3168 marked_p (Lisp_Object obj) | 3115 marked_p (Lisp_Object obj) |
3169 { | 3116 { |
3117 #ifdef ERROR_CHECK_GC | |
3118 assert (! (GC_EQ (obj, Qnull_pointer))); | |
3119 #endif | |
3170 /* Checks we used to perform. */ | 3120 /* Checks we used to perform. */ |
3171 /* if (EQ (obj, Qnull_pointer)) return 1; */ | 3121 /* if (EQ (obj, Qnull_pointer)) return 1; */ |
3172 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ | 3122 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ |
3173 /* if (PURIFIED (XPNTR (obj))) return 1; */ | 3123 /* if (PURIFIED (XPNTR (obj))) return 1; */ |
3174 | 3124 |
3175 if (XTYPE (obj) == Lisp_Type_Record) | 3125 if (XGCTYPE (obj) == Lisp_Type_Record) |
3176 { | 3126 { |
3177 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | 3127 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
3178 | 3128 #if defined (ERROR_CHECK_GC) |
3179 GC_CHECK_LHEADER_INVARIANTS (lheader); | 3129 assert (lheader->type <= last_lrecord_type_index_assigned); |
3180 | 3130 #endif |
3181 return MARKED_RECORD_HEADER_P (lheader); | 3131 return C_READONLY_RECORD_HEADER_P (lheader) || MARKED_RECORD_HEADER_P (lheader); |
3182 } | 3132 } |
3183 return 1; | 3133 return 1; |
3184 } | 3134 } |
3185 | 3135 |
3186 static void | 3136 static void |
3240 Dechain each one first from the buffer into which it points. */ | 3190 Dechain each one first from the buffer into which it points. */ |
3241 sweep_markers (); | 3191 sweep_markers (); |
3242 | 3192 |
3243 sweep_events (); | 3193 sweep_events (); |
3244 | 3194 |
3245 #ifdef PDUMP | |
3246 pdump_objects_unmark (); | |
3247 #endif | |
3248 } | 3195 } |
3249 | 3196 |
3250 /* Clearing for disksave. */ | 3197 /* Clearing for disksave. */ |
3251 | 3198 |
3252 void | 3199 void |
3257 To make it easier to tell when this has happened with strings(1) we | 3204 To make it easier to tell when this has happened with strings(1) we |
3258 clear some known-to-be-garbage blocks of memory, so that leftover | 3205 clear some known-to-be-garbage blocks of memory, so that leftover |
3259 results of old evaluation don't look like potential problems. | 3206 results of old evaluation don't look like potential problems. |
3260 But first we set some notable variables to nil and do one more GC, | 3207 But first we set some notable variables to nil and do one more GC, |
3261 to turn those strings into garbage. | 3208 to turn those strings into garbage. |
3262 */ | 3209 */ |
3263 | 3210 |
3264 /* Yeah, this list is pretty ad-hoc... */ | 3211 /* Yeah, this list is pretty ad-hoc... */ |
3265 Vprocess_environment = Qnil; | 3212 Vprocess_environment = Qnil; |
3266 Vexec_directory = Qnil; | 3213 Vexec_directory = Qnil; |
3267 Vdata_directory = Qnil; | 3214 Vdata_directory = Qnil; |
3293 for (scb = first_string_chars_block; scb; scb = scb->next) | 3240 for (scb = first_string_chars_block; scb; scb = scb->next) |
3294 { | 3241 { |
3295 int count = sizeof (scb->string_chars) - scb->pos; | 3242 int count = sizeof (scb->string_chars) - scb->pos; |
3296 | 3243 |
3297 assert (count >= 0 && count < STRING_CHARS_BLOCK_SIZE); | 3244 assert (count >= 0 && count < STRING_CHARS_BLOCK_SIZE); |
3298 if (count != 0) | 3245 if (count != 0) { |
3299 { | 3246 /* from the block's fill ptr to the end */ |
3300 /* from the block's fill ptr to the end */ | 3247 memset ((scb->string_chars + scb->pos), 0, count); |
3301 memset ((scb->string_chars + scb->pos), 0, count); | 3248 } |
3302 } | |
3303 } | 3249 } |
3304 } | 3250 } |
3305 | 3251 |
3306 /* There, that ought to be enough... */ | 3252 /* There, that ought to be enough... */ |
3307 | 3253 |
3394 char *msg = (STRINGP (Vgc_message) | 3340 char *msg = (STRINGP (Vgc_message) |
3395 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message)) | 3341 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message)) |
3396 : 0); | 3342 : 0); |
3397 Lisp_Object args[2], whole_msg; | 3343 Lisp_Object args[2], whole_msg; |
3398 args[0] = build_string (msg ? msg : | 3344 args[0] = build_string (msg ? msg : |
3399 GETTEXT ((const char *) gc_default_message)); | 3345 GETTEXT ((CONST char *) gc_default_message)); |
3400 args[1] = build_string ("..."); | 3346 args[1] = build_string ("..."); |
3401 whole_msg = Fconcat (2, args); | 3347 whole_msg = Fconcat (2, args); |
3402 echo_area_message (f, (Bufbyte *) 0, whole_msg, 0, -1, | 3348 echo_area_message (f, (Bufbyte *) 0, whole_msg, 0, -1, |
3403 Qgarbage_collecting); | 3349 Qgarbage_collecting); |
3404 } | 3350 } |
3445 | 3391 |
3446 { /* staticpro() */ | 3392 { /* staticpro() */ |
3447 int i; | 3393 int i; |
3448 for (i = 0; i < staticidx; i++) | 3394 for (i = 0; i < staticidx; i++) |
3449 mark_object (*(staticvec[i])); | 3395 mark_object (*(staticvec[i])); |
3450 for (i = 0; i < staticidx_nodump; i++) | |
3451 mark_object (*(staticvec_nodump[i])); | |
3452 } | 3396 } |
3453 | 3397 |
3454 { /* GCPRO() */ | 3398 { /* GCPRO() */ |
3455 struct gcpro *tail; | 3399 struct gcpro *tail; |
3456 int i; | 3400 int i; |
3491 for (i = 0; i < nargs; i++) | 3435 for (i = 0; i < nargs; i++) |
3492 mark_object (backlist->args[i]); | 3436 mark_object (backlist->args[i]); |
3493 } | 3437 } |
3494 } | 3438 } |
3495 | 3439 |
3496 mark_redisplay (); | 3440 mark_redisplay (mark_object); |
3497 mark_profiling_info (); | 3441 mark_profiling_info (mark_object); |
3498 | 3442 |
3499 /* OK, now do the after-mark stuff. This is for things that | 3443 /* OK, now do the after-mark stuff. This is for things that |
3500 are only marked when something else is marked (e.g. weak hash tables). | 3444 are only marked when something else is marked (e.g. weak hash tables). |
3501 There may be complex dependencies between such objects -- e.g. | 3445 There may be complex dependencies between such objects -- e.g. |
3502 a weak hash table might be unmarked, but after processing a later | 3446 a weak hash table might be unmarked, but after processing a later |
3503 weak hash table, the former one might get marked. So we have to | 3447 weak hash table, the former one might get marked. So we have to |
3504 iterate until nothing more gets marked. */ | 3448 iterate until nothing more gets marked. */ |
3505 | 3449 |
3506 while (finish_marking_weak_hash_tables () > 0 || | 3450 while (finish_marking_weak_hash_tables (marked_p, mark_object) > 0 || |
3507 finish_marking_weak_lists () > 0) | 3451 finish_marking_weak_lists (marked_p, mark_object) > 0) |
3508 ; | 3452 ; |
3509 | 3453 |
3510 /* And prune (this needs to be called after everything else has been | 3454 /* And prune (this needs to be called after everything else has been |
3511 marked and before we do any sweeping). */ | 3455 marked and before we do any sweeping). */ |
3512 /* #### this is somewhat ad-hoc and should probably be an object | 3456 /* #### this is somewhat ad-hoc and should probably be an object |
3513 method */ | 3457 method */ |
3514 prune_weak_hash_tables (); | 3458 prune_weak_hash_tables (marked_p); |
3515 prune_weak_lists (); | 3459 prune_weak_lists (marked_p); |
3516 prune_specifiers (); | 3460 prune_specifiers (marked_p); |
3517 prune_syntax_tables (); | 3461 prune_syntax_tables (marked_p); |
3518 | 3462 |
3519 gc_sweep (); | 3463 gc_sweep (); |
3520 | 3464 |
3521 consing_since_gc = 0; | 3465 consing_since_gc = 0; |
3522 #ifndef DEBUG_XEMACS | 3466 #ifndef DEBUG_XEMACS |
3546 if (NILP (clear_echo_area (selected_frame (), | 3490 if (NILP (clear_echo_area (selected_frame (), |
3547 Qgarbage_collecting, 0))) | 3491 Qgarbage_collecting, 0))) |
3548 { | 3492 { |
3549 Lisp_Object args[2], whole_msg; | 3493 Lisp_Object args[2], whole_msg; |
3550 args[0] = build_string (msg ? msg : | 3494 args[0] = build_string (msg ? msg : |
3551 GETTEXT ((const char *) | 3495 GETTEXT ((CONST char *) |
3552 gc_default_message)); | 3496 gc_default_message)); |
3553 args[1] = build_string ("... done"); | 3497 args[1] = build_string ("... done"); |
3554 whole_msg = Fconcat (2, args); | 3498 whole_msg = Fconcat (2, args); |
3555 echo_area_message (selected_frame (), (Bufbyte *) 0, | 3499 echo_area_message (selected_frame (), (Bufbyte *) 0, |
3556 whole_msg, 0, -1, | 3500 whole_msg, 0, -1, |
3572 } | 3516 } |
3573 | 3517 |
3574 /* Debugging aids. */ | 3518 /* Debugging aids. */ |
3575 | 3519 |
3576 static Lisp_Object | 3520 static Lisp_Object |
3577 gc_plist_hack (const char *name, int value, Lisp_Object tail) | 3521 gc_plist_hack (CONST char *name, int value, Lisp_Object tail) |
3578 { | 3522 { |
3579 /* C doesn't have local functions (or closures, or GC, or readable syntax, | 3523 /* C doesn't have local functions (or closures, or GC, or readable syntax, |
3580 or portable numeric datatypes, or bit-vectors, or characters, or | 3524 or portable numeric datatypes, or bit-vectors, or characters, or |
3581 arrays, or exceptions, or ...) */ | 3525 arrays, or exceptions, or ...) */ |
3582 return cons3 (intern (name), make_int (value), tail); | 3526 return cons3 (intern (name), make_int (value), tail); |
3606 int i; | 3550 int i; |
3607 int gc_count_vector_total_size = 0; | 3551 int gc_count_vector_total_size = 0; |
3608 | 3552 |
3609 garbage_collect_1 (); | 3553 garbage_collect_1 (); |
3610 | 3554 |
3611 for (i = 0; i < lrecord_type_count; i++) | 3555 for (i = 0; i < last_lrecord_type_index_assigned; i++) |
3612 { | 3556 { |
3613 if (lcrecord_stats[i].bytes_in_use != 0 | 3557 if (lcrecord_stats[i].bytes_in_use != 0 |
3614 || lcrecord_stats[i].bytes_freed != 0 | 3558 || lcrecord_stats[i].bytes_freed != 0 |
3615 || lcrecord_stats[i].instances_on_free_list != 0) | 3559 || lcrecord_stats[i].instances_on_free_list != 0) |
3616 { | 3560 { |
3617 char buf [255]; | 3561 char buf [255]; |
3618 const char *name = lrecord_implementations_table[i]->name; | 3562 CONST char *name = lrecord_implementations_table[i]->name; |
3619 int len = strlen (name); | 3563 int len = strlen (name); |
3620 /* save this for the FSFmacs-compatible part of the summary */ | 3564 /* save this for the FSFmacs-compatible part of the summary */ |
3621 if (i == lrecord_vector.lrecord_type_index) | 3565 if (i == *lrecord_vector.lrecord_type_index) |
3622 gc_count_vector_total_size = | 3566 gc_count_vector_total_size = |
3623 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed; | 3567 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed; |
3624 | 3568 |
3625 sprintf (buf, "%s-storage", name); | 3569 sprintf (buf, "%s-storage", name); |
3626 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl); | 3570 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl); |
3717 ()) | 3661 ()) |
3718 { | 3662 { |
3719 return make_int (consing_since_gc); | 3663 return make_int (consing_since_gc); |
3720 } | 3664 } |
3721 | 3665 |
3722 #if 0 | |
3723 DEFUN ("memory-limit", Fmemory_limit, 0, 0, "", /* | 3666 DEFUN ("memory-limit", Fmemory_limit, 0, 0, "", /* |
3724 Return the address of the last byte Emacs has allocated, divided by 1024. | 3667 Return the address of the last byte Emacs has allocated, divided by 1024. |
3725 This may be helpful in debugging Emacs's memory usage. | 3668 This may be helpful in debugging Emacs's memory usage. |
3726 The value is divided by 1024 to make sure it will fit in a lisp integer. | 3669 The value is divided by 1024 to make sure it will fit in a lisp integer. |
3727 */ | 3670 */ |
3728 ()) | 3671 ()) |
3729 { | 3672 { |
3730 return make_int ((EMACS_INT) sbrk (0) / 1024); | 3673 return make_int ((EMACS_INT) sbrk (0) / 1024); |
3731 } | 3674 } |
3732 #endif | 3675 |
3733 | 3676 |
3734 | 3677 |
3735 int | 3678 int |
3736 object_dead_p (Lisp_Object obj) | 3679 object_dead_p (Lisp_Object obj) |
3737 { | 3680 { |
3881 #endif /* MEMORY_USAGE_STATS */ | 3824 #endif /* MEMORY_USAGE_STATS */ |
3882 | 3825 |
3883 | 3826 |
3884 /* Initialization */ | 3827 /* Initialization */ |
3885 void | 3828 void |
3886 reinit_alloc_once_early (void) | 3829 init_alloc_once_early (void) |
3887 { | 3830 { |
3831 int iii; | |
3832 | |
3833 last_lrecord_type_index_assigned = -1; | |
3834 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) | |
3835 { | |
3836 lrecord_implementations_table[iii] = 0; | |
3837 } | |
3838 | |
3839 /* | |
3840 * All the staticly | |
3841 * defined subr lrecords were initialized with lheader->type == 0. | |
3842 * See subr_lheader_initializer in lisp.h. Force type index 0 to be | |
3843 * assigned to lrecord_subr so that those predefined indexes match | |
3844 * reality. | |
3845 */ | |
3846 lrecord_type_index (&lrecord_subr); | |
3847 assert (*(lrecord_subr.lrecord_type_index) == 0); | |
3848 /* | |
3849 * The same is true for symbol_value_forward objects, except the | |
3850 * type is 1. | |
3851 */ | |
3852 lrecord_type_index (&lrecord_symbol_value_forward); | |
3853 assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1); | |
3854 | |
3888 gc_generation_number[0] = 0; | 3855 gc_generation_number[0] = 0; |
3856 /* purify_flag 1 is correct even if CANNOT_DUMP. | |
3857 * loadup.el will set to nil at end. */ | |
3858 purify_flag = 1; | |
3889 breathing_space = 0; | 3859 breathing_space = 0; |
3890 XSETINT (all_bit_vectors, 0); /* Qzero may not be set yet. */ | 3860 XSETINT (all_bit_vectors, 0); /* Qzero may not be set yet. */ |
3891 XSETINT (Vgc_message, 0); | 3861 XSETINT (Vgc_message, 0); |
3892 all_lcrecords = 0; | 3862 all_lcrecords = 0; |
3893 ignore_malloc_warnings = 1; | 3863 ignore_malloc_warnings = 1; |
3909 init_marker_alloc (); | 3879 init_marker_alloc (); |
3910 init_extent_alloc (); | 3880 init_extent_alloc (); |
3911 init_event_alloc (); | 3881 init_event_alloc (); |
3912 | 3882 |
3913 ignore_malloc_warnings = 0; | 3883 ignore_malloc_warnings = 0; |
3914 | 3884 staticidx = 0; |
3915 staticidx_nodump = 0; | |
3916 dumpstructidx = 0; | |
3917 pdump_wireidx = 0; | |
3918 | |
3919 consing_since_gc = 0; | 3885 consing_since_gc = 0; |
3920 #if 1 | 3886 #if 1 |
3921 gc_cons_threshold = 500000; /* XEmacs change */ | 3887 gc_cons_threshold = 500000; /* XEmacs change */ |
3922 #else | 3888 #else |
3923 gc_cons_threshold = 15000; /* debugging */ | 3889 gc_cons_threshold = 15000; /* debugging */ |
3940 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 42; | 3906 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 42; |
3941 ERROR_ME_WARN. | 3907 ERROR_ME_WARN. |
3942 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = | 3908 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = |
3943 3333632; | 3909 3333632; |
3944 #endif /* ERROR_CHECK_TYPECHECK */ | 3910 #endif /* ERROR_CHECK_TYPECHECK */ |
3945 } | |
3946 | |
3947 void | |
3948 init_alloc_once_early (void) | |
3949 { | |
3950 reinit_alloc_once_early (); | |
3951 | |
3952 { | |
3953 int i; | |
3954 for (i = 0; i < countof (lrecord_implementations_table); i++) | |
3955 lrecord_implementations_table[i] = 0; | |
3956 } | |
3957 | |
3958 INIT_LRECORD_IMPLEMENTATION (cons); | |
3959 INIT_LRECORD_IMPLEMENTATION (vector); | |
3960 INIT_LRECORD_IMPLEMENTATION (string); | |
3961 INIT_LRECORD_IMPLEMENTATION (lcrecord_list); | |
3962 | |
3963 staticidx = 0; | |
3964 } | 3911 } |
3965 | 3912 |
3966 int pure_bytes_used = 0; | 3913 int pure_bytes_used = 0; |
3967 | 3914 |
3968 void | 3915 void |
3990 DEFSUBR (Fstring); | 3937 DEFSUBR (Fstring); |
3991 DEFSUBR (Fmake_symbol); | 3938 DEFSUBR (Fmake_symbol); |
3992 DEFSUBR (Fmake_marker); | 3939 DEFSUBR (Fmake_marker); |
3993 DEFSUBR (Fpurecopy); | 3940 DEFSUBR (Fpurecopy); |
3994 DEFSUBR (Fgarbage_collect); | 3941 DEFSUBR (Fgarbage_collect); |
3995 #if 0 | |
3996 DEFSUBR (Fmemory_limit); | 3942 DEFSUBR (Fmemory_limit); |
3997 #endif | |
3998 DEFSUBR (Fconsing_since_gc); | 3943 DEFSUBR (Fconsing_since_gc); |
3999 } | 3944 } |
4000 | 3945 |
4001 void | 3946 void |
4002 vars_of_alloc (void) | 3947 vars_of_alloc (void) |
4070 This is printed in the echo area. If the selected frame is on a | 4015 This is printed in the echo area. If the selected frame is on a |
4071 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer | 4016 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer |
4072 image instance) in the domain of the selected frame, the mouse pointer | 4017 image instance) in the domain of the selected frame, the mouse pointer |
4073 will change instead of this message being printed. | 4018 will change instead of this message being printed. |
4074 */ ); | 4019 */ ); |
4075 Vgc_message = build_string (gc_default_message); | 4020 Vgc_message = make_string_nocopy ((CONST Bufbyte *) gc_default_message, |
4021 countof (gc_default_message) - 1); | |
4076 | 4022 |
4077 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /* | 4023 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /* |
4078 Pointer glyph used to indicate that a garbage collection is in progress. | 4024 Pointer glyph used to indicate that a garbage collection is in progress. |
4079 If the selected window is on a window system and this glyph specifies a | 4025 If the selected window is on a window system and this glyph specifies a |
4080 value (i.e. a pointer image instance) in the domain of the selected | 4026 value (i.e. a pointer image instance) in the domain of the selected |