Mercurial > hg > xemacs-beta
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 */ |