comparison src/alloc.c @ 442:abe6d1db359e r21-2-36

Import from CVS: tag r21-2-36
author cvs
date Mon, 13 Aug 2007 11:35:02 +0200
parents 8de8e3f6228a
children 576fb035e263
comparison
equal deleted inserted replaced
441:72a7cfa4a488 442:abe6d1db359e
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. 39 og: Killed the purespace. Portable dumper (moved to dumper.c)
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"
45 #include "backtrace.h" 46 #include "backtrace.h"
46 #include "buffer.h" 47 #include "buffer.h"
47 #include "bytecode.h" 48 #include "bytecode.h"
48 #include "chartab.h" 49 #include "chartab.h"
49 #include "device.h" 50 #include "device.h"
54 #include "glyphs.h" 55 #include "glyphs.h"
55 #include "opaque.h" 56 #include "opaque.h"
56 #include "redisplay.h" 57 #include "redisplay.h"
57 #include "specifier.h" 58 #include "specifier.h"
58 #include "sysfile.h" 59 #include "sysfile.h"
60 #include "sysdep.h"
59 #include "window.h" 61 #include "window.h"
60 #include "console-stream.h" 62 #include "console-stream.h"
61 63
62 #ifdef DOUG_LEA_MALLOC 64 #ifdef DOUG_LEA_MALLOC
63 #include <malloc.h> 65 #include <malloc.h>
64 #endif 66 #endif
65 67
66 #ifdef HAVE_MMAP 68 #ifdef PDUMP
67 #include <unistd.h> 69 #include "dumper.h"
68 #include <sys/mman.h>
69 #endif 70 #endif
70 71
71 #ifdef PDUMP
72 typedef struct
73 {
74 const struct lrecord_description *desc;
75 int count;
76 } pdump_reloc_table;
77
78 static char *pdump_rt_list = 0;
79 #endif
80
81 EXFUN (Fgarbage_collect, 0); 72 EXFUN (Fgarbage_collect, 0);
82
83 /* Return the true size of a struct with a variable-length array field. */
84 #define STRETCHY_STRUCT_SIZEOF(stretchy_struct_type, \
85 stretchy_array_field, \
86 stretchy_array_length) \
87 (offsetof (stretchy_struct_type, stretchy_array_field) + \
88 (offsetof (stretchy_struct_type, stretchy_array_field[1]) - \
89 offsetof (stretchy_struct_type, stretchy_array_field[0])) * \
90 (stretchy_array_length))
91 73
92 #if 0 /* this is _way_ too slow to be part of the standard debug options */ 74 #if 0 /* this is _way_ too slow to be part of the standard debug options */
93 #if defined(DEBUG_XEMACS) && defined(MULE) 75 #if defined(DEBUG_XEMACS) && defined(MULE)
94 #define VERIFY_STRING_CHARS_INTEGRITY 76 #define VERIFY_STRING_CHARS_INTEGRITY
95 #endif 77 #endif
172 Lisp_Object Vpost_gc_hook, Qpost_gc_hook; 154 Lisp_Object Vpost_gc_hook, Qpost_gc_hook;
173 155
174 /* "Garbage collecting" */ 156 /* "Garbage collecting" */
175 Lisp_Object Vgc_message; 157 Lisp_Object Vgc_message;
176 Lisp_Object Vgc_pointer_glyph; 158 Lisp_Object Vgc_pointer_glyph;
177 static CONST char gc_default_message[] = "Garbage collecting"; 159 static const char gc_default_message[] = "Garbage collecting";
178 Lisp_Object Qgarbage_collecting; 160 Lisp_Object Qgarbage_collecting;
179
180 #ifndef VIRT_ADDR_VARIES
181 extern
182 #endif /* VIRT_ADDR_VARIES */
183 EMACS_INT malloc_sbrk_used;
184
185 #ifndef VIRT_ADDR_VARIES
186 extern
187 #endif /* VIRT_ADDR_VARIES */
188 EMACS_INT malloc_sbrk_unused;
189 161
190 /* Non-zero means we're in the process of doing the dump */ 162 /* Non-zero means we're in the process of doing the dump */
191 int purify_flag; 163 int purify_flag;
192 164
193 #ifdef ERROR_CHECK_TYPECHECK 165 #ifdef ERROR_CHECK_TYPECHECK
232 } 204 }
233 } 205 }
234 206
235 /* malloc calls this if it finds we are near exhausting storage */ 207 /* malloc calls this if it finds we are near exhausting storage */
236 void 208 void
237 malloc_warning (CONST char *str) 209 malloc_warning (const char *str)
238 { 210 {
239 if (ignore_malloc_warnings) 211 if (ignore_malloc_warnings)
240 return; 212 return;
241 213
242 warn_when_safe 214 warn_when_safe
355 327
356 #endif /* !ERROR_CHECK_GC */ 328 #endif /* !ERROR_CHECK_GC */
357 329
358 #undef xstrdup 330 #undef xstrdup
359 char * 331 char *
360 xstrdup (CONST char *str) 332 xstrdup (const char *str)
361 { 333 {
362 int len = strlen (str) + 1; /* for stupid terminating 0 */ 334 int len = strlen (str) + 1; /* for stupid terminating 0 */
363 335
364 void *val = xmalloc (len); 336 void *val = xmalloc (len);
365 if (val == 0) return 0; 337 if (val == 0) return 0;
366 return (char *) memcpy (val, str, len); 338 return (char *) memcpy (val, str, len);
367 } 339 }
368 340
369 #ifdef NEED_STRDUP 341 #ifdef NEED_STRDUP
370 char * 342 char *
371 strdup (CONST char *s) 343 strdup (const char *s)
372 { 344 {
373 return xstrdup (s); 345 return xstrdup (s);
374 } 346 }
375 #endif /* NEED_STRDUP */ 347 #endif /* NEED_STRDUP */
376 348
380 { 352 {
381 return xmalloc (size); 353 return xmalloc (size);
382 } 354 }
383 355
384 356
385 /* lrecords are chained together through their "next.v" field. 357 /* lcrecords are chained together through their "next" field.
386 * After doing the mark phase, the GC will walk this linked 358 After doing the mark phase, GC will walk this linked list
387 * list and free any record which hasn't been marked. 359 and free any lcrecord which hasn't been marked. */
388 */
389 static struct lcrecord_header *all_lcrecords; 360 static struct lcrecord_header *all_lcrecords;
390 361
391 void * 362 void *
392 alloc_lcrecord (size_t size, CONST struct lrecord_implementation *implementation) 363 alloc_lcrecord (size_t size, const struct lrecord_implementation *implementation)
393 { 364 {
394 struct lcrecord_header *lcheader; 365 struct lcrecord_header *lcheader;
395 366
396 #ifdef ERROR_CHECK_GC 367 type_checking_assert
397 if (implementation->static_size == 0) 368 ((implementation->static_size == 0 ?
398 assert (implementation->size_in_bytes_method); 369 implementation->size_in_bytes_method != NULL :
399 else 370 implementation->static_size == size)
400 assert (implementation->static_size == size); 371 &&
401 #endif 372 (! implementation->basic_p)
373 &&
374 (! (implementation->hash == NULL && implementation->equal != NULL)));
402 375
403 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); 376 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size);
404 set_lheader_implementation (&(lcheader->lheader), implementation); 377 set_lheader_implementation (&lcheader->lheader, implementation);
405 lcheader->next = all_lcrecords; 378 lcheader->next = all_lcrecords;
406 #if 1 /* mly prefers to see small ID numbers */ 379 #if 1 /* mly prefers to see small ID numbers */
407 lcheader->uid = lrecord_uid_counter++; 380 lcheader->uid = lrecord_uid_counter++;
408 #else /* jwz prefers to see real addrs */ 381 #else /* jwz prefers to see real addrs */
409 lcheader->uid = (int) &lcheader; 382 lcheader->uid = (int) &lcheader;
458 { 431 {
459 struct lcrecord_header *header; 432 struct lcrecord_header *header;
460 433
461 for (header = all_lcrecords; header; header = header->next) 434 for (header = all_lcrecords; header; header = header->next)
462 { 435 {
463 if (LHEADER_IMPLEMENTATION(&header->lheader)->finalizer && 436 if (LHEADER_IMPLEMENTATION (&header->lheader)->finalizer &&
464 !header->free) 437 !header->free)
465 ((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer) 438 LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1);
466 (header, 1)); 439 }
467 }
468 }
469
470 /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck
471 in CONST space and you get SEGV's if you attempt to mark them.
472 This sits in lheader->implementation->marker. */
473
474 Lisp_Object
475 this_one_is_unmarkable (Lisp_Object obj)
476 {
477 abort ();
478 return Qnil;
479 } 440 }
480 441
481 442
482 /************************************************************************/ 443 /************************************************************************/
483 /* Debugger support */ 444 /* Debugger support */
492 453
493 #ifdef USE_UNION_TYPE 454 #ifdef USE_UNION_TYPE
494 unsigned char dbg_USE_UNION_TYPE = 1; 455 unsigned char dbg_USE_UNION_TYPE = 1;
495 #else 456 #else
496 unsigned char dbg_USE_UNION_TYPE = 0; 457 unsigned char dbg_USE_UNION_TYPE = 0;
497 #endif
498
499 unsigned char Lisp_Type_Int = 100;
500 unsigned char Lisp_Type_Cons = 101;
501 unsigned char Lisp_Type_String = 102;
502 unsigned char Lisp_Type_Vector = 103;
503 unsigned char Lisp_Type_Symbol = 104;
504
505 #ifndef MULE
506 unsigned char lrecord_char_table_entry;
507 unsigned char lrecord_charset;
508 #ifndef FILE_CODING
509 unsigned char lrecord_coding_system;
510 #endif
511 #endif
512
513 #if !((defined HAVE_X_WINDOWS) && \
514 (defined (HAVE_MENUBARS) || \
515 defined (HAVE_SCROLLBARS) || \
516 defined (HAVE_DIALOGS) || \
517 defined (HAVE_TOOLBARS) || \
518 defined (HAVE_WIDGETS)))
519 unsigned char lrecord_popup_data;
520 #endif
521
522 #ifndef HAVE_TOOLBARS
523 unsigned char lrecord_toolbar_button;
524 #endif
525
526 #ifndef TOOLTALK
527 unsigned char lrecord_tooltalk_message;
528 unsigned char lrecord_tooltalk_pattern;
529 #endif
530
531 #ifndef HAVE_DATABASE
532 unsigned char lrecord_database;
533 #endif 458 #endif
534 459
535 unsigned char dbg_valbits = VALBITS; 460 unsigned char dbg_valbits = VALBITS;
536 unsigned char dbg_gctypebits = GCTYPEBITS; 461 unsigned char dbg_gctypebits = GCTYPEBITS;
537 462
711 try to set aside another reserve in case we run out once more. 636 try to set aside another reserve in case we run out once more.
712 637
713 This is called when a relocatable block is freed in ralloc.c. */ 638 This is called when a relocatable block is freed in ralloc.c. */
714 void refill_memory_reserve (void); 639 void refill_memory_reserve (void);
715 void 640 void
716 refill_memory_reserve () 641 refill_memory_reserve (void)
717 { 642 {
718 if (breathing_space == 0) 643 if (breathing_space == 0)
719 breathing_space = (char *) malloc (4096 - MALLOC_OVERHEAD); 644 breathing_space = (char *) malloc (4096 - MALLOC_OVERHEAD);
720 } 645 }
721 #endif 646 #endif
850 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFFFFFF 775 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFFFFFF
851 #else 776 #else
852 You have some weird system and need to supply a reasonable value here. 777 You have some weird system and need to supply a reasonable value here.
853 #endif 778 #endif
854 779
780 /* The construct (* (void **) (ptr)) would cause aliasing problems
781 with modern optimizing compilers like `gcc -O3 -fstrict-aliasing'.
782 But `char *' can legally alias any pointer. Hence this union trick. */
783 typedef union { char c; void *p; } *aliasing_voidpp;
784 #define ALIASING_VOIDPP_DEREFERENCE(ptr) \
785 (((aliasing_voidpp) (ptr))->p)
855 #define FREE_STRUCT_P(ptr) \ 786 #define FREE_STRUCT_P(ptr) \
856 (* (void **) ptr == (void *) INVALID_POINTER_VALUE) 787 (ALIASING_VOIDPP_DEREFERENCE (ptr) == (void *) INVALID_POINTER_VALUE)
857 #define MARK_STRUCT_AS_FREE(ptr) \ 788 #define MARK_STRUCT_AS_FREE(ptr) \
858 (* (void **) ptr = (void *) INVALID_POINTER_VALUE) 789 (ALIASING_VOIDPP_DEREFERENCE (ptr) = (void *) INVALID_POINTER_VALUE)
859 #define MARK_STRUCT_AS_NOT_FREE(ptr) \ 790 #define MARK_STRUCT_AS_NOT_FREE(ptr) \
860 (* (void **) ptr = 0) 791 (ALIASING_VOIDPP_DEREFERENCE (ptr) = 0)
861 792
862 #ifdef ERROR_CHECK_GC 793 #ifdef ERROR_CHECK_GC
863 794
864 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ 795 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \
865 do { if (type##_free_list_tail) \ 796 do { if (type##_free_list_tail) \
938 } 869 }
939 870
940 static int 871 static int
941 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) 872 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth)
942 { 873 {
943 while (internal_equal (XCAR (ob1), XCAR (ob2), depth + 1)) 874 depth++;
875 while (internal_equal (XCAR (ob1), XCAR (ob2), depth))
944 { 876 {
945 ob1 = XCDR (ob1); 877 ob1 = XCDR (ob1);
946 ob2 = XCDR (ob2); 878 ob2 = XCDR (ob2);
947 if (! CONSP (ob1) || ! CONSP (ob2)) 879 if (! CONSP (ob1) || ! CONSP (ob2))
948 return internal_equal (ob1, ob2, depth + 1); 880 return internal_equal (ob1, ob2, depth);
949 } 881 }
950 return 0; 882 return 0;
951 } 883 }
952 884
953 static const struct lrecord_description cons_description[] = { 885 static const struct lrecord_description cons_description[] = {
976 /* This cannot GC. */ 908 /* This cannot GC. */
977 Lisp_Object val; 909 Lisp_Object val;
978 Lisp_Cons *c; 910 Lisp_Cons *c;
979 911
980 ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); 912 ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c);
981 set_lheader_implementation (&(c->lheader), &lrecord_cons); 913 set_lheader_implementation (&c->lheader, &lrecord_cons);
982 XSETCONS (val, c); 914 XSETCONS (val, c);
983 c->car = car; 915 c->car = car;
984 c->cdr = cdr; 916 c->cdr = cdr;
985 return val; 917 return val;
986 } 918 }
993 { 925 {
994 Lisp_Object val; 926 Lisp_Object val;
995 Lisp_Cons *c; 927 Lisp_Cons *c;
996 928
997 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c); 929 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c);
998 set_lheader_implementation (&(c->lheader), &lrecord_cons); 930 set_lheader_implementation (&c->lheader, &lrecord_cons);
999 XSETCONS (val, c); 931 XSETCONS (val, c);
1000 XCAR (val) = car; 932 XCAR (val) = car;
1001 XCDR (val) = cdr; 933 XCDR (val) = cdr;
1002 return val; 934 return val;
1003 } 935 }
1110 1042
1111 /* Avoid dump-time `uninitialized memory read' purify warnings. */ 1043 /* Avoid dump-time `uninitialized memory read' purify warnings. */
1112 if (sizeof (struct lrecord_header) + sizeof (double) != sizeof (*f)) 1044 if (sizeof (struct lrecord_header) + sizeof (double) != sizeof (*f))
1113 xzero (*f); 1045 xzero (*f);
1114 1046
1115 set_lheader_implementation (&(f->lheader), &lrecord_float); 1047 set_lheader_implementation (&f->lheader, &lrecord_float);
1116 float_data (f) = float_value; 1048 float_data (f) = float_value;
1117 XSETFLOAT (val, f); 1049 XSETFLOAT (val, f);
1118 return val; 1050 return val;
1119 } 1051 }
1120 1052
1136 mark_object (ptr->contents[i]); 1068 mark_object (ptr->contents[i]);
1137 return (len > 0) ? ptr->contents[len - 1] : Qnil; 1069 return (len > 0) ? ptr->contents[len - 1] : Qnil;
1138 } 1070 }
1139 1071
1140 static size_t 1072 static size_t
1141 size_vector (CONST void *lheader) 1073 size_vector (const void *lheader)
1142 { 1074 {
1143 return STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, 1075 return FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Vector, contents,
1144 ((Lisp_Vector *) lheader)->size); 1076 ((Lisp_Vector *) lheader)->size);
1145 } 1077 }
1146 1078
1147 static int 1079 static int
1148 vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 1080 vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
1149 { 1081 {
1159 return 0; 1091 return 0;
1160 } 1092 }
1161 return 1; 1093 return 1;
1162 } 1094 }
1163 1095
1096 static hashcode_t
1097 vector_hash (Lisp_Object obj, int depth)
1098 {
1099 return HASH2 (XVECTOR_LENGTH (obj),
1100 internal_array_hash (XVECTOR_DATA (obj),
1101 XVECTOR_LENGTH (obj),
1102 depth + 1));
1103 }
1104
1164 static const struct lrecord_description vector_description[] = { 1105 static const struct lrecord_description vector_description[] = {
1165 { XD_LONG, offsetof (Lisp_Vector, size) }, 1106 { XD_LONG, offsetof (Lisp_Vector, size) },
1166 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Vector, contents), XD_INDIRECT(0, 0) }, 1107 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Vector, contents), XD_INDIRECT(0, 0) },
1167 { XD_END } 1108 { XD_END }
1168 }; 1109 };
1169 1110
1170 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector, 1111 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector,
1171 mark_vector, print_vector, 0, 1112 mark_vector, print_vector, 0,
1172 vector_equal, 1113 vector_equal,
1173 /* 1114 vector_hash,
1174 * No `hash' method needed for
1175 * vectors. internal_hash
1176 * knows how to handle vectors.
1177 */
1178 0,
1179 vector_description, 1115 vector_description,
1180 size_vector, Lisp_Vector); 1116 size_vector, Lisp_Vector);
1181 1117
1182 /* #### should allocate `small' vectors from a frob-block */ 1118 /* #### should allocate `small' vectors from a frob-block */
1183 static Lisp_Vector * 1119 static Lisp_Vector *
1184 make_vector_internal (size_t sizei) 1120 make_vector_internal (size_t sizei)
1185 { 1121 {
1186 /* no vector_next */ 1122 /* no vector_next */
1187 size_t sizem = STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, sizei); 1123 size_t sizem = FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Vector, contents, sizei);
1188 Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord (sizem, &lrecord_vector); 1124 Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord (sizem, &lrecord_vector);
1189 1125
1190 p->size = sizei; 1126 p->size = sizei;
1191 return p; 1127 return p;
1192 } 1128 }
1345 /* #### should allocate `small' bit vectors from a frob-block */ 1281 /* #### should allocate `small' bit vectors from a frob-block */
1346 static Lisp_Bit_Vector * 1282 static Lisp_Bit_Vector *
1347 make_bit_vector_internal (size_t sizei) 1283 make_bit_vector_internal (size_t sizei)
1348 { 1284 {
1349 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei); 1285 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei);
1350 size_t sizem = STRETCHY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, num_longs); 1286 size_t sizem = FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, num_longs);
1351 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem); 1287 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem);
1352 set_lheader_implementation (&(p->lheader), &lrecord_bit_vector); 1288 set_lheader_implementation (&p->lheader, &lrecord_bit_vector);
1353 1289
1354 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); 1290 INCREMENT_CONS_COUNTER (sizem, "bit-vector");
1355 1291
1356 bit_vector_length (p) = sizei; 1292 bit_vector_length (p) = sizei;
1357 bit_vector_next (p) = all_bit_vectors; 1293 bit_vector_next (p) = all_bit_vectors;
1451 { 1387 {
1452 Lisp_Compiled_Function *f; 1388 Lisp_Compiled_Function *f;
1453 Lisp_Object fun; 1389 Lisp_Object fun;
1454 1390
1455 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f); 1391 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f);
1456 set_lheader_implementation (&(f->lheader), &lrecord_compiled_function); 1392 set_lheader_implementation (&f->lheader, &lrecord_compiled_function);
1457 1393
1458 f->stack_depth = 0; 1394 f->stack_depth = 0;
1459 f->specpdl_depth = 0; 1395 f->specpdl_depth = 0;
1460 f->flags.documentationp = 0; 1396 f->flags.documentationp = 0;
1461 f->flags.interactivep = 0; 1397 f->flags.interactivep = 0;
1503 list2 (intern ("make-byte-code"), make_int (nargs))); 1439 list2 (intern ("make-byte-code"), make_int (nargs)));
1504 1440
1505 /* Check for valid formal parameter list now, to allow us to use 1441 /* Check for valid formal parameter list now, to allow us to use
1506 SPECBIND_FAST_UNSAFE() later in funcall_compiled_function(). */ 1442 SPECBIND_FAST_UNSAFE() later in funcall_compiled_function(). */
1507 { 1443 {
1508 Lisp_Object symbol, tail;
1509 EXTERNAL_LIST_LOOP_3 (symbol, arglist, tail) 1444 EXTERNAL_LIST_LOOP_3 (symbol, arglist, tail)
1510 { 1445 {
1511 CHECK_SYMBOL (symbol); 1446 CHECK_SYMBOL (symbol);
1512 if (EQ (symbol, Qt) || 1447 if (EQ (symbol, Qt) ||
1513 EQ (symbol, Qnil) || 1448 EQ (symbol, Qnil) ||
1535 if (!NILP (constants)) 1470 if (!NILP (constants))
1536 CHECK_VECTOR (constants); 1471 CHECK_VECTOR (constants);
1537 f->constants = constants; 1472 f->constants = constants;
1538 1473
1539 CHECK_NATNUM (stack_depth); 1474 CHECK_NATNUM (stack_depth);
1540 f->stack_depth = XINT (stack_depth); 1475 f->stack_depth = (unsigned short) XINT (stack_depth);
1541 1476
1542 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 1477 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
1543 if (!NILP (Vcurrent_compiled_function_annotation)) 1478 if (!NILP (Vcurrent_compiled_function_annotation))
1544 f->annotated = Fcopy (Vcurrent_compiled_function_annotation); 1479 f->annotated = Fcopy (Vcurrent_compiled_function_annotation);
1545 else if (!NILP (Vload_file_name_internal_the_purecopy)) 1480 else if (!NILP (Vload_file_name_internal_the_purecopy))
1598 Lisp_Symbol *p; 1533 Lisp_Symbol *p;
1599 1534
1600 CHECK_STRING (name); 1535 CHECK_STRING (name);
1601 1536
1602 ALLOCATE_FIXED_TYPE (symbol, Lisp_Symbol, p); 1537 ALLOCATE_FIXED_TYPE (symbol, Lisp_Symbol, p);
1603 set_lheader_implementation (&(p->lheader), &lrecord_symbol); 1538 set_lheader_implementation (&p->lheader, &lrecord_symbol);
1604 p->name = XSTRING (name); 1539 p->name = XSTRING (name);
1605 p->plist = Qnil; 1540 p->plist = Qnil;
1606 p->value = Qunbound; 1541 p->value = Qunbound;
1607 p->function = Qunbound; 1542 p->function = Qunbound;
1608 symbol_next (p) = 0; 1543 symbol_next (p) = 0;
1622 allocate_extent (void) 1557 allocate_extent (void)
1623 { 1558 {
1624 struct extent *e; 1559 struct extent *e;
1625 1560
1626 ALLOCATE_FIXED_TYPE (extent, struct extent, e); 1561 ALLOCATE_FIXED_TYPE (extent, struct extent, e);
1627 set_lheader_implementation (&(e->lheader), &lrecord_extent); 1562 set_lheader_implementation (&e->lheader, &lrecord_extent);
1628 extent_object (e) = Qnil; 1563 extent_object (e) = Qnil;
1629 set_extent_start (e, -1); 1564 set_extent_start (e, -1);
1630 set_extent_end (e, -1); 1565 set_extent_end (e, -1);
1631 e->plist = Qnil; 1566 e->plist = Qnil;
1632 1567
1652 { 1587 {
1653 Lisp_Object val; 1588 Lisp_Object val;
1654 Lisp_Event *e; 1589 Lisp_Event *e;
1655 1590
1656 ALLOCATE_FIXED_TYPE (event, Lisp_Event, e); 1591 ALLOCATE_FIXED_TYPE (event, Lisp_Event, e);
1657 set_lheader_implementation (&(e->lheader), &lrecord_event); 1592 set_lheader_implementation (&e->lheader, &lrecord_event);
1658 1593
1659 XSETEVENT (val, e); 1594 XSETEVENT (val, e);
1660 return val; 1595 return val;
1661 } 1596 }
1662 1597
1675 { 1610 {
1676 Lisp_Object val; 1611 Lisp_Object val;
1677 Lisp_Marker *p; 1612 Lisp_Marker *p;
1678 1613
1679 ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); 1614 ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p);
1680 set_lheader_implementation (&(p->lheader), &lrecord_marker); 1615 set_lheader_implementation (&p->lheader, &lrecord_marker);
1681 p->buffer = 0; 1616 p->buffer = 0;
1682 p->memind = 0; 1617 p->memind = 0;
1683 marker_next (p) = 0; 1618 marker_next (p) = 0;
1684 marker_prev (p) = 0; 1619 marker_prev (p) = 0;
1685 p->insertion_type = 0; 1620 p->insertion_type = 0;
1692 { 1627 {
1693 Lisp_Object val; 1628 Lisp_Object val;
1694 Lisp_Marker *p; 1629 Lisp_Marker *p;
1695 1630
1696 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p); 1631 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p);
1697 set_lheader_implementation (&(p->lheader), &lrecord_marker); 1632 set_lheader_implementation (&p->lheader, &lrecord_marker);
1698 p->buffer = 0; 1633 p->buffer = 0;
1699 p->memind = 0; 1634 p->memind = 0;
1700 marker_next (p) = 0; 1635 marker_next (p) = 0;
1701 marker_prev (p) = 0; 1636 marker_prev (p) = 0;
1702 p->insertion_type = 0; 1637 p->insertion_type = 0;
1750 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT(0, 1) }, 1685 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT(0, 1) },
1751 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, 1686 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) },
1752 { XD_END } 1687 { XD_END }
1753 }; 1688 };
1754 1689
1755 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string, 1690 /* We store the string's extent info as the first element of the string's
1756 mark_string, print_string, 1691 property list; and the string's MODIFF as the first or second element
1757 /* 1692 of the string's property list (depending on whether the extent info
1758 * No `finalize', or `hash' methods. 1693 is present), but only if the string has been modified. This is ugly
1759 * internal_hash already knows how 1694 but it reduces the memory allocated for the string in the vast
1760 * to hash strings and finalization 1695 majority of cases, where the string is never modified and has no
1761 * is done with the 1696 extent info.
1762 * ADDITIONAL_FREE_string macro, 1697
1763 * which is the standard way to do 1698 #### This means you can't use an int as a key in a string's plist. */
1764 * finalization when using 1699
1765 * SWEEP_FIXED_TYPE_BLOCK(). 1700 static Lisp_Object *
1766 */ 1701 string_plist_ptr (Lisp_Object string)
1767 0, string_equal, 0, 1702 {
1768 string_description, 1703 Lisp_Object *ptr = &XSTRING (string)->plist;
1769 Lisp_String); 1704
1705 if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr)))
1706 ptr = &XCDR (*ptr);
1707 if (CONSP (*ptr) && INTP (XCAR (*ptr)))
1708 ptr = &XCDR (*ptr);
1709 return ptr;
1710 }
1711
1712 static Lisp_Object
1713 string_getprop (Lisp_Object string, Lisp_Object property)
1714 {
1715 return external_plist_get (string_plist_ptr (string), property, 0, ERROR_ME);
1716 }
1717
1718 static int
1719 string_putprop (Lisp_Object string, Lisp_Object property, Lisp_Object value)
1720 {
1721 external_plist_put (string_plist_ptr (string), property, value, 0, ERROR_ME);
1722 return 1;
1723 }
1724
1725 static int
1726 string_remprop (Lisp_Object string, Lisp_Object property)
1727 {
1728 return external_remprop (string_plist_ptr (string), property, 0, ERROR_ME);
1729 }
1730
1731 static Lisp_Object
1732 string_plist (Lisp_Object string)
1733 {
1734 return *string_plist_ptr (string);
1735 }
1736
1737 /* No `finalize', or `hash' methods.
1738 internal_hash() already knows how to hash strings and finalization
1739 is done with the ADDITIONAL_FREE_string macro, which is the
1740 standard way to do finalization when using
1741 SWEEP_FIXED_TYPE_BLOCK(). */
1742 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS ("string", string,
1743 mark_string, print_string,
1744 0, string_equal, 0,
1745 string_description,
1746 string_getprop,
1747 string_putprop,
1748 string_remprop,
1749 string_plist,
1750 Lisp_String);
1770 1751
1771 /* String blocks contain this many useful bytes. */ 1752 /* String blocks contain this many useful bytes. */
1772 #define STRING_CHARS_BLOCK_SIZE \ 1753 #define STRING_CHARS_BLOCK_SIZE \
1773 ((Bytecount) (8192 - MALLOC_OVERHEAD - \ 1754 ((Bytecount) (8192 - MALLOC_OVERHEAD - \
1774 ((2 * sizeof (struct string_chars_block *)) \ 1755 ((2 * sizeof (struct string_chars_block *)) \
1866 1847
1867 assert (length >= 0 && fullsize > 0); 1848 assert (length >= 0 && fullsize > 0);
1868 1849
1869 /* Allocate the string header */ 1850 /* Allocate the string header */
1870 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); 1851 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
1871 set_lheader_implementation (&(s->lheader), &lrecord_string); 1852 set_lheader_implementation (&s->lheader, &lrecord_string);
1872 1853
1873 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize) 1854 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize)
1874 ? xnew_array (Bufbyte, length + 1) 1855 ? xnew_array (Bufbyte, length + 1)
1875 : allocate_string_chars_struct (s, fullsize)->chars); 1856 : allocate_string_chars_struct (s, fullsize)->chars);
1876 1857
2109 2090
2110 2091
2111 /* Take some raw memory, which MUST already be in internal format, 2092 /* Take some raw memory, which MUST already be in internal format,
2112 and package it up into a Lisp string. */ 2093 and package it up into a Lisp string. */
2113 Lisp_Object 2094 Lisp_Object
2114 make_string (CONST Bufbyte *contents, Bytecount length) 2095 make_string (const Bufbyte *contents, Bytecount length)
2115 { 2096 {
2116 Lisp_Object val; 2097 Lisp_Object val;
2117 2098
2118 /* Make sure we find out about bad make_string's when they happen */ 2099 /* Make sure we find out about bad make_string's when they happen */
2119 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) 2100 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE)
2126 } 2107 }
2127 2108
2128 /* Take some raw memory, encoded in some external data format, 2109 /* Take some raw memory, encoded in some external data format,
2129 and convert it into a Lisp string. */ 2110 and convert it into a Lisp string. */
2130 Lisp_Object 2111 Lisp_Object
2131 make_ext_string (CONST Extbyte *contents, EMACS_INT length, 2112 make_ext_string (const Extbyte *contents, EMACS_INT length,
2132 Lisp_Object coding_system) 2113 Lisp_Object coding_system)
2133 { 2114 {
2134 Lisp_Object string; 2115 Lisp_Object string;
2135 TO_INTERNAL_FORMAT (DATA, (contents, length), 2116 TO_INTERNAL_FORMAT (DATA, (contents, length),
2136 LISP_STRING, string, 2117 LISP_STRING, string,
2137 coding_system); 2118 coding_system);
2138 return string; 2119 return string;
2139 } 2120 }
2140 2121
2141 Lisp_Object 2122 Lisp_Object
2142 build_string (CONST char *str) 2123 build_string (const char *str)
2143 { 2124 {
2144 /* Some strlen's crash and burn if passed null. */ 2125 /* Some strlen's crash and burn if passed null. */
2145 return make_string ((CONST Bufbyte *) str, (str ? strlen(str) : 0)); 2126 return make_string ((const Bufbyte *) str, (str ? strlen(str) : 0));
2146 } 2127 }
2147 2128
2148 Lisp_Object 2129 Lisp_Object
2149 build_ext_string (CONST char *str, Lisp_Object coding_system) 2130 build_ext_string (const char *str, Lisp_Object coding_system)
2150 { 2131 {
2151 /* Some strlen's crash and burn if passed null. */ 2132 /* Some strlen's crash and burn if passed null. */
2152 return make_ext_string ((CONST Extbyte *) str, (str ? strlen(str) : 0), 2133 return make_ext_string ((const Extbyte *) str, (str ? strlen(str) : 0),
2153 coding_system); 2134 coding_system);
2154 } 2135 }
2155 2136
2156 Lisp_Object 2137 Lisp_Object
2157 build_translated_string (CONST char *str) 2138 build_translated_string (const char *str)
2158 { 2139 {
2159 return build_string (GETTEXT (str)); 2140 return build_string (GETTEXT (str));
2160 } 2141 }
2161 2142
2162 Lisp_Object 2143 Lisp_Object
2163 make_string_nocopy (CONST Bufbyte *contents, Bytecount length) 2144 make_string_nocopy (const Bufbyte *contents, Bytecount length)
2164 { 2145 {
2165 Lisp_String *s; 2146 Lisp_String *s;
2166 Lisp_Object val; 2147 Lisp_Object val;
2167 2148
2168 /* Make sure we find out about bad make_string_nocopy's when they happen */ 2149 /* Make sure we find out about bad make_string_nocopy's when they happen */
2170 bytecount_to_charcount (contents, length); /* Just for the assertions */ 2151 bytecount_to_charcount (contents, length); /* Just for the assertions */
2171 #endif 2152 #endif
2172 2153
2173 /* Allocate the string header */ 2154 /* Allocate the string header */
2174 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); 2155 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
2175 set_lheader_implementation (&(s->lheader), &lrecord_string); 2156 set_lheader_implementation (&s->lheader, &lrecord_string);
2176 SET_C_READONLY_RECORD_HEADER (&s->lheader); 2157 SET_C_READONLY_RECORD_HEADER (&s->lheader);
2177 s->plist = Qnil; 2158 s->plist = Qnil;
2178 set_string_data (s, (Bufbyte *)contents); 2159 set_string_data (s, (Bufbyte *)contents);
2179 set_string_length (s, length); 2160 set_string_length (s, length);
2180 2161
2225 { 2206 {
2226 struct lrecord_header *lheader = XRECORD_LHEADER (chain); 2207 struct lrecord_header *lheader = XRECORD_LHEADER (chain);
2227 struct free_lcrecord_header *free_header = 2208 struct free_lcrecord_header *free_header =
2228 (struct free_lcrecord_header *) lheader; 2209 (struct free_lcrecord_header *) lheader;
2229 2210
2230 #ifdef ERROR_CHECK_GC 2211 gc_checking_assert
2231 CONST struct lrecord_implementation *implementation 2212 (/* There should be no other pointers to the free list. */
2232 = LHEADER_IMPLEMENTATION(lheader); 2213 ! MARKED_RECORD_HEADER_P (lheader)
2233 2214 &&
2234 /* There should be no other pointers to the free list. */ 2215 /* Only lcrecords should be here. */
2235 assert (!MARKED_RECORD_HEADER_P (lheader)); 2216 ! LHEADER_IMPLEMENTATION (lheader)->basic_p
2236 /* Only lcrecords should be here. */ 2217 &&
2237 assert (!implementation->basic_p); 2218 /* Only free lcrecords should be here. */
2238 /* Only free lcrecords should be here. */ 2219 free_header->lcheader.free
2239 assert (free_header->lcheader.free); 2220 &&
2240 /* The type of the lcrecord must be right. */ 2221 /* The type of the lcrecord must be right. */
2241 assert (implementation == list->implementation); 2222 LHEADER_IMPLEMENTATION (lheader) == list->implementation
2242 /* So must the size. */ 2223 &&
2243 assert (implementation->static_size == 0 2224 /* So must the size. */
2244 || implementation->static_size == list->size); 2225 (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 ||
2245 #endif /* ERROR_CHECK_GC */ 2226 LHEADER_IMPLEMENTATION (lheader)->static_size == list->size)
2227 );
2246 2228
2247 MARK_RECORD_HEADER (lheader); 2229 MARK_RECORD_HEADER (lheader);
2248 chain = free_header->chain; 2230 chain = free_header->chain;
2249 } 2231 }
2250 2232
2254 DEFINE_LRECORD_IMPLEMENTATION ("lcrecord-list", lcrecord_list, 2236 DEFINE_LRECORD_IMPLEMENTATION ("lcrecord-list", lcrecord_list,
2255 mark_lcrecord_list, internal_object_printer, 2237 mark_lcrecord_list, internal_object_printer,
2256 0, 0, 0, 0, struct lcrecord_list); 2238 0, 0, 0, 0, struct lcrecord_list);
2257 Lisp_Object 2239 Lisp_Object
2258 make_lcrecord_list (size_t size, 2240 make_lcrecord_list (size_t size,
2259 CONST struct lrecord_implementation *implementation) 2241 const struct lrecord_implementation *implementation)
2260 { 2242 {
2261 struct lcrecord_list *p = alloc_lcrecord_type (struct lcrecord_list, 2243 struct lcrecord_list *p = alloc_lcrecord_type (struct lcrecord_list,
2262 &lrecord_lcrecord_list); 2244 &lrecord_lcrecord_list);
2263 Lisp_Object val; 2245 Lisp_Object val;
2264 2246
2278 Lisp_Object val = list->free; 2260 Lisp_Object val = list->free;
2279 struct free_lcrecord_header *free_header = 2261 struct free_lcrecord_header *free_header =
2280 (struct free_lcrecord_header *) XPNTR (val); 2262 (struct free_lcrecord_header *) XPNTR (val);
2281 2263
2282 #ifdef ERROR_CHECK_GC 2264 #ifdef ERROR_CHECK_GC
2283 struct lrecord_header *lheader = 2265 struct lrecord_header *lheader = &free_header->lcheader.lheader;
2284 (struct lrecord_header *) free_header;
2285 CONST struct lrecord_implementation *implementation
2286 = LHEADER_IMPLEMENTATION (lheader);
2287 2266
2288 /* There should be no other pointers to the free list. */ 2267 /* There should be no other pointers to the free list. */
2289 assert (!MARKED_RECORD_HEADER_P (lheader)); 2268 assert (! MARKED_RECORD_HEADER_P (lheader));
2290 /* Only lcrecords should be here. */ 2269 /* Only lcrecords should be here. */
2291 assert (!implementation->basic_p); 2270 assert (! LHEADER_IMPLEMENTATION (lheader)->basic_p);
2292 /* Only free lcrecords should be here. */ 2271 /* Only free lcrecords should be here. */
2293 assert (free_header->lcheader.free); 2272 assert (free_header->lcheader.free);
2294 /* The type of the lcrecord must be right. */ 2273 /* The type of the lcrecord must be right. */
2295 assert (implementation == list->implementation); 2274 assert (LHEADER_IMPLEMENTATION (lheader) == list->implementation);
2296 /* So must the size. */ 2275 /* So must the size. */
2297 assert (implementation->static_size == 0 2276 assert (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 ||
2298 || implementation->static_size == list->size); 2277 LHEADER_IMPLEMENTATION (lheader)->static_size == list->size);
2299 #endif /* ERROR_CHECK_GC */ 2278 #endif /* ERROR_CHECK_GC */
2279
2300 list->free = free_header->chain; 2280 list->free = free_header->chain;
2301 free_header->lcheader.free = 0; 2281 free_header->lcheader.free = 0;
2302 return val; 2282 return val;
2303 } 2283 }
2304 else 2284 else
2305 { 2285 {
2306 Lisp_Object val; 2286 Lisp_Object val;
2307 2287
2308 XSETOBJ (val, Lisp_Type_Record, 2288 XSETOBJ (val, alloc_lcrecord (list->size, list->implementation));
2309 alloc_lcrecord (list->size, list->implementation));
2310 return val; 2289 return val;
2311 } 2290 }
2312 } 2291 }
2313 2292
2314 void 2293 void
2315 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord) 2294 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord)
2316 { 2295 {
2317 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list); 2296 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list);
2318 struct free_lcrecord_header *free_header = 2297 struct free_lcrecord_header *free_header =
2319 (struct free_lcrecord_header *) XPNTR (lcrecord); 2298 (struct free_lcrecord_header *) XPNTR (lcrecord);
2320 struct lrecord_header *lheader = 2299 struct lrecord_header *lheader = &free_header->lcheader.lheader;
2321 (struct lrecord_header *) free_header; 2300 const struct lrecord_implementation *implementation
2322 CONST struct lrecord_implementation *implementation
2323 = LHEADER_IMPLEMENTATION (lheader); 2301 = LHEADER_IMPLEMENTATION (lheader);
2324 2302
2325 #ifdef ERROR_CHECK_GC
2326 /* Make sure the size is correct. This will catch, for example, 2303 /* Make sure the size is correct. This will catch, for example,
2327 putting a window configuration on the wrong free list. */ 2304 putting a window configuration on the wrong free list. */
2328 if (implementation->size_in_bytes_method) 2305 gc_checking_assert ((implementation->size_in_bytes_method ?
2329 assert (implementation->size_in_bytes_method (lheader) == list->size); 2306 implementation->size_in_bytes_method (lheader) :
2330 else 2307 implementation->static_size)
2331 assert (implementation->static_size == list->size); 2308 == list->size);
2332 #endif /* ERROR_CHECK_GC */
2333 2309
2334 if (implementation->finalizer) 2310 if (implementation->finalizer)
2335 implementation->finalizer (lheader, 0); 2311 implementation->finalizer (lheader, 0);
2336 free_header->chain = list->free; 2312 free_header->chain = list->free;
2337 free_header->lcheader.free = 1; 2313 free_header->lcheader.free = 1;
2351 (obj)) 2327 (obj))
2352 { 2328 {
2353 return obj; 2329 return obj;
2354 } 2330 }
2355 2331
2356
2357 2332
2358 /************************************************************************/ 2333 /************************************************************************/
2359 /* Garbage Collection */ 2334 /* Garbage Collection */
2360 /************************************************************************/ 2335 /************************************************************************/
2361 2336
2362 /* This will be used more extensively In The Future */ 2337 /* All the built-in lisp object types are enumerated in `enum lrecord_type'.
2363 static int last_lrecord_type_index_assigned; 2338 Additional ones may be defined by a module (none yet). We leave some
2364 2339 room in `lrecord_implementations_table' for such new lisp object types. */
2365 CONST struct lrecord_implementation *lrecord_implementations_table[128]; 2340 const struct lrecord_implementation *lrecord_implementations_table[(unsigned int)lrecord_type_last_built_in_type + MODULE_DEFINABLE_TYPE_COUNT];
2366 #define max_lrecord_type (countof (lrecord_implementations_table) - 1) 2341 unsigned int lrecord_type_count = (unsigned int)lrecord_type_last_built_in_type;
2342 /* Object marker functions are in the lrecord_implementation structure.
2343 But copying them to a parallel array is much more cache-friendly.
2344 This hack speeds up (garbage-collect) by about 5%. */
2345 Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object);
2367 2346
2368 struct gcpro *gcprolist; 2347 struct gcpro *gcprolist;
2369 2348
2370 /* 415 used Mly 29-Jun-93 */ 2349 /* 415 used Mly 29-Jun-93 */
2371 /* 1327 used slb 28-Feb-98 */ 2350 /* 1327 used slb 28-Feb-98 */
2373 #ifdef HAVE_SHLIB 2352 #ifdef HAVE_SHLIB
2374 #define NSTATICS 4000 2353 #define NSTATICS 4000
2375 #else 2354 #else
2376 #define NSTATICS 2000 2355 #define NSTATICS 2000
2377 #endif 2356 #endif
2378 /* Not "static" because of linker lossage on some systems */ 2357
2379 Lisp_Object *staticvec[NSTATICS] 2358 /* Not "static" because used by dumper.c */
2380 /* Force it into data space! */ 2359 Lisp_Object *staticvec[NSTATICS];
2381 = {0}; 2360 int staticidx;
2382 static int staticidx;
2383 2361
2384 /* Put an entry in staticvec, pointing at the variable whose address is given 2362 /* Put an entry in staticvec, pointing at the variable whose address is given
2385 */ 2363 */
2386 void 2364 void
2387 staticpro (Lisp_Object *varaddress) 2365 staticpro (Lisp_Object *varaddress)
2388 { 2366 {
2389 if (staticidx >= countof (staticvec)) 2367 /* #### This is now a dubious assert() since this routine may be called */
2390 /* #### This is now a dubious abort() since this routine may be called */ 2368 /* by Lisp attempting to load a DLL. */
2391 /* by Lisp attempting to load a DLL. */ 2369 assert (staticidx < countof (staticvec));
2392 abort ();
2393 staticvec[staticidx++] = varaddress; 2370 staticvec[staticidx++] = varaddress;
2394 } 2371 }
2395 2372
2396 /* Not "static" because of linker lossage on some systems */ 2373
2397 Lisp_Object *staticvec_nodump[200] 2374 Lisp_Object *staticvec_nodump[200];
2398 /* Force it into data space! */ 2375 int staticidx_nodump;
2399 = {0};
2400 static int staticidx_nodump;
2401 2376
2402 /* Put an entry in staticvec_nodump, pointing at the variable whose address is given 2377 /* Put an entry in staticvec_nodump, pointing at the variable whose address is given
2403 */ 2378 */
2404 void 2379 void
2405 staticpro_nodump (Lisp_Object *varaddress) 2380 staticpro_nodump (Lisp_Object *varaddress)
2406 { 2381 {
2407 if (staticidx_nodump >= countof (staticvec_nodump)) 2382 /* #### This is now a dubious assert() since this routine may be called */
2408 /* #### This is now a dubious abort() since this routine may be called */ 2383 /* by Lisp attempting to load a DLL. */
2409 /* by Lisp attempting to load a DLL. */ 2384 assert (staticidx_nodump < countof (staticvec_nodump));
2410 abort ();
2411 staticvec_nodump[staticidx_nodump++] = varaddress; 2385 staticvec_nodump[staticidx_nodump++] = varaddress;
2412 } 2386 }
2413 2387
2414 /* Not "static" because of linker lossage on some systems */ 2388
2415 struct 2389 struct pdump_dumpstructinfo dumpstructvec[200];
2416 { 2390 int dumpstructidx;
2417 void *data;
2418 const struct struct_description *desc;
2419 } dumpstructvec[200];
2420
2421 static int dumpstructidx;
2422 2391
2423 /* Put an entry in dumpstructvec, pointing at the variable whose address is given 2392 /* Put an entry in dumpstructvec, pointing at the variable whose address is given
2424 */ 2393 */
2425 void 2394 void
2426 dumpstruct (void *varaddress, const struct struct_description *desc) 2395 dumpstruct (void *varaddress, const struct struct_description *desc)
2427 { 2396 {
2428 if (dumpstructidx >= countof (dumpstructvec)) 2397 assert (dumpstructidx < countof (dumpstructvec));
2429 abort ();
2430 dumpstructvec[dumpstructidx].data = varaddress; 2398 dumpstructvec[dumpstructidx].data = varaddress;
2431 dumpstructvec[dumpstructidx].desc = desc; 2399 dumpstructvec[dumpstructidx].desc = desc;
2432 dumpstructidx++; 2400 dumpstructidx++;
2433 } 2401 }
2434 2402
2403 struct pdump_dumpopaqueinfo dumpopaquevec[250];
2404 int dumpopaqueidx;
2405
2406 /* Put an entry in dumpopaquevec, pointing at the variable whose address is given
2407 */
2408 void
2409 dumpopaque (void *varaddress, size_t size)
2410 {
2411 assert (dumpopaqueidx < countof (dumpopaquevec));
2412
2413 dumpopaquevec[dumpopaqueidx].data = varaddress;
2414 dumpopaquevec[dumpopaqueidx].size = size;
2415 dumpopaqueidx++;
2416 }
2417
2435 Lisp_Object *pdump_wirevec[50]; 2418 Lisp_Object *pdump_wirevec[50];
2436 static int pdump_wireidx; 2419 int pdump_wireidx;
2437 2420
2438 /* Put an entry in pdump_wirevec, pointing at the variable whose address is given 2421 /* Put an entry in pdump_wirevec, pointing at the variable whose address is given
2439 */ 2422 */
2440 void 2423 void
2441 pdump_wire (Lisp_Object *varaddress) 2424 pdump_wire (Lisp_Object *varaddress)
2442 { 2425 {
2443 if (pdump_wireidx >= countof (pdump_wirevec)) 2426 assert (pdump_wireidx < countof (pdump_wirevec));
2444 abort ();
2445 pdump_wirevec[pdump_wireidx++] = varaddress; 2427 pdump_wirevec[pdump_wireidx++] = varaddress;
2446 } 2428 }
2447 2429
2448 2430
2449 Lisp_Object *pdump_wirevec_list[50]; 2431 Lisp_Object *pdump_wirevec_list[50];
2450 static int pdump_wireidx_list; 2432 int pdump_wireidx_list;
2451 2433
2452 /* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given 2434 /* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given
2453 */ 2435 */
2454 void 2436 void
2455 pdump_wire_list (Lisp_Object *varaddress) 2437 pdump_wire_list (Lisp_Object *varaddress)
2456 { 2438 {
2457 if (pdump_wireidx_list >= countof (pdump_wirevec_list)) 2439 assert (pdump_wireidx_list < countof (pdump_wirevec_list));
2458 abort ();
2459 pdump_wirevec_list[pdump_wireidx_list++] = varaddress; 2440 pdump_wirevec_list[pdump_wireidx_list++] = varaddress;
2460 } 2441 }
2442
2443 #ifdef ERROR_CHECK_GC
2444 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \
2445 struct lrecord_header * GCLI_lh = (lheader); \
2446 assert (GCLI_lh != 0); \
2447 assert (GCLI_lh->type < lrecord_type_count); \
2448 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) || \
2449 (MARKED_RECORD_HEADER_P (GCLI_lh) && \
2450 LISP_READONLY_RECORD_HEADER_P (GCLI_lh))); \
2451 } while (0)
2452 #else
2453 #define GC_CHECK_LHEADER_INVARIANTS(lheader)
2454 #endif
2461 2455
2462 2456
2463 /* Mark reference to a Lisp_Object. If the object referred to has not been 2457 /* Mark reference to a Lisp_Object. If the object referred to has not been
2464 seen yet, recursively mark all the references contained in it. */ 2458 seen yet, recursively mark all the references contained in it. */
2465 2459
2466 void 2460 void
2467 mark_object (Lisp_Object obj) 2461 mark_object (Lisp_Object obj)
2468 { 2462 {
2469 tail_recurse: 2463 tail_recurse:
2470 2464
2471 #ifdef ERROR_CHECK_GC
2472 assert (! (EQ (obj, Qnull_pointer)));
2473 #endif
2474 /* Checks we used to perform */ 2465 /* Checks we used to perform */
2475 /* if (EQ (obj, Qnull_pointer)) return; */ 2466 /* if (EQ (obj, Qnull_pointer)) return; */
2476 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ 2467 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */
2477 /* if (PURIFIED (XPNTR (obj))) return; */ 2468 /* if (PURIFIED (XPNTR (obj))) return; */
2478 2469
2479 if (XTYPE (obj) == Lisp_Type_Record) 2470 if (XTYPE (obj) == Lisp_Type_Record)
2480 { 2471 {
2481 struct lrecord_header *lheader = XRECORD_LHEADER (obj); 2472 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
2482 #if defined (ERROR_CHECK_GC) 2473
2483 assert (lheader->type <= last_lrecord_type_index_assigned); 2474 GC_CHECK_LHEADER_INVARIANTS (lheader);
2484 #endif 2475
2485 if (C_READONLY_RECORD_HEADER_P (lheader)) 2476 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p ||
2486 return; 2477 ! ((struct lcrecord_header *) lheader)->free);
2487 2478
2488 if (! MARKED_RECORD_HEADER_P (lheader) && 2479 /* All c_readonly objects have their mark bit set,
2489 ! UNMARKABLE_RECORD_HEADER_P (lheader)) 2480 so that we only need to check the mark bit here. */
2481 if (! MARKED_RECORD_HEADER_P (lheader))
2490 { 2482 {
2491 CONST struct lrecord_implementation *implementation =
2492 LHEADER_IMPLEMENTATION (lheader);
2493 MARK_RECORD_HEADER (lheader); 2483 MARK_RECORD_HEADER (lheader);
2494 #ifdef ERROR_CHECK_GC 2484
2495 if (!implementation->basic_p) 2485 if (RECORD_MARKER (lheader))
2496 assert (! ((struct lcrecord_header *) lheader)->free);
2497 #endif
2498 if (implementation->marker)
2499 { 2486 {
2500 obj = implementation->marker (obj); 2487 obj = RECORD_MARKER (lheader) (obj);
2501 if (!NILP (obj)) goto tail_recurse; 2488 if (!NILP (obj)) goto tail_recurse;
2502 } 2489 }
2503 } 2490 }
2504 } 2491 }
2505 } 2492 }
2535 static int gc_count_short_string_total_size; 2522 static int gc_count_short_string_total_size;
2536 2523
2537 /* static int gc_count_total_records_used, gc_count_records_total_size; */ 2524 /* static int gc_count_total_records_used, gc_count_records_total_size; */
2538 2525
2539 2526
2540 int
2541 lrecord_type_index (CONST struct lrecord_implementation *implementation)
2542 {
2543 int type_index = *(implementation->lrecord_type_index);
2544 /* Have to do this circuitous validation test because of problems
2545 dumping out initialized variables (ie can't set xxx_type_index to -1
2546 because that would make xxx_type_index read-only in a dumped emacs. */
2547 if (type_index < 0 || type_index > max_lrecord_type
2548 || lrecord_implementations_table[type_index] != implementation)
2549 {
2550 assert (last_lrecord_type_index_assigned < max_lrecord_type);
2551 type_index = ++last_lrecord_type_index_assigned;
2552 lrecord_implementations_table[type_index] = implementation;
2553 *(implementation->lrecord_type_index) = type_index;
2554 }
2555 return type_index;
2556 }
2557
2558 /* stats on lcrecords in use - kinda kludgy */ 2527 /* stats on lcrecords in use - kinda kludgy */
2559 2528
2560 static struct 2529 static struct
2561 { 2530 {
2562 int instances_in_use; 2531 int instances_in_use;
2565 int bytes_freed; 2534 int bytes_freed;
2566 int instances_on_free_list; 2535 int instances_on_free_list;
2567 } lcrecord_stats [countof (lrecord_implementations_table)]; 2536 } lcrecord_stats [countof (lrecord_implementations_table)];
2568 2537
2569 static void 2538 static void
2570 tick_lcrecord_stats (CONST struct lrecord_header *h, int free_p) 2539 tick_lcrecord_stats (const struct lrecord_header *h, int free_p)
2571 { 2540 {
2572 CONST struct lrecord_implementation *implementation = 2541 unsigned int type_index = h->type;
2573 LHEADER_IMPLEMENTATION (h);
2574 int type_index = lrecord_type_index (implementation);
2575 2542
2576 if (((struct lcrecord_header *) h)->free) 2543 if (((struct lcrecord_header *) h)->free)
2577 { 2544 {
2578 assert (!free_p); 2545 gc_checking_assert (!free_p);
2579 lcrecord_stats[type_index].instances_on_free_list++; 2546 lcrecord_stats[type_index].instances_on_free_list++;
2580 } 2547 }
2581 else 2548 else
2582 { 2549 {
2583 size_t sz = (implementation->size_in_bytes_method 2550 const struct lrecord_implementation *implementation =
2584 ? implementation->size_in_bytes_method (h) 2551 LHEADER_IMPLEMENTATION (h);
2585 : implementation->static_size); 2552
2586 2553 size_t sz = (implementation->size_in_bytes_method ?
2554 implementation->size_in_bytes_method (h) :
2555 implementation->static_size);
2587 if (free_p) 2556 if (free_p)
2588 { 2557 {
2589 lcrecord_stats[type_index].instances_freed++; 2558 lcrecord_stats[type_index].instances_freed++;
2590 lcrecord_stats[type_index].bytes_freed += sz; 2559 lcrecord_stats[type_index].bytes_freed += sz;
2591 } 2560 }
2619 other object. */ 2588 other object. */
2620 2589
2621 for (header = *prev; header; header = header->next) 2590 for (header = *prev; header; header = header->next)
2622 { 2591 {
2623 struct lrecord_header *h = &(header->lheader); 2592 struct lrecord_header *h = &(header->lheader);
2624 if (!C_READONLY_RECORD_HEADER_P(h) 2593
2625 && !MARKED_RECORD_HEADER_P (h) 2594 GC_CHECK_LHEADER_INVARIANTS (h);
2626 && ! (header->free)) 2595
2596 if (! MARKED_RECORD_HEADER_P (h) && ! header->free)
2627 { 2597 {
2628 if (LHEADER_IMPLEMENTATION (h)->finalizer) 2598 if (LHEADER_IMPLEMENTATION (h)->finalizer)
2629 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0); 2599 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0);
2630 } 2600 }
2631 } 2601 }
2632 2602
2633 for (header = *prev; header; ) 2603 for (header = *prev; header; )
2634 { 2604 {
2635 struct lrecord_header *h = &(header->lheader); 2605 struct lrecord_header *h = &(header->lheader);
2636 if (C_READONLY_RECORD_HEADER_P(h) || MARKED_RECORD_HEADER_P (h)) 2606 if (MARKED_RECORD_HEADER_P (h))
2637 { 2607 {
2638 if (MARKED_RECORD_HEADER_P (h)) 2608 if (! C_READONLY_RECORD_HEADER_P (h))
2639 UNMARK_RECORD_HEADER (h); 2609 UNMARK_RECORD_HEADER (h);
2640 num_used++; 2610 num_used++;
2641 /* total_size += n->implementation->size_in_bytes (h);*/ 2611 /* total_size += n->implementation->size_in_bytes (h);*/
2642 /* #### May modify header->next on a C_READONLY lcrecord */ 2612 /* #### May modify header->next on a C_READONLY lcrecord */
2643 prev = &(header->next); 2613 prev = &(header->next);
2672 their implementation */ 2642 their implementation */
2673 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) 2643 for (bit_vector = *prev; !EQ (bit_vector, Qzero); )
2674 { 2644 {
2675 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); 2645 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector);
2676 int len = v->size; 2646 int len = v->size;
2677 if (C_READONLY_RECORD_HEADER_P(&(v->lheader)) || MARKED_RECORD_P (bit_vector)) 2647 if (MARKED_RECORD_P (bit_vector))
2678 { 2648 {
2679 if (MARKED_RECORD_P (bit_vector)) 2649 if (! C_READONLY_RECORD_HEADER_P(&(v->lheader)))
2680 UNMARK_RECORD_HEADER (&(v->lheader)); 2650 UNMARK_RECORD_HEADER (&(v->lheader));
2681 total_size += len; 2651 total_size += len;
2682 total_storage += 2652 total_storage +=
2683 MALLOC_OVERHEAD + 2653 MALLOC_OVERHEAD +
2684 STRETCHY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, 2654 FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits,
2685 BIT_VECTOR_LONG_STORAGE (len)); 2655 BIT_VECTOR_LONG_STORAGE (len));
2686 num_used++; 2656 num_used++;
2687 /* #### May modify next on a C_READONLY bitvector */ 2657 /* #### May modify next on a C_READONLY bitvector */
2688 prev = &(bit_vector_next (v)); 2658 prev = &(bit_vector_next (v));
2689 bit_vector = *prev; 2659 bit_vector = *prev;
2690 } 2660 }
2731 } \ 2701 } \
2732 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ 2702 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2733 { \ 2703 { \
2734 num_used++; \ 2704 num_used++; \
2735 } \ 2705 } \
2736 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ 2706 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2737 { \ 2707 { \
2738 num_free++; \ 2708 num_free++; \
2739 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ 2709 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \
2740 } \ 2710 } \
2741 else \ 2711 else \
2786 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ 2756 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2787 { \ 2757 { \
2788 SFTB_empty = 0; \ 2758 SFTB_empty = 0; \
2789 num_used++; \ 2759 num_used++; \
2790 } \ 2760 } \
2791 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ 2761 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2792 { \ 2762 { \
2793 num_free++; \ 2763 num_free++; \
2794 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ 2764 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \
2795 } \ 2765 } \
2796 else \ 2766 else \
2965 2935
2966 /* Explicitly free a marker. */ 2936 /* Explicitly free a marker. */
2967 void 2937 void
2968 free_marker (Lisp_Marker *ptr) 2938 free_marker (Lisp_Marker *ptr)
2969 { 2939 {
2970 #ifdef ERROR_CHECK_GC
2971 /* Perhaps this will catch freeing an already-freed marker. */ 2940 /* Perhaps this will catch freeing an already-freed marker. */
2972 Lisp_Object temmy; 2941 gc_checking_assert (ptr->lheader.type = lrecord_type_marker);
2973 XSETMARKER (temmy, ptr);
2974 assert (MARKERP (temmy));
2975 #endif /* ERROR_CHECK_GC */
2976 2942
2977 #ifndef ALLOC_NO_POOLS 2943 #ifndef ALLOC_NO_POOLS
2978 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, ptr); 2944 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, ptr);
2979 #endif /* ALLOC_NO_POOLS */ 2945 #endif /* ALLOC_NO_POOLS */
2980 } 2946 }
3071 assert (!(FREE_STRUCT_P (string))); 3037 assert (!(FREE_STRUCT_P (string)));
3072 3038
3073 size = string_length (string); 3039 size = string_length (string);
3074 fullsize = STRING_FULLSIZE (size); 3040 fullsize = STRING_FULLSIZE (size);
3075 3041
3076 if (BIG_STRING_FULLSIZE_P (fullsize)) 3042 gc_checking_assert (! BIG_STRING_FULLSIZE_P (fullsize));
3077 abort ();
3078 3043
3079 /* Just skip it if it isn't marked. */ 3044 /* Just skip it if it isn't marked. */
3080 if (! MARKED_RECORD_HEADER_P (&(string->lheader))) 3045 if (! MARKED_RECORD_HEADER_P (&(string->lheader)))
3081 { 3046 {
3082 from_pos += fullsize; 3047 from_pos += fullsize;
3134 static void 3099 static void
3135 debug_string_purity_print (Lisp_String *p) 3100 debug_string_purity_print (Lisp_String *p)
3136 { 3101 {
3137 Charcount i; 3102 Charcount i;
3138 Charcount s = string_char_length (p); 3103 Charcount s = string_char_length (p);
3139 putc ('\"', stderr); 3104 stderr_out ("\"");
3140 for (i = 0; i < s; i++) 3105 for (i = 0; i < s; i++)
3141 { 3106 {
3142 Emchar ch = string_char (p, i); 3107 Emchar ch = string_char (p, i);
3143 if (ch < 32 || ch >= 126) 3108 if (ch < 32 || ch >= 126)
3144 stderr_out ("\\%03o", ch); 3109 stderr_out ("\\%03o", ch);
3162 Lisp_String *p = (ptr); \ 3127 Lisp_String *p = (ptr); \
3163 size_t size = string_length (p); \ 3128 size_t size = string_length (p); \
3164 UNMARK_RECORD_HEADER (&(p->lheader)); \ 3129 UNMARK_RECORD_HEADER (&(p->lheader)); \
3165 num_bytes += size; \ 3130 num_bytes += size; \
3166 if (!BIG_STRING_SIZE_P (size)) \ 3131 if (!BIG_STRING_SIZE_P (size)) \
3167 { num_small_bytes += size; \ 3132 { \
3168 num_small_used++; \ 3133 num_small_bytes += size; \
3134 num_small_used++; \
3169 } \ 3135 } \
3170 if (debug) \ 3136 if (debug) \
3171 debug_string_purity_print (p); \ 3137 debug_string_purity_print (p); \
3172 } while (0) 3138 } while (0)
3173 #define ADDITIONAL_FREE_string(ptr) do { \ 3139 #define ADDITIONAL_FREE_string(ptr) do { \
3186 3152
3187 /* I hate duplicating all this crap! */ 3153 /* I hate duplicating all this crap! */
3188 int 3154 int
3189 marked_p (Lisp_Object obj) 3155 marked_p (Lisp_Object obj)
3190 { 3156 {
3191 #ifdef ERROR_CHECK_GC
3192 assert (! (EQ (obj, Qnull_pointer)));
3193 #endif
3194 /* Checks we used to perform. */ 3157 /* Checks we used to perform. */
3195 /* if (EQ (obj, Qnull_pointer)) return 1; */ 3158 /* if (EQ (obj, Qnull_pointer)) return 1; */
3196 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ 3159 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */
3197 /* if (PURIFIED (XPNTR (obj))) return 1; */ 3160 /* if (PURIFIED (XPNTR (obj))) return 1; */
3198 3161
3199 if (XTYPE (obj) == Lisp_Type_Record) 3162 if (XTYPE (obj) == Lisp_Type_Record)
3200 { 3163 {
3201 struct lrecord_header *lheader = XRECORD_LHEADER (obj); 3164 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3202 #if defined (ERROR_CHECK_GC) 3165
3203 assert (lheader->type <= last_lrecord_type_index_assigned); 3166 GC_CHECK_LHEADER_INVARIANTS (lheader);
3204 #endif 3167
3205 return C_READONLY_RECORD_HEADER_P (lheader) || MARKED_RECORD_HEADER_P (lheader); 3168 return MARKED_RECORD_HEADER_P (lheader);
3206 } 3169 }
3207 return 1; 3170 return 1;
3208 } 3171 }
3209 3172
3210 static void 3173 static void
3265 sweep_markers (); 3228 sweep_markers ();
3266 3229
3267 sweep_events (); 3230 sweep_events ();
3268 3231
3269 #ifdef PDUMP 3232 #ifdef PDUMP
3270 /* Unmark all dumped objects */ 3233 pdump_objects_unmark ();
3271 {
3272 int i;
3273 char *p = pdump_rt_list;
3274 if (p)
3275 for (;;)
3276 {
3277 pdump_reloc_table *rt = (pdump_reloc_table *)p;
3278 p += sizeof (pdump_reloc_table);
3279 if (rt->desc)
3280 {
3281 for (i=0; i<rt->count; i++)
3282 {
3283 UNMARK_RECORD_HEADER ((struct lrecord_header *)(*(EMACS_INT *)p));
3284 p += sizeof (EMACS_INT);
3285 }
3286 } else
3287 break;
3288 }
3289 }
3290 #endif 3234 #endif
3291 } 3235 }
3292 3236
3293 /* Clearing for disksave. */ 3237 /* Clearing for disksave. */
3294 3238
3437 char *msg = (STRINGP (Vgc_message) 3381 char *msg = (STRINGP (Vgc_message)
3438 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message)) 3382 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message))
3439 : 0); 3383 : 0);
3440 Lisp_Object args[2], whole_msg; 3384 Lisp_Object args[2], whole_msg;
3441 args[0] = build_string (msg ? msg : 3385 args[0] = build_string (msg ? msg :
3442 GETTEXT ((CONST char *) gc_default_message)); 3386 GETTEXT ((const char *) gc_default_message));
3443 args[1] = build_string ("..."); 3387 args[1] = build_string ("...");
3444 whole_msg = Fconcat (2, args); 3388 whole_msg = Fconcat (2, args);
3445 echo_area_message (f, (Bufbyte *) 0, whole_msg, 0, -1, 3389 echo_area_message (f, (Bufbyte *) 0, whole_msg, 0, -1,
3446 Qgarbage_collecting); 3390 Qgarbage_collecting);
3447 } 3391 }
3589 if (NILP (clear_echo_area (selected_frame (), 3533 if (NILP (clear_echo_area (selected_frame (),
3590 Qgarbage_collecting, 0))) 3534 Qgarbage_collecting, 0)))
3591 { 3535 {
3592 Lisp_Object args[2], whole_msg; 3536 Lisp_Object args[2], whole_msg;
3593 args[0] = build_string (msg ? msg : 3537 args[0] = build_string (msg ? msg :
3594 GETTEXT ((CONST char *) 3538 GETTEXT ((const char *)
3595 gc_default_message)); 3539 gc_default_message));
3596 args[1] = build_string ("... done"); 3540 args[1] = build_string ("... done");
3597 whole_msg = Fconcat (2, args); 3541 whole_msg = Fconcat (2, args);
3598 echo_area_message (selected_frame (), (Bufbyte *) 0, 3542 echo_area_message (selected_frame (), (Bufbyte *) 0,
3599 whole_msg, 0, -1, 3543 whole_msg, 0, -1,
3615 } 3559 }
3616 3560
3617 /* Debugging aids. */ 3561 /* Debugging aids. */
3618 3562
3619 static Lisp_Object 3563 static Lisp_Object
3620 gc_plist_hack (CONST char *name, int value, Lisp_Object tail) 3564 gc_plist_hack (const char *name, int value, Lisp_Object tail)
3621 { 3565 {
3622 /* C doesn't have local functions (or closures, or GC, or readable syntax, 3566 /* C doesn't have local functions (or closures, or GC, or readable syntax,
3623 or portable numeric datatypes, or bit-vectors, or characters, or 3567 or portable numeric datatypes, or bit-vectors, or characters, or
3624 arrays, or exceptions, or ...) */ 3568 arrays, or exceptions, or ...) */
3625 return cons3 (intern (name), make_int (value), tail); 3569 return cons3 (intern (name), make_int (value), tail);
3649 int i; 3593 int i;
3650 int gc_count_vector_total_size = 0; 3594 int gc_count_vector_total_size = 0;
3651 3595
3652 garbage_collect_1 (); 3596 garbage_collect_1 ();
3653 3597
3654 for (i = 0; i <= last_lrecord_type_index_assigned; i++) 3598 for (i = 0; i < lrecord_type_count; i++)
3655 { 3599 {
3656 if (lcrecord_stats[i].bytes_in_use != 0 3600 if (lcrecord_stats[i].bytes_in_use != 0
3657 || lcrecord_stats[i].bytes_freed != 0 3601 || lcrecord_stats[i].bytes_freed != 0
3658 || lcrecord_stats[i].instances_on_free_list != 0) 3602 || lcrecord_stats[i].instances_on_free_list != 0)
3659 { 3603 {
3660 char buf [255]; 3604 char buf [255];
3661 CONST char *name = lrecord_implementations_table[i]->name; 3605 const char *name = lrecord_implementations_table[i]->name;
3662 int len = strlen (name); 3606 int len = strlen (name);
3663 /* save this for the FSFmacs-compatible part of the summary */ 3607 /* save this for the FSFmacs-compatible part of the summary */
3664 if (i == *lrecord_vector.lrecord_type_index) 3608 if (i == lrecord_vector.lrecord_type_index)
3665 gc_count_vector_total_size = 3609 gc_count_vector_total_size =
3666 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed; 3610 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed;
3667 3611
3668 sprintf (buf, "%s-storage", name); 3612 sprintf (buf, "%s-storage", name);
3669 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl); 3613 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl);
3963 #if 1 3907 #if 1
3964 gc_cons_threshold = 500000; /* XEmacs change */ 3908 gc_cons_threshold = 500000; /* XEmacs change */
3965 #else 3909 #else
3966 gc_cons_threshold = 15000; /* debugging */ 3910 gc_cons_threshold = 15000; /* debugging */
3967 #endif 3911 #endif
3968 #ifdef VIRT_ADDR_VARIES
3969 malloc_sbrk_unused = 1<<22; /* A large number */
3970 malloc_sbrk_used = 100000; /* as reasonable as any number */
3971 #endif /* VIRT_ADDR_VARIES */
3972 lrecord_uid_counter = 259; 3912 lrecord_uid_counter = 259;
3973 debug_string_purity = 0; 3913 debug_string_purity = 0;
3974 gcprolist = 0; 3914 gcprolist = 0;
3975 3915
3976 gc_currently_forbidden = 0; 3916 gc_currently_forbidden = 0;
3988 } 3928 }
3989 3929
3990 void 3930 void
3991 init_alloc_once_early (void) 3931 init_alloc_once_early (void)
3992 { 3932 {
3993 int iii;
3994
3995 reinit_alloc_once_early (); 3933 reinit_alloc_once_early ();
3996 3934
3997 last_lrecord_type_index_assigned = -1; 3935 {
3998 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) 3936 int i;
3999 { 3937 for (i = 0; i < countof (lrecord_implementations_table); i++)
4000 lrecord_implementations_table[iii] = 0; 3938 lrecord_implementations_table[i] = 0;
4001 } 3939 }
4002 3940
4003 /* 3941 INIT_LRECORD_IMPLEMENTATION (cons);
4004 * All the staticly 3942 INIT_LRECORD_IMPLEMENTATION (vector);
4005 * defined subr lrecords were initialized with lheader->type == 0. 3943 INIT_LRECORD_IMPLEMENTATION (string);
4006 * See subr_lheader_initializer in lisp.h. Force type index 0 to be 3944 INIT_LRECORD_IMPLEMENTATION (lcrecord_list);
4007 * assigned to lrecord_subr so that those predefined indexes match
4008 * reality.
4009 */
4010 lrecord_type_index (&lrecord_subr);
4011 assert (*(lrecord_subr.lrecord_type_index) == 0);
4012 /*
4013 * The same is true for symbol_value_forward objects, except the
4014 * type is 1.
4015 */
4016 lrecord_type_index (&lrecord_symbol_value_forward);
4017 assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1);
4018 3945
4019 staticidx = 0; 3946 staticidx = 0;
4020 } 3947 }
4021 3948
4022 int pure_bytes_used = 0; 3949 int pure_bytes_used = 0;
4028 } 3955 }
4029 3956
4030 void 3957 void
4031 syms_of_alloc (void) 3958 syms_of_alloc (void)
4032 { 3959 {
4033 defsymbol (&Qpre_gc_hook, "pre-gc-hook"); 3960 DEFSYMBOL (Qpre_gc_hook);
4034 defsymbol (&Qpost_gc_hook, "post-gc-hook"); 3961 DEFSYMBOL (Qpost_gc_hook);
4035 defsymbol (&Qgarbage_collecting, "garbage-collecting"); 3962 DEFSYMBOL (Qgarbage_collecting);
4036 3963
4037 DEFSUBR (Fcons); 3964 DEFSUBR (Fcons);
4038 DEFSUBR (Flist); 3965 DEFSUBR (Flist);
4039 DEFSUBR (Fvector); 3966 DEFSUBR (Fvector);
4040 DEFSUBR (Fbit_vector); 3967 DEFSUBR (Fbit_vector);
4074 4001
4075 DEFVAR_INT ("pure-bytes-used", &pure_bytes_used /* 4002 DEFVAR_INT ("pure-bytes-used", &pure_bytes_used /*
4076 Number of bytes of sharable Lisp data allocated so far. 4003 Number of bytes of sharable Lisp data allocated so far.
4077 */ ); 4004 */ );
4078 4005
4079 #if 0
4080 DEFVAR_INT ("data-bytes-used", &malloc_sbrk_used /*
4081 Number of bytes of unshared memory allocated in this session.
4082 */ );
4083
4084 DEFVAR_INT ("data-bytes-free", &malloc_sbrk_unused /*
4085 Number of bytes of unshared memory remaining available in this session.
4086 */ );
4087 #endif
4088
4089 #ifdef DEBUG_XEMACS 4006 #ifdef DEBUG_XEMACS
4090 DEFVAR_INT ("debug-allocation", &debug_allocation /* 4007 DEFVAR_INT ("debug-allocation", &debug_allocation /*
4091 If non-zero, print out information to stderr about all objects allocated. 4008 If non-zero, print out information to stderr about all objects allocated.
4092 See also `debug-allocation-backtrace-length'. 4009 See also `debug-allocation-backtrace-length'.
4093 */ ); 4010 */ );
4143 void 4060 void
4144 complex_vars_of_alloc (void) 4061 complex_vars_of_alloc (void)
4145 { 4062 {
4146 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer); 4063 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer);
4147 } 4064 }
4148
4149
4150 #ifdef PDUMP
4151
4152 /* The structure of the file
4153 *
4154 * 0 - header
4155 * 256 - dumped objects
4156 * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec
4157 * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro
4158 * - nb_structdmp*pair(void *, adr) for pointers to structures
4159 * - lrecord_implementations_table[]
4160 * - relocation table
4161 * - wired variable address/value couples with the count preceding the list
4162 */
4163 typedef struct
4164 {
4165 char signature[8];
4166 EMACS_UINT stab_offset;
4167 EMACS_UINT reloc_address;
4168 int nb_staticpro;
4169 int nb_structdmp;
4170 int last_type;
4171 } dump_header;
4172
4173 char *pdump_start, *pdump_end;
4174
4175 static const unsigned char align_table[256] =
4176 {
4177 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4178 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4179 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4180 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4181 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4182 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4183 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4184 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4185 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4186 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4187 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4188 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4189 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4190 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4191 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4192 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
4193 };
4194
4195 typedef struct pdump_entry_list_elmt
4196 {
4197 struct pdump_entry_list_elmt *next;
4198 const void *obj;
4199 size_t size;
4200 int count;
4201 int is_lrecord;
4202 EMACS_INT save_offset;
4203 } pdump_entry_list_elmt;
4204
4205 typedef struct
4206 {
4207 pdump_entry_list_elmt *first;
4208 int align;
4209 int count;
4210 } pdump_entry_list;
4211
4212 typedef struct pdump_struct_list_elmt
4213 {
4214 pdump_entry_list list;
4215 const struct struct_description *sdesc;
4216 } pdump_struct_list_elmt;
4217
4218 typedef struct
4219 {
4220 pdump_struct_list_elmt *list;
4221 int count;
4222 int size;
4223 } pdump_struct_list;
4224
4225 static pdump_entry_list pdump_object_table[256];
4226 static pdump_entry_list pdump_opaque_data_list;
4227 static pdump_struct_list pdump_struct_table;
4228 static pdump_entry_list_elmt *pdump_qnil;
4229
4230 static int pdump_alert_undump_object[256];
4231
4232 static unsigned long cur_offset;
4233 static size_t max_size;
4234 static int pdump_fd;
4235 static void *pdump_buf;
4236
4237 #define PDUMP_HASHSIZE 200001
4238
4239 static pdump_entry_list_elmt **pdump_hash;
4240
4241 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
4242 static int
4243 pdump_make_hash (const void *obj)
4244 {
4245 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
4246 }
4247
4248 static pdump_entry_list_elmt *
4249 pdump_get_entry (const void *obj)
4250 {
4251 int pos = pdump_make_hash (obj);
4252 pdump_entry_list_elmt *e;
4253
4254 assert (obj != 0);
4255
4256 while ((e = pdump_hash[pos]) != 0)
4257 {
4258 if (e->obj == obj)
4259 return e;
4260
4261 pos++;
4262 if (pos == PDUMP_HASHSIZE)
4263 pos = 0;
4264 }
4265 return 0;
4266 }
4267
4268 static void
4269 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord)
4270 {
4271 pdump_entry_list_elmt *e;
4272 int align;
4273 int pos = pdump_make_hash (obj);
4274
4275 while ((e = pdump_hash[pos]) != 0)
4276 {
4277 if (e->obj == obj)
4278 return;
4279
4280 pos++;
4281 if (pos == PDUMP_HASHSIZE)
4282 pos = 0;
4283 }
4284
4285 e = xnew (pdump_entry_list_elmt);
4286
4287 e->next = list->first;
4288 e->obj = obj;
4289 e->size = size;
4290 e->count = count;
4291 e->is_lrecord = is_lrecord;
4292 list->first = e;
4293
4294 list->count += count;
4295 pdump_hash[pos] = e;
4296
4297 align = align_table[size & 255];
4298 if (align < 2 && is_lrecord)
4299 align = 2;
4300
4301 if (align < list->align)
4302 list->align = align;
4303 }
4304
4305 static pdump_entry_list *
4306 pdump_get_entry_list (const struct struct_description *sdesc)
4307 {
4308 int i;
4309 for (i=0; i<pdump_struct_table.count; i++)
4310 if (pdump_struct_table.list[i].sdesc == sdesc)
4311 return &pdump_struct_table.list[i].list;
4312
4313 if (pdump_struct_table.size <= pdump_struct_table.count)
4314 {
4315 if (pdump_struct_table.size == -1)
4316 pdump_struct_table.size = 10;
4317 else
4318 pdump_struct_table.size = pdump_struct_table.size * 2;
4319 pdump_struct_table.list = (pdump_struct_list_elmt *)
4320 xrealloc (pdump_struct_table.list,
4321 pdump_struct_table.size * sizeof (pdump_struct_list_elmt));
4322 }
4323 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
4324 pdump_struct_table.list[pdump_struct_table.count].list.align = 8;
4325 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
4326 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
4327
4328 return &pdump_struct_table.list[pdump_struct_table.count++].list;
4329 }
4330
4331 static struct
4332 {
4333 struct lrecord_header *obj;
4334 int position;
4335 int offset;
4336 } backtrace[65536];
4337
4338 static int depth;
4339
4340 static void pdump_backtrace (void)
4341 {
4342 int i;
4343 fprintf (stderr, "pdump backtrace :\n");
4344 for (i=0;i<depth;i++)
4345 {
4346 if (!backtrace[i].obj)
4347 fprintf (stderr, " - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset);
4348 else
4349 {
4350 fprintf (stderr, " - %s (%d, %d)\n",
4351 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
4352 backtrace[i].position,
4353 backtrace[i].offset);
4354 }
4355 }
4356 }
4357
4358 static void pdump_register_object (Lisp_Object obj);
4359 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count);
4360
4361 static EMACS_INT
4362 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata)
4363 {
4364 EMACS_INT count;
4365 const void *irdata;
4366
4367 int line = XD_INDIRECT_VAL (code);
4368 int delta = XD_INDIRECT_DELTA (code);
4369
4370 irdata = ((char *)idata) + idesc[line].offset;
4371 switch (idesc[line].type)
4372 {
4373 case XD_SIZE_T:
4374 count = *(size_t *)irdata;
4375 break;
4376 case XD_INT:
4377 count = *(int *)irdata;
4378 break;
4379 case XD_LONG:
4380 count = *(long *)irdata;
4381 break;
4382 case XD_BYTECOUNT:
4383 count = *(Bytecount *)irdata;
4384 break;
4385 default:
4386 fprintf (stderr, "Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code);
4387 pdump_backtrace ();
4388 abort ();
4389 }
4390 count += delta;
4391 return count;
4392 }
4393
4394 static void
4395 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
4396 {
4397 int pos;
4398
4399 restart:
4400 for (pos = 0; desc[pos].type != XD_END; pos++)
4401 {
4402 const void *rdata = (const char *)data + desc[pos].offset;
4403
4404 backtrace[me].position = pos;
4405 backtrace[me].offset = desc[pos].offset;
4406
4407 switch (desc[pos].type)
4408 {
4409 case XD_SPECIFIER_END:
4410 pos = 0;
4411 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
4412 goto restart;
4413 case XD_SIZE_T:
4414 case XD_INT:
4415 case XD_LONG:
4416 case XD_BYTECOUNT:
4417 case XD_LO_RESET_NIL:
4418 case XD_INT_RESET:
4419 case XD_LO_LINK:
4420 break;
4421 case XD_OPAQUE_DATA_PTR:
4422 {
4423 EMACS_INT count = desc[pos].data1;
4424 if (XD_IS_INDIRECT (count))
4425 count = pdump_get_indirect_count (count, desc, data);
4426
4427 pdump_add_entry (&pdump_opaque_data_list,
4428 *(void **)rdata,
4429 count,
4430 1,
4431 0);
4432 break;
4433 }
4434 case XD_C_STRING:
4435 {
4436 const char *str = *(const char **)rdata;
4437 if (str)
4438 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
4439 break;
4440 }
4441 case XD_DOC_STRING:
4442 {
4443 const char *str = *(const char **)rdata;
4444 if ((EMACS_INT)str > 0)
4445 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
4446 break;
4447 }
4448 case XD_LISP_OBJECT:
4449 {
4450 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
4451
4452 assert (desc[pos].data1 == 0);
4453
4454 backtrace[me].offset = (const char *)pobj - (const char *)data;
4455 pdump_register_object (*pobj);
4456 break;
4457 }
4458 case XD_LISP_OBJECT_ARRAY:
4459 {
4460 int i;
4461 EMACS_INT count = desc[pos].data1;
4462 if (XD_IS_INDIRECT (count))
4463 count = pdump_get_indirect_count (count, desc, data);
4464
4465 for (i = 0; i < count; i++)
4466 {
4467 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
4468 Lisp_Object dobj = *pobj;
4469
4470 backtrace[me].offset = (const char *)pobj - (const char *)data;
4471 pdump_register_object (dobj);
4472 }
4473 break;
4474 }
4475 case XD_STRUCT_PTR:
4476 {
4477 EMACS_INT count = desc[pos].data1;
4478 const struct struct_description *sdesc = desc[pos].data2;
4479 const char *dobj = *(const char **)rdata;
4480 if (dobj)
4481 {
4482 if (XD_IS_INDIRECT (count))
4483 count = pdump_get_indirect_count (count, desc, data);
4484
4485 pdump_register_struct (dobj, sdesc, count);
4486 }
4487 break;
4488 }
4489 default:
4490 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type);
4491 pdump_backtrace ();
4492 abort ();
4493 };
4494 }
4495 }
4496
4497 static void
4498 pdump_register_object (Lisp_Object obj)
4499 {
4500 struct lrecord_header *objh;
4501
4502 if (!POINTER_TYPE_P (XTYPE (obj)))
4503 return;
4504
4505 objh = XRECORD_LHEADER (obj);
4506 if (!objh)
4507 return;
4508
4509 if (pdump_get_entry (objh))
4510 return;
4511
4512 if (LHEADER_IMPLEMENTATION (objh)->description)
4513 {
4514 int me = depth++;
4515 if (me>65536)
4516 {
4517 fprintf (stderr, "Backtrace overflow, loop ?\n");
4518 abort ();
4519 }
4520 backtrace[me].obj = objh;
4521 backtrace[me].position = 0;
4522 backtrace[me].offset = 0;
4523
4524 pdump_add_entry (pdump_object_table + objh->type,
4525 objh,
4526 LHEADER_IMPLEMENTATION (objh)->static_size ?
4527 LHEADER_IMPLEMENTATION (objh)->static_size :
4528 LHEADER_IMPLEMENTATION (objh)->size_in_bytes_method (objh),
4529 1,
4530 1);
4531 pdump_register_sub (objh,
4532 LHEADER_IMPLEMENTATION (objh)->description,
4533 me);
4534 --depth;
4535 }
4536 else
4537 {
4538 pdump_alert_undump_object[objh->type]++;
4539 fprintf (stderr, "Undumpable object type : %s\n", LHEADER_IMPLEMENTATION (objh)->name);
4540 pdump_backtrace ();
4541 }
4542 }
4543
4544 static void
4545 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count)
4546 {
4547 if (data && !pdump_get_entry (data))
4548 {
4549 int me = depth++;
4550 int i;
4551 if (me>65536)
4552 {
4553 fprintf (stderr, "Backtrace overflow, loop ?\n");
4554 abort ();
4555 }
4556 backtrace[me].obj = 0;
4557 backtrace[me].position = 0;
4558 backtrace[me].offset = 0;
4559
4560 pdump_add_entry (pdump_get_entry_list (sdesc),
4561 data,
4562 sdesc->size,
4563 count,
4564 0);
4565 for (i=0; i<count; i++)
4566 {
4567 pdump_register_sub (((char *)data) + sdesc->size*i,
4568 sdesc->description,
4569 me);
4570 }
4571 --depth;
4572 }
4573 }
4574
4575 static void
4576 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
4577 {
4578 size_t size = elmt->size;
4579 int count = elmt->count;
4580 if (desc)
4581 {
4582 int pos, i;
4583 memcpy (pdump_buf, elmt->obj, size*count);
4584
4585 for (i=0; i<count; i++)
4586 {
4587 char *cur = ((char *)pdump_buf) + i*size;
4588 restart:
4589 for (pos = 0; desc[pos].type != XD_END; pos++)
4590 {
4591 void *rdata = cur + desc[pos].offset;
4592 switch (desc[pos].type)
4593 {
4594 case XD_SPECIFIER_END:
4595 desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description;
4596 goto restart;
4597 case XD_SIZE_T:
4598 case XD_INT:
4599 case XD_LONG:
4600 case XD_BYTECOUNT:
4601 break;
4602 case XD_LO_RESET_NIL:
4603 {
4604 EMACS_INT count = desc[pos].data1;
4605 int i;
4606 if (XD_IS_INDIRECT (count))
4607 count = pdump_get_indirect_count (count, desc, elmt->obj);
4608 for (i=0; i<count; i++)
4609 ((EMACS_INT *)rdata)[i] = pdump_qnil->save_offset;
4610 break;
4611 }
4612 case XD_INT_RESET:
4613 {
4614 EMACS_INT val = desc[pos].data1;
4615 if (XD_IS_INDIRECT (val))
4616 val = pdump_get_indirect_count (val, desc, elmt->obj);
4617 *(int *)rdata = val;
4618 break;
4619 }
4620 case XD_OPAQUE_DATA_PTR:
4621 case XD_C_STRING:
4622 case XD_STRUCT_PTR:
4623 {
4624 void *ptr = *(void **)rdata;
4625 if (ptr)
4626 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
4627 break;
4628 }
4629 case XD_LO_LINK:
4630 {
4631 Lisp_Object obj = *(Lisp_Object *)rdata;
4632 pdump_entry_list_elmt *elmt1;
4633 for (;;)
4634 {
4635 elmt1 = pdump_get_entry (XRECORD_LHEADER (obj));
4636 if (elmt1)
4637 break;
4638 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
4639 }
4640 *(EMACS_INT *)rdata = elmt1->save_offset;
4641 break;
4642 }
4643 case XD_LISP_OBJECT:
4644 {
4645 Lisp_Object *pobj = (Lisp_Object *) rdata;
4646
4647 assert (desc[pos].data1 == 0);
4648
4649 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
4650 *(EMACS_INT *)pobj =
4651 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
4652 break;
4653 }
4654 case XD_LISP_OBJECT_ARRAY:
4655 {
4656 EMACS_INT count = desc[pos].data1;
4657 int i;
4658 if (XD_IS_INDIRECT (count))
4659 count = pdump_get_indirect_count (count, desc, elmt->obj);
4660
4661 for (i=0; i<count; i++)
4662 {
4663 Lisp_Object *pobj = ((Lisp_Object *)rdata) + i;
4664 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
4665 *(EMACS_INT *)pobj =
4666 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
4667 }
4668 break;
4669 }
4670 case XD_DOC_STRING:
4671 {
4672 EMACS_INT str = *(EMACS_INT *)rdata;
4673 if (str > 0)
4674 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
4675 break;
4676 }
4677 default:
4678 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type);
4679 abort ();
4680 };
4681 }
4682 }
4683 }
4684 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count);
4685 if (elmt->is_lrecord && ((size*count) & 3))
4686 write (pdump_fd, "\0\0\0", 4-((size*count) & 3));
4687 }
4688
4689 static void
4690 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc)
4691 {
4692 int pos;
4693
4694 restart:
4695 for (pos = 0; desc[pos].type != XD_END; pos++)
4696 {
4697 void *rdata = (char *)data + desc[pos].offset;
4698 switch (desc[pos].type)
4699 {
4700 case XD_SPECIFIER_END:
4701 pos = 0;
4702 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
4703 goto restart;
4704 case XD_SIZE_T:
4705 case XD_INT:
4706 case XD_LONG:
4707 case XD_BYTECOUNT:
4708 case XD_INT_RESET:
4709 break;
4710 case XD_OPAQUE_DATA_PTR:
4711 case XD_C_STRING:
4712 case XD_STRUCT_PTR:
4713 case XD_LO_LINK:
4714 {
4715 EMACS_INT ptr = *(EMACS_INT *)rdata;
4716 if (ptr)
4717 *(EMACS_INT *)rdata = ptr+delta;
4718 break;
4719 }
4720 case XD_LISP_OBJECT:
4721 {
4722 Lisp_Object *pobj = (Lisp_Object *) rdata;
4723
4724 assert (desc[pos].data1 == 0);
4725
4726 if (POINTER_TYPE_P (XTYPE (*pobj))
4727 && ! EQ (*pobj, Qnull_pointer))
4728 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta);
4729
4730 break;
4731 }
4732 case XD_LISP_OBJECT_ARRAY:
4733 case XD_LO_RESET_NIL:
4734 {
4735 EMACS_INT count = desc[pos].data1;
4736 int i;
4737 if (XD_IS_INDIRECT (count))
4738 count = pdump_get_indirect_count (count, desc, data);
4739
4740 for (i=0; i<count; i++)
4741 {
4742 Lisp_Object *pobj = (Lisp_Object *) rdata + i;
4743
4744 if (POINTER_TYPE_P (XTYPE (*pobj))
4745 && ! EQ (*pobj, Qnull_pointer))
4746 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta);
4747 }
4748 break;
4749 }
4750 case XD_DOC_STRING:
4751 {
4752 EMACS_INT str = *(EMACS_INT *)rdata;
4753 if (str > 0)
4754 *(EMACS_INT *)rdata = str + delta;
4755 break;
4756 }
4757 default:
4758 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type);
4759 abort ();
4760 };
4761 }
4762 }
4763
4764 static void
4765 pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
4766 {
4767 size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count;
4768 elmt->save_offset = cur_offset;
4769 if (size>max_size)
4770 max_size = size;
4771 cur_offset += size;
4772 }
4773
4774 static void
4775 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *))
4776 {
4777 int align, i;
4778 const struct lrecord_description *idesc;
4779 pdump_entry_list_elmt *elmt;
4780 for (align=8; align>=0; align--)
4781 {
4782 for (i=0; i<=last_lrecord_type_index_assigned; i++)
4783 if (pdump_object_table[i].align == align)
4784 {
4785 elmt = pdump_object_table[i].first;
4786 if (!elmt)
4787 continue;
4788 idesc = lrecord_implementations_table[i]->description;
4789 while (elmt)
4790 {
4791 f (elmt, idesc);
4792 elmt = elmt->next;
4793 }
4794 }
4795
4796 for (i=0; i<pdump_struct_table.count; i++)
4797 if (pdump_struct_table.list[i].list.align == align)
4798 {
4799 elmt = pdump_struct_table.list[i].list.first;
4800 idesc = pdump_struct_table.list[i].sdesc->description;
4801 while (elmt)
4802 {
4803 f (elmt, idesc);
4804 elmt = elmt->next;
4805 }
4806 }
4807
4808 elmt = pdump_opaque_data_list.first;
4809 while (elmt)
4810 {
4811 if (align_table[elmt->size & 255] == align)
4812 f (elmt, 0);
4813 elmt = elmt->next;
4814 }
4815 }
4816 }
4817
4818 static void
4819 pdump_dump_staticvec (void)
4820 {
4821 EMACS_INT *reloc = xnew_array (EMACS_INT, staticidx);
4822 int i;
4823 write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *));
4824
4825 for (i=0; i<staticidx; i++)
4826 {
4827 Lisp_Object obj = *staticvec[i];
4828 if (POINTER_TYPE_P (XTYPE (obj)))
4829 reloc[i] = pdump_get_entry (XRECORD_LHEADER (obj))->save_offset;
4830 else
4831 reloc[i] = *(EMACS_INT *)(staticvec[i]);
4832 }
4833 write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object));
4834 free (reloc);
4835 }
4836
4837 static void
4838 pdump_dump_structvec (void)
4839 {
4840 int i;
4841 for (i=0; i<dumpstructidx; i++)
4842 {
4843 EMACS_INT adr;
4844 write (pdump_fd, &(dumpstructvec[i].data), sizeof (void *));
4845 adr = pdump_get_entry (*(void **)(dumpstructvec[i].data))->save_offset;
4846 write (pdump_fd, &adr, sizeof (adr));
4847 }
4848 }
4849
4850 static void
4851 pdump_dump_itable (void)
4852 {
4853 write (pdump_fd, lrecord_implementations_table, sizeof (lrecord_implementations_table));
4854 }
4855
4856 static void
4857 pdump_dump_rtables (void)
4858 {
4859 int i, j;
4860 pdump_entry_list_elmt *elmt;
4861 pdump_reloc_table rt;
4862
4863 for (i=0; i<=last_lrecord_type_index_assigned; i++)
4864 {
4865 elmt = pdump_object_table[i].first;
4866 if (!elmt)
4867 continue;
4868 rt.desc = lrecord_implementations_table[i]->description;
4869 rt.count = pdump_object_table[i].count;
4870 write (pdump_fd, &rt, sizeof (rt));
4871 while (elmt)
4872 {
4873 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
4874 write (pdump_fd, &rdata, sizeof (rdata));
4875 elmt = elmt->next;
4876 }
4877 }
4878
4879 rt.desc = 0;
4880 rt.count = 0;
4881 write (pdump_fd, &rt, sizeof (rt));
4882
4883 for (i=0; i<pdump_struct_table.count; i++)
4884 {
4885 elmt = pdump_struct_table.list[i].list.first;
4886 rt.desc = pdump_struct_table.list[i].sdesc->description;
4887 rt.count = pdump_struct_table.list[i].list.count;
4888 write (pdump_fd, &rt, sizeof (rt));
4889 while (elmt)
4890 {
4891 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
4892 for (j=0; j<elmt->count; j++)
4893 {
4894 write (pdump_fd, &rdata, sizeof (rdata));
4895 rdata += elmt->size;
4896 }
4897 elmt = elmt->next;
4898 }
4899 }
4900 rt.desc = 0;
4901 rt.count = 0;
4902 write (pdump_fd, &rt, sizeof (rt));
4903 }
4904
4905 static void
4906 pdump_dump_wired (void)
4907 {
4908 EMACS_INT count = pdump_wireidx + pdump_wireidx_list;
4909 int i;
4910
4911 write (pdump_fd, &count, sizeof (count));
4912
4913 for (i=0; i<pdump_wireidx; i++)
4914 {
4915 EMACS_INT obj = pdump_get_entry (XRECORD_LHEADER (*(pdump_wirevec[i])))->save_offset;
4916 write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i]));
4917 write (pdump_fd, &obj, sizeof (obj));
4918 }
4919
4920 for (i=0; i<pdump_wireidx_list; i++)
4921 {
4922 Lisp_Object obj = *(pdump_wirevec_list[i]);
4923 pdump_entry_list_elmt *elmt;
4924 EMACS_INT res;
4925
4926 for (;;)
4927 {
4928 const struct lrecord_description *desc;
4929 int pos;
4930 elmt = pdump_get_entry (XRECORD_LHEADER (obj));
4931 if (elmt)
4932 break;
4933 desc = XRECORD_LHEADER_IMPLEMENTATION (obj)->description;
4934 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
4935 if (desc[pos].type == XD_END)
4936 abort ();
4937
4938 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
4939 }
4940 res = elmt->save_offset;
4941
4942 write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i]));
4943 write (pdump_fd, &res, sizeof (res));
4944 }
4945 }
4946
4947 void
4948 pdump (void)
4949 {
4950 int i;
4951 Lisp_Object t_console, t_device, t_frame;
4952 int none;
4953 dump_header hd;
4954
4955 /* These appear in a DEFVAR_LISP, which does a staticpro() */
4956 t_console = Vterminal_console;
4957 t_frame = Vterminal_frame;
4958 t_device = Vterminal_device;
4959
4960 Vterminal_console = Qnil;
4961 Vterminal_frame = Qnil;
4962 Vterminal_device = Qnil;
4963
4964 pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE);
4965
4966 for (i=0; i<=last_lrecord_type_index_assigned; i++)
4967 {
4968 pdump_object_table[i].first = 0;
4969 pdump_object_table[i].align = 8;
4970 pdump_object_table[i].count = 0;
4971 pdump_alert_undump_object[i] = 0;
4972 }
4973 pdump_struct_table.count = 0;
4974 pdump_struct_table.size = -1;
4975
4976 pdump_opaque_data_list.first = 0;
4977 pdump_opaque_data_list.align = 8;
4978 pdump_opaque_data_list.count = 0;
4979 depth = 0;
4980
4981 for (i=0; i<staticidx; i++)
4982 pdump_register_object (*staticvec[i]);
4983 for (i=0; i<pdump_wireidx; i++)
4984 pdump_register_object (*pdump_wirevec[i]);
4985
4986 none = 1;
4987 for (i=0; i<=last_lrecord_type_index_assigned; i++)
4988 if (pdump_alert_undump_object[i])
4989 {
4990 if (none)
4991 printf ("Undumpable types list :\n");
4992 none = 0;
4993 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
4994 }
4995 if (!none)
4996 return;
4997
4998 for (i=0; i<dumpstructidx; i++)
4999 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1);
5000
5001 memcpy (hd.signature, "XEmacsDP", 8);
5002 hd.reloc_address = 0;
5003 hd.nb_staticpro = staticidx;
5004 hd.nb_structdmp = dumpstructidx;
5005 hd.last_type = last_lrecord_type_index_assigned;
5006
5007 cur_offset = 256;
5008 max_size = 0;
5009
5010 pdump_scan_by_alignment (pdump_allocate_offset);
5011 pdump_qnil = pdump_get_entry (XRECORD_LHEADER (Qnil));
5012
5013 pdump_buf = xmalloc (max_size);
5014 /* Avoid use of the `open' macro. We want the real function. */
5015 #undef open
5016 pdump_fd = open ("xemacs.dmp",
5017 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
5018 hd.stab_offset = (cur_offset + 3) & ~3;
5019
5020 write (pdump_fd, &hd, sizeof (hd));
5021 lseek (pdump_fd, 256, SEEK_SET);
5022
5023 pdump_scan_by_alignment (pdump_dump_data);
5024
5025 lseek (pdump_fd, hd.stab_offset, SEEK_SET);
5026
5027 pdump_dump_staticvec ();
5028 pdump_dump_structvec ();
5029 pdump_dump_itable ();
5030 pdump_dump_rtables ();
5031 pdump_dump_wired ();
5032
5033 close (pdump_fd);
5034 free (pdump_buf);
5035
5036 free (pdump_hash);
5037
5038 Vterminal_console = t_console;
5039 Vterminal_frame = t_frame;
5040 Vterminal_device = t_device;
5041 }
5042
5043 int
5044 pdump_load (void)
5045 {
5046 size_t length;
5047 int i;
5048 char *p;
5049 EMACS_INT delta;
5050 EMACS_INT count;
5051
5052 #define PDUMP_READ(p, type) (p = (char*) (((type *) p) + 1), *((type *) p - 1))
5053
5054 pdump_start = pdump_end = 0;
5055
5056 pdump_fd = open ("xemacs.dmp", O_RDONLY | OPEN_BINARY);
5057 if (pdump_fd<0)
5058 return 0;
5059
5060 length = lseek (pdump_fd, 0, SEEK_END);
5061 lseek (pdump_fd, 0, SEEK_SET);
5062
5063 #ifdef HAVE_MMAP
5064 pdump_start = (char *) mmap (0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, pdump_fd, 0);
5065 if (pdump_start == MAP_FAILED)
5066 pdump_start = 0;
5067 #endif
5068
5069 if (!pdump_start)
5070 {
5071 pdump_start = (char *)((((unsigned long)(xmalloc(length+255))) + 255) & ~255);
5072 read (pdump_fd, pdump_start, length);
5073 }
5074
5075 close (pdump_fd);
5076
5077 pdump_end = pdump_start + length;
5078
5079 staticidx = ((dump_header *)(pdump_start))->nb_staticpro;
5080 last_lrecord_type_index_assigned = ((dump_header *)pdump_start)->last_type;
5081 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address;
5082 p = pdump_start + ((dump_header *)pdump_start)->stab_offset;
5083
5084 /* Put back the staticvec in place */
5085 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *));
5086 p += staticidx*sizeof (Lisp_Object *);
5087 for (i=0; i<staticidx; i++)
5088 {
5089 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
5090 if (POINTER_TYPE_P (XTYPE (obj)))
5091 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
5092 *staticvec[i] = obj;
5093 }
5094
5095 /* Put back the dumpstructs */
5096 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++)
5097 {
5098 void **adr = PDUMP_READ (p, void **);
5099 *adr = (void *) (PDUMP_READ (p, char *) + delta);
5100 }
5101
5102 /* Put back the lrecord_implementations_table */
5103 memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table));
5104 p += sizeof (lrecord_implementations_table);
5105
5106 /* Give back their numbers to the lrecord implementations */
5107 for (i = 0; i < countof (lrecord_implementations_table); i++)
5108 if (lrecord_implementations_table[i])
5109 {
5110 *(lrecord_implementations_table[i]->lrecord_type_index) = i;
5111 last_lrecord_type_index_assigned = i;
5112 }
5113
5114 /* Do the relocations */
5115 pdump_rt_list = p;
5116 count = 2;
5117 for (;;)
5118 {
5119 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
5120 if (rt.desc)
5121 {
5122 for (i=0; i < rt.count; i++)
5123 {
5124 char *adr = delta + *(char **)p;
5125 *(char **)p = adr;
5126 pdump_reloc_one (adr, delta, rt.desc);
5127 p += sizeof (char *);
5128 }
5129 } else
5130 if (!(--count))
5131 break;
5132 }
5133
5134 /* Put the pdump_wire variables in place */
5135 count = PDUMP_READ (p, EMACS_INT);
5136
5137 for (i=0; i<count; i++)
5138 {
5139 Lisp_Object *var = PDUMP_READ (p, Lisp_Object *);
5140 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
5141
5142 if (POINTER_TYPE_P (XTYPE (obj)))
5143 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
5144
5145 *var = obj;
5146 }
5147
5148 /* Final cleanups */
5149 /* reorganize hash tables */
5150 p = pdump_rt_list;
5151 for (;;)
5152 {
5153 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
5154 if (!rt.desc)
5155 break;
5156 if (rt.desc == hash_table_description)
5157 {
5158 for (i=0; i < rt.count; i++)
5159 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
5160 break;
5161 } else
5162 p += sizeof (Lisp_Object) * rt.count;
5163 }
5164 return 1;
5165 }
5166
5167 #endif /* PDUMP */