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