comparison src/alloc.c @ 398:74fd4e045ea6 r21-2-29

Import from CVS: tag r21-2-29
author cvs
date Mon, 13 Aug 2007 11:13:30 +0200
parents 6719134a07c2
children a86b2b5e0111
comparison
equal deleted inserted replaced
397:f4aeb21a5bad 398:74fd4e045ea6
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 */ 40 */
40 41
41 #include <config.h> 42 #include <config.h>
42 #include "lisp.h" 43 #include "lisp.h"
43 44
54 #include "opaque.h" 55 #include "opaque.h"
55 #include "redisplay.h" 56 #include "redisplay.h"
56 #include "specifier.h" 57 #include "specifier.h"
57 #include "sysfile.h" 58 #include "sysfile.h"
58 #include "window.h" 59 #include "window.h"
59 60 #include "console-stream.h"
60 #include <stddef.h>
61 61
62 #ifdef DOUG_LEA_MALLOC 62 #ifdef DOUG_LEA_MALLOC
63 #include <malloc.h> 63 #include <malloc.h>
64 #endif 64 #endif
65 65
66 #ifdef HAVE_MMAP
67 #include <unistd.h>
68 #include <sys/mman.h>
69 #endif
70
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
66 EXFUN (Fgarbage_collect, 0); 81 EXFUN (Fgarbage_collect, 0);
67
68 /* Return the true size of a struct with a variable-length array field. */
69 #define STRETCHY_STRUCT_SIZEOF(stretchy_struct_type, \
70 stretchy_array_field, \
71 stretchy_array_length) \
72 (offsetof (stretchy_struct_type, stretchy_array_field) + \
73 (offsetof (stretchy_struct_type, stretchy_array_field[1]) - \
74 offsetof (stretchy_struct_type, stretchy_array_field[0])) * \
75 (stretchy_array_length))
76 82
77 #if 0 /* this is _way_ too slow to be part of the standard debug options */ 83 #if 0 /* this is _way_ too slow to be part of the standard debug options */
78 #if defined(DEBUG_XEMACS) && defined(MULE) 84 #if defined(DEBUG_XEMACS) && defined(MULE)
79 #define VERIFY_STRING_CHARS_INTEGRITY 85 #define VERIFY_STRING_CHARS_INTEGRITY
80 #endif 86 #endif
81 #endif
82
83 /* Define this to see where all that space is going... */
84 /* But the length of the printout is obnoxious, so limit it to testers */
85 #ifdef MEMORY_USAGE_STATS
86 #define PURESTAT
87 #endif 87 #endif
88 88
89 /* Define this to use malloc/free with no freelist for all datatypes, 89 /* Define this to use malloc/free with no freelist for all datatypes,
90 the hope being that some debugging tools may help detect 90 the hope being that some debugging tools may help detect
91 freed memory references */ 91 freed memory references */
92 #ifdef USE_DEBUG_MALLOC /* Taking the above comment at face value -slb */ 92 #ifdef USE_DEBUG_MALLOC /* Taking the above comment at face value -slb */
93 #include <dmalloc.h> 93 #include <dmalloc.h>
94 #define ALLOC_NO_POOLS 94 #define ALLOC_NO_POOLS
95 #endif 95 #endif
96
97 #include "puresize.h"
98 96
99 #ifdef DEBUG_XEMACS 97 #ifdef DEBUG_XEMACS
100 static int debug_allocation; 98 static int debug_allocation;
101 static int debug_allocation_backtrace_length; 99 static int debug_allocation_backtrace_length;
102 #endif 100 #endif
165 Lisp_Object Vpost_gc_hook, Qpost_gc_hook; 163 Lisp_Object Vpost_gc_hook, Qpost_gc_hook;
166 164
167 /* "Garbage collecting" */ 165 /* "Garbage collecting" */
168 Lisp_Object Vgc_message; 166 Lisp_Object Vgc_message;
169 Lisp_Object Vgc_pointer_glyph; 167 Lisp_Object Vgc_pointer_glyph;
170 static CONST char gc_default_message[] = "Garbage collecting"; 168 static const char gc_default_message[] = "Garbage collecting";
171 Lisp_Object Qgarbage_collecting; 169 Lisp_Object Qgarbage_collecting;
172 170
173 #ifndef VIRT_ADDR_VARIES 171 #ifndef VIRT_ADDR_VARIES
174 extern 172 extern
175 #endif /* VIRT_ADDR_VARIES */ 173 #endif /* VIRT_ADDR_VARIES */
178 #ifndef VIRT_ADDR_VARIES 176 #ifndef VIRT_ADDR_VARIES
179 extern 177 extern
180 #endif /* VIRT_ADDR_VARIES */ 178 #endif /* VIRT_ADDR_VARIES */
181 EMACS_INT malloc_sbrk_unused; 179 EMACS_INT malloc_sbrk_unused;
182 180
183 /* Non-zero means defun should do purecopy on the function definition */ 181 /* Non-zero means we're in the process of doing the dump */
184 int purify_flag; 182 int purify_flag;
185 183
186 #ifdef HEAP_IN_DATA 184 #ifdef ERROR_CHECK_TYPECHECK
187 extern void sheap_adjust_h(); 185
186 Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN;
187
188 #endif 188 #endif
189 189
190 /* Force linker to put it into data space! */
191 EMACS_INT pure[PURESIZE / sizeof (EMACS_INT)] = { (EMACS_INT) 0};
192
193 #define PUREBEG ((char *) pure)
194
195 #if 0 /* This is breathing_space in XEmacs */
196 /* Points to memory space allocated as "spare",
197 to be freed if we run out of memory. */
198 static char *spare_memory;
199
200 /* Amount of spare memory to keep in reserve. */
201 #define SPARE_MEMORY (1 << 14)
202 #endif
203
204 /* Index in pure at which next pure object will be allocated. */
205 static size_t pure_bytes_used;
206
207 #define PURIFIED(ptr) \
208 ((char *) (ptr) >= PUREBEG && \
209 (char *) (ptr) < PUREBEG + get_PURESIZE())
210
211 /* Non-zero if pure_bytes_used > get_PURESIZE();
212 accounts for excess purespace needs. */
213 static size_t pure_lossage;
214
215 #ifdef ERROR_CHECK_TYPECHECK
216
217 Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN;
218
219 #endif
220
221 int 190 int
222 purified (Lisp_Object obj) 191 c_readonly (Lisp_Object obj)
223 { 192 {
224 return POINTER_TYPE_P (XGCTYPE (obj)) && PURIFIED (XPNTR (obj)); 193 return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj);
225 } 194 }
226 195
227 size_t 196 int
228 purespace_usage (void) 197 lisp_readonly (Lisp_Object obj)
229 { 198 {
230 return pure_bytes_used; 199 return POINTER_TYPE_P (XTYPE (obj)) && LISP_READONLY (obj);
231 } 200 }
232
233 static int
234 check_purespace (size_t size)
235 {
236 if (pure_lossage)
237 {
238 pure_lossage += size;
239 return 0;
240 }
241 else if (pure_bytes_used + size > get_PURESIZE())
242 {
243 /* This can cause recursive bad behavior, we'll yell at the end */
244 /* when we're done. */
245 /* message ("\nERROR: Pure Lisp storage exhausted!\n"); */
246 pure_lossage = size;
247 return 0;
248 }
249 else
250 return 1;
251 }
252
253
254
255 #ifndef PURESTAT
256
257 #define bump_purestat(p,b) DO_NOTHING
258
259 #else /* PURESTAT */
260
261 static int purecopying_function_constants;
262
263 static size_t pure_sizeof (Lisp_Object);
264
265 /* Keep statistics on how much of what is in purespace */
266 static struct purestat
267 {
268 int nobjects;
269 int nbytes;
270 CONST char *name;
271 }
272 purestat_cons = {0, 0, "cons cells"},
273 purestat_float = {0, 0, "float objects"},
274 purestat_string_pname = {0, 0, "symbol-name strings"},
275 purestat_function = {0, 0, "compiled-function objects"},
276 purestat_opaque_instructions = {0, 0, "compiled-function instructions"},
277 purestat_vector_constants = {0, 0, "compiled-function constants vectors"},
278 purestat_string_interactive = {0, 0, "interactive strings"},
279 #ifdef I18N3
280 purestat_string_domain = {0, 0, "domain strings"},
281 #endif
282 purestat_string_documentation = {0, 0, "documentation strings"},
283 purestat_string_other_function = {0, 0, "other function strings"},
284 purestat_vector_other = {0, 0, "other vectors"},
285 purestat_string_other = {0, 0, "other strings"},
286 purestat_string_all = {0, 0, "all strings"},
287 purestat_vector_all = {0, 0, "all vectors"};
288
289 static void
290 bump_purestat (struct purestat *purestat, size_t nbytes)
291 {
292 if (pure_lossage) return;
293 purestat->nobjects += 1;
294 purestat->nbytes += nbytes;
295 }
296
297 static void
298 print_purestat (struct purestat *purestat)
299 {
300 char buf [100];
301 sprintf(buf, "%s:", purestat->name);
302 message (" %-36s %5d %7d %2d%%",
303 buf,
304 purestat->nobjects,
305 purestat->nbytes,
306 (int) (purestat->nbytes / (pure_bytes_used / 100.0) + 0.5));
307 }
308 #endif /* PURESTAT */
309 201
310 202
311 /* Maximum amount of C stack to save when a GC happens. */ 203 /* Maximum amount of C stack to save when a GC happens. */
312 204
313 #ifndef MAX_SAVE_STACK 205 #ifndef MAX_SAVE_STACK
331 } 223 }
332 } 224 }
333 225
334 /* malloc calls this if it finds we are near exhausting storage */ 226 /* malloc calls this if it finds we are near exhausting storage */
335 void 227 void
336 malloc_warning (CONST char *str) 228 malloc_warning (const char *str)
337 { 229 {
338 if (ignore_malloc_warnings) 230 if (ignore_malloc_warnings)
339 return; 231 return;
340 232
341 warn_when_safe 233 warn_when_safe
367 error ("Memory exhausted"); 259 error ("Memory exhausted");
368 } 260 }
369 261
370 /* like malloc and realloc but check for no memory left, and block input. */ 262 /* like malloc and realloc but check for no memory left, and block input. */
371 263
372 #ifdef xmalloc
373 #undef xmalloc 264 #undef xmalloc
374 #endif
375
376 void * 265 void *
377 xmalloc (size_t size) 266 xmalloc (size_t size)
378 { 267 {
379 void *val = malloc (size); 268 void *val = malloc (size);
380 269
381 if (!val && (size != 0)) memory_full (); 270 if (!val && (size != 0)) memory_full ();
382 return val; 271 return val;
383 } 272 }
384 273
385 #ifdef xcalloc
386 #undef xcalloc 274 #undef xcalloc
387 #endif
388
389 static void * 275 static void *
390 xcalloc (size_t nelem, size_t elsize) 276 xcalloc (size_t nelem, size_t elsize)
391 { 277 {
392 void *val = calloc (nelem, elsize); 278 void *val = calloc (nelem, elsize);
393 279
399 xmalloc_and_zero (size_t size) 285 xmalloc_and_zero (size_t size)
400 { 286 {
401 return xcalloc (size, sizeof (char)); 287 return xcalloc (size, sizeof (char));
402 } 288 }
403 289
404 #ifdef xrealloc
405 #undef xrealloc 290 #undef xrealloc
406 #endif
407
408 void * 291 void *
409 xrealloc (void *block, size_t size) 292 xrealloc (void *block, size_t size)
410 { 293 {
411 /* We must call malloc explicitly when BLOCK is 0, since some 294 /* We must call malloc explicitly when BLOCK is 0, since some
412 reallocs don't do this. */ 295 reallocs don't do this. */
461 344
462 #define deadbeef_memory(ptr, size) 345 #define deadbeef_memory(ptr, size)
463 346
464 #endif /* !ERROR_CHECK_GC */ 347 #endif /* !ERROR_CHECK_GC */
465 348
466 #ifdef xstrdup
467 #undef xstrdup 349 #undef xstrdup
468 #endif
469
470 char * 350 char *
471 xstrdup (CONST char *str) 351 xstrdup (const char *str)
472 { 352 {
473 int len = strlen (str) + 1; /* for stupid terminating 0 */ 353 int len = strlen (str) + 1; /* for stupid terminating 0 */
474 354
475 void *val = xmalloc (len); 355 void *val = xmalloc (len);
476 if (val == 0) return 0; 356 if (val == 0) return 0;
477 memcpy (val, str, len); 357 return (char *) memcpy (val, str, len);
478 return (char *) val;
479 } 358 }
480 359
481 #ifdef NEED_STRDUP 360 #ifdef NEED_STRDUP
482 char * 361 char *
483 strdup (CONST char *s) 362 strdup (const char *s)
484 { 363 {
485 return xstrdup (s); 364 return xstrdup (s);
486 } 365 }
487 #endif /* NEED_STRDUP */ 366 #endif /* NEED_STRDUP */
488 367
489 368
490 static void * 369 static void *
491 allocate_lisp_storage (size_t size) 370 allocate_lisp_storage (size_t size)
492 { 371 {
493 void *p = xmalloc (size); 372 return xmalloc (size);
494 #ifndef USE_MINIMAL_TAGBITS 373 }
495 char *lim = ((char *) p) + size; 374
496 Lisp_Object val; 375
497 376 /* lcrecords are chained together through their "next" field.
498 XSETOBJ (val, Lisp_Type_Record, lim); 377 After doing the mark phase, GC will walk this linked list
499 if ((char *) XPNTR (val) != lim) 378 and free any lcrecord which hasn't been marked. */
500 {
501 xfree (p);
502 memory_full ();
503 }
504 #endif /* ! USE_MINIMAL_TAGBITS */
505 return p;
506 }
507
508
509 /* lrecords are chained together through their "next.v" field.
510 * After doing the mark phase, the GC will walk this linked
511 * list and free any record which hasn't been marked.
512 */
513 static struct lcrecord_header *all_lcrecords; 379 static struct lcrecord_header *all_lcrecords;
514 380
515 void * 381 void *
516 alloc_lcrecord (size_t size, CONST struct lrecord_implementation *implementation) 382 alloc_lcrecord (size_t size, const struct lrecord_implementation *implementation)
517 { 383 {
518 struct lcrecord_header *lcheader; 384 struct lcrecord_header *lcheader;
519 385
520 #ifdef ERROR_CHECK_GC 386 #ifdef ERROR_CHECK_TYPECHECK
521 if (implementation->static_size == 0) 387 if (implementation->static_size == 0)
522 assert (implementation->size_in_bytes_method); 388 assert (implementation->size_in_bytes_method);
523 else 389 else
524 assert (implementation->static_size == size); 390 assert (implementation->static_size == size);
391
392 assert (! implementation->basic_p);
393
394 if (implementation->hash == NULL)
395 assert (implementation->equal == NULL);
525 #endif 396 #endif
526 397
527 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); 398 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size);
528 set_lheader_implementation (&(lcheader->lheader), implementation); 399 set_lheader_implementation (&(lcheader->lheader), implementation);
529 lcheader->next = all_lcrecords; 400 lcheader->next = all_lcrecords;
589 ((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer) 460 ((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer)
590 (header, 1)); 461 (header, 1));
591 } 462 }
592 } 463 }
593 464
594
595 /* This must not be called -- it just serves as for EQ test
596 * If lheader->implementation->finalizer is this_marks_a_marked_record,
597 * then lrecord has been marked by the GC sweeper
598 * header->implementation is put back to its correct value by
599 * sweep_records */
600 void
601 this_marks_a_marked_record (void *dummy0, int dummy1)
602 {
603 abort ();
604 }
605
606 /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck 465 /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck
607 in CONST space and you get SEGV's if you attempt to mark them. 466 in const space and you get SEGV's if you attempt to mark them.
608 This sits in lheader->implementation->marker. */ 467 This sits in lheader->implementation->marker. */
609 468
610 Lisp_Object 469 Lisp_Object
611 this_one_is_unmarkable (Lisp_Object obj, void (*markobj) (Lisp_Object)) 470 this_one_is_unmarkable (Lisp_Object obj)
612 { 471 {
613 abort (); 472 abort ();
614 return Qnil; 473 return Qnil;
615 }
616
617 /* XGCTYPE for records */
618 int
619 gc_record_type_p (Lisp_Object frob, CONST struct lrecord_implementation *type)
620 {
621 CONST struct lrecord_implementation *imp;
622
623 if (XGCTYPE (frob) != Lisp_Type_Record)
624 return 0;
625
626 imp = XRECORD_LHEADER_IMPLEMENTATION (frob);
627 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
628 return imp == type;
629 #else
630 return imp == type || imp == type + 1;
631 #endif
632 } 474 }
633 475
634 476
635 /************************************************************************/ 477 /************************************************************************/
636 /* Debugger support */ 478 /* Debugger support */
637 /************************************************************************/ 479 /************************************************************************/
638 /* Give gdb/dbx enough information to decode Lisp Objects. We make 480 /* Give gdb/dbx enough information to decode Lisp Objects. We make
639 sure certain symbols are always defined, so gdb doesn't complain 481 sure certain symbols are always defined, so gdb doesn't complain
640 about expressions in src/gdbinit. See src/gdbinit or src/dbxrc to 482 about expressions in src/.gdbinit. See src/.gdbinit or src/.dbxrc
641 see how this is used. */ 483 to see how this is used. */
642 484
643 #ifdef USE_MINIMAL_TAGBITS
644 EMACS_UINT dbg_valmask = ((1UL << VALBITS) - 1) << GCBITS; 485 EMACS_UINT dbg_valmask = ((1UL << VALBITS) - 1) << GCBITS;
645 EMACS_UINT dbg_typemask = (1UL << GCTYPEBITS) - 1; 486 EMACS_UINT dbg_typemask = (1UL << GCTYPEBITS) - 1;
646 unsigned char dbg_USE_MINIMAL_TAGBITS = 1;
647 unsigned char Lisp_Type_Int = 100;
648 #else
649 EMACS_UINT dbg_valmask = (1UL << VALBITS) - 1;
650 EMACS_UINT dbg_typemask = ((1UL << GCTYPEBITS) - 1) << (VALBITS + GCMARKBITS);
651 unsigned char dbg_USE_MINIMAL_TAGBITS = 0;
652 #endif
653 487
654 #ifdef USE_UNION_TYPE 488 #ifdef USE_UNION_TYPE
655 unsigned char dbg_USE_UNION_TYPE = 1; 489 unsigned char dbg_USE_UNION_TYPE = 1;
656 #else 490 #else
657 unsigned char dbg_USE_UNION_TYPE = 0; 491 unsigned char dbg_USE_UNION_TYPE = 0;
658 #endif 492 #endif
659 493
660 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION 494 unsigned char Lisp_Type_Int = 100;
661 unsigned char dbg_USE_INDEXED_LRECORD_IMPLEMENTATION = 1;
662 #else
663 unsigned char dbg_USE_INDEXED_LRECORD_IMPLEMENTATION = 0;
664 #endif
665
666 #ifdef LRECORD_CONS
667 unsigned char Lisp_Type_Cons = 101; 495 unsigned char Lisp_Type_Cons = 101;
668 #else
669 unsigned char lrecord_cons;
670 #endif
671
672 #ifdef LRECORD_STRING
673 unsigned char Lisp_Type_String = 102; 496 unsigned char Lisp_Type_String = 102;
674 #else
675 unsigned char lrecord_string;
676 #endif
677
678 #ifdef LRECORD_VECTOR
679 unsigned char Lisp_Type_Vector = 103; 497 unsigned char Lisp_Type_Vector = 103;
680 #else
681 unsigned char lrecord_vector;
682 #endif
683
684 #ifdef LRECORD_SYMBOL
685 unsigned char Lisp_Type_Symbol = 104; 498 unsigned char Lisp_Type_Symbol = 104;
686 #else
687 unsigned char lrecord_symbol;
688 #endif
689 499
690 #ifndef MULE 500 #ifndef MULE
691 unsigned char lrecord_char_table_entry; 501 unsigned char lrecord_char_table_entry;
692 unsigned char lrecord_charset; 502 unsigned char lrecord_charset;
693 #ifndef FILE_CODING 503 #ifndef FILE_CODING
694 unsigned char lrecord_coding_system; 504 unsigned char lrecord_coding_system;
695 #endif 505 #endif
506 #endif
507
508 #if !((defined HAVE_X_WINDOWS) && \
509 (defined (HAVE_MENUBARS) || \
510 defined (HAVE_SCROLLBARS) || \
511 defined (HAVE_DIALOGS) || \
512 defined (HAVE_TOOLBARS) || \
513 defined (HAVE_WIDGETS)))
514 unsigned char lrecord_popup_data;
696 #endif 515 #endif
697 516
698 #ifndef HAVE_TOOLBARS 517 #ifndef HAVE_TOOLBARS
699 unsigned char lrecord_toolbar_button; 518 unsigned char lrecord_toolbar_button;
700 #endif 519 #endif
751 (a struct Lisp_String) is a fixed-size structure and is managed the 570 (a struct Lisp_String) is a fixed-size structure and is managed the
752 same way as all the other such types. This structure contains a 571 same way as all the other such types. This structure contains a
753 pointer to the actual string data, which is stored in structures of 572 pointer to the actual string data, which is stored in structures of
754 type struct string_chars_block. Each string_chars_block consists 573 type struct string_chars_block. Each string_chars_block consists
755 of a pointer to a struct Lisp_String, followed by the data for that 574 of a pointer to a struct Lisp_String, followed by the data for that
756 string, followed by another pointer to a struct Lisp_String, 575 string, followed by another pointer to a Lisp_String, followed by
757 followed by the data for that string, etc. At GC time, the data in 576 the data for that string, etc. At GC time, the data in these
758 these blocks is compacted by searching sequentially through all the 577 blocks is compacted by searching sequentially through all the
759 blocks and compressing out any holes created by unmarked strings. 578 blocks and compressing out any holes created by unmarked strings.
760 Strings that are more than a certain size (bigger than the size of 579 Strings that are more than a certain size (bigger than the size of
761 a string_chars_block, although something like half as big might 580 a string_chars_block, although something like half as big might
762 make more sense) are malloc()ed separately and not stored in 581 make more sense) are malloc()ed separately and not stored in
763 string_chars_blocks. Furthermore, no one string stretches across 582 string_chars_blocks. Furthermore, no one string stretches across
867 Furthermore, we never take objects off the free list 686 Furthermore, we never take objects off the free list
868 unless there's a large number (usually 1000, but 687 unless there's a large number (usually 1000, but
869 varies depending on type) of them already on the list. 688 varies depending on type) of them already on the list.
870 This way, we ensure that an object that gets freed will 689 This way, we ensure that an object that gets freed will
871 remain free for the next 1000 (or whatever) times that 690 remain free for the next 1000 (or whatever) times that
872 an object of that type is allocated. 691 an object of that type is allocated. */
873 */
874 692
875 #ifndef MALLOC_OVERHEAD 693 #ifndef MALLOC_OVERHEAD
876 #ifdef GNU_MALLOC 694 #ifdef GNU_MALLOC
877 #define MALLOC_OVERHEAD 0 695 #define MALLOC_OVERHEAD 0
878 #elif defined (rcheck) 696 #elif defined (rcheck)
1097 915
1098 /************************************************************************/ 916 /************************************************************************/
1099 /* Cons allocation */ 917 /* Cons allocation */
1100 /************************************************************************/ 918 /************************************************************************/
1101 919
1102 DECLARE_FIXED_TYPE_ALLOC (cons, struct Lisp_Cons); 920 DECLARE_FIXED_TYPE_ALLOC (cons, Lisp_Cons);
1103 /* conses are used and freed so often that we set this really high */ 921 /* conses are used and freed so often that we set this really high */
1104 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */ 922 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 20000 */
1105 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 923 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000
1106 924
1107 #ifdef LRECORD_CONS
1108 static Lisp_Object 925 static Lisp_Object
1109 mark_cons (Lisp_Object obj, void (*markobj) (Lisp_Object)) 926 mark_cons (Lisp_Object obj)
1110 { 927 {
1111 if (GC_NILP (XCDR (obj))) 928 if (NILP (XCDR (obj)))
1112 return XCAR (obj); 929 return XCAR (obj);
1113 930
1114 markobj (XCAR (obj)); 931 mark_object (XCAR (obj));
1115 return XCDR (obj); 932 return XCDR (obj);
1116 } 933 }
1117 934
1118 static int 935 static int
1119 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth) 936 cons_equal (Lisp_Object ob1, Lisp_Object ob2, int depth)
1120 { 937 {
1121 while (internal_equal (XCAR (ob1), XCAR (ob2), depth + 1)) 938 depth++;
939 while (internal_equal (XCAR (ob1), XCAR (ob2), depth))
1122 { 940 {
1123 ob1 = XCDR (ob1); 941 ob1 = XCDR (ob1);
1124 ob2 = XCDR (ob2); 942 ob2 = XCDR (ob2);
1125 if (! CONSP (ob1) || ! CONSP (ob2)) 943 if (! CONSP (ob1) || ! CONSP (ob2))
1126 return internal_equal (ob1, ob2, depth + 1); 944 return internal_equal (ob1, ob2, depth);
1127 } 945 }
1128 return 0; 946 return 0;
1129 } 947 }
948
949 static const struct lrecord_description cons_description[] = {
950 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car) },
951 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr) },
952 { XD_END }
953 };
1130 954
1131 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("cons", cons, 955 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("cons", cons,
1132 mark_cons, print_cons, 0, 956 mark_cons, print_cons, 0,
1133 cons_equal, 957 cons_equal,
1134 /* 958 /*
1135 * No `hash' method needed. 959 * No `hash' method needed.
1136 * internal_hash knows how to 960 * internal_hash knows how to
1137 * handle conses. 961 * handle conses.
1138 */ 962 */
1139 0, 963 0,
1140 struct Lisp_Cons); 964 cons_description,
1141 #endif /* LRECORD_CONS */ 965 Lisp_Cons);
1142 966
1143 DEFUN ("cons", Fcons, 2, 2, 0, /* 967 DEFUN ("cons", Fcons, 2, 2, 0, /*
1144 Create a new cons, give it CAR and CDR as components, and return it. 968 Create a new cons, give it CAR and CDR as components, and return it.
1145 */ 969 */
1146 (car, cdr)) 970 (car, cdr))
1147 { 971 {
1148 /* This cannot GC. */ 972 /* This cannot GC. */
1149 Lisp_Object val; 973 Lisp_Object val;
1150 struct Lisp_Cons *c; 974 Lisp_Cons *c;
1151 975
1152 ALLOCATE_FIXED_TYPE (cons, struct Lisp_Cons, c); 976 ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c);
1153 #ifdef LRECORD_CONS 977 set_lheader_implementation (&(c->lheader), &lrecord_cons);
1154 set_lheader_implementation (&(c->lheader), lrecord_cons);
1155 #endif
1156 XSETCONS (val, c); 978 XSETCONS (val, c);
1157 c->car = car; 979 c->car = car;
1158 c->cdr = cdr; 980 c->cdr = cdr;
1159 return val; 981 return val;
1160 } 982 }
1164 "real" consing. */ 986 "real" consing. */
1165 Lisp_Object 987 Lisp_Object
1166 noseeum_cons (Lisp_Object car, Lisp_Object cdr) 988 noseeum_cons (Lisp_Object car, Lisp_Object cdr)
1167 { 989 {
1168 Lisp_Object val; 990 Lisp_Object val;
1169 struct Lisp_Cons *c; 991 Lisp_Cons *c;
1170 992
1171 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, struct Lisp_Cons, c); 993 NOSEEUM_ALLOCATE_FIXED_TYPE (cons, Lisp_Cons, c);
1172 #ifdef LRECORD_CONS 994 set_lheader_implementation (&(c->lheader), &lrecord_cons);
1173 set_lheader_implementation (&(c->lheader), lrecord_cons);
1174 #endif
1175 XSETCONS (val, c); 995 XSETCONS (val, c);
1176 XCAR (val) = car; 996 XCAR (val) = car;
1177 XCDR (val) = cdr; 997 XCDR (val) = cdr;
1178 return val; 998 return val;
1179 } 999 }
1256 { 1076 {
1257 CHECK_NATNUM (length); 1077 CHECK_NATNUM (length);
1258 1078
1259 { 1079 {
1260 Lisp_Object val = Qnil; 1080 Lisp_Object val = Qnil;
1261 int size = XINT (length); 1081 size_t size = XINT (length);
1262 1082
1263 while (size-- > 0) 1083 while (size--)
1264 val = Fcons (init, val); 1084 val = Fcons (init, val);
1265 return val; 1085 return val;
1266 } 1086 }
1267 } 1087 }
1268 1088
1271 /* Float allocation */ 1091 /* Float allocation */
1272 /************************************************************************/ 1092 /************************************************************************/
1273 1093
1274 #ifdef LISP_FLOAT_TYPE 1094 #ifdef LISP_FLOAT_TYPE
1275 1095
1276 DECLARE_FIXED_TYPE_ALLOC (float, struct Lisp_Float); 1096 DECLARE_FIXED_TYPE_ALLOC (float, Lisp_Float);
1277 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_float 1000 1097 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_float 1000
1278 1098
1279 Lisp_Object 1099 Lisp_Object
1280 make_float (double float_value) 1100 make_float (double float_value)
1281 { 1101 {
1282 Lisp_Object val; 1102 Lisp_Object val;
1283 struct Lisp_Float *f; 1103 Lisp_Float *f;
1284 1104
1285 ALLOCATE_FIXED_TYPE (float, struct Lisp_Float, f); 1105 ALLOCATE_FIXED_TYPE (float, Lisp_Float, f);
1286 set_lheader_implementation (&(f->lheader), lrecord_float); 1106
1107 /* Avoid dump-time `uninitialized memory read' purify warnings. */
1108 if (sizeof (struct lrecord_header) + sizeof (double) != sizeof (*f))
1109 xzero (*f);
1110
1111 set_lheader_implementation (&(f->lheader), &lrecord_float);
1287 float_data (f) = float_value; 1112 float_data (f) = float_value;
1288 XSETFLOAT (val, f); 1113 XSETFLOAT (val, f);
1289 return val; 1114 return val;
1290 } 1115 }
1291 1116
1294 1119
1295 /************************************************************************/ 1120 /************************************************************************/
1296 /* Vector allocation */ 1121 /* Vector allocation */
1297 /************************************************************************/ 1122 /************************************************************************/
1298 1123
1299 #ifdef LRECORD_VECTOR
1300 static Lisp_Object 1124 static Lisp_Object
1301 mark_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) 1125 mark_vector (Lisp_Object obj)
1302 { 1126 {
1303 Lisp_Vector *ptr = XVECTOR (obj); 1127 Lisp_Vector *ptr = XVECTOR (obj);
1304 int len = vector_length (ptr); 1128 int len = vector_length (ptr);
1305 int i; 1129 int i;
1306 1130
1307 for (i = 0; i < len - 1; i++) 1131 for (i = 0; i < len - 1; i++)
1308 markobj (ptr->contents[i]); 1132 mark_object (ptr->contents[i]);
1309 return (len > 0) ? ptr->contents[len - 1] : Qnil; 1133 return (len > 0) ? ptr->contents[len - 1] : Qnil;
1310 } 1134 }
1311 1135
1312 static size_t 1136 static size_t
1313 size_vector (CONST void *lheader) 1137 size_vector (const void *lheader)
1314 { 1138 {
1315 return STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, 1139 return offsetof (Lisp_Vector, contents[((Lisp_Vector *) lheader)->size]);
1316 ((Lisp_Vector *) lheader)->size);
1317 } 1140 }
1318 1141
1319 static int 1142 static int
1320 vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) 1143 vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth)
1321 { 1144 {
1331 return 0; 1154 return 0;
1332 } 1155 }
1333 return 1; 1156 return 1;
1334 } 1157 }
1335 1158
1159 static hashcode_t
1160 vector_hash (Lisp_Object obj, int depth)
1161 {
1162 return HASH2 (XVECTOR_LENGTH (obj),
1163 internal_array_hash (XVECTOR_DATA (obj),
1164 XVECTOR_LENGTH (obj),
1165 depth + 1));
1166 }
1167
1168 static const struct lrecord_description vector_description[] = {
1169 { XD_LONG, offsetof (Lisp_Vector, size) },
1170 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Vector, contents), XD_INDIRECT(0, 0) },
1171 { XD_END }
1172 };
1173
1336 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector, 1174 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector,
1337 mark_vector, print_vector, 0, 1175 mark_vector, print_vector, 0,
1338 vector_equal, 1176 vector_equal,
1339 /* 1177 vector_hash,
1340 * No `hash' method needed for 1178 vector_description,
1341 * vectors. internal_hash
1342 * knows how to handle vectors.
1343 */
1344 0,
1345 size_vector, Lisp_Vector); 1179 size_vector, Lisp_Vector);
1346 1180
1347 /* #### should allocate `small' vectors from a frob-block */ 1181 /* #### should allocate `small' vectors from a frob-block */
1348 static Lisp_Vector * 1182 static Lisp_Vector *
1349 make_vector_internal (size_t sizei) 1183 make_vector_internal (size_t sizei)
1350 { 1184 {
1351 /* no vector_next */ 1185 /* no vector_next */
1352 size_t sizem = STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, sizei); 1186 size_t sizem = offsetof (Lisp_Vector, contents[sizei]);
1353 Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord (sizem, lrecord_vector); 1187 Lisp_Vector *p = (Lisp_Vector *) alloc_lcrecord (sizem, &lrecord_vector);
1354 1188
1355 p->size = sizei; 1189 p->size = sizei;
1356 return p; 1190 return p;
1357 } 1191 }
1358
1359 #else /* ! LRECORD_VECTOR */
1360
1361 static Lisp_Object all_vectors;
1362
1363 /* #### should allocate `small' vectors from a frob-block */
1364 static Lisp_Vector *
1365 make_vector_internal (size_t sizei)
1366 {
1367 /* + 1 to account for vector_next */
1368 size_t sizem = STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, sizei+1);
1369 Lisp_Vector *p = (Lisp_Vector *) allocate_lisp_storage (sizem);
1370
1371 INCREMENT_CONS_COUNTER (sizem, "vector");
1372
1373 p->size = sizei;
1374 vector_next (p) = all_vectors;
1375 XSETVECTOR (all_vectors, p);
1376 return p;
1377 }
1378
1379 #endif /* ! LRECORD_VECTOR */
1380 1192
1381 Lisp_Object 1193 Lisp_Object
1382 make_vector (size_t length, Lisp_Object init) 1194 make_vector (size_t length, Lisp_Object init)
1383 { 1195 {
1384 Lisp_Vector *vecp = make_vector_internal (length); 1196 Lisp_Vector *vecp = make_vector_internal (length);
1528 /************************************************************************/ 1340 /************************************************************************/
1529 1341
1530 static Lisp_Object all_bit_vectors; 1342 static Lisp_Object all_bit_vectors;
1531 1343
1532 /* #### should allocate `small' bit vectors from a frob-block */ 1344 /* #### should allocate `small' bit vectors from a frob-block */
1533 static struct Lisp_Bit_Vector * 1345 static Lisp_Bit_Vector *
1534 make_bit_vector_internal (size_t sizei) 1346 make_bit_vector_internal (size_t sizei)
1535 { 1347 {
1536 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei); 1348 size_t num_longs = BIT_VECTOR_LONG_STORAGE (sizei);
1537 size_t sizem = STRETCHY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, num_longs); 1349 size_t sizem = offsetof (Lisp_Bit_Vector, bits[num_longs]);
1538 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem); 1350 Lisp_Bit_Vector *p = (Lisp_Bit_Vector *) allocate_lisp_storage (sizem);
1539 set_lheader_implementation (&(p->lheader), lrecord_bit_vector); 1351 set_lheader_implementation (&(p->lheader), &lrecord_bit_vector);
1540 1352
1541 INCREMENT_CONS_COUNTER (sizem, "bit-vector"); 1353 INCREMENT_CONS_COUNTER (sizem, "bit-vector");
1542 1354
1543 bit_vector_length (p) = sizei; 1355 bit_vector_length (p) = sizei;
1544 bit_vector_next (p) = all_bit_vectors; 1356 bit_vector_next (p) = all_bit_vectors;
1550 } 1362 }
1551 1363
1552 Lisp_Object 1364 Lisp_Object
1553 make_bit_vector (size_t length, Lisp_Object init) 1365 make_bit_vector (size_t length, Lisp_Object init)
1554 { 1366 {
1555 struct Lisp_Bit_Vector *p = make_bit_vector_internal (length); 1367 Lisp_Bit_Vector *p = make_bit_vector_internal (length);
1556 size_t num_longs = BIT_VECTOR_LONG_STORAGE (length); 1368 size_t num_longs = BIT_VECTOR_LONG_STORAGE (length);
1557 1369
1558 CHECK_BIT (init); 1370 CHECK_BIT (init);
1559 1371
1560 if (ZEROP (init)) 1372 if (ZEROP (init))
1632 1444
1633 DECLARE_FIXED_TYPE_ALLOC (compiled_function, Lisp_Compiled_Function); 1445 DECLARE_FIXED_TYPE_ALLOC (compiled_function, Lisp_Compiled_Function);
1634 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_compiled_function 1000 1446 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_compiled_function 1000
1635 1447
1636 static Lisp_Object 1448 static Lisp_Object
1637 make_compiled_function (int make_pure) 1449 make_compiled_function (void)
1638 { 1450 {
1639 Lisp_Compiled_Function *f; 1451 Lisp_Compiled_Function *f;
1640 Lisp_Object fun; 1452 Lisp_Object fun;
1641 size_t size = sizeof (Lisp_Compiled_Function); 1453
1642 1454 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f);
1643 if (make_pure && check_purespace (size)) 1455 set_lheader_implementation (&(f->lheader), &lrecord_compiled_function);
1644 { 1456
1645 f = (Lisp_Compiled_Function *) (PUREBEG + pure_bytes_used);
1646 set_lheader_implementation (&(f->lheader), lrecord_compiled_function);
1647 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
1648 f->lheader.pure = 1;
1649 #endif
1650 pure_bytes_used += size;
1651 bump_purestat (&purestat_function, size);
1652 }
1653 else
1654 {
1655 ALLOCATE_FIXED_TYPE (compiled_function, Lisp_Compiled_Function, f);
1656 set_lheader_implementation (&(f->lheader), lrecord_compiled_function);
1657 }
1658 f->stack_depth = 0; 1457 f->stack_depth = 0;
1659 f->specpdl_depth = 0; 1458 f->specpdl_depth = 0;
1660 f->flags.documentationp = 0; 1459 f->flags.documentationp = 0;
1661 f->flags.interactivep = 0; 1460 f->flags.interactivep = 0;
1662 f->flags.domainp = 0; /* I18N3 */ 1461 f->flags.domainp = 0; /* I18N3 */
1686 (int nargs, Lisp_Object *args)) 1485 (int nargs, Lisp_Object *args))
1687 { 1486 {
1688 /* In a non-insane world this function would have this arglist... 1487 /* In a non-insane world this function would have this arglist...
1689 (arglist instructions constants stack_depth &optional doc_string interactive) 1488 (arglist instructions constants stack_depth &optional doc_string interactive)
1690 */ 1489 */
1691 Lisp_Object fun = make_compiled_function (purify_flag); 1490 Lisp_Object fun = make_compiled_function ();
1692 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun); 1491 Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (fun);
1693 1492
1694 Lisp_Object arglist = args[0]; 1493 Lisp_Object arglist = args[0];
1695 Lisp_Object instructions = args[1]; 1494 Lisp_Object instructions = args[1];
1696 Lisp_Object constants = args[2]; 1495 Lisp_Object constants = args[2];
1697 Lisp_Object stack_depth = args[3]; 1496 Lisp_Object stack_depth = args[3];
1698 Lisp_Object doc_string = (nargs > 4) ? args[4] : Qnil; 1497 Lisp_Object doc_string = (nargs > 4) ? args[4] : Qnil;
1699 Lisp_Object interactive = (nargs > 5) ? args[5] : Qunbound; 1498 Lisp_Object interactive = (nargs > 5) ? args[5] : Qunbound;
1700
1701 /* Don't purecopy the doc references in instructions because it's
1702 wasteful; they will get fixed up later.
1703
1704 #### If something goes wrong and they don't get fixed up,
1705 we're screwed, because pure stuff isn't marked and thus the
1706 cons references won't be marked and will get reused.
1707
1708 Note: there will be a window after the byte code is created and
1709 before the doc references are fixed up in which there will be
1710 impure objects inside a pure object, which apparently won't
1711 get marked, leading to trouble. But during that entire window,
1712 the objects are sitting on Vload_force_doc_string_list, which
1713 is staticpro'd, so we're OK. */
1714 Lisp_Object (*cons) (Lisp_Object, Lisp_Object)
1715 = purify_flag ? pure_cons : Fcons;
1716 1499
1717 if (nargs < 4 || nargs > 6) 1500 if (nargs < 4 || nargs > 6)
1718 return Fsignal (Qwrong_number_of_arguments, 1501 return Fsignal (Qwrong_number_of_arguments,
1719 list2 (intern ("make-byte-code"), make_int (nargs))); 1502 list2 (intern ("make-byte-code"), make_int (nargs)));
1720 1503
1751 if (!NILP (constants)) 1534 if (!NILP (constants))
1752 CHECK_VECTOR (constants); 1535 CHECK_VECTOR (constants);
1753 f->constants = constants; 1536 f->constants = constants;
1754 1537
1755 CHECK_NATNUM (stack_depth); 1538 CHECK_NATNUM (stack_depth);
1756 f->stack_depth = XINT (stack_depth); 1539 f->stack_depth = XINT (stack_depth);
1757 1540
1758 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 1541 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
1759 if (!NILP (Vcurrent_compiled_function_annotation)) 1542 if (!NILP (Vcurrent_compiled_function_annotation))
1760 f->annotated = Fpurecopy (Vcurrent_compiled_function_annotation); 1543 f->annotated = Fcopy (Vcurrent_compiled_function_annotation);
1761 else if (!NILP (Vload_file_name_internal_the_purecopy)) 1544 else if (!NILP (Vload_file_name_internal_the_purecopy))
1762 f->annotated = Vload_file_name_internal_the_purecopy; 1545 f->annotated = Vload_file_name_internal_the_purecopy;
1763 else if (!NILP (Vload_file_name_internal)) 1546 else if (!NILP (Vload_file_name_internal))
1764 { 1547 {
1765 struct gcpro gcpro1; 1548 struct gcpro gcpro1;
1766 GCPRO1 (fun); /* don't let fun get reaped */ 1549 GCPRO1 (fun); /* don't let fun get reaped */
1767 Vload_file_name_internal_the_purecopy = 1550 Vload_file_name_internal_the_purecopy =
1768 Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); 1551 Ffile_name_nondirectory (Vload_file_name_internal);
1769 f->annotated = Vload_file_name_internal_the_purecopy; 1552 f->annotated = Vload_file_name_internal_the_purecopy;
1770 UNGCPRO; 1553 UNGCPRO;
1771 } 1554 }
1772 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */ 1555 #endif /* COMPILED_FUNCTION_ANNOTATION_HACK */
1773 1556
1778 if ((f->flags.domainp = !NILP (Vfile_domain)) != 0) 1561 if ((f->flags.domainp = !NILP (Vfile_domain)) != 0)
1779 f->doc_and_interactive = Vfile_domain; 1562 f->doc_and_interactive = Vfile_domain;
1780 #endif 1563 #endif
1781 if ((f->flags.interactivep = !UNBOUNDP (interactive)) != 0) 1564 if ((f->flags.interactivep = !UNBOUNDP (interactive)) != 0)
1782 { 1565 {
1783 if (purify_flag)
1784 {
1785 interactive = Fpurecopy (interactive);
1786 if (STRINGP (interactive))
1787 bump_purestat (&purestat_string_interactive,
1788 pure_sizeof (interactive));
1789 }
1790 f->doc_and_interactive 1566 f->doc_and_interactive
1791 = (UNBOUNDP (f->doc_and_interactive) ? interactive : 1567 = (UNBOUNDP (f->doc_and_interactive) ? interactive :
1792 cons (interactive, f->doc_and_interactive)); 1568 Fcons (interactive, f->doc_and_interactive));
1793 } 1569 }
1794 if ((f->flags.documentationp = !NILP (doc_string)) != 0) 1570 if ((f->flags.documentationp = !NILP (doc_string)) != 0)
1795 { 1571 {
1796 if (purify_flag)
1797 {
1798 doc_string = Fpurecopy (doc_string);
1799 if (STRINGP (doc_string))
1800 /* These should have been snagged by make-docfile... */
1801 bump_purestat (&purestat_string_documentation,
1802 pure_sizeof (doc_string));
1803 }
1804 f->doc_and_interactive 1572 f->doc_and_interactive
1805 = (UNBOUNDP (f->doc_and_interactive) ? doc_string : 1573 = (UNBOUNDP (f->doc_and_interactive) ? doc_string :
1806 cons (doc_string, f->doc_and_interactive)); 1574 Fcons (doc_string, f->doc_and_interactive));
1807 } 1575 }
1808 if (UNBOUNDP (f->doc_and_interactive)) 1576 if (UNBOUNDP (f->doc_and_interactive))
1809 f->doc_and_interactive = Qnil; 1577 f->doc_and_interactive = Qnil;
1810
1811 if (purify_flag)
1812 {
1813
1814 if (!purified (f->arglist))
1815 f->arglist = Fpurecopy (f->arglist);
1816
1817 /* Statistics are kept differently for the constants */
1818 if (!purified (f->constants))
1819 {
1820 #ifdef PURESTAT
1821 int old = purecopying_function_constants;
1822 purecopying_function_constants = 1;
1823 f->constants = Fpurecopy (f->constants);
1824 bump_purestat (&purestat_vector_constants,
1825 pure_sizeof (f->constants));
1826 purecopying_function_constants = old;
1827 #else
1828 f->constants = Fpurecopy (f->constants);
1829 #endif /* PURESTAT */
1830 }
1831
1832 optimize_compiled_function (fun);
1833
1834 bump_purestat (&purestat_opaque_instructions,
1835 pure_sizeof (f->instructions));
1836 }
1837 1578
1838 return fun; 1579 return fun;
1839 } 1580 }
1840 1581
1841 1582
1842 /************************************************************************/ 1583 /************************************************************************/
1843 /* Symbol allocation */ 1584 /* Symbol allocation */
1844 /************************************************************************/ 1585 /************************************************************************/
1845 1586
1846 DECLARE_FIXED_TYPE_ALLOC (symbol, struct Lisp_Symbol); 1587 DECLARE_FIXED_TYPE_ALLOC (symbol, Lisp_Symbol);
1847 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_symbol 1000 1588 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_symbol 1000
1848 1589
1849 DEFUN ("make-symbol", Fmake_symbol, 1, 1, 0, /* 1590 DEFUN ("make-symbol", Fmake_symbol, 1, 1, 0, /*
1850 Return a newly allocated uninterned symbol whose name is NAME. 1591 Return a newly allocated uninterned symbol whose name is NAME.
1851 Its value and function definition are void, and its property list is nil. 1592 Its value and function definition are void, and its property list is nil.
1852 */ 1593 */
1853 (name)) 1594 (name))
1854 { 1595 {
1855 Lisp_Object val; 1596 Lisp_Object val;
1856 struct Lisp_Symbol *p; 1597 Lisp_Symbol *p;
1857 1598
1858 CHECK_STRING (name); 1599 CHECK_STRING (name);
1859 1600
1860 ALLOCATE_FIXED_TYPE (symbol, struct Lisp_Symbol, p); 1601 ALLOCATE_FIXED_TYPE (symbol, Lisp_Symbol, p);
1861 #ifdef LRECORD_SYMBOL 1602 set_lheader_implementation (&(p->lheader), &lrecord_symbol);
1862 set_lheader_implementation (&(p->lheader), lrecord_symbol);
1863 #endif
1864 p->name = XSTRING (name); 1603 p->name = XSTRING (name);
1865 p->plist = Qnil; 1604 p->plist = Qnil;
1866 p->value = Qunbound; 1605 p->value = Qunbound;
1867 p->function = Qunbound; 1606 p->function = Qunbound;
1868 p->obarray = Qnil;
1869 symbol_next (p) = 0; 1607 symbol_next (p) = 0;
1870 XSETSYMBOL (val, p); 1608 XSETSYMBOL (val, p);
1871 return val; 1609 return val;
1872 } 1610 }
1873 1611
1883 allocate_extent (void) 1621 allocate_extent (void)
1884 { 1622 {
1885 struct extent *e; 1623 struct extent *e;
1886 1624
1887 ALLOCATE_FIXED_TYPE (extent, struct extent, e); 1625 ALLOCATE_FIXED_TYPE (extent, struct extent, e);
1888 set_lheader_implementation (&(e->lheader), lrecord_extent); 1626 set_lheader_implementation (&(e->lheader), &lrecord_extent);
1889 extent_object (e) = Qnil; 1627 extent_object (e) = Qnil;
1890 set_extent_start (e, -1); 1628 set_extent_start (e, -1);
1891 set_extent_end (e, -1); 1629 set_extent_end (e, -1);
1892 e->plist = Qnil; 1630 e->plist = Qnil;
1893 1631
1903 1641
1904 /************************************************************************/ 1642 /************************************************************************/
1905 /* Event allocation */ 1643 /* Event allocation */
1906 /************************************************************************/ 1644 /************************************************************************/
1907 1645
1908 DECLARE_FIXED_TYPE_ALLOC (event, struct Lisp_Event); 1646 DECLARE_FIXED_TYPE_ALLOC (event, Lisp_Event);
1909 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_event 1000 1647 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_event 1000
1910 1648
1911 Lisp_Object 1649 Lisp_Object
1912 allocate_event (void) 1650 allocate_event (void)
1913 { 1651 {
1914 Lisp_Object val; 1652 Lisp_Object val;
1915 struct Lisp_Event *e; 1653 Lisp_Event *e;
1916 1654
1917 ALLOCATE_FIXED_TYPE (event, struct Lisp_Event, e); 1655 ALLOCATE_FIXED_TYPE (event, Lisp_Event, e);
1918 set_lheader_implementation (&(e->lheader), lrecord_event); 1656 set_lheader_implementation (&(e->lheader), &lrecord_event);
1919 1657
1920 XSETEVENT (val, e); 1658 XSETEVENT (val, e);
1921 return val; 1659 return val;
1922 } 1660 }
1923 1661
1924 1662
1925 /************************************************************************/ 1663 /************************************************************************/
1926 /* Marker allocation */ 1664 /* Marker allocation */
1927 /************************************************************************/ 1665 /************************************************************************/
1928 1666
1929 DECLARE_FIXED_TYPE_ALLOC (marker, struct Lisp_Marker); 1667 DECLARE_FIXED_TYPE_ALLOC (marker, Lisp_Marker);
1930 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_marker 1000 1668 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_marker 1000
1931 1669
1932 DEFUN ("make-marker", Fmake_marker, 0, 0, 0, /* 1670 DEFUN ("make-marker", Fmake_marker, 0, 0, 0, /*
1933 Return a new marker which does not point at any place. 1671 Return a new marker which does not point at any place.
1934 */ 1672 */
1935 ()) 1673 ())
1936 { 1674 {
1937 Lisp_Object val; 1675 Lisp_Object val;
1938 struct Lisp_Marker *p; 1676 Lisp_Marker *p;
1939 1677
1940 ALLOCATE_FIXED_TYPE (marker, struct Lisp_Marker, p); 1678 ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p);
1941 set_lheader_implementation (&(p->lheader), lrecord_marker); 1679 set_lheader_implementation (&(p->lheader), &lrecord_marker);
1942 p->buffer = 0; 1680 p->buffer = 0;
1943 p->memind = 0; 1681 p->memind = 0;
1944 marker_next (p) = 0; 1682 marker_next (p) = 0;
1945 marker_prev (p) = 0; 1683 marker_prev (p) = 0;
1946 p->insertion_type = 0; 1684 p->insertion_type = 0;
1950 1688
1951 Lisp_Object 1689 Lisp_Object
1952 noseeum_make_marker (void) 1690 noseeum_make_marker (void)
1953 { 1691 {
1954 Lisp_Object val; 1692 Lisp_Object val;
1955 struct Lisp_Marker *p; 1693 Lisp_Marker *p;
1956 1694
1957 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, struct Lisp_Marker, p); 1695 NOSEEUM_ALLOCATE_FIXED_TYPE (marker, Lisp_Marker, p);
1958 set_lheader_implementation (&(p->lheader), lrecord_marker); 1696 set_lheader_implementation (&(p->lheader), &lrecord_marker);
1959 p->buffer = 0; 1697 p->buffer = 0;
1960 p->memind = 0; 1698 p->memind = 0;
1961 marker_next (p) = 0; 1699 marker_next (p) = 0;
1962 marker_prev (p) = 0; 1700 marker_prev (p) = 0;
1963 p->insertion_type = 0; 1701 p->insertion_type = 0;
1981 strings (since EVERY REFERENCE to a short string needed to be GCPRO'd so 1719 strings (since EVERY REFERENCE to a short string needed to be GCPRO'd so
1982 that the reference would get relocated). 1720 that the reference would get relocated).
1983 1721
1984 This new method makes things somewhat bigger, but it is MUCH safer. */ 1722 This new method makes things somewhat bigger, but it is MUCH safer. */
1985 1723
1986 DECLARE_FIXED_TYPE_ALLOC (string, struct Lisp_String); 1724 DECLARE_FIXED_TYPE_ALLOC (string, Lisp_String);
1987 /* strings are used and freed quite often */ 1725 /* strings are used and freed quite often */
1988 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */ 1726 /* #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 10000 */
1989 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000 1727 #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000
1990 1728
1991 #ifdef LRECORD_STRING
1992 static Lisp_Object 1729 static Lisp_Object
1993 mark_string (Lisp_Object obj, void (*markobj) (Lisp_Object)) 1730 mark_string (Lisp_Object obj)
1994 { 1731 {
1995 struct Lisp_String *ptr = XSTRING (obj); 1732 Lisp_String *ptr = XSTRING (obj);
1996 1733
1997 if (GC_CONSP (ptr->plist) && GC_EXTENT_INFOP (XCAR (ptr->plist))) 1734 if (CONSP (ptr->plist) && EXTENT_INFOP (XCAR (ptr->plist)))
1998 flush_cached_extent_info (XCAR (ptr->plist)); 1735 flush_cached_extent_info (XCAR (ptr->plist));
1999 return ptr->plist; 1736 return ptr->plist;
2000 } 1737 }
2001 1738
2002 static int 1739 static int
2005 Bytecount len; 1742 Bytecount len;
2006 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && 1743 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) &&
2007 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); 1744 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len));
2008 } 1745 }
2009 1746
2010 DEFINE_BASIC_LRECORD_IMPLEMENTATION ("string", string, 1747 static const struct lrecord_description string_description[] = {
2011 mark_string, print_string, 1748 { XD_BYTECOUNT, offsetof (Lisp_String, size) },
2012 /* 1749 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data), XD_INDIRECT(0, 1) },
2013 * No `finalize', or `hash' methods. 1750 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) },
2014 * internal_hash already knows how 1751 { XD_END }
2015 * to hash strings and finalization 1752 };
2016 * is done with the 1753
2017 * ADDITIONAL_FREE_string macro, 1754 /* We store the string's extent info as the first element of the string's
2018 * which is the standard way to do 1755 property list; and the string's MODIFF as the first or second element
2019 * finalization when using 1756 of the string's property list (depending on whether the extent info
2020 * SWEEP_FIXED_TYPE_BLOCK(). 1757 is present), but only if the string has been modified. This is ugly
2021 */ 1758 but it reduces the memory allocated for the string in the vast
2022 0, string_equal, 0, 1759 majority of cases, where the string is never modified and has no
2023 struct Lisp_String); 1760 extent info.
2024 #endif /* LRECORD_STRING */ 1761
1762 #### This means you can't use an int as a key in a string's plist. */
1763
1764 static Lisp_Object *
1765 string_plist_ptr (Lisp_Object string)
1766 {
1767 Lisp_Object *ptr = &XSTRING (string)->plist;
1768
1769 if (CONSP (*ptr) && EXTENT_INFOP (XCAR (*ptr)))
1770 ptr = &XCDR (*ptr);
1771 if (CONSP (*ptr) && INTP (XCAR (*ptr)))
1772 ptr = &XCDR (*ptr);
1773 return ptr;
1774 }
1775
1776 static Lisp_Object
1777 string_getprop (Lisp_Object string, Lisp_Object property)
1778 {
1779 return external_plist_get (string_plist_ptr (string), property, 0, ERROR_ME);
1780 }
1781
1782 static int
1783 string_putprop (Lisp_Object string, Lisp_Object property, Lisp_Object value)
1784 {
1785 external_plist_put (string_plist_ptr (string), property, value, 0, ERROR_ME);
1786 return 1;
1787 }
1788
1789 static int
1790 string_remprop (Lisp_Object string, Lisp_Object property)
1791 {
1792 return external_remprop (string_plist_ptr (string), property, 0, ERROR_ME);
1793 }
1794
1795 static Lisp_Object
1796 string_plist (Lisp_Object string)
1797 {
1798 return *string_plist_ptr (string);
1799 }
1800
1801 /* No `finalize', or `hash' methods.
1802 internal_hash() already knows how to hash strings and finalization
1803 is done with the ADDITIONAL_FREE_string macro, which is the
1804 standard way to do finalization when using
1805 SWEEP_FIXED_TYPE_BLOCK(). */
1806 DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS ("string", string,
1807 mark_string, print_string,
1808 0, string_equal, 0,
1809 string_description,
1810 string_getprop,
1811 string_putprop,
1812 string_remprop,
1813 string_plist,
1814 Lisp_String);
2025 1815
2026 /* String blocks contain this many useful bytes. */ 1816 /* String blocks contain this many useful bytes. */
2027 #define STRING_CHARS_BLOCK_SIZE \ 1817 #define STRING_CHARS_BLOCK_SIZE \
2028 ((Bytecount) (8192 - MALLOC_OVERHEAD - \ 1818 ((Bytecount) (8192 - MALLOC_OVERHEAD - \
2029 ((2 * sizeof (struct string_chars_block *)) \ 1819 ((2 * sizeof (struct string_chars_block *)) \
2037 /* Contents of string_chars_block->string_chars are interleaved 1827 /* Contents of string_chars_block->string_chars are interleaved
2038 string_chars structures (see below) and the actual string data */ 1828 string_chars structures (see below) and the actual string data */
2039 unsigned char string_chars[STRING_CHARS_BLOCK_SIZE]; 1829 unsigned char string_chars[STRING_CHARS_BLOCK_SIZE];
2040 }; 1830 };
2041 1831
2042 struct string_chars_block *first_string_chars_block; 1832 static struct string_chars_block *first_string_chars_block;
2043 struct string_chars_block *current_string_chars_block; 1833 static struct string_chars_block *current_string_chars_block;
2044 1834
2045 /* If SIZE is the length of a string, this returns how many bytes 1835 /* If SIZE is the length of a string, this returns how many bytes
2046 * the string occupies in string_chars_block->string_chars 1836 * the string occupies in string_chars_block->string_chars
2047 * (including alignment padding). 1837 * (including alignment padding).
2048 */ 1838 */
2049 #define STRING_FULLSIZE(s) \ 1839 #define STRING_FULLSIZE(size) \
2050 ALIGN_SIZE (((s) + 1 + sizeof (struct Lisp_String *)),\ 1840 ALIGN_SIZE (((size) + 1 + sizeof (Lisp_String *)),\
2051 ALIGNOF (struct Lisp_String *)) 1841 ALIGNOF (Lisp_String *))
2052 1842
2053 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) 1843 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE)
2054 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) 1844 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size)))
2055 1845
2056 #define CHARS_TO_STRING_CHAR(x) \
2057 ((struct string_chars *) \
2058 (((char *) (x)) - (slot_offset (struct string_chars, chars[0]))))
2059
2060
2061 struct string_chars 1846 struct string_chars
2062 { 1847 {
2063 struct Lisp_String *string; 1848 Lisp_String *string;
2064 unsigned char chars[1]; 1849 unsigned char chars[1];
2065 }; 1850 };
2066 1851
2067 struct unused_string_chars 1852 struct unused_string_chars
2068 { 1853 {
2069 struct Lisp_String *string; 1854 Lisp_String *string;
2070 EMACS_INT fullsize; 1855 EMACS_INT fullsize;
2071 }; 1856 };
2072 1857
2073 static void 1858 static void
2074 init_string_chars_alloc (void) 1859 init_string_chars_alloc (void)
2079 first_string_chars_block->pos = 0; 1864 first_string_chars_block->pos = 0;
2080 current_string_chars_block = first_string_chars_block; 1865 current_string_chars_block = first_string_chars_block;
2081 } 1866 }
2082 1867
2083 static struct string_chars * 1868 static struct string_chars *
2084 allocate_string_chars_struct (struct Lisp_String *string_it_goes_with, 1869 allocate_string_chars_struct (Lisp_String *string_it_goes_with,
2085 EMACS_INT fullsize) 1870 EMACS_INT fullsize)
2086 { 1871 {
2087 struct string_chars *s_chars; 1872 struct string_chars *s_chars;
2088 1873
2089 /* Allocate the string's actual data */ 1874 if (fullsize <=
2090 if (BIG_STRING_FULLSIZE_P (fullsize)) 1875 (countof (current_string_chars_block->string_chars)
2091 { 1876 - current_string_chars_block->pos))
2092 s_chars = (struct string_chars *) xmalloc (fullsize);
2093 }
2094 else if (fullsize <=
2095 (countof (current_string_chars_block->string_chars)
2096 - current_string_chars_block->pos))
2097 { 1877 {
2098 /* This string can fit in the current string chars block */ 1878 /* This string can fit in the current string chars block */
2099 s_chars = (struct string_chars *) 1879 s_chars = (struct string_chars *)
2100 (current_string_chars_block->string_chars 1880 (current_string_chars_block->string_chars
2101 + current_string_chars_block->pos); 1881 + current_string_chars_block->pos);
2123 } 1903 }
2124 1904
2125 Lisp_Object 1905 Lisp_Object
2126 make_uninit_string (Bytecount length) 1906 make_uninit_string (Bytecount length)
2127 { 1907 {
2128 struct Lisp_String *s; 1908 Lisp_String *s;
2129 struct string_chars *s_chars;
2130 EMACS_INT fullsize = STRING_FULLSIZE (length); 1909 EMACS_INT fullsize = STRING_FULLSIZE (length);
2131 Lisp_Object val; 1910 Lisp_Object val;
2132 1911
2133 if ((length < 0) || (fullsize <= 0)) 1912 assert (length >= 0 && fullsize > 0);
2134 abort ();
2135 1913
2136 /* Allocate the string header */ 1914 /* Allocate the string header */
2137 ALLOCATE_FIXED_TYPE (string, struct Lisp_String, s); 1915 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
2138 #ifdef LRECORD_STRING 1916 set_lheader_implementation (&(s->lheader), &lrecord_string);
2139 set_lheader_implementation (&(s->lheader), lrecord_string); 1917
2140 #endif 1918 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize)
2141 1919 ? xnew_array (Bufbyte, length + 1)
2142 s_chars = allocate_string_chars_struct (s, fullsize); 1920 : allocate_string_chars_struct (s, fullsize)->chars);
2143 1921
2144 set_string_data (s, &(s_chars->chars[0]));
2145 set_string_length (s, length); 1922 set_string_length (s, length);
2146 s->plist = Qnil; 1923 s->plist = Qnil;
2147 1924
2148 set_string_byte (s, length, 0); 1925 set_string_byte (s, length, 0);
2149 1926
2160 POS < 0, resize the string but don't copy any characters. Use 1937 POS < 0, resize the string but don't copy any characters. Use
2161 this if you're planning on completely overwriting the string. 1938 this if you're planning on completely overwriting the string.
2162 */ 1939 */
2163 1940
2164 void 1941 void
2165 resize_string (struct Lisp_String *s, Bytecount pos, Bytecount delta) 1942 resize_string (Lisp_String *s, Bytecount pos, Bytecount delta)
2166 { 1943 {
1944 Bytecount oldfullsize, newfullsize;
2167 #ifdef VERIFY_STRING_CHARS_INTEGRITY 1945 #ifdef VERIFY_STRING_CHARS_INTEGRITY
2168 verify_string_chars_integrity (); 1946 verify_string_chars_integrity ();
2169 #endif 1947 #endif
2170 1948
2171 #ifdef ERROR_CHECK_BUFPOS 1949 #ifdef ERROR_CHECK_BUFPOS
2180 if (delta < 0) 1958 if (delta < 0)
2181 assert ((-delta) <= string_length (s)); 1959 assert ((-delta) <= string_length (s));
2182 } 1960 }
2183 #endif /* ERROR_CHECK_BUFPOS */ 1961 #endif /* ERROR_CHECK_BUFPOS */
2184 1962
2185 if (pos >= 0 && delta < 0)
2186 /* If DELTA < 0, the functions below will delete the characters
2187 before POS. We want to delete characters *after* POS, however,
2188 so convert this to the appropriate form. */
2189 pos += -delta;
2190
2191 if (delta == 0) 1963 if (delta == 0)
2192 /* simplest case: no size change. */ 1964 /* simplest case: no size change. */
2193 return; 1965 return;
2194 else 1966
2195 { 1967 if (pos >= 0 && delta < 0)
2196 Bytecount oldfullsize = STRING_FULLSIZE (string_length (s)); 1968 /* If DELTA < 0, the functions below will delete the characters
2197 Bytecount newfullsize = STRING_FULLSIZE (string_length (s) + delta); 1969 before POS. We want to delete characters *after* POS, however,
2198 1970 so convert this to the appropriate form. */
1971 pos += -delta;
1972
1973 oldfullsize = STRING_FULLSIZE (string_length (s));
1974 newfullsize = STRING_FULLSIZE (string_length (s) + delta);
1975
1976 if (BIG_STRING_FULLSIZE_P (oldfullsize))
1977 {
1978 if (BIG_STRING_FULLSIZE_P (newfullsize))
1979 {
1980 /* Both strings are big. We can just realloc().
1981 But careful! If the string is shrinking, we have to
1982 memmove() _before_ realloc(), and if growing, we have to
1983 memmove() _after_ realloc() - otherwise the access is
1984 illegal, and we might crash. */
1985 Bytecount len = string_length (s) + 1 - pos;
1986
1987 if (delta < 0 && pos >= 0)
1988 memmove (string_data (s) + pos + delta, string_data (s) + pos, len);
1989 set_string_data (s, (Bufbyte *) xrealloc (string_data (s),
1990 string_length (s) + delta + 1));
1991 if (delta > 0 && pos >= 0)
1992 memmove (string_data (s) + pos + delta, string_data (s) + pos, len);
1993 }
1994 else /* String has been demoted from BIG_STRING. */
1995 {
1996 Bufbyte *new_data =
1997 allocate_string_chars_struct (s, newfullsize)->chars;
1998 Bufbyte *old_data = string_data (s);
1999
2000 if (pos >= 0)
2001 {
2002 memcpy (new_data, old_data, pos);
2003 memcpy (new_data + pos + delta, old_data + pos,
2004 string_length (s) + 1 - pos);
2005 }
2006 set_string_data (s, new_data);
2007 xfree (old_data);
2008 }
2009 }
2010 else /* old string is small */
2011 {
2199 if (oldfullsize == newfullsize) 2012 if (oldfullsize == newfullsize)
2200 { 2013 {
2201 /* next simplest case; size change but the necessary 2014 /* special case; size change but the necessary
2202 allocation size won't change (up or down; code somewhere 2015 allocation size won't change (up or down; code
2203 depends on there not being any unused allocation space, 2016 somewhere depends on there not being any unused
2204 modulo any alignment constraints). */ 2017 allocation space, modulo any alignment
2205 if (pos >= 0) 2018 constraints). */
2206 {
2207 Bufbyte *addroff = pos + string_data (s);
2208
2209 memmove (addroff + delta, addroff,
2210 /* +1 due to zero-termination. */
2211 string_length (s) + 1 - pos);
2212 }
2213 }
2214 else if (BIG_STRING_FULLSIZE_P (oldfullsize) &&
2215 BIG_STRING_FULLSIZE_P (newfullsize))
2216 {
2217 /* next simplest case; the string is big enough to be malloc()ed
2218 itself, so we just realloc.
2219
2220 It's important not to let the string get below the threshold
2221 for making big strings and still remain malloc()ed; if that
2222 were the case, repeated calls to this function on the same
2223 string could result in memory leakage. */
2224 set_string_data (s, (Bufbyte *) xrealloc (string_data (s),
2225 newfullsize));
2226 if (pos >= 0) 2019 if (pos >= 0)
2227 { 2020 {
2228 Bufbyte *addroff = pos + string_data (s); 2021 Bufbyte *addroff = pos + string_data (s);
2229 2022
2230 memmove (addroff + delta, addroff, 2023 memmove (addroff + delta, addroff,
2232 string_length (s) + 1 - pos); 2025 string_length (s) + 1 - pos);
2233 } 2026 }
2234 } 2027 }
2235 else 2028 else
2236 { 2029 {
2237 /* worst case. We make a new string_chars struct and copy 2030 Bufbyte *old_data = string_data (s);
2238 the string's data into it, inserting/deleting the delta 2031 Bufbyte *new_data =
2239 in the process. The old string data will either get 2032 BIG_STRING_FULLSIZE_P (newfullsize)
2240 freed by us (if it was malloc()ed) or will be reclaimed 2033 ? xnew_array (Bufbyte, string_length (s) + delta + 1)
2241 in the normal course of garbage collection. */ 2034 : allocate_string_chars_struct (s, newfullsize)->chars;
2242 struct string_chars *s_chars = 2035
2243 allocate_string_chars_struct (s, newfullsize);
2244 Bufbyte *new_addr = &(s_chars->chars[0]);
2245 Bufbyte *old_addr = string_data (s);
2246 if (pos >= 0) 2036 if (pos >= 0)
2247 { 2037 {
2248 memcpy (new_addr, old_addr, pos); 2038 memcpy (new_data, old_data, pos);
2249 memcpy (new_addr + pos + delta, old_addr + pos, 2039 memcpy (new_data + pos + delta, old_data + pos,
2250 string_length (s) + 1 - pos); 2040 string_length (s) + 1 - pos);
2251 } 2041 }
2252 set_string_data (s, new_addr); 2042 set_string_data (s, new_data);
2253 if (BIG_STRING_FULLSIZE_P (oldfullsize)) 2043
2254 xfree (old_addr); 2044 {
2255 else 2045 /* We need to mark this chunk of the string_chars_block
2256 { 2046 as unused so that compact_string_chars() doesn't
2257 /* We need to mark this chunk of the string_chars_block 2047 freak. */
2258 as unused so that compact_string_chars() doesn't 2048 struct string_chars *old_s_chars = (struct string_chars *)
2259 freak. */ 2049 ((char *) old_data - offsetof (struct string_chars, chars));
2260 struct string_chars *old_s_chars = 2050 /* Sanity check to make sure we aren't hosed by strange
2261 (struct string_chars *) ((char *) old_addr - 2051 alignment/padding. */
2262 sizeof (struct Lisp_String *)); 2052 assert (old_s_chars->string == s);
2263 /* Sanity check to make sure we aren't hosed by strange 2053 MARK_STRUCT_AS_FREE (old_s_chars);
2264 alignment/padding. */ 2054 ((struct unused_string_chars *) old_s_chars)->fullsize =
2265 assert (old_s_chars->string == s); 2055 oldfullsize;
2266 MARK_STRUCT_AS_FREE (old_s_chars); 2056 }
2267 ((struct unused_string_chars *) old_s_chars)->fullsize =
2268 oldfullsize;
2269 }
2270 } 2057 }
2271 2058 }
2272 set_string_length (s, string_length (s) + delta); 2059
2273 /* If pos < 0, the string won't be zero-terminated. 2060 set_string_length (s, string_length (s) + delta);
2274 Terminate now just to make sure. */ 2061 /* If pos < 0, the string won't be zero-terminated.
2275 string_data (s)[string_length (s)] = '\0'; 2062 Terminate now just to make sure. */
2276 2063 string_data (s)[string_length (s)] = '\0';
2277 if (pos >= 0) 2064
2278 { 2065 if (pos >= 0)
2279 Lisp_Object string; 2066 {
2280 2067 Lisp_Object string;
2281 XSETSTRING (string, s); 2068
2282 /* We also have to adjust all of the extent indices after the 2069 XSETSTRING (string, s);
2283 place we did the change. We say "pos - 1" because 2070 /* We also have to adjust all of the extent indices after the
2284 adjust_extents() is exclusive of the starting position 2071 place we did the change. We say "pos - 1" because
2285 passed to it. */ 2072 adjust_extents() is exclusive of the starting position
2286 adjust_extents (string, pos - 1, string_length (s), 2073 passed to it. */
2287 delta); 2074 adjust_extents (string, pos - 1, string_length (s),
2288 } 2075 delta);
2289 } 2076 }
2290 2077
2291 #ifdef VERIFY_STRING_CHARS_INTEGRITY 2078 #ifdef VERIFY_STRING_CHARS_INTEGRITY
2292 verify_string_chars_integrity (); 2079 verify_string_chars_integrity ();
2293 #endif 2080 #endif
2294 } 2081 }
2295 2082
2296 #ifdef MULE 2083 #ifdef MULE
2297 2084
2298 void 2085 void
2299 set_string_char (struct Lisp_String *s, Charcount i, Emchar c) 2086 set_string_char (Lisp_String *s, Charcount i, Emchar c)
2300 { 2087 {
2301 Bufbyte newstr[MAX_EMCHAR_LEN]; 2088 Bufbyte newstr[MAX_EMCHAR_LEN];
2302 Bytecount bytoff = charcount_to_bytecount (string_data (s), i); 2089 Bytecount bytoff = charcount_to_bytecount (string_data (s), i);
2303 Bytecount oldlen = charcount_to_bytecount (string_data (s) + bytoff, 1); 2090 Bytecount oldlen = charcount_to_bytecount (string_data (s) + bytoff, 1);
2304 Bytecount newlen = set_charptr_emchar (newstr, c); 2091 Bytecount newlen = set_charptr_emchar (newstr, c);
2327 if (len == 1) 2114 if (len == 1)
2328 /* Optimize the single-byte case */ 2115 /* Optimize the single-byte case */
2329 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); 2116 memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val));
2330 else 2117 else
2331 { 2118 {
2332 int i; 2119 size_t i;
2333 Bufbyte *ptr = XSTRING_DATA (val); 2120 Bufbyte *ptr = XSTRING_DATA (val);
2334 2121
2335 for (i = XINT (length); i; i--) 2122 for (i = XINT (length); i; i--)
2336 { 2123 {
2337 Bufbyte *init_ptr = init_str; 2124 Bufbyte *init_ptr = init_str;
2363 p += set_charptr_emchar (p, XCHAR (lisp_char)); 2150 p += set_charptr_emchar (p, XCHAR (lisp_char));
2364 } 2151 }
2365 return make_string (storage, p - storage); 2152 return make_string (storage, p - storage);
2366 } 2153 }
2367 2154
2155
2368 /* Take some raw memory, which MUST already be in internal format, 2156 /* Take some raw memory, which MUST already be in internal format,
2369 and package it up into a Lisp string. */ 2157 and package it up into a Lisp string. */
2370 Lisp_Object 2158 Lisp_Object
2371 make_string (CONST Bufbyte *contents, Bytecount length) 2159 make_string (const Bufbyte *contents, Bytecount length)
2372 { 2160 {
2373 Lisp_Object val; 2161 Lisp_Object val;
2374 2162
2375 /* Make sure we find out about bad make_string's when they happen */ 2163 /* Make sure we find out about bad make_string's when they happen */
2376 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE) 2164 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE)
2383 } 2171 }
2384 2172
2385 /* Take some raw memory, encoded in some external data format, 2173 /* Take some raw memory, encoded in some external data format,
2386 and convert it into a Lisp string. */ 2174 and convert it into a Lisp string. */
2387 Lisp_Object 2175 Lisp_Object
2388 make_ext_string (CONST Extbyte *contents, EMACS_INT length, 2176 make_ext_string (const Extbyte *contents, EMACS_INT length,
2389 enum external_data_format fmt) 2177 Lisp_Object coding_system)
2390 { 2178 {
2391 Bufbyte *intstr; 2179 Lisp_Object string;
2392 Bytecount intlen; 2180 TO_INTERNAL_FORMAT (DATA, (contents, length),
2393 2181 LISP_STRING, string,
2394 GET_CHARPTR_INT_DATA_ALLOCA (contents, length, fmt, intstr, intlen); 2182 coding_system);
2395 return make_string (intstr, intlen); 2183 return string;
2396 } 2184 }
2397 2185
2398 Lisp_Object 2186 Lisp_Object
2399 build_string (CONST char *str) 2187 build_string (const char *str)
2400 { 2188 {
2401 /* Some strlen's crash and burn if passed null. */ 2189 /* Some strlen's crash and burn if passed null. */
2402 return make_string ((CONST Bufbyte *) str, (str ? strlen(str) : 0)); 2190 return make_string ((const Bufbyte *) str, (str ? strlen(str) : 0));
2403 } 2191 }
2404 2192
2405 Lisp_Object 2193 Lisp_Object
2406 build_ext_string (CONST char *str, enum external_data_format fmt) 2194 build_ext_string (const char *str, Lisp_Object coding_system)
2407 { 2195 {
2408 /* Some strlen's crash and burn if passed null. */ 2196 /* Some strlen's crash and burn if passed null. */
2409 return make_ext_string ((CONST Extbyte *) str, (str ? strlen(str) : 0), fmt); 2197 return make_ext_string ((const Extbyte *) str, (str ? strlen(str) : 0),
2198 coding_system);
2410 } 2199 }
2411 2200
2412 Lisp_Object 2201 Lisp_Object
2413 build_translated_string (CONST char *str) 2202 build_translated_string (const char *str)
2414 { 2203 {
2415 return build_string (GETTEXT (str)); 2204 return build_string (GETTEXT (str));
2205 }
2206
2207 Lisp_Object
2208 make_string_nocopy (const Bufbyte *contents, Bytecount length)
2209 {
2210 Lisp_String *s;
2211 Lisp_Object val;
2212
2213 /* Make sure we find out about bad make_string_nocopy's when they happen */
2214 #if defined (ERROR_CHECK_BUFPOS) && defined (MULE)
2215 bytecount_to_charcount (contents, length); /* Just for the assertions */
2216 #endif
2217
2218 /* Allocate the string header */
2219 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
2220 set_lheader_implementation (&(s->lheader), &lrecord_string);
2221 SET_C_READONLY_RECORD_HEADER (&s->lheader);
2222 s->plist = Qnil;
2223 set_string_data (s, (Bufbyte *)contents);
2224 set_string_length (s, length);
2225
2226 XSETSTRING (val, s);
2227 return val;
2416 } 2228 }
2417 2229
2418 2230
2419 /************************************************************************/ 2231 /************************************************************************/
2420 /* lcrecord lists */ 2232 /* lcrecord lists */
2426 It is similar to the Blocktype class. 2238 It is similar to the Blocktype class.
2427 2239
2428 It works like this: 2240 It works like this:
2429 2241
2430 1) Create an lcrecord-list object using make_lcrecord_list(). 2242 1) Create an lcrecord-list object using make_lcrecord_list().
2431 This is often done at initialization. Remember to staticpro 2243 This is often done at initialization. Remember to staticpro_nodump
2432 this object! The arguments to make_lcrecord_list() are the 2244 this object! The arguments to make_lcrecord_list() are the
2433 same as would be passed to alloc_lcrecord(). 2245 same as would be passed to alloc_lcrecord().
2434 2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord() 2246 2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord()
2435 and pass the lcrecord-list earlier created. 2247 and pass the lcrecord-list earlier created.
2436 3) When done with the lcrecord, call free_managed_lcrecord(). 2248 3) When done with the lcrecord, call free_managed_lcrecord().
2447 at the time that free_managed_lcrecord() is called. 2259 at the time that free_managed_lcrecord() is called.
2448 2260
2449 */ 2261 */
2450 2262
2451 static Lisp_Object 2263 static Lisp_Object
2452 mark_lcrecord_list (Lisp_Object obj, void (*markobj) (Lisp_Object)) 2264 mark_lcrecord_list (Lisp_Object obj)
2453 { 2265 {
2454 struct lcrecord_list *list = XLCRECORD_LIST (obj); 2266 struct lcrecord_list *list = XLCRECORD_LIST (obj);
2455 Lisp_Object chain = list->free; 2267 Lisp_Object chain = list->free;
2456 2268
2457 while (!NILP (chain)) 2269 while (!NILP (chain))
2459 struct lrecord_header *lheader = XRECORD_LHEADER (chain); 2271 struct lrecord_header *lheader = XRECORD_LHEADER (chain);
2460 struct free_lcrecord_header *free_header = 2272 struct free_lcrecord_header *free_header =
2461 (struct free_lcrecord_header *) lheader; 2273 (struct free_lcrecord_header *) lheader;
2462 2274
2463 #ifdef ERROR_CHECK_GC 2275 #ifdef ERROR_CHECK_GC
2464 CONST struct lrecord_implementation *implementation 2276 const struct lrecord_implementation *implementation
2465 = LHEADER_IMPLEMENTATION(lheader); 2277 = LHEADER_IMPLEMENTATION(lheader);
2466 2278
2467 /* There should be no other pointers to the free list. */ 2279 /* There should be no other pointers to the free list. */
2468 assert (!MARKED_RECORD_HEADER_P (lheader)); 2280 assert (!MARKED_RECORD_HEADER_P (lheader));
2469 /* Only lcrecords should be here. */ 2281 /* Only lcrecords should be here. */
2484 return Qnil; 2296 return Qnil;
2485 } 2297 }
2486 2298
2487 DEFINE_LRECORD_IMPLEMENTATION ("lcrecord-list", lcrecord_list, 2299 DEFINE_LRECORD_IMPLEMENTATION ("lcrecord-list", lcrecord_list,
2488 mark_lcrecord_list, internal_object_printer, 2300 mark_lcrecord_list, internal_object_printer,
2489 0, 0, 0, struct lcrecord_list); 2301 0, 0, 0, 0, struct lcrecord_list);
2490 Lisp_Object 2302 Lisp_Object
2491 make_lcrecord_list (size_t size, 2303 make_lcrecord_list (size_t size,
2492 CONST struct lrecord_implementation *implementation) 2304 const struct lrecord_implementation *implementation)
2493 { 2305 {
2494 struct lcrecord_list *p = alloc_lcrecord_type (struct lcrecord_list, 2306 struct lcrecord_list *p = alloc_lcrecord_type (struct lcrecord_list,
2495 lrecord_lcrecord_list); 2307 &lrecord_lcrecord_list);
2496 Lisp_Object val; 2308 Lisp_Object val;
2497 2309
2498 p->implementation = implementation; 2310 p->implementation = implementation;
2499 p->size = size; 2311 p->size = size;
2500 p->free = Qnil; 2312 p->free = Qnil;
2513 (struct free_lcrecord_header *) XPNTR (val); 2325 (struct free_lcrecord_header *) XPNTR (val);
2514 2326
2515 #ifdef ERROR_CHECK_GC 2327 #ifdef ERROR_CHECK_GC
2516 struct lrecord_header *lheader = 2328 struct lrecord_header *lheader =
2517 (struct lrecord_header *) free_header; 2329 (struct lrecord_header *) free_header;
2518 CONST struct lrecord_implementation *implementation 2330 const struct lrecord_implementation *implementation
2519 = LHEADER_IMPLEMENTATION (lheader); 2331 = LHEADER_IMPLEMENTATION (lheader);
2520 2332
2521 /* There should be no other pointers to the free list. */ 2333 /* There should be no other pointers to the free list. */
2522 assert (!MARKED_RECORD_HEADER_P (lheader)); 2334 assert (!MARKED_RECORD_HEADER_P (lheader));
2523 /* Only lcrecords should be here. */ 2335 /* Only lcrecords should be here. */
2550 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list); 2362 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list);
2551 struct free_lcrecord_header *free_header = 2363 struct free_lcrecord_header *free_header =
2552 (struct free_lcrecord_header *) XPNTR (lcrecord); 2364 (struct free_lcrecord_header *) XPNTR (lcrecord);
2553 struct lrecord_header *lheader = 2365 struct lrecord_header *lheader =
2554 (struct lrecord_header *) free_header; 2366 (struct lrecord_header *) free_header;
2555 CONST struct lrecord_implementation *implementation 2367 const struct lrecord_implementation *implementation
2556 = LHEADER_IMPLEMENTATION (lheader); 2368 = LHEADER_IMPLEMENTATION (lheader);
2557 2369
2558 #ifdef ERROR_CHECK_GC 2370 #ifdef ERROR_CHECK_GC
2559 /* Make sure the size is correct. This will catch, for example, 2371 /* Make sure the size is correct. This will catch, for example,
2560 putting a window configuration on the wrong free list. */ 2372 putting a window configuration on the wrong free list. */
2570 free_header->lcheader.free = 1; 2382 free_header->lcheader.free = 1;
2571 list->free = lcrecord; 2383 list->free = lcrecord;
2572 } 2384 }
2573 2385
2574 2386
2575 /************************************************************************/
2576 /* Purity of essence, peace on earth */
2577 /************************************************************************/
2578
2579 static int symbols_initialized;
2580
2581 Lisp_Object
2582 make_pure_string (CONST Bufbyte *data, Bytecount length,
2583 Lisp_Object plist, int no_need_to_copy_data)
2584 {
2585 Lisp_String *s;
2586 size_t size = sizeof (Lisp_String) +
2587 (no_need_to_copy_data ? 0 : (length + 1)); /* + 1 for terminating 0 */
2588 size = ALIGN_SIZE (size, ALIGNOF (Lisp_Object));
2589
2590 if (symbols_initialized && !pure_lossage)
2591 {
2592 /* Try to share some names. Saves a few kbytes. */
2593 Lisp_Object tem = oblookup (Vobarray, data, length);
2594 if (SYMBOLP (tem))
2595 {
2596 s = XSYMBOL (tem)->name;
2597 if (!PURIFIED (s)) abort ();
2598
2599 {
2600 Lisp_Object string;
2601 XSETSTRING (string, s);
2602 return string;
2603 }
2604 }
2605 }
2606
2607 if (!check_purespace (size))
2608 return make_string (data, length);
2609
2610 s = (Lisp_String *) (PUREBEG + pure_bytes_used);
2611 #ifdef LRECORD_STRING
2612 set_lheader_implementation (&(s->lheader), lrecord_string);
2613 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
2614 s->lheader.pure = 1;
2615 #endif
2616 #endif
2617 set_string_length (s, length);
2618 if (no_need_to_copy_data)
2619 {
2620 set_string_data (s, (Bufbyte *) data);
2621 }
2622 else
2623 {
2624 set_string_data (s, (Bufbyte *) s + sizeof (Lisp_String));
2625 memcpy (string_data (s), data, length);
2626 set_string_byte (s, length, 0);
2627 }
2628 s->plist = Qnil;
2629 pure_bytes_used += size;
2630
2631 #ifdef PURESTAT
2632 bump_purestat (&purestat_string_all, size);
2633 if (purecopying_function_constants)
2634 bump_purestat (&purestat_string_other_function, size);
2635 #endif /* PURESTAT */
2636
2637 /* Do this after the official "completion" of the purecopying. */
2638 s->plist = Fpurecopy (plist);
2639
2640 {
2641 Lisp_Object string;
2642 XSETSTRING (string, s);
2643 return string;
2644 }
2645 }
2646
2647
2648 Lisp_Object
2649 make_pure_pname (CONST Bufbyte *data, Bytecount length,
2650 int no_need_to_copy_data)
2651 {
2652 Lisp_Object name = make_pure_string (data, length, Qnil,
2653 no_need_to_copy_data);
2654 bump_purestat (&purestat_string_pname, pure_sizeof (name));
2655
2656 /* We've made (at least) Qnil now, and Vobarray will soon be set up. */
2657 symbols_initialized = 1;
2658
2659 return name;
2660 }
2661
2662
2663 Lisp_Object
2664 pure_cons (Lisp_Object car, Lisp_Object cdr)
2665 {
2666 Lisp_Cons *c;
2667
2668 if (!check_purespace (sizeof (Lisp_Cons)))
2669 return Fcons (Fpurecopy (car), Fpurecopy (cdr));
2670
2671 c = (Lisp_Cons *) (PUREBEG + pure_bytes_used);
2672 #ifdef LRECORD_CONS
2673 set_lheader_implementation (&(c->lheader), lrecord_cons);
2674 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
2675 c->lheader.pure = 1;
2676 #endif
2677 #endif
2678 pure_bytes_used += sizeof (Lisp_Cons);
2679 bump_purestat (&purestat_cons, sizeof (Lisp_Cons));
2680
2681 c->car = Fpurecopy (car);
2682 c->cdr = Fpurecopy (cdr);
2683
2684 {
2685 Lisp_Object cons;
2686 XSETCONS (cons, c);
2687 return cons;
2688 }
2689 }
2690
2691 Lisp_Object
2692 pure_list (int nargs, Lisp_Object *args)
2693 {
2694 Lisp_Object val = Qnil;
2695
2696 for (--nargs; nargs >= 0; nargs--)
2697 val = pure_cons (args[nargs], val);
2698
2699 return val;
2700 }
2701
2702 #ifdef LISP_FLOAT_TYPE
2703
2704 static Lisp_Object
2705 make_pure_float (double num)
2706 {
2707 struct Lisp_Float *f;
2708 Lisp_Object val;
2709
2710 /* Make sure that PUREBEG + pure_bytes_used is aligned on at least a sizeof
2711 (double) boundary. Some architectures (like the sparc) require
2712 this, and I suspect that floats are rare enough that it's no
2713 tragedy for those that don't. */
2714 {
2715 #if defined (__GNUC__) && (__GNUC__ >= 2)
2716 /* In gcc, we can directly ask what the alignment constraints of a
2717 structure are, but in general, that's not possible... Arrgh!!
2718 */
2719 int alignment = __alignof (struct Lisp_Float);
2720 #else /* !GNUC */
2721 /* Best guess is to make the `double' slot be aligned to the size
2722 of double (which is probably 8 bytes). This assumes that it's
2723 ok to align the beginning of the structure to the same boundary
2724 that the `double' slot in it is supposed to be aligned to; this
2725 should be ok because presumably there is padding in the layout
2726 of the struct to account for this.
2727 */
2728 int alignment = sizeof (float_data (f));
2729 #endif /* !GNUC */
2730 char *p = ((char *) PUREBEG + pure_bytes_used);
2731
2732 p = (char *) (((EMACS_UINT) p + alignment - 1) & - alignment);
2733 pure_bytes_used = p - (char *) PUREBEG;
2734 }
2735
2736 if (!check_purespace (sizeof (struct Lisp_Float)))
2737 return make_float (num);
2738
2739 f = (struct Lisp_Float *) (PUREBEG + pure_bytes_used);
2740 set_lheader_implementation (&(f->lheader), lrecord_float);
2741 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
2742 f->lheader.pure = 1;
2743 #endif
2744 pure_bytes_used += sizeof (struct Lisp_Float);
2745 bump_purestat (&purestat_float, sizeof (struct Lisp_Float));
2746
2747 float_data (f) = num;
2748 XSETFLOAT (val, f);
2749 return val;
2750 }
2751
2752 #endif /* LISP_FLOAT_TYPE */
2753
2754 Lisp_Object
2755 make_pure_vector (size_t len, Lisp_Object init)
2756 {
2757 Lisp_Vector *v;
2758 size_t size = STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, len);
2759
2760 init = Fpurecopy (init);
2761
2762 if (!check_purespace (size))
2763 return make_vector (len, init);
2764
2765 v = (Lisp_Vector *) (PUREBEG + pure_bytes_used);
2766 #ifdef LRECORD_VECTOR
2767 set_lheader_implementation (&(v->header.lheader), lrecord_vector);
2768 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
2769 v->header.lheader.pure = 1;
2770 #endif
2771 #endif
2772 pure_bytes_used += size;
2773 bump_purestat (&purestat_vector_all, size);
2774
2775 v->size = len;
2776
2777 for (size = 0; size < len; size++)
2778 v->contents[size] = init;
2779
2780 {
2781 Lisp_Object vector;
2782 XSETVECTOR (vector, v);
2783 return vector;
2784 }
2785 }
2786
2787 #if 0
2788 /* Presently unused */
2789 void *
2790 alloc_pure_lrecord (int size, struct lrecord_implementation *implementation)
2791 {
2792 struct lrecord_header *header = (void *) (PUREBEG + pure_bytes_used);
2793
2794 if (pure_bytes_used + size > get_PURESIZE())
2795 pure_storage_exhausted ();
2796
2797 set_lheader_implementation (header, implementation);
2798 header->next = 0;
2799 return header;
2800 }
2801 #endif /* unused */
2802
2803 2387
2804 2388
2805 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /* 2389 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /*
2390 Kept for compatibility, returns its argument.
2391 Old:
2806 Make a copy of OBJECT in pure storage. 2392 Make a copy of OBJECT in pure storage.
2807 Recursively copies contents of vectors and cons cells. 2393 Recursively copies contents of vectors and cons cells.
2808 Does not copy symbols. 2394 Does not copy symbols.
2809 */ 2395 */
2810 (obj)) 2396 (obj))
2811 { 2397 {
2812 if (!purify_flag) 2398 return obj;
2813 { 2399 }
2814 return obj; 2400
2815 }
2816 else if (!POINTER_TYPE_P (XTYPE (obj))
2817 || PURIFIED (XPNTR (obj))
2818 /* happens when bootstrapping Qnil */
2819 || EQ (obj, Qnull_pointer))
2820 {
2821 return obj;
2822 }
2823 /* Order of subsequent tests determined via profiling. */
2824 else if (SYMBOLP (obj))
2825 {
2826 /* Symbols can't be made pure (and thus read-only), because
2827 assigning to their function, value or plist slots would
2828 produced a SEGV in the dumped XEmacs. So we previously would
2829 just return the symbol unchanged.
2830
2831 But purified aggregate objects like lists and vectors can
2832 contain uninterned symbols. If there are no other non-pure
2833 references to the symbol, then the symbol is not protected
2834 from garbage collection because the collector does not mark
2835 the contents of purified objects. So to protect the symbols,
2836 an impure reference has to be kept for each uninterned symbol
2837 that is referenced by a pure object. All such symbols are
2838 stored in the hash table pointed to by
2839 Vpure_uninterned_symbol_table, which is itself
2840 staticpro'd. */
2841 if (NILP (XSYMBOL (obj)->obarray))
2842 Fputhash (obj, Qnil, Vpure_uninterned_symbol_table);
2843 return obj;
2844 }
2845 else if (CONSP (obj))
2846 {
2847 return pure_cons (XCAR (obj), XCDR (obj));
2848 }
2849 else if (STRINGP (obj))
2850 {
2851 return make_pure_string (XSTRING_DATA (obj),
2852 XSTRING_LENGTH (obj),
2853 XSTRING (obj)->plist,
2854 0);
2855 }
2856 else if (VECTORP (obj))
2857 {
2858 int i;
2859 Lisp_Vector *o = XVECTOR (obj);
2860 Lisp_Object pure_obj = make_pure_vector (vector_length (o), Qnil);
2861 for (i = 0; i < vector_length (o); i++)
2862 XVECTOR_DATA (pure_obj)[i] = Fpurecopy (o->contents[i]);
2863 return pure_obj;
2864 }
2865 #ifdef LISP_FLOAT_TYPE
2866 else if (FLOATP (obj))
2867 {
2868 return make_pure_float (XFLOAT_DATA (obj));
2869 }
2870 #endif
2871 else if (COMPILED_FUNCTIONP (obj))
2872 {
2873 Lisp_Object pure_obj = make_compiled_function (1);
2874 Lisp_Compiled_Function *o = XCOMPILED_FUNCTION (obj);
2875 Lisp_Compiled_Function *n = XCOMPILED_FUNCTION (pure_obj);
2876 n->flags = o->flags;
2877 n->instructions = o->instructions;
2878 n->constants = Fpurecopy (o->constants);
2879 n->arglist = Fpurecopy (o->arglist);
2880 n->doc_and_interactive = Fpurecopy (o->doc_and_interactive);
2881 n->stack_depth = o->stack_depth;
2882 optimize_compiled_function (pure_obj);
2883 return pure_obj;
2884 }
2885 else if (OPAQUEP (obj))
2886 {
2887 Lisp_Object pure_obj;
2888 Lisp_Opaque *old_opaque = XOPAQUE (obj);
2889 Lisp_Opaque *new_opaque = (Lisp_Opaque *) (PUREBEG + pure_bytes_used);
2890 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
2891 CONST struct lrecord_implementation *implementation
2892 = LHEADER_IMPLEMENTATION (lheader);
2893 size_t size = implementation->size_in_bytes_method (lheader);
2894 size_t pure_size = ALIGN_SIZE (size, ALIGNOF (Lisp_Object));
2895 if (!check_purespace (pure_size))
2896 return obj;
2897 pure_bytes_used += pure_size;
2898
2899 memcpy (new_opaque, old_opaque, size);
2900 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
2901 lheader->pure = 1;
2902 #endif
2903 new_opaque->header.next = 0;
2904
2905 XSETOPAQUE (pure_obj, new_opaque);
2906 return pure_obj;
2907 }
2908 else
2909 {
2910 signal_simple_error ("Can't purecopy %S", obj);
2911 }
2912 return obj; /* Unreached */
2913 }
2914
2915
2916
2917 static void
2918 puresize_adjust_h (size_t puresize)
2919 {
2920 FILE *stream = fopen ("puresize-adjust.h", "w");
2921
2922 if (stream == NULL)
2923 report_file_error ("Opening puresize adjustment file",
2924 Fcons (build_string ("puresize-adjust.h"), Qnil));
2925
2926 fprintf (stream,
2927 "/*\tDo not edit this file!\n"
2928 "\tAutomatically generated by XEmacs */\n"
2929 "# define PURESIZE_ADJUSTMENT (%ld)\n",
2930 (long) (puresize - RAW_PURESIZE));
2931 fclose (stream);
2932 }
2933
2934 void
2935 report_pure_usage (int report_impurities,
2936 int die_if_pure_storage_exceeded)
2937 {
2938 int rc = 0;
2939
2940 if (pure_lossage)
2941 {
2942 message ("\n****\tPure Lisp storage exhausted!\n"
2943 "\tPurespace usage: %ld of %ld\n"
2944 "****",
2945 (long) get_PURESIZE() + pure_lossage,
2946 (long) get_PURESIZE());
2947 if (die_if_pure_storage_exceeded)
2948 {
2949 puresize_adjust_h (get_PURESIZE() + pure_lossage);
2950 #ifdef HEAP_IN_DATA
2951 sheap_adjust_h();
2952 #endif
2953 rc = -1;
2954 }
2955 }
2956 else
2957 {
2958 size_t lost = (get_PURESIZE() - pure_bytes_used) / 1024;
2959 char buf[200];
2960 /* extern Lisp_Object Vemacs_beta_version; */
2961 /* This used to be NILP(Vemacs_beta_version) ? 512 : 4; */
2962 #ifndef PURESIZE_SLOP
2963 #define PURESIZE_SLOP 0
2964 #endif
2965 size_t slop = PURESIZE_SLOP;
2966
2967 sprintf (buf, "Purespace usage: %ld of %ld (%d%%",
2968 (long) pure_bytes_used,
2969 (long) get_PURESIZE(),
2970 (int) (pure_bytes_used / (get_PURESIZE() / 100.0) + 0.5));
2971 if (lost > ((slop ? slop : 1) / 1024)) {
2972 sprintf (buf + strlen (buf), " -- %ldk wasted", (long)lost);
2973 if (die_if_pure_storage_exceeded) {
2974 puresize_adjust_h (pure_bytes_used + slop);
2975 #ifdef HEAP_IN_DATA
2976 sheap_adjust_h();
2977 #endif
2978 rc = -1;
2979 }
2980 }
2981
2982 strcat (buf, ").");
2983 message ("%s", buf);
2984 }
2985
2986 #ifdef PURESTAT
2987
2988 purestat_vector_other.nbytes =
2989 purestat_vector_all.nbytes -
2990 purestat_vector_constants.nbytes;
2991 purestat_vector_other.nobjects =
2992 purestat_vector_all.nobjects -
2993 purestat_vector_constants.nobjects;
2994
2995 purestat_string_other.nbytes =
2996 purestat_string_all.nbytes -
2997 (purestat_string_pname.nbytes +
2998 purestat_string_interactive.nbytes +
2999 purestat_string_documentation.nbytes +
3000 #ifdef I18N3
3001 purestat_string_domain.nbytes +
3002 #endif
3003 purestat_string_other_function.nbytes);
3004
3005 purestat_string_other.nobjects =
3006 purestat_string_all.nobjects -
3007 (purestat_string_pname.nobjects +
3008 purestat_string_interactive.nobjects +
3009 purestat_string_documentation.nobjects +
3010 #ifdef I18N3
3011 purestat_string_domain.nobjects +
3012 #endif
3013 purestat_string_other_function.nobjects);
3014
3015 message (" %-34s Objects Bytes", "");
3016
3017 print_purestat (&purestat_cons);
3018 print_purestat (&purestat_float);
3019 print_purestat (&purestat_string_pname);
3020 print_purestat (&purestat_function);
3021 print_purestat (&purestat_opaque_instructions);
3022 print_purestat (&purestat_vector_constants);
3023 print_purestat (&purestat_string_interactive);
3024 #ifdef I18N3
3025 print_purestat (&purestat_string_domain);
3026 #endif
3027 print_purestat (&purestat_string_documentation);
3028 print_purestat (&purestat_string_other_function);
3029 print_purestat (&purestat_vector_other);
3030 print_purestat (&purestat_string_other);
3031 print_purestat (&purestat_string_all);
3032 print_purestat (&purestat_vector_all);
3033
3034 #endif /* PURESTAT */
3035
3036
3037 if (report_impurities)
3038 {
3039 Lisp_Object plist;
3040 struct gcpro gcpro1;
3041 plist = XCAR (XCDR (XCDR (XCDR (XCDR (XCDR (Fgarbage_collect()))))));
3042 GCPRO1 (plist);
3043 message ("\nImpurities:");
3044 for (; CONSP (plist); plist = XCDR (XCDR (plist)))
3045 {
3046 Lisp_Object symbol = XCAR (plist);
3047 int size = XINT (XCAR (XCDR (plist)));
3048 if (size > 0)
3049 {
3050 char buf [100];
3051 char *s = buf;
3052 memcpy (buf,
3053 string_data (XSYMBOL (symbol)->name),
3054 string_length (XSYMBOL (symbol)->name) + 1);
3055 while (*s++) if (*s == '-') *s = ' ';
3056 *(s-1) = ':'; *s = 0;
3057 message (" %-34s %6d", buf, size);
3058 }
3059 }
3060 UNGCPRO;
3061 garbage_collect_1 (); /* collect Fgarbage_collect()'s garbage */
3062 }
3063 clear_message ();
3064
3065 if (rc < 0) {
3066 unlink("SATISFIED");
3067 fatal ("Pure size adjusted, Don't Panic! I will restart the `make'");
3068 } else if (pure_lossage && die_if_pure_storage_exceeded) {
3069 fatal ("Pure storage exhausted");
3070 }
3071 }
3072 2401
3073 2402
3074 /************************************************************************/ 2403 /************************************************************************/
3075 /* Garbage Collection */ 2404 /* Garbage Collection */
3076 /************************************************************************/ 2405 /************************************************************************/
3077 2406
3078 /* This will be used more extensively In The Future */ 2407 /* This will be used more extensively In The Future */
3079 static int last_lrecord_type_index_assigned; 2408 static int last_lrecord_type_index_assigned;
3080 2409
3081 CONST struct lrecord_implementation *lrecord_implementations_table[128]; 2410 const struct lrecord_implementation *lrecord_implementations_table[128];
3082 #define max_lrecord_type (countof (lrecord_implementations_table) - 1) 2411 #define max_lrecord_type (countof (lrecord_implementations_table) - 1)
3083 2412
3084 struct gcpro *gcprolist; 2413 struct gcpro *gcprolist;
3085 2414
3086 /* 415 used Mly 29-Jun-93 */ 2415 /* 415 used Mly 29-Jun-93 */
3087 /* 1327 used slb 28-Feb-98 */ 2416 /* 1327 used slb 28-Feb-98 */
2417 /* 1328 used og 03-Oct-99 (moving slowly, heh?) */
3088 #ifdef HAVE_SHLIB 2418 #ifdef HAVE_SHLIB
3089 #define NSTATICS 4000 2419 #define NSTATICS 4000
3090 #else 2420 #else
3091 #define NSTATICS 2000 2421 #define NSTATICS 2000
3092 #endif 2422 #endif
3106 /* by Lisp attempting to load a DLL. */ 2436 /* by Lisp attempting to load a DLL. */
3107 abort (); 2437 abort ();
3108 staticvec[staticidx++] = varaddress; 2438 staticvec[staticidx++] = varaddress;
3109 } 2439 }
3110 2440
2441 /* Not "static" because of linker lossage on some systems */
2442 Lisp_Object *staticvec_nodump[200]
2443 /* Force it into data space! */
2444 = {0};
2445 static int staticidx_nodump;
2446
2447 /* Put an entry in staticvec_nodump, pointing at the variable whose address is given
2448 */
2449 void
2450 staticpro_nodump (Lisp_Object *varaddress)
2451 {
2452 if (staticidx_nodump >= countof (staticvec_nodump))
2453 /* #### This is now a dubious abort() since this routine may be called */
2454 /* by Lisp attempting to load a DLL. */
2455 abort ();
2456 staticvec_nodump[staticidx_nodump++] = varaddress;
2457 }
2458
2459 /* Not "static" because of linker lossage on some systems */
2460 struct
2461 {
2462 void *data;
2463 const struct struct_description *desc;
2464 } dumpstructvec[200];
2465
2466 static int dumpstructidx;
2467
2468 /* Put an entry in dumpstructvec, pointing at the variable whose address is given
2469 */
2470 void
2471 dumpstruct (void *varaddress, const struct struct_description *desc)
2472 {
2473 if (dumpstructidx >= countof (dumpstructvec))
2474 abort ();
2475 dumpstructvec[dumpstructidx].data = varaddress;
2476 dumpstructvec[dumpstructidx].desc = desc;
2477 dumpstructidx++;
2478 }
2479
2480 /* Not "static" because of linker lossage on some systems */
2481 struct dumpopaque_info
2482 {
2483 void *data;
2484 size_t size;
2485 } dumpopaquevec[200];
2486
2487 static int dumpopaqueidx;
2488
2489 /* Put an entry in dumpopaquevec, pointing at the variable whose address is given
2490 */
2491 void
2492 dumpopaque (void *varaddress, size_t size)
2493 {
2494 if (dumpopaqueidx >= countof (dumpopaquevec))
2495 abort ();
2496 dumpopaquevec[dumpopaqueidx].data = varaddress;
2497 dumpopaquevec[dumpopaqueidx].size = size;
2498 dumpopaqueidx++;
2499 }
2500
2501 Lisp_Object *pdump_wirevec[50];
2502 static int pdump_wireidx;
2503
2504 /* Put an entry in pdump_wirevec, pointing at the variable whose address is given
2505 */
2506 void
2507 pdump_wire (Lisp_Object *varaddress)
2508 {
2509 if (pdump_wireidx >= countof (pdump_wirevec))
2510 abort ();
2511 pdump_wirevec[pdump_wireidx++] = varaddress;
2512 }
2513
2514
2515 Lisp_Object *pdump_wirevec_list[50];
2516 static int pdump_wireidx_list;
2517
2518 /* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given
2519 */
2520 void
2521 pdump_wire_list (Lisp_Object *varaddress)
2522 {
2523 if (pdump_wireidx_list >= countof (pdump_wirevec_list))
2524 abort ();
2525 pdump_wirevec_list[pdump_wireidx_list++] = varaddress;
2526 }
2527
3111 2528
3112 /* Mark reference to a Lisp_Object. If the object referred to has not been 2529 /* Mark reference to a Lisp_Object. If the object referred to has not been
3113 seen yet, recursively mark all the references contained in it. */ 2530 seen yet, recursively mark all the references contained in it. */
3114 2531
3115 static void 2532 void
3116 mark_object (Lisp_Object obj) 2533 mark_object (Lisp_Object obj)
3117 { 2534 {
3118 tail_recurse: 2535 tail_recurse:
3119 2536
3120 #ifdef ERROR_CHECK_GC 2537 #ifdef ERROR_CHECK_GC
3121 assert (! (GC_EQ (obj, Qnull_pointer))); 2538 assert (! (EQ (obj, Qnull_pointer)));
3122 #endif 2539 #endif
3123 /* Checks we used to perform */ 2540 /* Checks we used to perform */
3124 /* if (EQ (obj, Qnull_pointer)) return; */ 2541 /* if (EQ (obj, Qnull_pointer)) return; */
3125 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ 2542 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */
3126 /* if (PURIFIED (XPNTR (obj))) return; */ 2543 /* if (PURIFIED (XPNTR (obj))) return; */
3127 2544
3128 switch (XGCTYPE (obj)) 2545 if (XTYPE (obj) == Lisp_Type_Record)
3129 { 2546 {
3130 #ifndef LRECORD_CONS 2547 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3131 case Lisp_Type_Cons: 2548 #if defined (ERROR_CHECK_GC)
3132 { 2549 assert (lheader->type <= last_lrecord_type_index_assigned);
3133 struct Lisp_Cons *ptr = XCONS (obj);
3134 if (PURIFIED (ptr))
3135 break;
3136 if (CONS_MARKED_P (ptr))
3137 break;
3138 MARK_CONS (ptr);
3139 /* If the cdr is nil, tail-recurse on the car. */
3140 if (GC_NILP (ptr->cdr))
3141 {
3142 obj = ptr->car;
3143 }
3144 else
3145 {
3146 mark_object (ptr->car);
3147 obj = ptr->cdr;
3148 }
3149 goto tail_recurse;
3150 }
3151 #endif 2550 #endif
3152 2551 if (C_READONLY_RECORD_HEADER_P (lheader))
3153 case Lisp_Type_Record: 2552 return;
3154 { 2553
3155 struct lrecord_header *lheader = XRECORD_LHEADER (obj); 2554 if (! MARKED_RECORD_HEADER_P (lheader) &&
3156 #if defined (ERROR_CHECK_GC) && defined (USE_INDEXED_LRECORD_IMPLEMENTATION) 2555 ! UNMARKABLE_RECORD_HEADER_P (lheader))
3157 assert (lheader->type <= last_lrecord_type_index_assigned); 2556 {
2557 const struct lrecord_implementation *implementation =
2558 LHEADER_IMPLEMENTATION (lheader);
2559 MARK_RECORD_HEADER (lheader);
2560 #ifdef ERROR_CHECK_GC
2561 if (!implementation->basic_p)
2562 assert (! ((struct lcrecord_header *) lheader)->free);
3158 #endif 2563 #endif
3159 if (PURIFIED (lheader)) 2564 if (implementation->marker)
3160 return;
3161
3162 if (! MARKED_RECORD_HEADER_P (lheader) &&
3163 ! UNMARKABLE_RECORD_HEADER_P (lheader))
3164 {
3165 CONST struct lrecord_implementation *implementation =
3166 LHEADER_IMPLEMENTATION (lheader);
3167 MARK_RECORD_HEADER (lheader);
3168 #ifdef ERROR_CHECK_GC
3169 if (!implementation->basic_p)
3170 assert (! ((struct lcrecord_header *) lheader)->free);
3171 #endif
3172 if (implementation->marker)
3173 {
3174 obj = implementation->marker (obj, mark_object);
3175 if (!GC_NILP (obj)) goto tail_recurse;
3176 }
3177 }
3178 }
3179 break;
3180
3181 #ifndef LRECORD_STRING
3182 case Lisp_Type_String:
3183 {
3184 struct Lisp_String *ptr = XSTRING (obj);
3185 if (PURIFIED (ptr))
3186 return;
3187
3188 if (!XMARKBIT (ptr->plist))
3189 {
3190 if (CONSP (ptr->plist) &&
3191 EXTENT_INFOP (XCAR (ptr->plist)))
3192 flush_cached_extent_info (XCAR (ptr->plist));
3193 XMARK (ptr->plist);
3194 obj = ptr->plist;
3195 goto tail_recurse;
3196 }
3197 }
3198 break;
3199 #endif /* ! LRECORD_STRING */
3200
3201 #ifndef LRECORD_VECTOR
3202 case Lisp_Type_Vector:
3203 {
3204 struct Lisp_Vector *ptr = XVECTOR (obj);
3205 int len, i;
3206
3207 if (PURIFIED (ptr))
3208 return;
3209
3210 len = vector_length (ptr);
3211
3212 if (len < 0)
3213 break; /* Already marked */
3214 ptr->size = -1 - len; /* Else mark it */
3215 for (i = 0; i < len - 1; i++) /* and then mark its elements */
3216 mark_object (ptr->contents[i]);
3217 if (len > 0)
3218 {
3219 obj = ptr->contents[len - 1];
3220 goto tail_recurse;
3221 }
3222 }
3223 break;
3224 #endif /* !LRECORD_VECTOR */
3225
3226 #ifndef LRECORD_SYMBOL
3227 case Lisp_Type_Symbol:
3228 {
3229 struct Lisp_Symbol *sym = XSYMBOL (obj);
3230
3231 if (PURIFIED (sym))
3232 return;
3233
3234 while (!XMARKBIT (sym->plist))
3235 {
3236 XMARK (sym->plist);
3237 mark_object (sym->value);
3238 mark_object (sym->function);
3239 { 2565 {
3240 /* 2566 obj = implementation->marker (obj);
3241 * symbol->name is a struct Lisp_String *, not a 2567 if (!NILP (obj)) goto tail_recurse;
3242 * Lisp_Object. Fix it up and pass to mark_object.
3243 */
3244 Lisp_Object symname;
3245 XSETSTRING (symname, sym->name);
3246 mark_object (symname);
3247 } 2568 }
3248 if (!symbol_next (sym)) 2569 }
3249 {
3250 obj = sym->plist;
3251 goto tail_recurse;
3252 }
3253 mark_object (sym->plist);
3254 /* Mark the rest of the symbols in the hash-chain */
3255 sym = symbol_next (sym);
3256 }
3257 }
3258 break;
3259 #endif /* !LRECORD_SYMBOL */
3260
3261 /* Check for invalid Lisp_Object types */
3262 #if defined (ERROR_CHECK_GC) && ! defined (USE_MINIMAL_TAGBITS)
3263 case Lisp_Type_Int:
3264 case Lisp_Type_Char:
3265 break;
3266 default:
3267 abort();
3268 break;
3269 #endif /* ERROR_CHECK_GC && ! USE_MINIMAL_TAGBITS */
3270 } 2570 }
3271 } 2571 }
3272 2572
3273 /* mark all of the conses in a list and mark the final cdr; but 2573 /* mark all of the conses in a list and mark the final cdr; but
3274 DO NOT mark the cars. 2574 DO NOT mark the cars.
3290 2590
3291 mark_object (rest); 2591 mark_object (rest);
3292 } 2592 }
3293 2593
3294 2594
3295 #ifdef PURESTAT
3296 /* Simpler than mark-object, because pure structure can't
3297 have any circularities */
3298
3299 static size_t
3300 pure_string_sizeof (Lisp_Object obj)
3301 {
3302 struct Lisp_String *ptr = XSTRING (obj);
3303
3304 if (string_data (ptr) != (Bufbyte *) ptr + sizeof (*ptr))
3305 {
3306 /* string-data not allocated contiguously.
3307 Probably (better be!!) a pointer constant "C" data. */
3308 return sizeof (*ptr);
3309 }
3310 else
3311 {
3312 size_t size = sizeof (*ptr) + string_length (ptr) + 1;
3313 size = ALIGN_SIZE (size, sizeof (Lisp_Object));
3314 return size;
3315 }
3316 }
3317
3318 static size_t
3319 pure_sizeof (Lisp_Object obj)
3320 {
3321 if (!POINTER_TYPE_P (XTYPE (obj))
3322 || !PURIFIED (XPNTR (obj)))
3323 return 0;
3324 /* symbol sizes are accounted for separately */
3325 else if (SYMBOLP (obj))
3326 return 0;
3327 else if (STRINGP (obj))
3328 return pure_string_sizeof (obj);
3329 else if (LRECORDP (obj))
3330 {
3331 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3332 CONST struct lrecord_implementation *implementation
3333 = LHEADER_IMPLEMENTATION (lheader);
3334
3335 return implementation->size_in_bytes_method
3336 ? implementation->size_in_bytes_method (lheader)
3337 : implementation->static_size;
3338 }
3339 #ifndef LRECORD_VECTOR
3340 else if (VECTORP (obj))
3341 return STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, XVECTOR_LENGTH (obj));
3342 #endif /* !LRECORD_VECTOR */
3343
3344 #ifndef LRECORD_CONS
3345 else if (CONSP (obj))
3346 return sizeof (struct Lisp_Cons);
3347 #endif /* !LRECORD_CONS */
3348 else
3349 /* Others can't be purified */
3350 abort ();
3351 return 0; /* unreached */
3352 }
3353 #endif /* PURESTAT */
3354
3355
3356
3357
3358 /* Find all structures not marked, and free them. */ 2595 /* Find all structures not marked, and free them. */
3359 2596
3360 #ifndef LRECORD_VECTOR
3361 static int gc_count_num_vector_used, gc_count_vector_total_size;
3362 static int gc_count_vector_storage;
3363 #endif
3364 static int gc_count_num_bit_vector_used, gc_count_bit_vector_total_size; 2597 static int gc_count_num_bit_vector_used, gc_count_bit_vector_total_size;
3365 static int gc_count_bit_vector_storage; 2598 static int gc_count_bit_vector_storage;
3366 static int gc_count_num_short_string_in_use; 2599 static int gc_count_num_short_string_in_use;
3367 static int gc_count_string_total_size; 2600 static int gc_count_string_total_size;
3368 static int gc_count_short_string_total_size; 2601 static int gc_count_short_string_total_size;
3369 2602
3370 /* static int gc_count_total_records_used, gc_count_records_total_size; */ 2603 /* static int gc_count_total_records_used, gc_count_records_total_size; */
3371 2604
3372 2605
3373 int 2606 int
3374 lrecord_type_index (CONST struct lrecord_implementation *implementation) 2607 lrecord_type_index (const struct lrecord_implementation *implementation)
3375 { 2608 {
3376 int type_index = *(implementation->lrecord_type_index); 2609 int type_index = *(implementation->lrecord_type_index);
3377 /* Have to do this circuitous validation test because of problems 2610 /* Have to do this circuitous validation test because of problems
3378 dumping out initialized variables (ie can't set xxx_type_index to -1 2611 dumping out initialized variables (ie can't set xxx_type_index to -1
3379 because that would make xxx_type_index read-only in a dumped emacs. */ 2612 because that would make xxx_type_index read-only in a dumped emacs. */
3398 int bytes_freed; 2631 int bytes_freed;
3399 int instances_on_free_list; 2632 int instances_on_free_list;
3400 } lcrecord_stats [countof (lrecord_implementations_table)]; 2633 } lcrecord_stats [countof (lrecord_implementations_table)];
3401 2634
3402 static void 2635 static void
3403 tick_lcrecord_stats (CONST struct lrecord_header *h, int free_p) 2636 tick_lcrecord_stats (const struct lrecord_header *h, int free_p)
3404 { 2637 {
3405 CONST struct lrecord_implementation *implementation = 2638 const struct lrecord_implementation *implementation =
3406 LHEADER_IMPLEMENTATION (h); 2639 LHEADER_IMPLEMENTATION (h);
3407 int type_index = lrecord_type_index (implementation); 2640 int type_index = lrecord_type_index (implementation);
3408 2641
3409 if (((struct lcrecord_header *) h)->free) 2642 if (((struct lcrecord_header *) h)->free)
3410 { 2643 {
3452 other object. */ 2685 other object. */
3453 2686
3454 for (header = *prev; header; header = header->next) 2687 for (header = *prev; header; header = header->next)
3455 { 2688 {
3456 struct lrecord_header *h = &(header->lheader); 2689 struct lrecord_header *h = &(header->lheader);
3457 if (!MARKED_RECORD_HEADER_P (h) && ! (header->free)) 2690 if (!C_READONLY_RECORD_HEADER_P(h)
2691 && !MARKED_RECORD_HEADER_P (h)
2692 && ! (header->free))
3458 { 2693 {
3459 if (LHEADER_IMPLEMENTATION (h)->finalizer) 2694 if (LHEADER_IMPLEMENTATION (h)->finalizer)
3460 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0); 2695 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0);
3461 } 2696 }
3462 } 2697 }
3463 2698
3464 for (header = *prev; header; ) 2699 for (header = *prev; header; )
3465 { 2700 {
3466 struct lrecord_header *h = &(header->lheader); 2701 struct lrecord_header *h = &(header->lheader);
3467 if (MARKED_RECORD_HEADER_P (h)) 2702 if (C_READONLY_RECORD_HEADER_P(h) || MARKED_RECORD_HEADER_P (h))
3468 { 2703 {
3469 UNMARK_RECORD_HEADER (h); 2704 if (MARKED_RECORD_HEADER_P (h))
2705 UNMARK_RECORD_HEADER (h);
3470 num_used++; 2706 num_used++;
3471 /* total_size += n->implementation->size_in_bytes (h);*/ 2707 /* total_size += n->implementation->size_in_bytes (h);*/
2708 /* #### May modify header->next on a C_READONLY lcrecord */
3472 prev = &(header->next); 2709 prev = &(header->next);
3473 header = *prev; 2710 header = *prev;
3474 tick_lcrecord_stats (h, 0); 2711 tick_lcrecord_stats (h, 0);
3475 } 2712 }
3476 else 2713 else
3485 } 2722 }
3486 *used = num_used; 2723 *used = num_used;
3487 /* *total = total_size; */ 2724 /* *total = total_size; */
3488 } 2725 }
3489 2726
3490 #ifndef LRECORD_VECTOR
3491
3492 static void
3493 sweep_vectors_1 (Lisp_Object *prev,
3494 int *used, int *total, int *storage)
3495 {
3496 Lisp_Object vector;
3497 int num_used = 0;
3498 int total_size = 0;
3499 int total_storage = 0;
3500
3501 for (vector = *prev; VECTORP (vector); )
3502 {
3503 Lisp_Vector *v = XVECTOR (vector);
3504 int len = v->size;
3505 if (len < 0) /* marked */
3506 {
3507 len = - (len + 1);
3508 v->size = len;
3509 total_size += len;
3510 total_storage +=
3511 MALLOC_OVERHEAD +
3512 STRETCHY_STRUCT_SIZEOF (Lisp_Vector, contents, len + 1);
3513 num_used++;
3514 prev = &(vector_next (v));
3515 vector = *prev;
3516 }
3517 else
3518 {
3519 Lisp_Object next = vector_next (v);
3520 *prev = next;
3521 xfree (v);
3522 vector = next;
3523 }
3524 }
3525 *used = num_used;
3526 *total = total_size;
3527 *storage = total_storage;
3528 }
3529
3530 #endif /* ! LRECORD_VECTOR */
3531 2727
3532 static void 2728 static void
3533 sweep_bit_vectors_1 (Lisp_Object *prev, 2729 sweep_bit_vectors_1 (Lisp_Object *prev,
3534 int *used, int *total, int *storage) 2730 int *used, int *total, int *storage)
3535 { 2731 {
3542 their implementation */ 2738 their implementation */
3543 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) 2739 for (bit_vector = *prev; !EQ (bit_vector, Qzero); )
3544 { 2740 {
3545 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); 2741 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector);
3546 int len = v->size; 2742 int len = v->size;
3547 if (MARKED_RECORD_P (bit_vector)) 2743 if (C_READONLY_RECORD_HEADER_P(&(v->lheader)) || MARKED_RECORD_P (bit_vector))
3548 { 2744 {
3549 UNMARK_RECORD_HEADER (&(v->lheader)); 2745 if (MARKED_RECORD_P (bit_vector))
2746 UNMARK_RECORD_HEADER (&(v->lheader));
3550 total_size += len; 2747 total_size += len;
3551 total_storage += 2748 total_storage +=
3552 MALLOC_OVERHEAD + 2749 MALLOC_OVERHEAD +
3553 STRETCHY_STRUCT_SIZEOF (Lisp_Bit_Vector, bits, 2750 offsetof (Lisp_Bit_Vector, bits[BIT_VECTOR_LONG_STORAGE (len)]);
3554 BIT_VECTOR_LONG_STORAGE (len));
3555 num_used++; 2751 num_used++;
2752 /* #### May modify next on a C_READONLY bitvector */
3556 prev = &(bit_vector_next (v)); 2753 prev = &(bit_vector_next (v));
3557 bit_vector = *prev; 2754 bit_vector = *prev;
3558 } 2755 }
3559 else 2756 else
3560 { 2757 {
3595 \ 2792 \
3596 if (FREE_STRUCT_P (SFTB_victim)) \ 2793 if (FREE_STRUCT_P (SFTB_victim)) \
3597 { \ 2794 { \
3598 num_free++; \ 2795 num_free++; \
3599 } \ 2796 } \
3600 else if (!MARKED_##typename##_P (SFTB_victim)) \ 2797 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2798 { \
2799 num_used++; \
2800 } \
2801 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \
3601 { \ 2802 { \
3602 num_free++; \ 2803 num_free++; \
3603 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ 2804 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \
3604 } \ 2805 } \
3605 else \ 2806 else \
3645 if (FREE_STRUCT_P (SFTB_victim)) \ 2846 if (FREE_STRUCT_P (SFTB_victim)) \
3646 { \ 2847 { \
3647 num_free++; \ 2848 num_free++; \
3648 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \ 2849 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \
3649 } \ 2850 } \
3650 else if (!MARKED_##typename##_P (SFTB_victim)) \ 2851 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2852 { \
2853 SFTB_empty = 0; \
2854 num_used++; \
2855 } \
2856 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \
3651 { \ 2857 { \
3652 num_free++; \ 2858 num_free++; \
3653 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ 2859 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \
3654 } \ 2860 } \
3655 else \ 2861 else \
3698 2904
3699 2905
3700 static void 2906 static void
3701 sweep_conses (void) 2907 sweep_conses (void)
3702 { 2908 {
3703 #ifndef LRECORD_CONS 2909 #define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3704 # define MARKED_cons_P(ptr) XMARKBIT ((ptr)->car)
3705 # define UNMARK_cons(ptr) do { XUNMARK ((ptr)->car); } while (0)
3706 #else /* LRECORD_CONS */
3707 # define MARKED_cons_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
3708 # define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3709 #endif /* LRECORD_CONS */
3710 #define ADDITIONAL_FREE_cons(ptr) 2910 #define ADDITIONAL_FREE_cons(ptr)
3711 2911
3712 SWEEP_FIXED_TYPE_BLOCK (cons, struct Lisp_Cons); 2912 SWEEP_FIXED_TYPE_BLOCK (cons, Lisp_Cons);
3713 } 2913 }
3714 2914
3715 /* Explicitly free a cons cell. */ 2915 /* Explicitly free a cons cell. */
3716 void 2916 void
3717 free_cons (struct Lisp_Cons *ptr) 2917 free_cons (Lisp_Cons *ptr)
3718 { 2918 {
3719 #ifdef ERROR_CHECK_GC 2919 #ifdef ERROR_CHECK_GC
3720 /* If the CAR is not an int, then it will be a pointer, which will 2920 /* If the CAR is not an int, then it will be a pointer, which will
3721 always be four-byte aligned. If this cons cell has already been 2921 always be four-byte aligned. If this cons cell has already been
3722 placed on the free list, however, its car will probably contain 2922 placed on the free list, however, its car will probably contain
3726 if (POINTER_TYPE_P (XTYPE (ptr->car))) 2926 if (POINTER_TYPE_P (XTYPE (ptr->car)))
3727 ASSERT_VALID_POINTER (XPNTR (ptr->car)); 2927 ASSERT_VALID_POINTER (XPNTR (ptr->car));
3728 #endif /* ERROR_CHECK_GC */ 2928 #endif /* ERROR_CHECK_GC */
3729 2929
3730 #ifndef ALLOC_NO_POOLS 2930 #ifndef ALLOC_NO_POOLS
3731 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, struct Lisp_Cons, ptr); 2931 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, Lisp_Cons, ptr);
3732 #endif /* ALLOC_NO_POOLS */ 2932 #endif /* ALLOC_NO_POOLS */
3733 } 2933 }
3734 2934
3735 /* explicitly free a list. You **must make sure** that you have 2935 /* explicitly free a list. You **must make sure** that you have
3736 created all the cons cells that make up this list and that there 2936 created all the cons cells that make up this list and that there
3768 } 2968 }
3769 2969
3770 static void 2970 static void
3771 sweep_compiled_functions (void) 2971 sweep_compiled_functions (void)
3772 { 2972 {
3773 #define MARKED_compiled_function_P(ptr) \
3774 MARKED_RECORD_HEADER_P (&((ptr)->lheader))
3775 #define UNMARK_compiled_function(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 2973 #define UNMARK_compiled_function(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3776 #define ADDITIONAL_FREE_compiled_function(ptr) 2974 #define ADDITIONAL_FREE_compiled_function(ptr)
3777 2975
3778 SWEEP_FIXED_TYPE_BLOCK (compiled_function, Lisp_Compiled_Function); 2976 SWEEP_FIXED_TYPE_BLOCK (compiled_function, Lisp_Compiled_Function);
3779 } 2977 }
3781 2979
3782 #ifdef LISP_FLOAT_TYPE 2980 #ifdef LISP_FLOAT_TYPE
3783 static void 2981 static void
3784 sweep_floats (void) 2982 sweep_floats (void)
3785 { 2983 {
3786 #define MARKED_float_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
3787 #define UNMARK_float(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 2984 #define UNMARK_float(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3788 #define ADDITIONAL_FREE_float(ptr) 2985 #define ADDITIONAL_FREE_float(ptr)
3789 2986
3790 SWEEP_FIXED_TYPE_BLOCK (float, struct Lisp_Float); 2987 SWEEP_FIXED_TYPE_BLOCK (float, Lisp_Float);
3791 } 2988 }
3792 #endif /* LISP_FLOAT_TYPE */ 2989 #endif /* LISP_FLOAT_TYPE */
3793 2990
3794 static void 2991 static void
3795 sweep_symbols (void) 2992 sweep_symbols (void)
3796 { 2993 {
3797 #ifndef LRECORD_SYMBOL 2994 #define UNMARK_symbol(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3798 # define MARKED_symbol_P(ptr) XMARKBIT ((ptr)->plist)
3799 # define UNMARK_symbol(ptr) do { XUNMARK ((ptr)->plist); } while (0)
3800 #else
3801 # define MARKED_symbol_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
3802 # define UNMARK_symbol(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3803 #endif /* !LRECORD_SYMBOL */
3804 #define ADDITIONAL_FREE_symbol(ptr) 2995 #define ADDITIONAL_FREE_symbol(ptr)
3805 2996
3806 SWEEP_FIXED_TYPE_BLOCK (symbol, struct Lisp_Symbol); 2997 SWEEP_FIXED_TYPE_BLOCK (symbol, Lisp_Symbol);
3807 } 2998 }
3808 2999
3809 static void 3000 static void
3810 sweep_extents (void) 3001 sweep_extents (void)
3811 { 3002 {
3812 #define MARKED_extent_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
3813 #define UNMARK_extent(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3003 #define UNMARK_extent(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3814 #define ADDITIONAL_FREE_extent(ptr) 3004 #define ADDITIONAL_FREE_extent(ptr)
3815 3005
3816 SWEEP_FIXED_TYPE_BLOCK (extent, struct extent); 3006 SWEEP_FIXED_TYPE_BLOCK (extent, struct extent);
3817 } 3007 }
3818 3008
3819 static void 3009 static void
3820 sweep_events (void) 3010 sweep_events (void)
3821 { 3011 {
3822 #define MARKED_event_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
3823 #define UNMARK_event(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3012 #define UNMARK_event(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3824 #define ADDITIONAL_FREE_event(ptr) 3013 #define ADDITIONAL_FREE_event(ptr)
3825 3014
3826 SWEEP_FIXED_TYPE_BLOCK (event, struct Lisp_Event); 3015 SWEEP_FIXED_TYPE_BLOCK (event, Lisp_Event);
3827 } 3016 }
3828 3017
3829 static void 3018 static void
3830 sweep_markers (void) 3019 sweep_markers (void)
3831 { 3020 {
3832 #define MARKED_marker_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader))
3833 #define UNMARK_marker(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3021 #define UNMARK_marker(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
3834 #define ADDITIONAL_FREE_marker(ptr) \ 3022 #define ADDITIONAL_FREE_marker(ptr) \
3835 do { Lisp_Object tem; \ 3023 do { Lisp_Object tem; \
3836 XSETMARKER (tem, ptr); \ 3024 XSETMARKER (tem, ptr); \
3837 unchain_marker (tem); \ 3025 unchain_marker (tem); \
3838 } while (0) 3026 } while (0)
3839 3027
3840 SWEEP_FIXED_TYPE_BLOCK (marker, struct Lisp_Marker); 3028 SWEEP_FIXED_TYPE_BLOCK (marker, Lisp_Marker);
3841 } 3029 }
3842 3030
3843 /* Explicitly free a marker. */ 3031 /* Explicitly free a marker. */
3844 void 3032 void
3845 free_marker (struct Lisp_Marker *ptr) 3033 free_marker (Lisp_Marker *ptr)
3846 { 3034 {
3847 #ifdef ERROR_CHECK_GC 3035 #ifdef ERROR_CHECK_GC
3848 /* Perhaps this will catch freeing an already-freed marker. */ 3036 /* Perhaps this will catch freeing an already-freed marker. */
3849 Lisp_Object temmy; 3037 Lisp_Object temmy;
3850 XSETMARKER (temmy, ptr); 3038 XSETMARKER (temmy, ptr);
3851 assert (GC_MARKERP (temmy)); 3039 assert (MARKERP (temmy));
3852 #endif /* ERROR_CHECK_GC */ 3040 #endif /* ERROR_CHECK_GC */
3853 3041
3854 #ifndef ALLOC_NO_POOLS 3042 #ifndef ALLOC_NO_POOLS
3855 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, struct Lisp_Marker, ptr); 3043 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, ptr);
3856 #endif /* ALLOC_NO_POOLS */ 3044 #endif /* ALLOC_NO_POOLS */
3857 } 3045 }
3858 3046
3859 3047
3860 #if defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) 3048 #if defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY)
3871 /* POS is the index of the next string in the block. */ 3059 /* POS is the index of the next string in the block. */
3872 while (pos < sb->pos) 3060 while (pos < sb->pos)
3873 { 3061 {
3874 struct string_chars *s_chars = 3062 struct string_chars *s_chars =
3875 (struct string_chars *) &(sb->string_chars[pos]); 3063 (struct string_chars *) &(sb->string_chars[pos]);
3876 struct Lisp_String *string; 3064 Lisp_String *string;
3877 int size; 3065 int size;
3878 int fullsize; 3066 int fullsize;
3879 3067
3880 /* If the string_chars struct is marked as free (i.e. the STRING 3068 /* If the string_chars struct is marked as free (i.e. the STRING
3881 pointer is 0xFFFFFFFF) then this is an unused chunk of string 3069 pointer is 0xFFFFFFFF) then this is an unused chunk of string
3922 while (from_pos < from_sb->pos) 3110 while (from_pos < from_sb->pos)
3923 { 3111 {
3924 struct string_chars *from_s_chars = 3112 struct string_chars *from_s_chars =
3925 (struct string_chars *) &(from_sb->string_chars[from_pos]); 3113 (struct string_chars *) &(from_sb->string_chars[from_pos]);
3926 struct string_chars *to_s_chars; 3114 struct string_chars *to_s_chars;
3927 struct Lisp_String *string; 3115 Lisp_String *string;
3928 int size; 3116 int size;
3929 int fullsize; 3117 int fullsize;
3930 3118
3931 /* If the string_chars struct is marked as free (i.e. the STRING 3119 /* If the string_chars struct is marked as free (i.e. the STRING
3932 pointer is 0xFFFFFFFF) then this is an unused chunk of string 3120 pointer is 0xFFFFFFFF) then this is an unused chunk of string
3952 3140
3953 if (BIG_STRING_FULLSIZE_P (fullsize)) 3141 if (BIG_STRING_FULLSIZE_P (fullsize))
3954 abort (); 3142 abort ();
3955 3143
3956 /* Just skip it if it isn't marked. */ 3144 /* Just skip it if it isn't marked. */
3957 #ifdef LRECORD_STRING
3958 if (! MARKED_RECORD_HEADER_P (&(string->lheader))) 3145 if (! MARKED_RECORD_HEADER_P (&(string->lheader)))
3959 #else
3960 if (!XMARKBIT (string->plist))
3961 #endif
3962 { 3146 {
3963 from_pos += fullsize; 3147 from_pos += fullsize;
3964 continue; 3148 continue;
3965 } 3149 }
3966 3150
4011 3195
4012 #if 1 /* Hack to debug missing purecopy's */ 3196 #if 1 /* Hack to debug missing purecopy's */
4013 static int debug_string_purity; 3197 static int debug_string_purity;
4014 3198
4015 static void 3199 static void
4016 debug_string_purity_print (struct Lisp_String *p) 3200 debug_string_purity_print (Lisp_String *p)
4017 { 3201 {
4018 Charcount i; 3202 Charcount i;
4019 Charcount s = string_char_length (p); 3203 Charcount s = string_char_length (p);
4020 putc ('\"', stderr); 3204 putc ('\"', stderr);
4021 for (i = 0; i < s; i++) 3205 for (i = 0; i < s; i++)
4037 sweep_strings (void) 3221 sweep_strings (void)
4038 { 3222 {
4039 int num_small_used = 0, num_small_bytes = 0, num_bytes = 0; 3223 int num_small_used = 0, num_small_bytes = 0, num_bytes = 0;
4040 int debug = debug_string_purity; 3224 int debug = debug_string_purity;
4041 3225
4042 #ifdef LRECORD_STRING 3226 #define UNMARK_string(ptr) do { \
4043 3227 Lisp_String *p = (ptr); \
4044 # define MARKED_string_P(ptr) MARKED_RECORD_HEADER_P (&((ptr)->lheader)) 3228 size_t size = string_length (p); \
4045 # define UNMARK_string(ptr) \ 3229 UNMARK_RECORD_HEADER (&(p->lheader)); \
4046 do { struct Lisp_String *p = (ptr); \ 3230 num_bytes += size; \
4047 int size = string_length (p); \ 3231 if (!BIG_STRING_SIZE_P (size)) \
4048 UNMARK_RECORD_HEADER (&(p->lheader)); \ 3232 { num_small_bytes += size; \
4049 num_bytes += size; \ 3233 num_small_used++; \
4050 if (!BIG_STRING_SIZE_P (size)) \ 3234 } \
4051 { num_small_bytes += size; \ 3235 if (debug) \
4052 num_small_used++; \ 3236 debug_string_purity_print (p); \
4053 } \ 3237 } while (0)
4054 if (debug) debug_string_purity_print (p); \ 3238 #define ADDITIONAL_FREE_string(ptr) do { \
4055 } while (0) 3239 size_t size = string_length (ptr); \
4056 # define ADDITIONAL_FREE_string(p) \ 3240 if (BIG_STRING_SIZE_P (size)) \
4057 do { int size = string_length (p); \ 3241 xfree (ptr->data); \
4058 if (BIG_STRING_SIZE_P (size)) \ 3242 } while (0)
4059 xfree_1 (CHARS_TO_STRING_CHAR (string_data (p))); \ 3243
4060 } while (0) 3244 SWEEP_FIXED_TYPE_BLOCK (string, Lisp_String);
4061
4062 #else
4063
4064 # define MARKED_string_P(ptr) XMARKBIT ((ptr)->plist)
4065 # define UNMARK_string(ptr) \
4066 do { struct Lisp_String *p = (ptr); \
4067 int size = string_length (p); \
4068 XUNMARK (p->plist); \
4069 num_bytes += size; \
4070 if (!BIG_STRING_SIZE_P (size)) \
4071 { num_small_bytes += size; \
4072 num_small_used++; \
4073 } \
4074 if (debug) debug_string_purity_print (p); \
4075 } while (0)
4076 # define ADDITIONAL_FREE_string(p) \
4077 do { int size = string_length (p); \
4078 if (BIG_STRING_SIZE_P (size)) \
4079 xfree_1 (CHARS_TO_STRING_CHAR (string_data (p))); \
4080 } while (0)
4081
4082 #endif /* ! LRECORD_STRING */
4083
4084 SWEEP_FIXED_TYPE_BLOCK (string, struct Lisp_String);
4085 3245
4086 gc_count_num_short_string_in_use = num_small_used; 3246 gc_count_num_short_string_in_use = num_small_used;
4087 gc_count_string_total_size = num_bytes; 3247 gc_count_string_total_size = num_bytes;
4088 gc_count_short_string_total_size = num_small_bytes; 3248 gc_count_short_string_total_size = num_small_bytes;
4089 } 3249 }
4090 3250
4091 3251
4092 /* I hate duplicating all this crap! */ 3252 /* I hate duplicating all this crap! */
4093 static int 3253 int
4094 marked_p (Lisp_Object obj) 3254 marked_p (Lisp_Object obj)
4095 { 3255 {
4096 #ifdef ERROR_CHECK_GC 3256 #ifdef ERROR_CHECK_GC
4097 assert (! (GC_EQ (obj, Qnull_pointer))); 3257 assert (! (EQ (obj, Qnull_pointer)));
4098 #endif 3258 #endif
4099 /* Checks we used to perform. */ 3259 /* Checks we used to perform. */
4100 /* if (EQ (obj, Qnull_pointer)) return 1; */ 3260 /* if (EQ (obj, Qnull_pointer)) return 1; */
4101 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ 3261 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */
4102 /* if (PURIFIED (XPNTR (obj))) return 1; */ 3262 /* if (PURIFIED (XPNTR (obj))) return 1; */
4103 3263
4104 switch (XGCTYPE (obj)) 3264 if (XTYPE (obj) == Lisp_Type_Record)
4105 { 3265 {
4106 #ifndef LRECORD_CONS 3266 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
4107 case Lisp_Type_Cons: 3267 #if defined (ERROR_CHECK_GC)
4108 { 3268 assert (lheader->type <= last_lrecord_type_index_assigned);
4109 struct Lisp_Cons *ptr = XCONS (obj);
4110 return PURIFIED (ptr) || XMARKBIT (ptr->car);
4111 }
4112 #endif 3269 #endif
4113 case Lisp_Type_Record: 3270 return C_READONLY_RECORD_HEADER_P (lheader) || MARKED_RECORD_HEADER_P (lheader);
4114 { 3271 }
4115 struct lrecord_header *lheader = XRECORD_LHEADER (obj); 3272 return 1;
4116 #if defined (ERROR_CHECK_GC) && defined (USE_INDEXED_LRECORD_IMPLEMENTATION)
4117 assert (lheader->type <= last_lrecord_type_index_assigned);
4118 #endif
4119 return PURIFIED (lheader) || MARKED_RECORD_HEADER_P (lheader);
4120 }
4121 #ifndef LRECORD_STRING
4122 case Lisp_Type_String:
4123 {
4124 struct Lisp_String *ptr = XSTRING (obj);
4125 return PURIFIED (ptr) || XMARKBIT (ptr->plist);
4126 }
4127 #endif /* ! LRECORD_STRING */
4128 #ifndef LRECORD_VECTOR
4129 case Lisp_Type_Vector:
4130 {
4131 struct Lisp_Vector *ptr = XVECTOR (obj);
4132 return PURIFIED (ptr) || vector_length (ptr) < 0;
4133 }
4134 #endif /* !LRECORD_VECTOR */
4135 #ifndef LRECORD_SYMBOL
4136 case Lisp_Type_Symbol:
4137 {
4138 struct Lisp_Symbol *ptr = XSYMBOL (obj);
4139 return PURIFIED (ptr) || XMARKBIT (ptr->plist);
4140 }
4141 #endif
4142
4143 /* Ints and Chars don't need GC */
4144 #if defined (USE_MINIMAL_TAGBITS) || ! defined (ERROR_CHECK_GC)
4145 default:
4146 return 1;
4147 #else
4148 default:
4149 abort();
4150 case Lisp_Type_Int:
4151 case Lisp_Type_Char:
4152 return 1;
4153 #endif
4154 }
4155 } 3273 }
4156 3274
4157 static void 3275 static void
4158 gc_sweep (void) 3276 gc_sweep (void)
4159 { 3277 {
4185 sweep_strings (); 3303 sweep_strings ();
4186 3304
4187 /* Put all unmarked conses on free list */ 3305 /* Put all unmarked conses on free list */
4188 sweep_conses (); 3306 sweep_conses ();
4189 3307
4190 #ifndef LRECORD_VECTOR
4191 /* Free all unmarked vectors */
4192 sweep_vectors_1 (&all_vectors,
4193 &gc_count_num_vector_used, &gc_count_vector_total_size,
4194 &gc_count_vector_storage);
4195 #endif
4196
4197 /* Free all unmarked bit vectors */ 3308 /* Free all unmarked bit vectors */
4198 sweep_bit_vectors_1 (&all_bit_vectors, 3309 sweep_bit_vectors_1 (&all_bit_vectors,
4199 &gc_count_num_bit_vector_used, 3310 &gc_count_num_bit_vector_used,
4200 &gc_count_bit_vector_total_size, 3311 &gc_count_bit_vector_total_size,
4201 &gc_count_bit_vector_storage); 3312 &gc_count_bit_vector_storage);
4218 Dechain each one first from the buffer into which it points. */ 3329 Dechain each one first from the buffer into which it points. */
4219 sweep_markers (); 3330 sweep_markers ();
4220 3331
4221 sweep_events (); 3332 sweep_events ();
4222 3333
3334 #ifdef PDUMP
3335 /* Unmark all dumped objects */
3336 {
3337 int i;
3338 char *p = pdump_rt_list;
3339 if (p)
3340 for (;;)
3341 {
3342 pdump_reloc_table *rt = (pdump_reloc_table *)p;
3343 p += sizeof (pdump_reloc_table);
3344 if (rt->desc)
3345 {
3346 for (i=0; i<rt->count; i++)
3347 {
3348 UNMARK_RECORD_HEADER ((struct lrecord_header *)(*(EMACS_INT *)p));
3349 p += sizeof (EMACS_INT);
3350 }
3351 } else
3352 break;
3353 }
3354 }
3355 #endif
4223 } 3356 }
4224 3357
4225 /* Clearing for disksave. */ 3358 /* Clearing for disksave. */
4226 3359
4227 void 3360 void
4232 To make it easier to tell when this has happened with strings(1) we 3365 To make it easier to tell when this has happened with strings(1) we
4233 clear some known-to-be-garbage blocks of memory, so that leftover 3366 clear some known-to-be-garbage blocks of memory, so that leftover
4234 results of old evaluation don't look like potential problems. 3367 results of old evaluation don't look like potential problems.
4235 But first we set some notable variables to nil and do one more GC, 3368 But first we set some notable variables to nil and do one more GC,
4236 to turn those strings into garbage. 3369 to turn those strings into garbage.
4237 */ 3370 */
4238 3371
4239 /* Yeah, this list is pretty ad-hoc... */ 3372 /* Yeah, this list is pretty ad-hoc... */
4240 Vprocess_environment = Qnil; 3373 Vprocess_environment = Qnil;
4241 Vexec_directory = Qnil; 3374 Vexec_directory = Qnil;
4242 Vdata_directory = Qnil; 3375 Vdata_directory = Qnil;
4245 Vconfigure_info_directory = Qnil; 3378 Vconfigure_info_directory = Qnil;
4246 Vexec_path = Qnil; 3379 Vexec_path = Qnil;
4247 Vload_path = Qnil; 3380 Vload_path = Qnil;
4248 /* Vdump_load_path = Qnil; */ 3381 /* Vdump_load_path = Qnil; */
4249 /* Release hash tables for locate_file */ 3382 /* Release hash tables for locate_file */
4250 Fset (intern ("early-package-load-path"), Qnil); 3383 Flocate_file_clear_hashing (Qt);
4251 Fset (intern ("late-package-load-path"), Qnil);
4252 Fset (intern ("last-package-load-path"), Qnil);
4253 uncache_home_directory(); 3384 uncache_home_directory();
4254 3385
4255 #if defined(LOADHIST) && !(defined(LOADHIST_DUMPED) || \ 3386 #if defined(LOADHIST) && !(defined(LOADHIST_DUMPED) || \
4256 defined(LOADHIST_BUILTIN)) 3387 defined(LOADHIST_BUILTIN))
4257 Vload_history = Qnil; 3388 Vload_history = Qnil;
4260 3391
4261 garbage_collect_1 (); 3392 garbage_collect_1 ();
4262 3393
4263 /* Run the disksave finalization methods of all live objects. */ 3394 /* Run the disksave finalization methods of all live objects. */
4264 disksave_object_finalization_1 (); 3395 disksave_object_finalization_1 ();
4265
4266 #if 0 /* I don't see any point in this. The purespace starts out all 0's */
4267 /* Zero out the unused portion of purespace */
4268 if (!pure_lossage)
4269 memset ( (char *) (PUREBEG + pure_bytes_used), 0,
4270 (((char *) (PUREBEG + get_PURESIZE())) -
4271 ((char *) (PUREBEG + pure_bytes_used))));
4272 #endif
4273 3396
4274 /* Zero out the uninitialized (really, unused) part of the containers 3397 /* Zero out the uninitialized (really, unused) part of the containers
4275 for the live strings. */ 3398 for the live strings. */
4276 { 3399 {
4277 struct string_chars_block *scb; 3400 struct string_chars_block *scb;
4278 for (scb = first_string_chars_block; scb; scb = scb->next) 3401 for (scb = first_string_chars_block; scb; scb = scb->next)
4279 { 3402 {
4280 int count = sizeof (scb->string_chars) - scb->pos; 3403 int count = sizeof (scb->string_chars) - scb->pos;
4281 3404
4282 assert (count >= 0 && count < STRING_CHARS_BLOCK_SIZE); 3405 assert (count >= 0 && count < STRING_CHARS_BLOCK_SIZE);
4283 if (count != 0) { 3406 if (count != 0)
4284 /* from the block's fill ptr to the end */ 3407 {
4285 memset ((scb->string_chars + scb->pos), 0, count); 3408 /* from the block's fill ptr to the end */
4286 } 3409 memset ((scb->string_chars + scb->pos), 0, count);
3410 }
4287 } 3411 }
4288 } 3412 }
4289 3413
4290 /* There, that ought to be enough... */ 3414 /* There, that ought to be enough... */
4291 3415
4378 char *msg = (STRINGP (Vgc_message) 3502 char *msg = (STRINGP (Vgc_message)
4379 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message)) 3503 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message))
4380 : 0); 3504 : 0);
4381 Lisp_Object args[2], whole_msg; 3505 Lisp_Object args[2], whole_msg;
4382 args[0] = build_string (msg ? msg : 3506 args[0] = build_string (msg ? msg :
4383 GETTEXT ((CONST char *) gc_default_message)); 3507 GETTEXT ((const char *) gc_default_message));
4384 args[1] = build_string ("..."); 3508 args[1] = build_string ("...");
4385 whole_msg = Fconcat (2, args); 3509 whole_msg = Fconcat (2, args);
4386 echo_area_message (f, (Bufbyte *) 0, whole_msg, 0, -1, 3510 echo_area_message (f, (Bufbyte *) 0, whole_msg, 0, -1,
4387 Qgarbage_collecting); 3511 Qgarbage_collecting);
4388 } 3512 }
4429 3553
4430 { /* staticpro() */ 3554 { /* staticpro() */
4431 int i; 3555 int i;
4432 for (i = 0; i < staticidx; i++) 3556 for (i = 0; i < staticidx; i++)
4433 mark_object (*(staticvec[i])); 3557 mark_object (*(staticvec[i]));
3558 for (i = 0; i < staticidx_nodump; i++)
3559 mark_object (*(staticvec_nodump[i]));
4434 } 3560 }
4435 3561
4436 { /* GCPRO() */ 3562 { /* GCPRO() */
4437 struct gcpro *tail; 3563 struct gcpro *tail;
4438 int i; 3564 int i;
4473 for (i = 0; i < nargs; i++) 3599 for (i = 0; i < nargs; i++)
4474 mark_object (backlist->args[i]); 3600 mark_object (backlist->args[i]);
4475 } 3601 }
4476 } 3602 }
4477 3603
4478 mark_redisplay (mark_object); 3604 mark_redisplay ();
4479 mark_profiling_info (mark_object); 3605 mark_profiling_info ();
4480 3606
4481 /* OK, now do the after-mark stuff. This is for things that 3607 /* OK, now do the after-mark stuff. This is for things that
4482 are only marked when something else is marked (e.g. weak hash tables). 3608 are only marked when something else is marked (e.g. weak hash tables).
4483 There may be complex dependencies between such objects -- e.g. 3609 There may be complex dependencies between such objects -- e.g.
4484 a weak hash table might be unmarked, but after processing a later 3610 a weak hash table might be unmarked, but after processing a later
4485 weak hash table, the former one might get marked. So we have to 3611 weak hash table, the former one might get marked. So we have to
4486 iterate until nothing more gets marked. */ 3612 iterate until nothing more gets marked. */
4487 3613
4488 while (finish_marking_weak_hash_tables (marked_p, mark_object) > 0 || 3614 while (finish_marking_weak_hash_tables () > 0 ||
4489 finish_marking_weak_lists (marked_p, mark_object) > 0) 3615 finish_marking_weak_lists () > 0)
4490 ; 3616 ;
4491 3617
4492 /* And prune (this needs to be called after everything else has been 3618 /* And prune (this needs to be called after everything else has been
4493 marked and before we do any sweeping). */ 3619 marked and before we do any sweeping). */
4494 /* #### this is somewhat ad-hoc and should probably be an object 3620 /* #### this is somewhat ad-hoc and should probably be an object
4495 method */ 3621 method */
4496 prune_weak_hash_tables (marked_p); 3622 prune_weak_hash_tables ();
4497 prune_weak_lists (marked_p); 3623 prune_weak_lists ();
4498 prune_specifiers (marked_p); 3624 prune_specifiers ();
4499 prune_syntax_tables (marked_p); 3625 prune_syntax_tables ();
4500 3626
4501 gc_sweep (); 3627 gc_sweep ();
4502 3628
4503 consing_since_gc = 0; 3629 consing_since_gc = 0;
4504 #ifndef DEBUG_XEMACS 3630 #ifndef DEBUG_XEMACS
4528 if (NILP (clear_echo_area (selected_frame (), 3654 if (NILP (clear_echo_area (selected_frame (),
4529 Qgarbage_collecting, 0))) 3655 Qgarbage_collecting, 0)))
4530 { 3656 {
4531 Lisp_Object args[2], whole_msg; 3657 Lisp_Object args[2], whole_msg;
4532 args[0] = build_string (msg ? msg : 3658 args[0] = build_string (msg ? msg :
4533 GETTEXT ((CONST char *) 3659 GETTEXT ((const char *)
4534 gc_default_message)); 3660 gc_default_message));
4535 args[1] = build_string ("... done"); 3661 args[1] = build_string ("... done");
4536 whole_msg = Fconcat (2, args); 3662 whole_msg = Fconcat (2, args);
4537 echo_area_message (selected_frame (), (Bufbyte *) 0, 3663 echo_area_message (selected_frame (), (Bufbyte *) 0,
4538 whole_msg, 0, -1, 3664 whole_msg, 0, -1,
4554 } 3680 }
4555 3681
4556 /* Debugging aids. */ 3682 /* Debugging aids. */
4557 3683
4558 static Lisp_Object 3684 static Lisp_Object
4559 gc_plist_hack (CONST char *name, int value, Lisp_Object tail) 3685 gc_plist_hack (const char *name, int value, Lisp_Object tail)
4560 { 3686 {
4561 /* C doesn't have local functions (or closures, or GC, or readable syntax, 3687 /* C doesn't have local functions (or closures, or GC, or readable syntax,
4562 or portable numeric datatypes, or bit-vectors, or characters, or 3688 or portable numeric datatypes, or bit-vectors, or characters, or
4563 arrays, or exceptions, or ...) */ 3689 arrays, or exceptions, or ...) */
4564 return cons3 (intern (name), make_int (value), tail); 3690 return cons3 (intern (name), make_int (value), tail);
4584 */ 3710 */
4585 ()) 3711 ())
4586 { 3712 {
4587 Lisp_Object pl = Qnil; 3713 Lisp_Object pl = Qnil;
4588 int i; 3714 int i;
4589 #ifdef LRECORD_VECTOR
4590 int gc_count_vector_total_size = 0; 3715 int gc_count_vector_total_size = 0;
4591 #endif
4592
4593 if (purify_flag && pure_lossage)
4594 return Qnil;
4595 3716
4596 garbage_collect_1 (); 3717 garbage_collect_1 ();
4597 3718
4598 for (i = 0; i < last_lrecord_type_index_assigned; i++) 3719 for (i = 0; i <= last_lrecord_type_index_assigned; i++)
4599 { 3720 {
4600 if (lcrecord_stats[i].bytes_in_use != 0 3721 if (lcrecord_stats[i].bytes_in_use != 0
4601 || lcrecord_stats[i].bytes_freed != 0 3722 || lcrecord_stats[i].bytes_freed != 0
4602 || lcrecord_stats[i].instances_on_free_list != 0) 3723 || lcrecord_stats[i].instances_on_free_list != 0)
4603 { 3724 {
4604 char buf [255]; 3725 char buf [255];
4605 CONST char *name = lrecord_implementations_table[i]->name; 3726 const char *name = lrecord_implementations_table[i]->name;
4606 int len = strlen (name); 3727 int len = strlen (name);
4607 #ifdef LRECORD_VECTOR
4608 /* save this for the FSFmacs-compatible part of the summary */ 3728 /* save this for the FSFmacs-compatible part of the summary */
4609 if (i == *lrecord_vector[0].lrecord_type_index) 3729 if (i == *lrecord_vector.lrecord_type_index)
4610 gc_count_vector_total_size = 3730 gc_count_vector_total_size =
4611 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed; 3731 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed;
4612 #endif 3732
4613 sprintf (buf, "%s-storage", name); 3733 sprintf (buf, "%s-storage", name);
4614 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl); 3734 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl);
4615 /* Okay, simple pluralization check for `symbol-value-varalias' */ 3735 /* Okay, simple pluralization check for `symbol-value-varalias' */
4616 if (name[len-1] == 's') 3736 if (name[len-1] == 's')
4617 sprintf (buf, "%ses-freed", name); 3737 sprintf (buf, "%ses-freed", name);
4666 pl = gc_plist_hack ("compiled-functions-free", 3786 pl = gc_plist_hack ("compiled-functions-free",
4667 gc_count_num_compiled_function_freelist, pl); 3787 gc_count_num_compiled_function_freelist, pl);
4668 pl = gc_plist_hack ("compiled-functions-used", 3788 pl = gc_plist_hack ("compiled-functions-used",
4669 gc_count_num_compiled_function_in_use, pl); 3789 gc_count_num_compiled_function_in_use, pl);
4670 3790
4671 #ifndef LRECORD_VECTOR
4672 pl = gc_plist_hack ("vector-storage", gc_count_vector_storage, pl);
4673 pl = gc_plist_hack ("vectors-total-length",
4674 gc_count_vector_total_size, pl);
4675 pl = gc_plist_hack ("vectors-used", gc_count_num_vector_used, pl);
4676 #endif
4677
4678 pl = gc_plist_hack ("bit-vector-storage", gc_count_bit_vector_storage, pl); 3791 pl = gc_plist_hack ("bit-vector-storage", gc_count_bit_vector_storage, pl);
4679 pl = gc_plist_hack ("bit-vectors-total-length", 3792 pl = gc_plist_hack ("bit-vectors-total-length",
4680 gc_count_bit_vector_total_size, pl); 3793 gc_count_bit_vector_total_size, pl);
4681 pl = gc_plist_hack ("bit-vectors-used", gc_count_num_bit_vector_used, pl); 3794 pl = gc_plist_hack ("bit-vectors-used", gc_count_num_bit_vector_used, pl);
4682 3795
4712 ()) 3825 ())
4713 { 3826 {
4714 return make_int (consing_since_gc); 3827 return make_int (consing_since_gc);
4715 } 3828 }
4716 3829
3830 #if 0
4717 DEFUN ("memory-limit", Fmemory_limit, 0, 0, "", /* 3831 DEFUN ("memory-limit", Fmemory_limit, 0, 0, "", /*
4718 Return the address of the last byte Emacs has allocated, divided by 1024. 3832 Return the address of the last byte Emacs has allocated, divided by 1024.
4719 This may be helpful in debugging Emacs's memory usage. 3833 This may be helpful in debugging Emacs's memory usage.
4720 The value is divided by 1024 to make sure it will fit in a lisp integer. 3834 The value is divided by 1024 to make sure it will fit in a lisp integer.
4721 */ 3835 */
4722 ()) 3836 ())
4723 { 3837 {
4724 return make_int ((EMACS_INT) sbrk (0) / 1024); 3838 return make_int ((EMACS_INT) sbrk (0) / 1024);
4725 } 3839 }
4726 3840 #endif
4727 3841
4728 3842
4729 int 3843 int
4730 object_dead_p (Lisp_Object obj) 3844 object_dead_p (Lisp_Object obj)
4731 { 3845 {
4875 #endif /* MEMORY_USAGE_STATS */ 3989 #endif /* MEMORY_USAGE_STATS */
4876 3990
4877 3991
4878 /* Initialization */ 3992 /* Initialization */
4879 void 3993 void
4880 init_alloc_once_early (void) 3994 reinit_alloc_once_early (void)
4881 { 3995 {
4882 int iii;
4883
4884 last_lrecord_type_index_assigned = -1;
4885 for (iii = 0; iii < countof (lrecord_implementations_table); iii++)
4886 {
4887 lrecord_implementations_table[iii] = 0;
4888 }
4889
4890 #ifdef USE_INDEXED_LRECORD_IMPLEMENTATION
4891 /*
4892 * If USE_INDEXED_LRECORD_IMPLEMENTATION is defined, all the staticly
4893 * defined subr lrecords were initialized with lheader->type == 0.
4894 * See subr_lheader_initializer in lisp.h. Force type index 0 to be
4895 * assigned to lrecord_subr so that those predefined indexes match
4896 * reality.
4897 */
4898 lrecord_type_index (lrecord_subr);
4899 assert (*(lrecord_subr[0].lrecord_type_index) == 0);
4900 /*
4901 * The same is true for symbol_value_forward objects, except the
4902 * type is 1.
4903 */
4904 lrecord_type_index (lrecord_symbol_value_forward);
4905 assert (*(lrecord_symbol_value_forward[0].lrecord_type_index) == 1);
4906 #endif /* USE_INDEXED_LRECORD_IMPLEMENTATION */
4907
4908 symbols_initialized = 0;
4909
4910 gc_generation_number[0] = 0; 3996 gc_generation_number[0] = 0;
4911 /* purify_flag 1 is correct even if CANNOT_DUMP.
4912 * loadup.el will set to nil at end. */
4913 purify_flag = 1;
4914 pure_bytes_used = 0;
4915 pure_lossage = 0;
4916 breathing_space = 0; 3997 breathing_space = 0;
4917 #ifndef LRECORD_VECTOR
4918 XSETINT (all_vectors, 0); /* Qzero may not be set yet. */
4919 #endif
4920 XSETINT (all_bit_vectors, 0); /* Qzero may not be set yet. */ 3998 XSETINT (all_bit_vectors, 0); /* Qzero may not be set yet. */
4921 XSETINT (Vgc_message, 0); 3999 XSETINT (Vgc_message, 0);
4922 all_lcrecords = 0; 4000 all_lcrecords = 0;
4923 ignore_malloc_warnings = 1; 4001 ignore_malloc_warnings = 1;
4924 #ifdef DOUG_LEA_MALLOC 4002 #ifdef DOUG_LEA_MALLOC
4939 init_marker_alloc (); 4017 init_marker_alloc ();
4940 init_extent_alloc (); 4018 init_extent_alloc ();
4941 init_event_alloc (); 4019 init_event_alloc ();
4942 4020
4943 ignore_malloc_warnings = 0; 4021 ignore_malloc_warnings = 0;
4944 staticidx = 0; 4022
4023 staticidx_nodump = 0;
4024 dumpstructidx = 0;
4025 pdump_wireidx = 0;
4026
4945 consing_since_gc = 0; 4027 consing_since_gc = 0;
4946 #if 1 4028 #if 1
4947 gc_cons_threshold = 500000; /* XEmacs change */ 4029 gc_cons_threshold = 500000; /* XEmacs change */
4948 #else 4030 #else
4949 gc_cons_threshold = 15000; /* debugging */ 4031 gc_cons_threshold = 15000; /* debugging */
4967 ERROR_ME_WARN. 4049 ERROR_ME_WARN.
4968 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 4050 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
4969 3333632; 4051 3333632;
4970 #endif /* ERROR_CHECK_TYPECHECK */ 4052 #endif /* ERROR_CHECK_TYPECHECK */
4971 } 4053 }
4054
4055 void
4056 init_alloc_once_early (void)
4057 {
4058 int iii;
4059
4060 reinit_alloc_once_early ();
4061
4062 last_lrecord_type_index_assigned = -1;
4063 for (iii = 0; iii < countof (lrecord_implementations_table); iii++)
4064 {
4065 lrecord_implementations_table[iii] = 0;
4066 }
4067
4068 /*
4069 * All the staticly
4070 * defined subr lrecords were initialized with lheader->type == 0.
4071 * See subr_lheader_initializer in lisp.h. Force type index 0 to be
4072 * assigned to lrecord_subr so that those predefined indexes match
4073 * reality.
4074 */
4075 lrecord_type_index (&lrecord_subr);
4076 assert (*(lrecord_subr.lrecord_type_index) == 0);
4077 /*
4078 * The same is true for symbol_value_forward objects, except the
4079 * type is 1.
4080 */
4081 lrecord_type_index (&lrecord_symbol_value_forward);
4082 assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1);
4083
4084 staticidx = 0;
4085 }
4086
4087 int pure_bytes_used = 0;
4972 4088
4973 void 4089 void
4974 reinit_alloc (void) 4090 reinit_alloc (void)
4975 { 4091 {
4976 gcprolist = 0; 4092 gcprolist = 0;
4995 DEFSUBR (Fstring); 4111 DEFSUBR (Fstring);
4996 DEFSUBR (Fmake_symbol); 4112 DEFSUBR (Fmake_symbol);
4997 DEFSUBR (Fmake_marker); 4113 DEFSUBR (Fmake_marker);
4998 DEFSUBR (Fpurecopy); 4114 DEFSUBR (Fpurecopy);
4999 DEFSUBR (Fgarbage_collect); 4115 DEFSUBR (Fgarbage_collect);
4116 #if 0
5000 DEFSUBR (Fmemory_limit); 4117 DEFSUBR (Fmemory_limit);
4118 #endif
5001 DEFSUBR (Fconsing_since_gc); 4119 DEFSUBR (Fconsing_since_gc);
5002 } 4120 }
5003 4121
5004 void 4122 void
5005 vars_of_alloc (void) 4123 vars_of_alloc (void)
5047 debug_allocation_backtrace_length = 2; 4165 debug_allocation_backtrace_length = 2;
5048 #endif 4166 #endif
5049 4167
5050 DEFVAR_BOOL ("purify-flag", &purify_flag /* 4168 DEFVAR_BOOL ("purify-flag", &purify_flag /*
5051 Non-nil means loading Lisp code in order to dump an executable. 4169 Non-nil means loading Lisp code in order to dump an executable.
5052 This means that certain objects should be allocated in shared (pure) space. 4170 This means that certain objects should be allocated in readonly space.
5053 */ ); 4171 */ );
5054 4172
5055 DEFVAR_LISP ("pre-gc-hook", &Vpre_gc_hook /* 4173 DEFVAR_LISP ("pre-gc-hook", &Vpre_gc_hook /*
5056 Function or functions to be run just before each garbage collection. 4174 Function or functions to be run just before each garbage collection.
5057 Interrupts, garbage collection, and errors are inhibited while this hook 4175 Interrupts, garbage collection, and errors are inhibited while this hook
5073 This is printed in the echo area. If the selected frame is on a 4191 This is printed in the echo area. If the selected frame is on a
5074 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer 4192 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer
5075 image instance) in the domain of the selected frame, the mouse pointer 4193 image instance) in the domain of the selected frame, the mouse pointer
5076 will change instead of this message being printed. 4194 will change instead of this message being printed.
5077 */ ); 4195 */ );
5078 Vgc_message = make_pure_string ((CONST Bufbyte *) gc_default_message, 4196 Vgc_message = build_string (gc_default_message);
5079 countof (gc_default_message) - 1,
5080 Qnil, 1);
5081 4197
5082 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /* 4198 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /*
5083 Pointer glyph used to indicate that a garbage collection is in progress. 4199 Pointer glyph used to indicate that a garbage collection is in progress.
5084 If the selected window is on a window system and this glyph specifies a 4200 If the selected window is on a window system and this glyph specifies a
5085 value (i.e. a pointer image instance) in the domain of the selected 4201 value (i.e. a pointer image instance) in the domain of the selected
5092 void 4208 void
5093 complex_vars_of_alloc (void) 4209 complex_vars_of_alloc (void)
5094 { 4210 {
5095 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer); 4211 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer);
5096 } 4212 }
4213
4214
4215 #ifdef PDUMP
4216
4217 /* The structure of the file
4218 *
4219 * 0 - header
4220 * 256 - dumped objects
4221 * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec
4222 * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro
4223 * - nb_structdmp*pair(void *, adr) for pointers to structures
4224 * - lrecord_implementations_table[]
4225 * - relocation table
4226 * - wired variable address/value couples with the count preceding the list
4227 */
4228 typedef struct
4229 {
4230 char signature[8];
4231 EMACS_UINT stab_offset;
4232 EMACS_UINT reloc_address;
4233 int nb_staticpro;
4234 int nb_structdmp;
4235 int nb_opaquedmp;
4236 int last_type;
4237 } dump_header;
4238
4239 char *pdump_start, *pdump_end;
4240
4241 static const unsigned char align_table[256] =
4242 {
4243 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4244 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4245 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4246 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4247 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4248 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4249 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4250 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4251 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4252 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4253 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4254 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4255 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4256 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4257 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0,
4258 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
4259 };
4260
4261 typedef struct pdump_entry_list_elmt
4262 {
4263 struct pdump_entry_list_elmt *next;
4264 const void *obj;
4265 size_t size;
4266 int count;
4267 int is_lrecord;
4268 EMACS_INT save_offset;
4269 } pdump_entry_list_elmt;
4270
4271 typedef struct
4272 {
4273 pdump_entry_list_elmt *first;
4274 int align;
4275 int count;
4276 } pdump_entry_list;
4277
4278 typedef struct pdump_struct_list_elmt
4279 {
4280 pdump_entry_list list;
4281 const struct struct_description *sdesc;
4282 } pdump_struct_list_elmt;
4283
4284 typedef struct
4285 {
4286 pdump_struct_list_elmt *list;
4287 int count;
4288 int size;
4289 } pdump_struct_list;
4290
4291 static pdump_entry_list pdump_object_table[256];
4292 static pdump_entry_list pdump_opaque_data_list;
4293 static pdump_struct_list pdump_struct_table;
4294 static pdump_entry_list_elmt *pdump_qnil;
4295
4296 static int pdump_alert_undump_object[256];
4297
4298 static unsigned long cur_offset;
4299 static size_t max_size;
4300 static int pdump_fd;
4301 static void *pdump_buf;
4302
4303 #define PDUMP_HASHSIZE 200001
4304
4305 static pdump_entry_list_elmt **pdump_hash;
4306
4307 /* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */
4308 static int
4309 pdump_make_hash (const void *obj)
4310 {
4311 return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE;
4312 }
4313
4314 static pdump_entry_list_elmt *
4315 pdump_get_entry (const void *obj)
4316 {
4317 int pos = pdump_make_hash (obj);
4318 pdump_entry_list_elmt *e;
4319
4320 assert (obj != 0);
4321
4322 while ((e = pdump_hash[pos]) != 0)
4323 {
4324 if (e->obj == obj)
4325 return e;
4326
4327 pos++;
4328 if (pos == PDUMP_HASHSIZE)
4329 pos = 0;
4330 }
4331 return 0;
4332 }
4333
4334 static void
4335 pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord)
4336 {
4337 pdump_entry_list_elmt *e;
4338 int align;
4339 int pos = pdump_make_hash (obj);
4340
4341 while ((e = pdump_hash[pos]) != 0)
4342 {
4343 if (e->obj == obj)
4344 return;
4345
4346 pos++;
4347 if (pos == PDUMP_HASHSIZE)
4348 pos = 0;
4349 }
4350
4351 e = xnew (pdump_entry_list_elmt);
4352
4353 e->next = list->first;
4354 e->obj = obj;
4355 e->size = size;
4356 e->count = count;
4357 e->is_lrecord = is_lrecord;
4358 list->first = e;
4359
4360 list->count += count;
4361 pdump_hash[pos] = e;
4362
4363 align = align_table[size & 255];
4364 if (align < 2 && is_lrecord)
4365 align = 2;
4366
4367 if (align < list->align)
4368 list->align = align;
4369 }
4370
4371 static pdump_entry_list *
4372 pdump_get_entry_list (const struct struct_description *sdesc)
4373 {
4374 int i;
4375 for (i=0; i<pdump_struct_table.count; i++)
4376 if (pdump_struct_table.list[i].sdesc == sdesc)
4377 return &pdump_struct_table.list[i].list;
4378
4379 if (pdump_struct_table.size <= pdump_struct_table.count)
4380 {
4381 if (pdump_struct_table.size == -1)
4382 pdump_struct_table.size = 10;
4383 else
4384 pdump_struct_table.size = pdump_struct_table.size * 2;
4385 pdump_struct_table.list = (pdump_struct_list_elmt *)
4386 xrealloc (pdump_struct_table.list,
4387 pdump_struct_table.size * sizeof (pdump_struct_list_elmt));
4388 }
4389 pdump_struct_table.list[pdump_struct_table.count].list.first = 0;
4390 pdump_struct_table.list[pdump_struct_table.count].list.align = 8;
4391 pdump_struct_table.list[pdump_struct_table.count].list.count = 0;
4392 pdump_struct_table.list[pdump_struct_table.count].sdesc = sdesc;
4393
4394 return &pdump_struct_table.list[pdump_struct_table.count++].list;
4395 }
4396
4397 static struct
4398 {
4399 struct lrecord_header *obj;
4400 int position;
4401 int offset;
4402 } backtrace[65536];
4403
4404 static int depth;
4405
4406 static void pdump_backtrace (void)
4407 {
4408 int i;
4409 fprintf (stderr, "pdump backtrace :\n");
4410 for (i=0;i<depth;i++)
4411 {
4412 if (!backtrace[i].obj)
4413 fprintf (stderr, " - ind. (%d, %d)\n", backtrace[i].position, backtrace[i].offset);
4414 else
4415 {
4416 fprintf (stderr, " - %s (%d, %d)\n",
4417 LHEADER_IMPLEMENTATION (backtrace[i].obj)->name,
4418 backtrace[i].position,
4419 backtrace[i].offset);
4420 }
4421 }
4422 }
4423
4424 static void pdump_register_object (Lisp_Object obj);
4425 static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count);
4426
4427 static EMACS_INT
4428 pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata)
4429 {
4430 EMACS_INT count;
4431 const void *irdata;
4432
4433 int line = XD_INDIRECT_VAL (code);
4434 int delta = XD_INDIRECT_DELTA (code);
4435
4436 irdata = ((char *)idata) + idesc[line].offset;
4437 switch (idesc[line].type)
4438 {
4439 case XD_SIZE_T:
4440 count = *(size_t *)irdata;
4441 break;
4442 case XD_INT:
4443 count = *(int *)irdata;
4444 break;
4445 case XD_LONG:
4446 count = *(long *)irdata;
4447 break;
4448 case XD_BYTECOUNT:
4449 count = *(Bytecount *)irdata;
4450 break;
4451 default:
4452 fprintf (stderr, "Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code);
4453 pdump_backtrace ();
4454 abort ();
4455 }
4456 count += delta;
4457 return count;
4458 }
4459
4460 static void
4461 pdump_register_sub (const void *data, const struct lrecord_description *desc, int me)
4462 {
4463 int pos;
4464
4465 restart:
4466 for (pos = 0; desc[pos].type != XD_END; pos++)
4467 {
4468 const void *rdata = (const char *)data + desc[pos].offset;
4469
4470 backtrace[me].position = pos;
4471 backtrace[me].offset = desc[pos].offset;
4472
4473 switch (desc[pos].type)
4474 {
4475 case XD_SPECIFIER_END:
4476 pos = 0;
4477 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
4478 goto restart;
4479 case XD_SIZE_T:
4480 case XD_INT:
4481 case XD_LONG:
4482 case XD_BYTECOUNT:
4483 case XD_LO_RESET_NIL:
4484 case XD_INT_RESET:
4485 case XD_LO_LINK:
4486 break;
4487 case XD_OPAQUE_DATA_PTR:
4488 {
4489 EMACS_INT count = desc[pos].data1;
4490 if (XD_IS_INDIRECT (count))
4491 count = pdump_get_indirect_count (count, desc, data);
4492
4493 pdump_add_entry (&pdump_opaque_data_list,
4494 *(void **)rdata,
4495 count,
4496 1,
4497 0);
4498 break;
4499 }
4500 case XD_C_STRING:
4501 {
4502 const char *str = *(const char **)rdata;
4503 if (str)
4504 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
4505 break;
4506 }
4507 case XD_DOC_STRING:
4508 {
4509 const char *str = *(const char **)rdata;
4510 if ((EMACS_INT)str > 0)
4511 pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0);
4512 break;
4513 }
4514 case XD_LISP_OBJECT:
4515 {
4516 const Lisp_Object *pobj = (const Lisp_Object *)rdata;
4517
4518 assert (desc[pos].data1 == 0);
4519
4520 backtrace[me].offset = (const char *)pobj - (const char *)data;
4521 pdump_register_object (*pobj);
4522 break;
4523 }
4524 case XD_LISP_OBJECT_ARRAY:
4525 {
4526 int i;
4527 EMACS_INT count = desc[pos].data1;
4528 if (XD_IS_INDIRECT (count))
4529 count = pdump_get_indirect_count (count, desc, data);
4530
4531 for (i = 0; i < count; i++)
4532 {
4533 const Lisp_Object *pobj = ((const Lisp_Object *)rdata) + i;
4534 Lisp_Object dobj = *pobj;
4535
4536 backtrace[me].offset = (const char *)pobj - (const char *)data;
4537 pdump_register_object (dobj);
4538 }
4539 break;
4540 }
4541 case XD_STRUCT_PTR:
4542 {
4543 EMACS_INT count = desc[pos].data1;
4544 const struct struct_description *sdesc = desc[pos].data2;
4545 const char *dobj = *(const char **)rdata;
4546 if (dobj)
4547 {
4548 if (XD_IS_INDIRECT (count))
4549 count = pdump_get_indirect_count (count, desc, data);
4550
4551 pdump_register_struct (dobj, sdesc, count);
4552 }
4553 break;
4554 }
4555 default:
4556 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type);
4557 pdump_backtrace ();
4558 abort ();
4559 };
4560 }
4561 }
4562
4563 static void
4564 pdump_register_object (Lisp_Object obj)
4565 {
4566 struct lrecord_header *objh;
4567
4568 if (!POINTER_TYPE_P (XTYPE (obj)))
4569 return;
4570
4571 objh = XRECORD_LHEADER (obj);
4572 if (!objh)
4573 return;
4574
4575 if (pdump_get_entry (objh))
4576 return;
4577
4578 if (LHEADER_IMPLEMENTATION (objh)->description)
4579 {
4580 int me = depth++;
4581 if (me>65536)
4582 {
4583 fprintf (stderr, "Backtrace overflow, loop ?\n");
4584 abort ();
4585 }
4586 backtrace[me].obj = objh;
4587 backtrace[me].position = 0;
4588 backtrace[me].offset = 0;
4589
4590 pdump_add_entry (pdump_object_table + objh->type,
4591 objh,
4592 LHEADER_IMPLEMENTATION (objh)->static_size ?
4593 LHEADER_IMPLEMENTATION (objh)->static_size :
4594 LHEADER_IMPLEMENTATION (objh)->size_in_bytes_method (objh),
4595 1,
4596 1);
4597 pdump_register_sub (objh,
4598 LHEADER_IMPLEMENTATION (objh)->description,
4599 me);
4600 --depth;
4601 }
4602 else
4603 {
4604 pdump_alert_undump_object[objh->type]++;
4605 fprintf (stderr, "Undumpable object type : %s\n", LHEADER_IMPLEMENTATION (objh)->name);
4606 pdump_backtrace ();
4607 }
4608 }
4609
4610 static void
4611 pdump_register_struct (const void *data, const struct struct_description *sdesc, int count)
4612 {
4613 if (data && !pdump_get_entry (data))
4614 {
4615 int me = depth++;
4616 int i;
4617 if (me>65536)
4618 {
4619 fprintf (stderr, "Backtrace overflow, loop ?\n");
4620 abort ();
4621 }
4622 backtrace[me].obj = 0;
4623 backtrace[me].position = 0;
4624 backtrace[me].offset = 0;
4625
4626 pdump_add_entry (pdump_get_entry_list (sdesc),
4627 data,
4628 sdesc->size,
4629 count,
4630 0);
4631 for (i=0; i<count; i++)
4632 {
4633 pdump_register_sub (((char *)data) + sdesc->size*i,
4634 sdesc->description,
4635 me);
4636 }
4637 --depth;
4638 }
4639 }
4640
4641 static void
4642 pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
4643 {
4644 size_t size = elmt->size;
4645 int count = elmt->count;
4646 if (desc)
4647 {
4648 int pos, i;
4649 memcpy (pdump_buf, elmt->obj, size*count);
4650
4651 for (i=0; i<count; i++)
4652 {
4653 char *cur = ((char *)pdump_buf) + i*size;
4654 restart:
4655 for (pos = 0; desc[pos].type != XD_END; pos++)
4656 {
4657 void *rdata = cur + desc[pos].offset;
4658 switch (desc[pos].type)
4659 {
4660 case XD_SPECIFIER_END:
4661 desc = ((const Lisp_Specifier *)(elmt->obj))->methods->extra_description;
4662 goto restart;
4663 case XD_SIZE_T:
4664 case XD_INT:
4665 case XD_LONG:
4666 case XD_BYTECOUNT:
4667 break;
4668 case XD_LO_RESET_NIL:
4669 {
4670 EMACS_INT count = desc[pos].data1;
4671 int i;
4672 if (XD_IS_INDIRECT (count))
4673 count = pdump_get_indirect_count (count, desc, elmt->obj);
4674 for (i=0; i<count; i++)
4675 ((EMACS_INT *)rdata)[i] = pdump_qnil->save_offset;
4676 break;
4677 }
4678 case XD_INT_RESET:
4679 {
4680 EMACS_INT val = desc[pos].data1;
4681 if (XD_IS_INDIRECT (val))
4682 val = pdump_get_indirect_count (val, desc, elmt->obj);
4683 *(int *)rdata = val;
4684 break;
4685 }
4686 case XD_OPAQUE_DATA_PTR:
4687 case XD_C_STRING:
4688 case XD_STRUCT_PTR:
4689 {
4690 void *ptr = *(void **)rdata;
4691 if (ptr)
4692 *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset;
4693 break;
4694 }
4695 case XD_LO_LINK:
4696 {
4697 Lisp_Object obj = *(Lisp_Object *)rdata;
4698 pdump_entry_list_elmt *elmt1;
4699 for (;;)
4700 {
4701 elmt1 = pdump_get_entry (XRECORD_LHEADER (obj));
4702 if (elmt1)
4703 break;
4704 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
4705 }
4706 *(EMACS_INT *)rdata = elmt1->save_offset;
4707 break;
4708 }
4709 case XD_LISP_OBJECT:
4710 {
4711 Lisp_Object *pobj = (Lisp_Object *) rdata;
4712
4713 assert (desc[pos].data1 == 0);
4714
4715 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
4716 *(EMACS_INT *)pobj =
4717 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
4718 break;
4719 }
4720 case XD_LISP_OBJECT_ARRAY:
4721 {
4722 EMACS_INT count = desc[pos].data1;
4723 int i;
4724 if (XD_IS_INDIRECT (count))
4725 count = pdump_get_indirect_count (count, desc, elmt->obj);
4726
4727 for (i=0; i<count; i++)
4728 {
4729 Lisp_Object *pobj = ((Lisp_Object *)rdata) + i;
4730 if (POINTER_TYPE_P (XTYPE (*pobj)) && XRECORD_LHEADER (*pobj))
4731 *(EMACS_INT *)pobj =
4732 pdump_get_entry (XRECORD_LHEADER (*pobj))->save_offset;
4733 }
4734 break;
4735 }
4736 case XD_DOC_STRING:
4737 {
4738 EMACS_INT str = *(EMACS_INT *)rdata;
4739 if (str > 0)
4740 *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset;
4741 break;
4742 }
4743 default:
4744 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type);
4745 abort ();
4746 };
4747 }
4748 }
4749 }
4750 write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count);
4751 if (elmt->is_lrecord && ((size*count) & 3))
4752 write (pdump_fd, "\0\0\0", 4-((size*count) & 3));
4753 }
4754
4755 static void
4756 pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc)
4757 {
4758 int pos;
4759
4760 restart:
4761 for (pos = 0; desc[pos].type != XD_END; pos++)
4762 {
4763 void *rdata = (char *)data + desc[pos].offset;
4764 switch (desc[pos].type)
4765 {
4766 case XD_SPECIFIER_END:
4767 pos = 0;
4768 desc = ((const Lisp_Specifier *)data)->methods->extra_description;
4769 goto restart;
4770 case XD_SIZE_T:
4771 case XD_INT:
4772 case XD_LONG:
4773 case XD_BYTECOUNT:
4774 case XD_INT_RESET:
4775 break;
4776 case XD_OPAQUE_DATA_PTR:
4777 case XD_C_STRING:
4778 case XD_STRUCT_PTR:
4779 case XD_LO_LINK:
4780 {
4781 EMACS_INT ptr = *(EMACS_INT *)rdata;
4782 if (ptr)
4783 *(EMACS_INT *)rdata = ptr+delta;
4784 break;
4785 }
4786 case XD_LISP_OBJECT:
4787 {
4788 Lisp_Object *pobj = (Lisp_Object *) rdata;
4789
4790 assert (desc[pos].data1 == 0);
4791
4792 if (POINTER_TYPE_P (XTYPE (*pobj))
4793 && ! EQ (*pobj, Qnull_pointer))
4794 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta);
4795
4796 break;
4797 }
4798 case XD_LISP_OBJECT_ARRAY:
4799 case XD_LO_RESET_NIL:
4800 {
4801 EMACS_INT count = desc[pos].data1;
4802 int i;
4803 if (XD_IS_INDIRECT (count))
4804 count = pdump_get_indirect_count (count, desc, data);
4805
4806 for (i=0; i<count; i++)
4807 {
4808 Lisp_Object *pobj = (Lisp_Object *) rdata + i;
4809
4810 if (POINTER_TYPE_P (XTYPE (*pobj))
4811 && ! EQ (*pobj, Qnull_pointer))
4812 XSETOBJ (*pobj, XTYPE (*pobj), (char *) XPNTR (*pobj) + delta);
4813 }
4814 break;
4815 }
4816 case XD_DOC_STRING:
4817 {
4818 EMACS_INT str = *(EMACS_INT *)rdata;
4819 if (str > 0)
4820 *(EMACS_INT *)rdata = str + delta;
4821 break;
4822 }
4823 default:
4824 fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type);
4825 abort ();
4826 };
4827 }
4828 }
4829
4830 static void
4831 pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc)
4832 {
4833 size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count;
4834 elmt->save_offset = cur_offset;
4835 if (size>max_size)
4836 max_size = size;
4837 cur_offset += size;
4838 }
4839
4840 static void
4841 pdump_scan_by_alignment (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *))
4842 {
4843 int align, i;
4844 const struct lrecord_description *idesc;
4845 pdump_entry_list_elmt *elmt;
4846 for (align=8; align>=0; align--)
4847 {
4848 for (i=0; i<=last_lrecord_type_index_assigned; i++)
4849 if (pdump_object_table[i].align == align)
4850 {
4851 elmt = pdump_object_table[i].first;
4852 if (!elmt)
4853 continue;
4854 idesc = lrecord_implementations_table[i]->description;
4855 while (elmt)
4856 {
4857 f (elmt, idesc);
4858 elmt = elmt->next;
4859 }
4860 }
4861
4862 for (i=0; i<pdump_struct_table.count; i++)
4863 if (pdump_struct_table.list[i].list.align == align)
4864 {
4865 elmt = pdump_struct_table.list[i].list.first;
4866 idesc = pdump_struct_table.list[i].sdesc->description;
4867 while (elmt)
4868 {
4869 f (elmt, idesc);
4870 elmt = elmt->next;
4871 }
4872 }
4873
4874 elmt = pdump_opaque_data_list.first;
4875 while (elmt)
4876 {
4877 if (align_table[elmt->size & 255] == align)
4878 f (elmt, 0);
4879 elmt = elmt->next;
4880 }
4881 }
4882 }
4883
4884 static void
4885 pdump_dump_staticvec (void)
4886 {
4887 EMACS_INT *reloc = xnew_array (EMACS_INT, staticidx);
4888 int i;
4889 write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *));
4890
4891 for (i=0; i<staticidx; i++)
4892 {
4893 Lisp_Object obj = *staticvec[i];
4894 if (POINTER_TYPE_P (XTYPE (obj)))
4895 reloc[i] = pdump_get_entry (XRECORD_LHEADER (obj))->save_offset;
4896 else
4897 reloc[i] = *(EMACS_INT *)(staticvec[i]);
4898 }
4899 write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object));
4900 free (reloc);
4901 }
4902
4903 static void
4904 pdump_dump_structvec (void)
4905 {
4906 int i;
4907 for (i=0; i<dumpstructidx; i++)
4908 {
4909 EMACS_INT adr;
4910 write (pdump_fd, &(dumpstructvec[i].data), sizeof (void *));
4911 adr = pdump_get_entry (*(void **)(dumpstructvec[i].data))->save_offset;
4912 write (pdump_fd, &adr, sizeof (adr));
4913 }
4914 }
4915
4916 static void
4917 pdump_dump_opaquevec (void)
4918 {
4919 int i;
4920 for (i=0; i<dumpopaqueidx; i++)
4921 {
4922 write (pdump_fd, &(dumpopaquevec[i]), sizeof (dumpopaquevec[i]));
4923 write (pdump_fd, dumpopaquevec[i].data, dumpopaquevec[i].size);
4924 }
4925 }
4926
4927 static void
4928 pdump_dump_itable (void)
4929 {
4930 write (pdump_fd, lrecord_implementations_table, sizeof (lrecord_implementations_table));
4931 }
4932
4933 static void
4934 pdump_dump_rtables (void)
4935 {
4936 int i, j;
4937 pdump_entry_list_elmt *elmt;
4938 pdump_reloc_table rt;
4939
4940 for (i=0; i<=last_lrecord_type_index_assigned; i++)
4941 {
4942 elmt = pdump_object_table[i].first;
4943 if (!elmt)
4944 continue;
4945 rt.desc = lrecord_implementations_table[i]->description;
4946 rt.count = pdump_object_table[i].count;
4947 write (pdump_fd, &rt, sizeof (rt));
4948 while (elmt)
4949 {
4950 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
4951 write (pdump_fd, &rdata, sizeof (rdata));
4952 elmt = elmt->next;
4953 }
4954 }
4955
4956 rt.desc = 0;
4957 rt.count = 0;
4958 write (pdump_fd, &rt, sizeof (rt));
4959
4960 for (i=0; i<pdump_struct_table.count; i++)
4961 {
4962 elmt = pdump_struct_table.list[i].list.first;
4963 rt.desc = pdump_struct_table.list[i].sdesc->description;
4964 rt.count = pdump_struct_table.list[i].list.count;
4965 write (pdump_fd, &rt, sizeof (rt));
4966 while (elmt)
4967 {
4968 EMACS_INT rdata = pdump_get_entry (elmt->obj)->save_offset;
4969 for (j=0; j<elmt->count; j++)
4970 {
4971 write (pdump_fd, &rdata, sizeof (rdata));
4972 rdata += elmt->size;
4973 }
4974 elmt = elmt->next;
4975 }
4976 }
4977 rt.desc = 0;
4978 rt.count = 0;
4979 write (pdump_fd, &rt, sizeof (rt));
4980 }
4981
4982 static void
4983 pdump_dump_wired (void)
4984 {
4985 EMACS_INT count = pdump_wireidx + pdump_wireidx_list;
4986 int i;
4987
4988 write (pdump_fd, &count, sizeof (count));
4989
4990 for (i=0; i<pdump_wireidx; i++)
4991 {
4992 EMACS_INT obj = pdump_get_entry (XRECORD_LHEADER (*(pdump_wirevec[i])))->save_offset;
4993 write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i]));
4994 write (pdump_fd, &obj, sizeof (obj));
4995 }
4996
4997 for (i=0; i<pdump_wireidx_list; i++)
4998 {
4999 Lisp_Object obj = *(pdump_wirevec_list[i]);
5000 pdump_entry_list_elmt *elmt;
5001 EMACS_INT res;
5002
5003 for (;;)
5004 {
5005 const struct lrecord_description *desc;
5006 int pos;
5007 elmt = pdump_get_entry (XRECORD_LHEADER (obj));
5008 if (elmt)
5009 break;
5010 desc = XRECORD_LHEADER_IMPLEMENTATION (obj)->description;
5011 for (pos = 0; desc[pos].type != XD_LO_LINK; pos++)
5012 if (desc[pos].type == XD_END)
5013 abort ();
5014
5015 obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj)));
5016 }
5017 res = elmt->save_offset;
5018
5019 write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i]));
5020 write (pdump_fd, &res, sizeof (res));
5021 }
5022 }
5023
5024 void
5025 pdump (void)
5026 {
5027 int i;
5028 Lisp_Object t_console, t_device, t_frame;
5029 int none;
5030 dump_header hd;
5031
5032 /* These appear in a DEFVAR_LISP, which does a staticpro() */
5033 t_console = Vterminal_console;
5034 t_frame = Vterminal_frame;
5035 t_device = Vterminal_device;
5036
5037 Vterminal_console = Qnil;
5038 Vterminal_frame = Qnil;
5039 Vterminal_device = Qnil;
5040
5041 pdump_hash = xnew_array_and_zero (pdump_entry_list_elmt *, PDUMP_HASHSIZE);
5042
5043 for (i=0; i<=last_lrecord_type_index_assigned; i++)
5044 {
5045 pdump_object_table[i].first = 0;
5046 pdump_object_table[i].align = 8;
5047 pdump_object_table[i].count = 0;
5048 pdump_alert_undump_object[i] = 0;
5049 }
5050 pdump_struct_table.count = 0;
5051 pdump_struct_table.size = -1;
5052
5053 pdump_opaque_data_list.first = 0;
5054 pdump_opaque_data_list.align = 8;
5055 pdump_opaque_data_list.count = 0;
5056 depth = 0;
5057
5058 for (i=0; i<staticidx; i++)
5059 pdump_register_object (*staticvec[i]);
5060 for (i=0; i<pdump_wireidx; i++)
5061 pdump_register_object (*pdump_wirevec[i]);
5062
5063 none = 1;
5064 for (i=0; i<=last_lrecord_type_index_assigned; i++)
5065 if (pdump_alert_undump_object[i])
5066 {
5067 if (none)
5068 printf ("Undumpable types list :\n");
5069 none = 0;
5070 printf (" - %s (%d)\n", lrecord_implementations_table[i]->name, pdump_alert_undump_object[i]);
5071 }
5072 if (!none)
5073 return;
5074
5075 for (i=0; i<dumpstructidx; i++)
5076 pdump_register_struct (*(void **)(dumpstructvec[i].data), dumpstructvec[i].desc, 1);
5077
5078 memcpy (hd.signature, "XEmacsDP", 8);
5079 hd.reloc_address = 0;
5080 hd.nb_staticpro = staticidx;
5081 hd.nb_structdmp = dumpstructidx;
5082 hd.nb_opaquedmp = dumpopaqueidx;
5083 hd.last_type = last_lrecord_type_index_assigned;
5084
5085 cur_offset = 256;
5086 max_size = 0;
5087
5088 pdump_scan_by_alignment (pdump_allocate_offset);
5089 pdump_qnil = pdump_get_entry (XRECORD_LHEADER (Qnil));
5090
5091 pdump_buf = xmalloc (max_size);
5092 /* Avoid use of the `open' macro. We want the real function. */
5093 #undef open
5094 pdump_fd = open ("xemacs.dmp",
5095 O_WRONLY | O_CREAT | O_TRUNC | OPEN_BINARY, 0666);
5096 hd.stab_offset = (cur_offset + 3) & ~3;
5097
5098 write (pdump_fd, &hd, sizeof (hd));
5099 lseek (pdump_fd, 256, SEEK_SET);
5100
5101 pdump_scan_by_alignment (pdump_dump_data);
5102
5103 lseek (pdump_fd, hd.stab_offset, SEEK_SET);
5104
5105 pdump_dump_staticvec ();
5106 pdump_dump_structvec ();
5107 pdump_dump_opaquevec ();
5108 pdump_dump_itable ();
5109 pdump_dump_rtables ();
5110 pdump_dump_wired ();
5111
5112 close (pdump_fd);
5113 free (pdump_buf);
5114
5115 free (pdump_hash);
5116
5117 Vterminal_console = t_console;
5118 Vterminal_frame = t_frame;
5119 Vterminal_device = t_device;
5120 }
5121
5122 int
5123 pdump_load (void)
5124 {
5125 size_t length;
5126 int i;
5127 char *p;
5128 EMACS_INT delta;
5129 EMACS_INT count;
5130
5131 #define PDUMP_READ(p, type) (p = (char*) (((type *) p) + 1), *((type *) p - 1))
5132
5133 pdump_start = pdump_end = 0;
5134
5135 pdump_fd = open ("xemacs.dmp", O_RDONLY | OPEN_BINARY);
5136 if (pdump_fd<0)
5137 return 0;
5138
5139 length = lseek (pdump_fd, 0, SEEK_END);
5140 lseek (pdump_fd, 0, SEEK_SET);
5141
5142 #ifdef HAVE_MMAP
5143 pdump_start = (char *) mmap (0, length, PROT_READ|PROT_WRITE, MAP_PRIVATE, pdump_fd, 0);
5144 if (pdump_start == MAP_FAILED)
5145 pdump_start = 0;
5146 #endif
5147
5148 if (!pdump_start)
5149 {
5150 pdump_start = (char *)((((unsigned long)(xmalloc(length+255))) + 255) & ~255);
5151 read (pdump_fd, pdump_start, length);
5152 }
5153
5154 close (pdump_fd);
5155
5156 pdump_end = pdump_start + length;
5157
5158 staticidx = ((dump_header *)(pdump_start))->nb_staticpro;
5159 last_lrecord_type_index_assigned = ((dump_header *)pdump_start)->last_type;
5160 delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address;
5161 p = pdump_start + ((dump_header *)pdump_start)->stab_offset;
5162
5163 /* Put back the staticvec in place */
5164 memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *));
5165 p += staticidx*sizeof (Lisp_Object *);
5166 for (i=0; i<staticidx; i++)
5167 {
5168 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
5169 if (POINTER_TYPE_P (XTYPE (obj)))
5170 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
5171 *staticvec[i] = obj;
5172 }
5173
5174 /* Put back the dumpstructs */
5175 for (i=0; i<((dump_header *)pdump_start)->nb_structdmp; i++)
5176 {
5177 void **adr = PDUMP_READ (p, void **);
5178 *adr = (void *) (PDUMP_READ (p, char *) + delta);
5179 }
5180
5181 /* Put back the opaques */
5182 for (i=0; i<((dump_header *)pdump_start)->nb_opaquedmp; i++)
5183 {
5184 struct dumpopaque_info di = PDUMP_READ (p, struct dumpopaque_info);
5185 memcpy (di.data, p, di.size);
5186 p += di.size;
5187 }
5188
5189 /* Put back the lrecord_implementations_table */
5190 memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table));
5191 p += sizeof (lrecord_implementations_table);
5192
5193 /* Give back their numbers to the lrecord implementations */
5194 for (i = 0; i < countof (lrecord_implementations_table); i++)
5195 if (lrecord_implementations_table[i])
5196 {
5197 *(lrecord_implementations_table[i]->lrecord_type_index) = i;
5198 last_lrecord_type_index_assigned = i;
5199 }
5200
5201 /* Do the relocations */
5202 pdump_rt_list = p;
5203 count = 2;
5204 for (;;)
5205 {
5206 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
5207 if (rt.desc)
5208 {
5209 for (i=0; i < rt.count; i++)
5210 {
5211 char *adr = delta + *(char **)p;
5212 *(char **)p = adr;
5213 pdump_reloc_one (adr, delta, rt.desc);
5214 p += sizeof (char *);
5215 }
5216 } else
5217 if (!(--count))
5218 break;
5219 }
5220
5221 /* Put the pdump_wire variables in place */
5222 count = PDUMP_READ (p, EMACS_INT);
5223
5224 for (i=0; i<count; i++)
5225 {
5226 Lisp_Object *var = PDUMP_READ (p, Lisp_Object *);
5227 Lisp_Object obj = PDUMP_READ (p, Lisp_Object);
5228
5229 if (POINTER_TYPE_P (XTYPE (obj)))
5230 XSETOBJ (obj, XTYPE (obj), (char *) XPNTR (obj) + delta);
5231
5232 *var = obj;
5233 }
5234
5235 /* Final cleanups */
5236 /* reorganize hash tables */
5237 p = pdump_rt_list;
5238 for (;;)
5239 {
5240 pdump_reloc_table rt = PDUMP_READ (p, pdump_reloc_table);
5241 if (!rt.desc)
5242 break;
5243 if (rt.desc == hash_table_description)
5244 {
5245 for (i=0; i < rt.count; i++)
5246 pdump_reorganize_hash_table (PDUMP_READ (p, Lisp_Object));
5247 break;
5248 } else
5249 p += sizeof (Lisp_Object) * rt.count;
5250 }
5251
5252 /* Put back noninteractive1 to its real value */
5253 noninteractive1 = noninteractive;
5254
5255 return 1;
5256 }
5257
5258 #endif /* PDUMP */