comparison src/alloc.c @ 5118:e0db3c197671 ben-lisp-object

merge up to latest default branch, doesn't compile yet
author Ben Wing <ben@xemacs.org>
date Sat, 26 Dec 2009 21:18:49 -0600
parents 3742ea8250b5 73e8632018ad
children d1247f3cc363
comparison
equal deleted inserted replaced
5117:3742ea8250b5 5118:e0db3c197671
50 #include "elhash.h" 50 #include "elhash.h"
51 #include "events.h" 51 #include "events.h"
52 #include "extents-impl.h" 52 #include "extents-impl.h"
53 #include "file-coding.h" 53 #include "file-coding.h"
54 #include "frame-impl.h" 54 #include "frame-impl.h"
55 #include "gc.h"
55 #include "glyphs.h" 56 #include "glyphs.h"
56 #include "opaque.h" 57 #include "opaque.h"
57 #include "lstream.h" 58 #include "lstream.h"
58 #include "process.h" 59 #include "process.h"
59 #include "profile.h" 60 #include "profile.h"
60 #include "redisplay.h" 61 #include "redisplay.h"
61 #include "specifier.h" 62 #include "specifier.h"
62 #include "sysfile.h" 63 #include "sysfile.h"
63 #include "sysdep.h" 64 #include "sysdep.h"
64 #include "window.h" 65 #include "window.h"
66 #ifdef NEW_GC
67 #include "vdb.h"
68 #endif /* NEW_GC */
65 #include "console-stream.h" 69 #include "console-stream.h"
66 70
67 #ifdef DOUG_LEA_MALLOC 71 #ifdef DOUG_LEA_MALLOC
68 #include <malloc.h> 72 #include <malloc.h>
69 #endif 73 #endif
70 74
71 EXFUN (Fgarbage_collect, 0); 75 EXFUN (Fgarbage_collect, 0);
72
73 static void recompute_need_to_garbage_collect (void);
74 76
75 #if 0 /* this is _way_ too slow to be part of the standard debug options */ 77 #if 0 /* this is _way_ too slow to be part of the standard debug options */
76 #if defined(DEBUG_XEMACS) && defined(MULE) 78 #if defined(DEBUG_XEMACS) && defined(MULE)
77 #define VERIFY_STRING_CHARS_INTEGRITY 79 #define VERIFY_STRING_CHARS_INTEGRITY
78 #endif 80 #endif
89 #ifdef DEBUG_XEMACS 91 #ifdef DEBUG_XEMACS
90 static Fixnum debug_allocation; 92 static Fixnum debug_allocation;
91 static Fixnum debug_allocation_backtrace_length; 93 static Fixnum debug_allocation_backtrace_length;
92 #endif 94 #endif
93 95
94 /* Number of bytes of consing done since the last gc */
95 static EMACS_INT consing_since_gc;
96 EMACS_UINT total_consing;
97 EMACS_INT total_gc_usage;
98 int total_gc_usage_set;
99
100 int need_to_garbage_collect;
101 int need_to_check_c_alloca; 96 int need_to_check_c_alloca;
102 int need_to_signal_post_gc; 97 int need_to_signal_post_gc;
103 int funcall_allocation_flag; 98 int funcall_allocation_flag;
104 Bytecount __temp_alloca_size__; 99 Bytecount __temp_alloca_size__;
105 Bytecount funcall_alloca_count; 100 Bytecount funcall_alloca_count;
147 #define INCREMENT_CONS_COUNTER(size, type) INCREMENT_CONS_COUNTER_1 (size) 142 #define INCREMENT_CONS_COUNTER(size, type) INCREMENT_CONS_COUNTER_1 (size)
148 #define NOSEEUM_INCREMENT_CONS_COUNTER(size, type) \ 143 #define NOSEEUM_INCREMENT_CONS_COUNTER(size, type) \
149 INCREMENT_CONS_COUNTER_1 (size) 144 INCREMENT_CONS_COUNTER_1 (size)
150 #endif 145 #endif
151 146
147 #ifdef NEW_GC
148 /* The call to recompute_need_to_garbage_collect is moved to
149 free_lrecord, since DECREMENT_CONS_COUNTER is extensively called
150 during sweep and recomputing need_to_garbage_collect all the time
151 is not needed. */
152 #define DECREMENT_CONS_COUNTER(size) do { \
153 consing_since_gc -= (size); \
154 total_consing -= (size); \
155 if (profiling_active) \
156 profile_record_unconsing (size); \
157 if (consing_since_gc < 0) \
158 consing_since_gc = 0; \
159 } while (0)
160 #else /* not NEW_GC */
152 #define DECREMENT_CONS_COUNTER(size) do { \ 161 #define DECREMENT_CONS_COUNTER(size) do { \
153 consing_since_gc -= (size); \ 162 consing_since_gc -= (size); \
154 total_consing -= (size); \ 163 total_consing -= (size); \
155 if (profiling_active) \ 164 if (profiling_active) \
156 profile_record_unconsing (size); \ 165 profile_record_unconsing (size); \
157 if (consing_since_gc < 0) \ 166 if (consing_since_gc < 0) \
158 consing_since_gc = 0; \ 167 consing_since_gc = 0; \
159 recompute_need_to_garbage_collect (); \ 168 recompute_need_to_garbage_collect (); \
160 } while (0) 169 } while (0)
161 170 #endif /*not NEW_GC */
162 /* Number of bytes of consing since gc before another gc should be done. */
163 static EMACS_INT gc_cons_threshold;
164
165 /* Percentage of consing of total data size before another GC. */
166 static EMACS_INT gc_cons_percentage;
167
168 #ifdef ERROR_CHECK_GC
169 int always_gc; /* Debugging hack; equivalent to
170 (setq gc-cons-thresold -1) */
171 #else
172 #define always_gc 0
173 #endif
174
175 /* Nonzero during gc */
176 int gc_in_progress;
177
178 /* Nonzero means display messages at beginning and end of GC. */
179
180 int garbage_collection_messages;
181
182 /* Number of times GC has happened at this level or below.
183 * Level 0 is most volatile, contrary to usual convention.
184 * (Of course, there's only one level at present) */
185 EMACS_INT gc_generation_number[1];
186 171
187 /* This is just for use by the printer, to allow things to print uniquely */ 172 /* This is just for use by the printer, to allow things to print uniquely */
188 int lrecord_uid_counter; 173 int lrecord_uid_counter;
189
190 /* Nonzero when calling certain hooks or doing other things where
191 a GC would be bad */
192 int gc_currently_forbidden;
193
194 /* Hooks. */
195 Lisp_Object Vpre_gc_hook, Qpre_gc_hook;
196 Lisp_Object Vpost_gc_hook, Qpost_gc_hook;
197
198 /* "Garbage collecting" */
199 Lisp_Object Vgc_message;
200 Lisp_Object Vgc_pointer_glyph;
201 static const Ascbyte gc_default_message[] = "Garbage collecting";
202 Lisp_Object Qgarbage_collecting;
203
204 static Lisp_Object QSin_garbage_collection;
205 174
206 /* Non-zero means we're in the process of doing the dump */ 175 /* Non-zero means we're in the process of doing the dump */
207 int purify_flag; 176 int purify_flag;
208 177
209 /* Non-zero means we're pdumping out or in */ 178 /* Non-zero means we're pdumping out or in */
220 /* Very cheesy ways of figuring out how much memory is being used for 189 /* Very cheesy ways of figuring out how much memory is being used for
221 data. #### Need better (system-dependent) ways. */ 190 data. #### Need better (system-dependent) ways. */
222 void *minimum_address_seen; 191 void *minimum_address_seen;
223 void *maximum_address_seen; 192 void *maximum_address_seen;
224 193
225 #ifndef MC_ALLOC 194 #ifndef NEW_GC
226 int 195 int
227 c_readonly (Lisp_Object obj) 196 c_readonly (Lisp_Object obj)
228 { 197 {
229 return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj); 198 return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj);
230 } 199 }
231 #endif /* MC_ALLOC */ 200 #endif /* not NEW_GC */
232 201
233 int 202 int
234 lisp_readonly (Lisp_Object obj) 203 lisp_readonly (Lisp_Object obj)
235 { 204 {
236 return POINTER_TYPE_P (XTYPE (obj)) && LISP_READONLY (obj); 205 return POINTER_TYPE_P (XTYPE (obj)) && LISP_READONLY (obj);
245 214
246 /* Non-zero means ignore malloc warnings. Set during initialization. */ 215 /* Non-zero means ignore malloc warnings. Set during initialization. */
247 int ignore_malloc_warnings; 216 int ignore_malloc_warnings;
248 217
249 218
250 #ifndef MC_ALLOC 219 #ifndef NEW_GC
251 static void *breathing_space; 220 void *breathing_space;
252 221
253 void 222 void
254 release_breathing_space (void) 223 release_breathing_space (void)
255 { 224 {
256 if (breathing_space) 225 if (breathing_space)
258 void *tmp = breathing_space; 227 void *tmp = breathing_space;
259 breathing_space = 0; 228 breathing_space = 0;
260 xfree (tmp, void *); 229 xfree (tmp, void *);
261 } 230 }
262 } 231 }
263 #endif /* not MC_ALLOC */ 232 #endif /* not NEW_GC */
264
265 /* malloc calls this if it finds we are near exhausting storage */
266 void
267 malloc_warning (const char *str)
268 {
269 if (ignore_malloc_warnings)
270 return;
271
272 warn_when_safe
273 (Qmemory, Qemergency,
274 "%s\n"
275 "Killing some buffers may delay running out of memory.\n"
276 "However, certainly by the time you receive the 95%% warning,\n"
277 "you should clean up, kill this Emacs, and start a new one.",
278 str);
279 }
280
281 /* Called if malloc returns zero */
282 DOESNT_RETURN
283 memory_full (void)
284 {
285 /* Force a GC next time eval is called.
286 It's better to loop garbage-collecting (we might reclaim enough
287 to win) than to loop beeping and barfing "Memory exhausted"
288 */
289 consing_since_gc = gc_cons_threshold + 1;
290 recompute_need_to_garbage_collect ();
291 #ifndef MC_ALLOC
292 release_breathing_space ();
293 #endif /* not MC_ALLOC */
294
295 /* Flush some histories which might conceivably contain garbalogical
296 inhibitors. */
297 if (!NILP (Fboundp (Qvalues)))
298 Fset (Qvalues, Qnil);
299 Vcommand_history = Qnil;
300
301 out_of_memory ("Memory exhausted", Qunbound);
302 }
303 233
304 static void 234 static void
305 set_alloc_mins_and_maxes (void *val, Bytecount size) 235 set_alloc_mins_and_maxes (void *val, Bytecount size)
306 { 236 {
307 if (!val) 237 if (!val)
330 assert (!regex_malloc_disallowed); \ 260 assert (!regex_malloc_disallowed); \
331 in_malloc = 1; \ 261 in_malloc = 1; \
332 } \ 262 } \
333 while (0) 263 while (0)
334 264
335 #ifdef MC_ALLOC 265 #ifdef NEW_GC
336 #define FREE_OR_REALLOC_BEGIN(block) \ 266 #define FREE_OR_REALLOC_BEGIN(block) \
337 do \ 267 do \
338 { \ 268 { \
339 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an \ 269 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an \
340 error until much later on for many system mallocs, such as \ 270 error until much later on for many system mallocs, such as \
341 the one that comes with Solaris 2.3. FMH!! */ \ 271 the one that comes with Solaris 2.3. FMH!! */ \
342 assert (block != (void *) 0xDEADBEEF); \ 272 assert (block != (void *) 0xDEADBEEF); \
343 MALLOC_BEGIN (); \ 273 MALLOC_BEGIN (); \
344 } \ 274 } \
345 while (0) 275 while (0)
346 #else /* not MC_ALLOC */ 276 #else /* not NEW_GC */
347 #define FREE_OR_REALLOC_BEGIN(block) \ 277 #define FREE_OR_REALLOC_BEGIN(block) \
348 do \ 278 do \
349 { \ 279 { \
350 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an \ 280 /* Unbelievably, calling free() on 0xDEADBEEF doesn't cause an \
351 error until much later on for many system mallocs, such as \ 281 error until much later on for many system mallocs, such as \
357 DUMPEDP. */ \ 287 DUMPEDP. */ \
358 assert (!DUMPEDP (block)); \ 288 assert (!DUMPEDP (block)); \
359 MALLOC_BEGIN (); \ 289 MALLOC_BEGIN (); \
360 } \ 290 } \
361 while (0) 291 while (0)
362 #endif /* not MC_ALLOC */ 292 #endif /* not NEW_GC */
363 293
364 #define MALLOC_END() \ 294 #define MALLOC_END() \
365 do \ 295 do \
366 { \ 296 { \
367 in_malloc = 0; \ 297 in_malloc = 0; \
382 if (!val && size != 0) 312 if (!val && size != 0)
383 memory_full (); 313 memory_full ();
384 set_alloc_mins_and_maxes (val, size); 314 set_alloc_mins_and_maxes (val, size);
385 } 315 }
386 316
317 /* malloc calls this if it finds we are near exhausting storage */
318 void
319 malloc_warning (const char *str)
320 {
321 if (ignore_malloc_warnings)
322 return;
323
324 /* Remove the malloc lock here, because warn_when_safe may allocate
325 again. It is safe to remove the malloc lock here, because malloc
326 is already finished (malloc_warning is called via
327 after_morecore_hook -> check_memory_limits -> save_warn_fun ->
328 malloc_warning). */
329 MALLOC_END ();
330
331 warn_when_safe
332 (Qmemory, Qemergency,
333 "%s\n"
334 "Killing some buffers may delay running out of memory.\n"
335 "However, certainly by the time you receive the 95%% warning,\n"
336 "you should clean up, kill this Emacs, and start a new one.",
337 str);
338 }
339
340 /* Called if malloc returns zero */
341 DOESNT_RETURN
342 memory_full (void)
343 {
344 /* Force a GC next time eval is called.
345 It's better to loop garbage-collecting (we might reclaim enough
346 to win) than to loop beeping and barfing "Memory exhausted"
347 */
348 consing_since_gc = gc_cons_threshold + 1;
349 recompute_need_to_garbage_collect ();
350 #ifdef NEW_GC
351 /* Put mc-alloc into memory shortage mode. This may keep XEmacs
352 alive until the garbage collector can free enough memory to get
353 us out of the memory exhaustion. If already in memory shortage
354 mode, we are in a loop and hopelessly lost. */
355 if (memory_shortage)
356 {
357 fprintf (stderr, "Memory full, cannot recover.\n");
358 ABORT ();
359 }
360 fprintf (stderr,
361 "Memory full, try to recover.\n"
362 "You should clean up, kill this Emacs, and start a new one.\n");
363 memory_shortage++;
364 #else /* not NEW_GC */
365 release_breathing_space ();
366 #endif /* not NEW_GC */
367
368 /* Flush some histories which might conceivably contain garbalogical
369 inhibitors. */
370 if (!NILP (Fboundp (Qvalues)))
371 Fset (Qvalues, Qnil);
372 Vcommand_history = Qnil;
373
374 out_of_memory ("Memory exhausted", Qunbound);
375 }
376
387 /* like malloc, calloc, realloc, free but: 377 /* like malloc, calloc, realloc, free but:
388 378
389 -- check for no memory left 379 -- check for no memory left
390 -- set internal mins and maxes 380 -- set internal mins and maxes
391 -- with error-checking on, check for reentrancy, invalid freeing, etc. 381 -- with error-checking on, check for reentrancy, invalid freeing, etc.
443 MALLOC_END (); 433 MALLOC_END ();
444 } 434 }
445 435
446 #ifdef ERROR_CHECK_GC 436 #ifdef ERROR_CHECK_GC
447 437
448 #ifndef MC_ALLOC 438 #ifndef NEW_GC
449 static void 439 static void
450 deadbeef_memory (void *ptr, Bytecount size) 440 deadbeef_memory (void *ptr, Bytecount size)
451 { 441 {
452 UINT_32_BIT *ptr4 = (UINT_32_BIT *) ptr; 442 UINT_32_BIT *ptr4 = (UINT_32_BIT *) ptr;
453 Bytecount beefs = size >> 2; 443 Bytecount beefs = size >> 2;
454 444
455 /* In practice, size will always be a multiple of four. */ 445 /* In practice, size will always be a multiple of four. */
456 while (beefs--) 446 while (beefs--)
457 (*ptr4++) = 0xDEADBEEF; /* -559038737 base 10 */ 447 (*ptr4++) = 0xDEADBEEF; /* -559038737 base 10 */
458 } 448 }
459 #endif /* not MC_ALLOC */ 449 #endif /* not NEW_GC */
460 450
461 #else /* !ERROR_CHECK_GC */ 451 #else /* !ERROR_CHECK_GC */
462 452
463 453
464 #define deadbeef_memory(ptr, size) 454 #define deadbeef_memory(ptr, size)
483 return xstrdup (s); 473 return xstrdup (s);
484 } 474 }
485 #endif /* NEED_STRDUP */ 475 #endif /* NEED_STRDUP */
486 476
487 477
488 #ifndef MC_ALLOC 478 #ifndef NEW_GC
489 static void * 479 static void *
490 allocate_lisp_storage (Bytecount size) 480 allocate_lisp_storage (Bytecount size)
491 { 481 {
492 void *val = xmalloc (size); 482 void *val = xmalloc (size);
493 /* We don't increment the cons counter anymore. Calling functions do 483 /* We don't increment the cons counter anymore. Calling functions do
508 if (need_to_check_c_alloca) 498 if (need_to_check_c_alloca)
509 xemacs_c_alloca (0); 499 xemacs_c_alloca (0);
510 500
511 return val; 501 return val;
512 } 502 }
513 #endif /* not MC_ALLOC */ 503 #endif /* not NEW_GC */
514 504
515 #if defined (MC_ALLOC) && defined (ALLOC_TYPE_STATS) 505 #if defined (NEW_GC) && defined (ALLOC_TYPE_STATS)
516 static struct 506 static struct
517 { 507 {
518 int instances_in_use; 508 int instances_in_use;
519 int bytes_in_use; 509 int bytes_in_use;
520 int bytes_in_use_including_overhead; 510 int bytes_in_use_including_overhead;
521 } lrecord_stats [countof (lrecord_implementations_table) 511 } lrecord_stats [countof (lrecord_implementations_table)];
522 + MODULE_DEFINABLE_TYPE_COUNT];
523
524 int lrecord_string_data_instances_in_use;
525 int lrecord_string_data_bytes_in_use;
526 int lrecord_string_data_bytes_in_use_including_overhead;
527 512
528 void 513 void
529 init_lrecord_stats () 514 init_lrecord_stats ()
530 { 515 {
531 xzero (lrecord_stats); 516 xzero (lrecord_stats);
532 lrecord_string_data_instances_in_use = 0;
533 lrecord_string_data_bytes_in_use = 0;
534 lrecord_string_data_bytes_in_use_including_overhead = 0;
535 }
536
537 void
538 inc_lrecord_string_data_stats (Bytecount size)
539 {
540 lrecord_string_data_instances_in_use++;
541 lrecord_string_data_bytes_in_use += size;
542 lrecord_string_data_bytes_in_use_including_overhead += size;
543 }
544
545 void
546 dec_lrecord_string_data_stats (Bytecount size)
547 {
548 lrecord_string_data_instances_in_use--;
549 lrecord_string_data_bytes_in_use -= size;
550 lrecord_string_data_bytes_in_use_including_overhead -= size;
551 } 517 }
552 518
553 void 519 void
554 inc_lrecord_stats (Bytecount size, const struct lrecord_header *h) 520 inc_lrecord_stats (Bytecount size, const struct lrecord_header *h)
555 { 521 {
579 lrecord_stats[type_index].bytes_in_use_including_overhead 545 lrecord_stats[type_index].bytes_in_use_including_overhead
580 -= size_including_overhead; 546 -= size_including_overhead;
581 547
582 DECREMENT_CONS_COUNTER (size); 548 DECREMENT_CONS_COUNTER (size);
583 } 549 }
584 #endif /* not (MC_ALLOC && ALLOC_TYPE_STATS) */ 550
551 int
552 lrecord_stats_heap_size (void)
553 {
554 int i;
555 int size = 0;
556 for (i = 0; i < countof (lrecord_implementations_table); i++)
557 size += lrecord_stats[i].bytes_in_use;
558 return size;
559 }
560 #endif /* NEW_GC && ALLOC_TYPE_STATS */
585 561
586 #define assert_proper_sizing(size) \ 562 #define assert_proper_sizing(size) \
587 type_checking_assert \ 563 type_checking_assert \
588 (implementation->static_size == 0 ? \ 564 (implementation->static_size == 0 ? \
589 implementation->size_in_bytes_method != NULL : \ 565 implementation->size_in_bytes_method != NULL : \
590 implementation->size_in_bytes_method == NULL && \ 566 implementation->size_in_bytes_method == NULL && \
591 implementation->static_size == size) 567 implementation->static_size == size)
592 568
593 #ifndef MC_ALLOC 569 #ifndef NEW_GC
594 /* lcrecords are chained together through their "next" field. 570 /* lcrecords are chained together through their "next" field.
595 After doing the mark phase, GC will walk this linked list 571 After doing the mark phase, GC will walk this linked list
596 and free any lcrecord which hasn't been marked. */ 572 and free any lcrecord which hasn't been marked. */
597 static struct old_lcrecord_header *all_lcrecords; 573 static struct old_lcrecord_header *all_lcrecords;
598 #endif /* not MC_ALLOC */ 574 #endif /* not NEW_GC */
599 575
600 #ifdef MC_ALLOC 576 #ifdef NEW_GC
601
602 /* The basic lrecord allocation functions. See lrecord.h for details. */ 577 /* The basic lrecord allocation functions. See lrecord.h for details. */
603 static Lisp_Object 578 static Lisp_Object
604 alloc_sized_lrecord_1 (Bytecount size, 579 alloc_sized_lrecord_1 (Bytecount size,
605 const struct lrecord_implementation *implementation, 580 const struct lrecord_implementation *implementation,
606 int noseeum) 581 int noseeum)
610 assert_proper_sizing (size); 585 assert_proper_sizing (size);
611 586
612 lheader = (struct lrecord_header *) mc_alloc (size); 587 lheader = (struct lrecord_header *) mc_alloc (size);
613 gc_checking_assert (LRECORD_FREE_P (lheader)); 588 gc_checking_assert (LRECORD_FREE_P (lheader));
614 set_lheader_implementation (lheader, implementation); 589 set_lheader_implementation (lheader, implementation);
590 lheader->uid = lrecord_uid_counter++;
615 #ifdef ALLOC_TYPE_STATS 591 #ifdef ALLOC_TYPE_STATS
616 inc_lrecord_stats (size, lheader); 592 inc_lrecord_stats (size, lheader);
617 #endif /* ALLOC_TYPE_STATS */ 593 #endif /* ALLOC_TYPE_STATS */
594 if (implementation->finalizer)
595 add_finalizable_obj (wrap_pointer_1 (lheader));
618 if (noseeum) 596 if (noseeum)
619 NOSEEUM_INCREMENT_CONS_COUNTER (size, implementation->name); 597 NOSEEUM_INCREMENT_CONS_COUNTER (size, implementation->name);
620 else 598 else
621 INCREMENT_CONS_COUNTER (size, implementation->name); 599 INCREMENT_CONS_COUNTER (size, implementation->name);
622 return wrap_pointer_1 (lheader); 600 return wrap_pointer_1 (lheader);
642 { 620 {
643 type_checking_assert (implementation->static_size > 0); 621 type_checking_assert (implementation->static_size > 0);
644 return alloc_sized_lrecord (implementation->static_size, implementation); 622 return alloc_sized_lrecord (implementation->static_size, implementation);
645 } 623 }
646 624
625 Lisp_Object
626 noseeum_alloc_lrecord (const struct lrecord_implementation *implementation)
627 {
628 type_checking_assert (implementation->static_size > 0);
629 return noseeum_alloc_sized_lrecord (implementation->static_size, implementation);
630 }
631
632 Lisp_Object
633 alloc_sized_lrecord_array (Bytecount size, int elemcount,
634 const struct lrecord_implementation *implementation)
635 {
636 struct lrecord_header *lheader;
637 Rawbyte *start, *stop;
638
639 assert_proper_sizing (size);
640
641 lheader = (struct lrecord_header *) mc_alloc_array (size, elemcount);
642 gc_checking_assert (LRECORD_FREE_P (lheader));
643
644 for (start = (Rawbyte *) lheader,
645 /* #### FIXME: why is this -1 present? */
646 stop = ((Rawbyte *) lheader) + (size * elemcount -1);
647 start < stop; start += size)
648 {
649 struct lrecord_header *lh = (struct lrecord_header *) start;
650 set_lheader_implementation (lh, implementation);
651 lh->uid = lrecord_uid_counter++;
652 #ifdef ALLOC_TYPE_STATS
653 inc_lrecord_stats (size, lh);
654 #endif /* not ALLOC_TYPE_STATS */
655 if (implementation->finalizer)
656 add_finalizable_obj (wrap_pointer_1 (lh));
657 }
658
659 INCREMENT_CONS_COUNTER (size * elemcount, implementation->name);
660 return wrap_pointer_1 (lheader);
661 }
662
663 Lisp_Object
664 alloc_lrecord_array (int elemcount,
665 const struct lrecord_implementation *implementation)
666 {
667 type_checking_assert (implementation->static_size > 0);
668 return alloc_sized_lrecord_array (implementation->static_size, elemcount,
669 implementation);
670 }
671
647 void 672 void
648 free_lrecord (Lisp_Object lrecord) 673 free_lrecord (Lisp_Object UNUSED (lrecord))
649 { 674 {
650 gc_checking_assert (!gc_in_progress); 675 /* Manual frees are not allowed with asynchronous finalization */
651 gc_checking_assert (!LRECORD_FREE_P (XRECORD_LHEADER (lrecord))); 676 return;
652 gc_checking_assert (!XRECORD_LHEADER (lrecord)->free); 677 }
653 678 #else /* not NEW_GC */
654 MC_ALLOC_CALL_FINALIZER (XPNTR (lrecord));
655 mc_free (XPNTR (lrecord));
656 }
657 #else /* not MC_ALLOC */
658 679
659 /* The most basic of the lcrecord allocation functions. Not usually called 680 /* The most basic of the lcrecord allocation functions. Not usually called
660 directly. Allocates an lrecord not managed by any lcrecord-list, of a 681 directly. Allocates an lrecord not managed by any lcrecord-list, of a
661 specified size. See lrecord.h. */ 682 specified size. See lrecord.h. */
662 683
729 lrecord->implementation->finalizer (lrecord, 0); 750 lrecord->implementation->finalizer (lrecord, 0);
730 xfree (lrecord); 751 xfree (lrecord);
731 return; 752 return;
732 } 753 }
733 #endif /* Unused */ 754 #endif /* Unused */
734 #endif /* not MC_ALLOC */ 755 #endif /* not NEW_GC */
735 756
736 757
737 static void 758 static void
738 disksave_object_finalization_1 (void) 759 disksave_object_finalization_1 (void)
739 { 760 {
740 #ifdef MC_ALLOC 761 #ifdef NEW_GC
741 mc_finalize_for_disksave (); 762 mc_finalize_for_disksave ();
742 #else /* not MC_ALLOC */ 763 #else /* not NEW_GC */
743 struct old_lcrecord_header *header; 764 struct old_lcrecord_header *header;
744 765
745 for (header = all_lcrecords; header; header = header->next) 766 for (header = all_lcrecords; header; header = header->next)
746 { 767 {
747 if (LHEADER_IMPLEMENTATION (&header->lheader)->finalizer && 768 if (LHEADER_IMPLEMENTATION (&header->lheader)->finalizer &&
748 !header->free) 769 !header->free)
749 LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1); 770 LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1);
750 } 771 }
751 #endif /* not MC_ALLOC */ 772 #endif /* not NEW_GC */
752 } 773 }
753 774
754 /* Bitwise copy all parts of a Lisp object other than the header */ 775 /* Bitwise copy all parts of a Lisp object other than the header */
755 776
756 void 777 void
761 Bytecount size = lisp_object_size (src); 782 Bytecount size = lisp_object_size (src);
762 783
763 assert (imp == XRECORD_LHEADER_IMPLEMENTATION (dst)); 784 assert (imp == XRECORD_LHEADER_IMPLEMENTATION (dst));
764 assert (size == lisp_object_size (dst)); 785 assert (size == lisp_object_size (dst));
765 786
766 #ifdef MC_ALLOC 787 #ifdef NEW_GC
767 memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header), 788 memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header),
768 (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header), 789 (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header),
769 size - sizeof (struct lrecord_header)); 790 size - sizeof (struct lrecord_header));
770 #else /* not MC_ALLOC */ 791 #else /* not NEW_GC */
771 if (imp->basic_p) 792 if (imp->basic_p)
772 memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header), 793 memcpy ((char *) XRECORD_LHEADER (dst) + sizeof (struct lrecord_header),
773 (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header), 794 (char *) XRECORD_LHEADER (src) + sizeof (struct lrecord_header),
774 size - sizeof (struct lrecord_header)); 795 size - sizeof (struct lrecord_header));
775 else 796 else
776 memcpy ((char *) XRECORD_LHEADER (dst) + 797 memcpy ((char *) XRECORD_LHEADER (dst) +
777 sizeof (struct old_lcrecord_header), 798 sizeof (struct old_lcrecord_header),
778 (char *) XRECORD_LHEADER (src) + 799 (char *) XRECORD_LHEADER (src) +
779 sizeof (struct old_lcrecord_header), 800 sizeof (struct old_lcrecord_header),
780 size - sizeof (struct old_lcrecord_header)); 801 size - sizeof (struct old_lcrecord_header));
781 #endif /* not MC_ALLOC */ 802 #endif /* not NEW_GC */
782 } 803 }
783 804
784 805
785 /************************************************************************/ 806 /************************************************************************/
786 /* Debugger support */ 807 /* Debugger support */
824 { 845 {
825 return EQ (obj1, obj2); 846 return EQ (obj1, obj2);
826 } 847 }
827 848
828 849
829 #ifdef MC_ALLOC 850 #ifdef NEW_GC
830 #define DECLARE_FIXED_TYPE_ALLOC(type, structture) struct __foo__ 851 #define DECLARE_FIXED_TYPE_ALLOC(type, structture) struct __foo__
831 #else 852 #else
832 /************************************************************************/ 853 /************************************************************************/
833 /* Fixed-size type macros */ 854 /* Fixed-size type macros */
834 /************************************************************************/ 855 /************************************************************************/
967 unless there's a large number (usually 1000, but 988 unless there's a large number (usually 1000, but
968 varies depending on type) of them already on the list. 989 varies depending on type) of them already on the list.
969 This way, we ensure that an object that gets freed will 990 This way, we ensure that an object that gets freed will
970 remain free for the next 1000 (or whatever) times that 991 remain free for the next 1000 (or whatever) times that
971 an object of that type is allocated. */ 992 an object of that type is allocated. */
972
973 #ifndef MALLOC_OVERHEAD
974 #ifdef GNU_MALLOC
975 #define MALLOC_OVERHEAD 0
976 #elif defined (rcheck)
977 #define MALLOC_OVERHEAD 20
978 #else
979 #define MALLOC_OVERHEAD 8
980 #endif
981 #endif /* MALLOC_OVERHEAD */
982 993
983 #if !defined(HAVE_MMAP) || defined(DOUG_LEA_MALLOC) 994 #if !defined(HAVE_MMAP) || defined(DOUG_LEA_MALLOC)
984 /* If we released our reserve (due to running out of memory), 995 /* If we released our reserve (due to running out of memory),
985 and we have a fair amount free once again, 996 and we have a fair amount free once again,
986 try to set aside another reserve in case we run out once more. 997 try to set aside another reserve in case we run out once more.
1184 gc_count_num_##type##_freelist++; \ 1195 gc_count_num_##type##_freelist++; \
1185 } while (0) 1196 } while (0)
1186 #else 1197 #else
1187 #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr) 1198 #define FREE_FIXED_TYPE_WHEN_NOT_IN_GC(type, structtype, ptr)
1188 #endif 1199 #endif
1189 #endif /* not MC_ALLOC */ 1200 #endif /* NEW_GC */
1190 1201
1191 #ifdef MC_ALLOC 1202 #ifdef NEW_GC
1192 #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \ 1203 #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \
1193 do { \ 1204 do { \
1194 (var) = alloc_lrecord_type (lisp_type, lrec_ptr); \ 1205 (var) = alloc_lrecord_type (lisp_type, lrec_ptr); \
1195 } while (0) 1206 } while (0)
1196 #define NOSEEUM_ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, \ 1207 #define NOSEEUM_ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, \
1197 lrec_ptr) \ 1208 lrec_ptr) \
1198 do { \ 1209 do { \
1199 (var) = noseeum_alloc_lrecord_type (lisp_type, lrec_ptr); \ 1210 (var) = noseeum_alloc_lrecord_type (lisp_type, lrec_ptr); \
1200 } while (0) 1211 } while (0)
1201 #else /* not MC_ALLOC */ 1212 #else /* not NEW_GC */
1202 #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \ 1213 #define ALLOCATE_FIXED_TYPE_AND_SET_IMPL(type, lisp_type, var, lrec_ptr) \
1203 do \ 1214 do \
1204 { \ 1215 { \
1205 ALLOCATE_FIXED_TYPE (type, lisp_type, var); \ 1216 ALLOCATE_FIXED_TYPE (type, lisp_type, var); \
1206 set_lheader_implementation (&(var)->lheader, lrec_ptr); \ 1217 set_lheader_implementation (&(var)->lheader, lrec_ptr); \
1210 do \ 1221 do \
1211 { \ 1222 { \
1212 NOSEEUM_ALLOCATE_FIXED_TYPE (type, lisp_type, var); \ 1223 NOSEEUM_ALLOCATE_FIXED_TYPE (type, lisp_type, var); \
1213 set_lheader_implementation (&(var)->lheader, lrec_ptr); \ 1224 set_lheader_implementation (&(var)->lheader, lrec_ptr); \
1214 } while (0) 1225 } while (0)
1215 #endif /* MC_ALLOC */ 1226 #endif /* not NEW_GC */
1216 1227
1217 1228
1218 1229
1219 /************************************************************************/ 1230 /************************************************************************/
1220 /* Cons allocation */ 1231 /* Cons allocation */
1253 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car_) }, 1264 { XD_LISP_OBJECT, offsetof (Lisp_Cons, car_) },
1254 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr_) }, 1265 { XD_LISP_OBJECT, offsetof (Lisp_Cons, cdr_) },
1255 { XD_END } 1266 { XD_END }
1256 }; 1267 };
1257 1268
1258 DEFINE_FROB_BLOCK_LISP_OBJECT ("cons", cons, Lisp_Cons, cons_description, 1269 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("cons", cons,
1259 1, /*dumpable-flag*/ 1270 mark_cons, print_cons, 0, cons_equal,
1260 mark_cons, print_cons, cons_equal, 1271 /*
1261 /* 1272 * No `hash' method needed.
1262 * No `hash' method needed. 1273 * internal_hash knows how to
1263 * internal_hash knows how to 1274 * handle conses.
1264 * handle conses. 1275 */
1265 */ 1276 0, cons_description, Lisp_Cons);
1266 0, 0);
1267 1277
1268 DEFUN ("cons", Fcons, 2, 2, 0, /* 1278 DEFUN ("cons", Fcons, 2, 2, 0, /*
1269 Create a new cons, give it CAR and CDR as components, and return it. 1279 Create a new cons cell, give it CAR and CDR as components, and return it.
1280
1281 A cons cell is a Lisp object (an area in memory) made up of two pointers
1282 called the CAR and the CDR. Each of these pointers can point to any other
1283 Lisp object. The common Lisp data type, the list, is a specially-structured
1284 series of cons cells.
1285
1286 The pointers are accessed from Lisp with `car' and `cdr', and mutated with
1287 `setcar' and `setcdr' respectively. For historical reasons, the aliases
1288 `rplaca' and `rplacd' (for `setcar' and `setcdr') are supported.
1270 */ 1289 */
1271 (car, cdr)) 1290 (car, cdr))
1272 { 1291 {
1273 /* This cannot GC. */ 1292 /* This cannot GC. */
1274 Lisp_Object val; 1293 Lisp_Object val;
1296 XCDR (val) = cdr; 1315 XCDR (val) = cdr;
1297 return val; 1316 return val;
1298 } 1317 }
1299 1318
1300 DEFUN ("list", Flist, 0, MANY, 0, /* 1319 DEFUN ("list", Flist, 0, MANY, 0, /*
1301 Return a newly created list with specified arguments as elements. 1320 Return a newly created list with specified ARGS as elements.
1302 Any number of arguments, even zero arguments, are allowed. 1321 Any number of arguments, even zero arguments, are allowed.
1322
1323 arguments: (&rest ARGS)
1303 */ 1324 */
1304 (int nargs, Lisp_Object *args)) 1325 (int nargs, Lisp_Object *args))
1305 { 1326 {
1306 Lisp_Object val = Qnil; 1327 Lisp_Object val = Qnil;
1307 Lisp_Object *argp = args + nargs; 1328 Lisp_Object *argp = args + nargs;
1575 { XD_LONG, offsetof (Lisp_Vector, size) }, 1596 { XD_LONG, offsetof (Lisp_Vector, size) },
1576 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Vector, contents), XD_INDIRECT(0, 0) }, 1597 { XD_LISP_OBJECT_ARRAY, offsetof (Lisp_Vector, contents), XD_INDIRECT(0, 0) },
1577 { XD_END } 1598 { XD_END }
1578 }; 1599 };
1579 1600
1580 DEFINE_SIZABLE_LISP_OBJECT ("vector", vector, 1601 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("vector", vector,
1581 1, /*dumpable-flag*/ 1602 mark_vector, print_vector, 0,
1582 mark_vector, print_vector, 0, 1603 vector_equal,
1583 vector_equal, 1604 vector_hash,
1584 vector_hash, 1605 vector_description,
1585 vector_description, 1606 size_vector, Lisp_Vector);
1586 size_vector, Lisp_Vector);
1587 /* #### should allocate `small' vectors from a frob-block */ 1607 /* #### should allocate `small' vectors from a frob-block */
1588 static Lisp_Vector * 1608 static Lisp_Vector *
1589 make_vector_internal (Elemcount sizei) 1609 make_vector_internal (Elemcount sizei)
1590 { 1610 {
1591 /* no `next' field; we use lcrecords */ 1611 /* no `next' field; we use lcrecords */
1619 CONCHECK_NATNUM (length); 1639 CONCHECK_NATNUM (length);
1620 return make_vector (XINT (length), object); 1640 return make_vector (XINT (length), object);
1621 } 1641 }
1622 1642
1623 DEFUN ("vector", Fvector, 0, MANY, 0, /* 1643 DEFUN ("vector", Fvector, 0, MANY, 0, /*
1624 Return a newly created vector with specified arguments as elements. 1644 Return a newly created vector with specified ARGS as elements.
1625 Any number of arguments, even zero arguments, are allowed. 1645 Any number of arguments, even zero arguments, are allowed.
1646
1647 arguments: (&rest ARGS)
1626 */ 1648 */
1627 (int nargs, Lisp_Object *args)) 1649 (int nargs, Lisp_Object *args))
1628 { 1650 {
1629 Lisp_Vector *vecp = make_vector_internal (nargs); 1651 Lisp_Vector *vecp = make_vector_internal (nargs);
1630 Lisp_Object *p = vector_data (vecp); 1652 Lisp_Object *p = vector_data (vecp);
1800 1822
1801 return make_bit_vector (XINT (length), bit); 1823 return make_bit_vector (XINT (length), bit);
1802 } 1824 }
1803 1825
1804 DEFUN ("bit-vector", Fbit_vector, 0, MANY, 0, /* 1826 DEFUN ("bit-vector", Fbit_vector, 0, MANY, 0, /*
1805 Return a newly created bit vector with specified arguments as elements. 1827 Return a newly created bit vector with specified ARGS as elements.
1806 Any number of arguments, even zero arguments, are allowed. 1828 Any number of arguments, even zero arguments, are allowed.
1807 Each argument must be one of the integers 0 or 1. 1829 Each argument must be one of the integers 0 or 1.
1830
1831 arguments: (&rest ARGS)
1808 */ 1832 */
1809 (int nargs, Lisp_Object *args)) 1833 (int nargs, Lisp_Object *args))
1810 { 1834 {
1811 int i; 1835 int i;
1812 Lisp_Bit_Vector *p = make_bit_vector_internal (nargs); 1836 Lisp_Bit_Vector *p = make_bit_vector_internal (nargs);
1842 f->flags.interactivep = 0; 1866 f->flags.interactivep = 0;
1843 f->flags.domainp = 0; /* I18N3 */ 1867 f->flags.domainp = 0; /* I18N3 */
1844 f->instructions = Qzero; 1868 f->instructions = Qzero;
1845 f->constants = Qzero; 1869 f->constants = Qzero;
1846 f->arglist = Qnil; 1870 f->arglist = Qnil;
1871 #ifdef NEW_GC
1872 f->arguments = Qnil;
1873 #else /* not NEW_GC */
1847 f->args = NULL; 1874 f->args = NULL;
1875 #endif /* not NEW_GC */
1848 f->max_args = f->min_args = f->args_in_array = 0; 1876 f->max_args = f->min_args = f->args_in_array = 0;
1849 f->doc_and_interactive = Qnil; 1877 f->doc_and_interactive = Qnil;
1850 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 1878 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
1851 f->annotated = Qnil; 1879 f->annotated = Qnil;
1852 #endif 1880 #endif
1853 return wrap_compiled_function (f); 1881 return wrap_compiled_function (f);
1854 } 1882 }
1855 1883
1856 DEFUN ("make-byte-code", Fmake_byte_code, 4, MANY, 0, /* 1884 DEFUN ("make-byte-code", Fmake_byte_code, 4, MANY, 0, /*
1857 Return a new compiled-function object. 1885 Return a new compiled-function object.
1858 Usage: (arglist instructions constants stack-depth
1859 &optional doc-string interactive)
1860 Note that, unlike all other emacs-lisp functions, calling this with five 1886 Note that, unlike all other emacs-lisp functions, calling this with five
1861 arguments is NOT the same as calling it with six arguments, the last of 1887 arguments is NOT the same as calling it with six arguments, the last of
1862 which is nil. If the INTERACTIVE arg is specified as nil, then that means 1888 which is nil. If the INTERACTIVE arg is specified as nil, then that means
1863 that this function was defined with `(interactive)'. If the arg is not 1889 that this function was defined with `(interactive)'. If the arg is not
1864 specified, then that means the function is not interactive. 1890 specified, then that means the function is not interactive.
1865 This is terrible behavior which is retained for compatibility with old 1891 This is terrible behavior which is retained for compatibility with old
1866 `.elc' files which expect these semantics. 1892 `.elc' files which expect these semantics.
1893
1894 arguments: (ARGLIST INSTRUCTIONS CONSTANTS STACK-DEPTH &optional DOC-STRING INTERACTIVE)
1867 */ 1895 */
1868 (int nargs, Lisp_Object *args)) 1896 (int nargs, Lisp_Object *args))
1869 { 1897 {
1870 /* In a non-insane world this function would have this arglist... 1898 /* In a non-insane world this function would have this arglist...
1871 (arglist instructions constants stack_depth &optional doc_string interactive) 1899 (arglist instructions constants stack_depth &optional doc_string interactive)
2248 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && 2276 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) &&
2249 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); 2277 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len));
2250 } 2278 }
2251 2279
2252 static const struct memory_description string_description[] = { 2280 static const struct memory_description string_description[] = {
2281 #ifdef NEW_GC
2282 { XD_LISP_OBJECT, offsetof (Lisp_String, data_object) },
2283 #else /* not NEW_GC */
2253 { XD_BYTECOUNT, offsetof (Lisp_String, size_) }, 2284 { XD_BYTECOUNT, offsetof (Lisp_String, size_) },
2254 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data_), XD_INDIRECT(0, 1) }, 2285 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data_), XD_INDIRECT(0, 1) },
2286 #endif /* not NEW_GC */
2255 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, 2287 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) },
2256 { XD_END } 2288 { XD_END }
2257 }; 2289 };
2258 2290
2259 /* We store the string's extent info as the first element of the string's 2291 /* We store the string's extent info as the first element of the string's
2301 string_plist (Lisp_Object string) 2333 string_plist (Lisp_Object string)
2302 { 2334 {
2303 return *string_plist_ptr (string); 2335 return *string_plist_ptr (string);
2304 } 2336 }
2305 2337
2306 #ifndef MC_ALLOC 2338 #ifndef NEW_GC
2307 /* No `finalize', or `hash' methods. 2339 /* No `finalize', or `hash' methods.
2308 internal_hash() already knows how to hash strings and finalization 2340 internal_hash() already knows how to hash strings and finalization
2309 is done with the ADDITIONAL_FREE_string macro, which is the 2341 is done with the ADDITIONAL_FREE_string macro, which is the
2310 standard way to do finalization when using 2342 standard way to do finalization when using
2311 SWEEP_FIXED_TYPE_BLOCK(). */ 2343 SWEEP_FIXED_TYPE_BLOCK(). */
2312 2344
2313 DEFINE_BASIC_LISP_OBJECT_WITH_PROPS ("string", string, 2345 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT_WITH_PROPS ("string", string,
2314 mark_string, print_string, 2346 mark_string, print_string,
2315 0, string_equal, 0, 2347 0, string_equal, 0,
2316 string_description, 2348 string_description,
2317 string_getprop, 2349 string_getprop,
2318 string_putprop, 2350 string_putprop,
2319 string_remprop, 2351 string_remprop,
2320 string_plist, 2352 string_plist,
2321 Lisp_String); 2353 Lisp_String);
2322 #endif /* not MC_ALLOC */ 2354 #endif /* not NEW_GC */
2323 2355
2356 #ifdef NEW_GC
2357 #define STRING_FULLSIZE(size) \
2358 ALIGN_SIZE (FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_String_Direct_Data, Lisp_Object, data, (size) + 1), sizeof (Lisp_Object *));
2359 #else /* not NEW_GC */
2324 /* String blocks contain this many useful bytes. */ 2360 /* String blocks contain this many useful bytes. */
2325 #define STRING_CHARS_BLOCK_SIZE \ 2361 #define STRING_CHARS_BLOCK_SIZE \
2326 ((Bytecount) (8192 - MALLOC_OVERHEAD - \ 2362 ((Bytecount) (8192 - MALLOC_OVERHEAD - \
2327 ((2 * sizeof (struct string_chars_block *)) \ 2363 ((2 * sizeof (struct string_chars_block *)) \
2328 + sizeof (EMACS_INT)))) 2364 + sizeof (EMACS_INT))))
2350 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) 2386 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE)
2351 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) 2387 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size)))
2352 2388
2353 #define STRING_CHARS_FREE_P(ptr) ((ptr)->string == NULL) 2389 #define STRING_CHARS_FREE_P(ptr) ((ptr)->string == NULL)
2354 #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL)) 2390 #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL))
2355 2391 #endif /* not NEW_GC */
2356 #ifdef MC_ALLOC 2392
2357 static void 2393 #ifdef NEW_GC
2358 finalize_string (void *header, int for_disksave) 2394 DEFINE_DUMPABLE_LISP_OBJECT_WITH_PROPS ("string", string,
2359 { 2395 mark_string, print_string,
2360 if (!for_disksave) 2396 0,
2361 { 2397 string_equal, 0,
2362 Lisp_String *s = (Lisp_String *) header; 2398 string_description,
2363 Bytecount size = s->size_; 2399 string_getprop,
2364 #ifdef ALLOC_TYPE_STATS 2400 string_putprop,
2365 dec_lrecord_string_data_stats (size); 2401 string_remprop,
2366 #endif /* ALLOC_TYPE_STATS */ 2402 string_plist,
2367 if (BIG_STRING_SIZE_P (size)) 2403 Lisp_String);
2368 xfree (s->data_, Ibyte *); 2404
2369 } 2405
2370 } 2406 static const struct memory_description string_direct_data_description[] = {
2371 2407 { XD_BYTECOUNT, offsetof (Lisp_String_Direct_Data, size) },
2372 DEFINE_LISP_OBJECT_WITH_PROPS ("string", string, 2408 { XD_END }
2373 mark_string, print_string, 2409 };
2374 finalize_string, 2410
2375 string_equal, 0, 2411 static Bytecount
2376 string_description, 2412 size_string_direct_data (const void *lheader)
2377 string_getprop, 2413 {
2378 string_putprop, 2414 return STRING_FULLSIZE (((Lisp_String_Direct_Data *) lheader)->size);
2379 string_remprop, 2415 }
2380 string_plist, 2416
2381 Lisp_String); 2417
2382 2418 DEFINE_DUMPABLE_SIZABLE_INTERNAL_LISP_OBJECT ("string-direct-data",
2383 #endif /* MC_ALLOC */ 2419 string_direct_data,
2384 2420 0,
2421 string_direct_data_description,
2422 size_string_direct_data,
2423 Lisp_String_Direct_Data);
2424
2425
2426 static const struct memory_description string_indirect_data_description[] = {
2427 { XD_BYTECOUNT, offsetof (Lisp_String_Indirect_Data, size) },
2428 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String_Indirect_Data, data),
2429 XD_INDIRECT(0, 1) },
2430 { XD_END }
2431 };
2432
2433 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("string-indirect-data",
2434 string_indirect_data,
2435 0,
2436 string_indirect_data_description,
2437 Lisp_String_Indirect_Data);
2438 #endif /* NEW_GC */
2439
2440 #ifndef NEW_GC
2385 struct string_chars 2441 struct string_chars
2386 { 2442 {
2387 Lisp_String *string; 2443 Lisp_String *string;
2388 unsigned char chars[1]; 2444 unsigned char chars[1];
2389 }; 2445 };
2446 2502
2447 INCREMENT_CONS_COUNTER (fullsize, "string chars"); 2503 INCREMENT_CONS_COUNTER (fullsize, "string chars");
2448 2504
2449 return s_chars; 2505 return s_chars;
2450 } 2506 }
2507 #endif /* not NEW_GC */
2451 2508
2452 #ifdef SLEDGEHAMMER_CHECK_ASCII_BEGIN 2509 #ifdef SLEDGEHAMMER_CHECK_ASCII_BEGIN
2453 void 2510 void
2454 sledgehammer_check_ascii_begin (Lisp_Object str) 2511 sledgehammer_check_ascii_begin (Lisp_Object str)
2455 { 2512 {
2478 Lisp_String *s; 2535 Lisp_String *s;
2479 Bytecount fullsize = STRING_FULLSIZE (length); 2536 Bytecount fullsize = STRING_FULLSIZE (length);
2480 2537
2481 assert (length >= 0 && fullsize > 0); 2538 assert (length >= 0 && fullsize > 0);
2482 2539
2483 #ifdef MC_ALLOC 2540 #ifdef NEW_GC
2484 s = alloc_lrecord_type (Lisp_String, &lrecord_string); 2541 s = alloc_lrecord_type (Lisp_String, &lrecord_string);
2485 #ifdef ALLOC_TYPE_STATS 2542 #else /* not NEW_GC */
2486 inc_lrecord_string_data_stats (length);
2487 #endif /* ALLOC_TYPE_STATS */
2488 #else /* not MC_ALLOC */
2489 /* Allocate the string header */ 2543 /* Allocate the string header */
2490 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); 2544 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
2491 xzero (*s); 2545 xzero (*s);
2492 set_lheader_implementation (&s->u.lheader, &lrecord_string); 2546 set_lheader_implementation (&s->u.lheader, &lrecord_string);
2493 #endif /* not MC_ALLOC */ 2547 #endif /* not NEW_GC */
2494 2548
2495 /* The above allocations set the UID field, which overlaps with the 2549 /* The above allocations set the UID field, which overlaps with the
2496 ascii-length field, to some non-zero value. We need to zero it. */ 2550 ascii-length field, to some non-zero value. We need to zero it. */
2497 XSET_STRING_ASCII_BEGIN (wrap_string (s), 0); 2551 XSET_STRING_ASCII_BEGIN (wrap_string (s), 0);
2498 2552
2553 #ifdef NEW_GC
2554 set_lispstringp_direct (s);
2555 STRING_DATA_OBJECT (s) =
2556 alloc_sized_lrecord (fullsize, &lrecord_string_direct_data);
2557 #else /* not NEW_GC */
2499 set_lispstringp_data (s, BIG_STRING_FULLSIZE_P (fullsize) 2558 set_lispstringp_data (s, BIG_STRING_FULLSIZE_P (fullsize)
2500 ? allocate_big_string_chars (length + 1) 2559 ? allocate_big_string_chars (length + 1)
2501 : allocate_string_chars_struct (wrap_string (s), 2560 : allocate_string_chars_struct (wrap_string (s),
2502 fullsize)->chars); 2561 fullsize)->chars);
2562 #endif /* not NEW_GC */
2503 2563
2504 set_lispstringp_length (s, length); 2564 set_lispstringp_length (s, length);
2505 s->plist = Qnil; 2565 s->plist = Qnil;
2506 set_string_byte (wrap_string (s), length, 0); 2566 set_string_byte (wrap_string (s), length, 0);
2507 2567
2519 */ 2579 */
2520 2580
2521 void 2581 void
2522 resize_string (Lisp_Object s, Bytecount pos, Bytecount delta) 2582 resize_string (Lisp_Object s, Bytecount pos, Bytecount delta)
2523 { 2583 {
2584 #ifdef NEW_GC
2585 Bytecount newfullsize, len;
2586 #else /* not NEW_GC */
2524 Bytecount oldfullsize, newfullsize; 2587 Bytecount oldfullsize, newfullsize;
2588 #endif /* not NEW_GC */
2525 #ifdef VERIFY_STRING_CHARS_INTEGRITY 2589 #ifdef VERIFY_STRING_CHARS_INTEGRITY
2526 verify_string_chars_integrity (); 2590 verify_string_chars_integrity ();
2527 #endif 2591 #endif
2528 #ifdef ERROR_CHECK_TEXT 2592 #ifdef ERROR_CHECK_TEXT
2529 if (pos >= 0) 2593 if (pos >= 0)
2547 /* If DELTA < 0, the functions below will delete the characters 2611 /* If DELTA < 0, the functions below will delete the characters
2548 before POS. We want to delete characters *after* POS, however, 2612 before POS. We want to delete characters *after* POS, however,
2549 so convert this to the appropriate form. */ 2613 so convert this to the appropriate form. */
2550 pos += -delta; 2614 pos += -delta;
2551 2615
2616 #ifdef NEW_GC
2617 newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta);
2618
2619 len = XSTRING_LENGTH (s) + 1 - pos;
2620
2621 if (delta < 0 && pos >= 0)
2622 memmove (XSTRING_DATA (s) + pos + delta,
2623 XSTRING_DATA (s) + pos, len);
2624
2625 XSTRING_DATA_OBJECT (s) =
2626 wrap_string_direct_data (mc_realloc (XPNTR (XSTRING_DATA_OBJECT (s)),
2627 newfullsize));
2628 if (delta > 0 && pos >= 0)
2629 memmove (XSTRING_DATA (s) + pos + delta, XSTRING_DATA (s) + pos,
2630 len);
2631
2632 #else /* not NEW_GC */
2552 oldfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s)); 2633 oldfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s));
2553 newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta); 2634 newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta);
2554 2635
2555 if (BIG_STRING_FULLSIZE_P (oldfullsize)) 2636 if (BIG_STRING_FULLSIZE_P (oldfullsize))
2556 { 2637 {
2624 memcpy (new_data + pos + delta, old_data + pos, 2705 memcpy (new_data + pos + delta, old_data + pos,
2625 XSTRING_LENGTH (s) + 1 - pos); 2706 XSTRING_LENGTH (s) + 1 - pos);
2626 } 2707 }
2627 XSET_STRING_DATA (s, new_data); 2708 XSET_STRING_DATA (s, new_data);
2628 2709
2629 { 2710 if (!DUMPEDP (old_data)) /* Can't free dumped data. */
2630 /* We need to mark this chunk of the string_chars_block 2711 {
2631 as unused so that compact_string_chars() doesn't 2712 /* We need to mark this chunk of the string_chars_block
2632 freak. */ 2713 as unused so that compact_string_chars() doesn't
2633 struct string_chars *old_s_chars = (struct string_chars *) 2714 freak. */
2634 ((char *) old_data - offsetof (struct string_chars, chars)); 2715 struct string_chars *old_s_chars = (struct string_chars *)
2635 /* Sanity check to make sure we aren't hosed by strange 2716 ((char *) old_data - offsetof (struct string_chars, chars));
2636 alignment/padding. */ 2717 /* Sanity check to make sure we aren't hosed by strange
2637 assert (old_s_chars->string == XSTRING (s)); 2718 alignment/padding. */
2638 MARK_STRING_CHARS_AS_FREE (old_s_chars); 2719 assert (old_s_chars->string == XSTRING (s));
2639 ((struct unused_string_chars *) old_s_chars)->fullsize = 2720 MARK_STRING_CHARS_AS_FREE (old_s_chars);
2640 oldfullsize; 2721 ((struct unused_string_chars *) old_s_chars)->fullsize =
2641 } 2722 oldfullsize;
2723 }
2642 } 2724 }
2643 } 2725 }
2726 #endif /* not NEW_GC */
2644 2727
2645 XSET_STRING_LENGTH (s, XSTRING_LENGTH (s) + delta); 2728 XSET_STRING_LENGTH (s, XSTRING_LENGTH (s) + delta);
2646 /* If pos < 0, the string won't be zero-terminated. 2729 /* If pos < 0, the string won't be zero-terminated.
2647 Terminate now just to make sure. */ 2730 Terminate now just to make sure. */
2648 XSTRING_DATA (s)[XSTRING_LENGTH (s)] = '\0'; 2731 XSTRING_DATA (s)[XSTRING_LENGTH (s)] = '\0';
2741 } 2824 }
2742 } 2825 }
2743 2826
2744 DEFUN ("string", Fstring, 0, MANY, 0, /* 2827 DEFUN ("string", Fstring, 0, MANY, 0, /*
2745 Concatenate all the argument characters and make the result a string. 2828 Concatenate all the argument characters and make the result a string.
2829
2830 arguments: (&rest ARGS)
2746 */ 2831 */
2747 (int nargs, Lisp_Object *args)) 2832 (int nargs, Lisp_Object *args))
2748 { 2833 {
2749 Ibyte *storage = alloca_ibytes (nargs * MAX_ICHAR_LEN); 2834 Ibyte *storage = alloca_ibytes (nargs * MAX_ICHAR_LEN);
2750 Ibyte *p = storage; 2835 Ibyte *p = storage;
2858 /* Make sure we find out about bad make_string_nocopy's when they happen */ 2943 /* Make sure we find out about bad make_string_nocopy's when they happen */
2859 #if defined (ERROR_CHECK_TEXT) && defined (MULE) 2944 #if defined (ERROR_CHECK_TEXT) && defined (MULE)
2860 bytecount_to_charcount (contents, length); /* Just for the assertions */ 2945 bytecount_to_charcount (contents, length); /* Just for the assertions */
2861 #endif 2946 #endif
2862 2947
2863 #ifdef MC_ALLOC 2948 #ifdef NEW_GC
2864 s = alloc_lrecord_type (Lisp_String, &lrecord_string); 2949 s = alloc_lrecord_type (Lisp_String, &lrecord_string);
2865 #ifdef ALLOC_TYPE_STATS
2866 inc_lrecord_string_data_stats (length);
2867 #endif /* ALLOC_TYPE_STATS */
2868 mcpro (wrap_pointer_1 (s)); /* otherwise nocopy_strings get 2950 mcpro (wrap_pointer_1 (s)); /* otherwise nocopy_strings get
2869 collected and static data is tried to 2951 collected and static data is tried to
2870 be freed. */ 2952 be freed. */
2871 #else /* not MC_ALLOC */ 2953 #else /* not NEW_GC */
2872 /* Allocate the string header */ 2954 /* Allocate the string header */
2873 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); 2955 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
2874 set_lheader_implementation (&s->u.lheader, &lrecord_string); 2956 set_lheader_implementation (&s->u.lheader, &lrecord_string);
2875 SET_C_READONLY_RECORD_HEADER (&s->u.lheader); 2957 SET_C_READONLY_RECORD_HEADER (&s->u.lheader);
2876 #endif /* not MC_ALLOC */ 2958 #endif /* not NEW_GC */
2877 /* Don't need to XSET_STRING_ASCII_BEGIN() here because it happens in 2959 /* Don't need to XSET_STRING_ASCII_BEGIN() here because it happens in
2878 init_string_ascii_begin(). */ 2960 init_string_ascii_begin(). */
2879 s->plist = Qnil; 2961 s->plist = Qnil;
2962 #ifdef NEW_GC
2963 set_lispstringp_indirect (s);
2964 STRING_DATA_OBJECT (s) =
2965 wrap_string_indirect_data
2966 (alloc_lrecord_type (Lisp_String_Indirect_Data,
2967 &lrecord_string_indirect_data));
2968 XSTRING_INDIRECT_DATA_DATA (STRING_DATA_OBJECT (s)) = (Ibyte *) contents;
2969 XSTRING_INDIRECT_DATA_SIZE (STRING_DATA_OBJECT (s)) = length;
2970 #else /* not NEW_GC */
2880 set_lispstringp_data (s, (Ibyte *) contents); 2971 set_lispstringp_data (s, (Ibyte *) contents);
2881 set_lispstringp_length (s, length); 2972 set_lispstringp_length (s, length);
2973 #endif /* not NEW_GC */
2882 val = wrap_string (s); 2974 val = wrap_string (s);
2883 init_string_ascii_begin (val); 2975 init_string_ascii_begin (val);
2884 sledgehammer_check_ascii_begin (val); 2976 sledgehammer_check_ascii_begin (val);
2885 2977
2886 return val; 2978 return val;
2887 } 2979 }
2888 2980
2889 2981
2890 #ifndef MC_ALLOC 2982 #ifndef NEW_GC
2891 /************************************************************************/ 2983 /************************************************************************/
2892 /* lcrecord lists */ 2984 /* lcrecord lists */
2893 /************************************************************************/ 2985 /************************************************************************/
2894 2986
2895 /* Lcrecord lists are used to manage the allocation of particular 2987 /* Lcrecord lists are used to manage the allocation of particular
2904 { XD_LISP_OBJECT, offsetof (struct free_lcrecord_header, chain), 0, { 0 }, 2996 { XD_LISP_OBJECT, offsetof (struct free_lcrecord_header, chain), 0, { 0 },
2905 XD_FLAG_FREE_LISP_OBJECT }, 2997 XD_FLAG_FREE_LISP_OBJECT },
2906 { XD_END } 2998 { XD_END }
2907 }; 2999 };
2908 3000
2909 DEFINE_NONDUMPABLE_LISP_OBJECT ("free", free, 0, 0, 3001 DEFINE_NODUMP_INTERNAL_LISP_OBJECT ("free", free, 0, free_description,
2910 0, 0, 0, free_description, 3002 struct free_lcrecord_header);
2911 struct free_lcrecord_header);
2912 3003
2913 const struct memory_description lcrecord_list_description[] = { 3004 const struct memory_description lcrecord_list_description[] = {
2914 { XD_LISP_OBJECT, offsetof (struct lcrecord_list, free), 0, { 0 }, 3005 { XD_LISP_OBJECT, offsetof (struct lcrecord_list, free), 0, { 0 },
2915 XD_FLAG_FREE_LISP_OBJECT }, 3006 XD_FLAG_FREE_LISP_OBJECT },
2916 { XD_END } 3007 { XD_END }
2951 } 3042 }
2952 3043
2953 return Qnil; 3044 return Qnil;
2954 } 3045 }
2955 3046
2956 DEFINE_NONDUMPABLE_LISP_OBJECT ("lcrecord-list", lcrecord_list, 3047 DEFINE_NODUMP_INTERNAL_LISP_OBJECT ("lcrecord-list", lcrecord_list,
2957 mark_lcrecord_list, 3048 mark_lcrecord_list,
2958 0, 3049 lcrecord_list_description,
2959 0, 0, 0, lcrecord_list_description, 3050 struct lcrecord_list);
2960 struct lcrecord_list);
2961 3051
2962 Lisp_Object 3052 Lisp_Object
2963 make_lcrecord_list (Elemcount size, 3053 make_lcrecord_list (Elemcount size,
2964 const struct lrecord_implementation *implementation) 3054 const struct lrecord_implementation *implementation)
2965 { 3055 {
3097 3187
3098 assert (!EQ (all_lcrecord_lists[type], Qzero)); 3188 assert (!EQ (all_lcrecord_lists[type], Qzero));
3099 3189
3100 free_managed_lcrecord (all_lcrecord_lists[type], rec); 3190 free_managed_lcrecord (all_lcrecord_lists[type], rec);
3101 } 3191 }
3102 #endif /* not MC_ALLOC */ 3192 #endif /* not NEW_GC */
3103 3193
3104 3194
3105 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /* 3195 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /*
3106 Kept for compatibility, returns its argument. 3196 Kept for compatibility, returns its argument.
3107 Old: 3197 Old:
3276 3366
3277 3367
3278 3368
3279 3369
3280 3370
3281 #ifdef MC_ALLOC 3371 #ifdef NEW_GC
3282 static const struct memory_description mcpro_description_1[] = { 3372 static const struct memory_description mcpro_description_1[] = {
3283 { XD_END } 3373 { XD_END }
3284 }; 3374 };
3285 3375
3286 static const struct sized_memory_description mcpro_description = { 3376 static const struct sized_memory_description mcpro_description = {
3347 { 3437 {
3348 Dynarr_add (mcpros, varaddress); 3438 Dynarr_add (mcpros, varaddress);
3349 } 3439 }
3350 3440
3351 #endif /* not DEBUG_XEMACS */ 3441 #endif /* not DEBUG_XEMACS */
3352 #endif /* MC_ALLOC */ 3442 #endif /* NEW_GC */
3353 3443
3354 #ifdef ERROR_CHECK_GC 3444
3355 #ifdef MC_ALLOC 3445 #ifndef NEW_GC
3356 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \
3357 struct lrecord_header * GCLI_lh = (lheader); \
3358 assert (GCLI_lh != 0); \
3359 assert (GCLI_lh->type < (unsigned int) lrecord_type_count); \
3360 } while (0)
3361 #else /* not MC_ALLOC */
3362 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \
3363 struct lrecord_header * GCLI_lh = (lheader); \
3364 assert (GCLI_lh != 0); \
3365 assert (GCLI_lh->type < (unsigned int) lrecord_type_count); \
3366 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) || \
3367 (MARKED_RECORD_HEADER_P (GCLI_lh) && \
3368 LISP_READONLY_RECORD_HEADER_P (GCLI_lh))); \
3369 } while (0)
3370 #endif /* not MC_ALLOC */
3371 #else
3372 #define GC_CHECK_LHEADER_INVARIANTS(lheader)
3373 #endif
3374
3375
3376 static const struct memory_description lisp_object_description_1[] = {
3377 { XD_LISP_OBJECT, 0 },
3378 { XD_END }
3379 };
3380
3381 const struct sized_memory_description lisp_object_description = {
3382 sizeof (Lisp_Object),
3383 lisp_object_description_1
3384 };
3385
3386 #if defined (USE_KKCC) || defined (PDUMP)
3387
3388 /* This function extracts the value of a count variable described somewhere
3389 else in the description. It is converted corresponding to the type */
3390 EMACS_INT
3391 lispdesc_indirect_count_1 (EMACS_INT code,
3392 const struct memory_description *idesc,
3393 const void *idata)
3394 {
3395 EMACS_INT count;
3396 const void *irdata;
3397
3398 int line = XD_INDIRECT_VAL (code);
3399 int delta = XD_INDIRECT_DELTA (code);
3400
3401 irdata = ((char *) idata) +
3402 lispdesc_indirect_count (idesc[line].offset, idesc, idata);
3403 switch (idesc[line].type)
3404 {
3405 case XD_BYTECOUNT:
3406 count = * (Bytecount *) irdata;
3407 break;
3408 case XD_ELEMCOUNT:
3409 count = * (Elemcount *) irdata;
3410 break;
3411 case XD_HASHCODE:
3412 count = * (Hashcode *) irdata;
3413 break;
3414 case XD_INT:
3415 count = * (int *) irdata;
3416 break;
3417 case XD_LONG:
3418 count = * (long *) irdata;
3419 break;
3420 default:
3421 stderr_out ("Unsupported count type : %d (line = %d, code = %ld)\n",
3422 idesc[line].type, line, (long) code);
3423 #if defined(USE_KKCC) && defined(DEBUG_XEMACS)
3424 if (gc_in_progress)
3425 kkcc_backtrace ();
3426 #endif
3427 #ifdef PDUMP
3428 if (in_pdump)
3429 pdump_backtrace ();
3430 #endif
3431 count = 0; /* warning suppression */
3432 ABORT ();
3433 }
3434 count += delta;
3435 return count;
3436 }
3437
3438 /* SDESC is a "description map" (basically, a list of offsets used for
3439 successive indirections) and OBJ is the first object to indirect off of.
3440 Return the description ultimately found. */
3441
3442 const struct sized_memory_description *
3443 lispdesc_indirect_description_1 (const void *obj,
3444 const struct sized_memory_description *sdesc)
3445 {
3446 int pos;
3447
3448 for (pos = 0; sdesc[pos].size >= 0; pos++)
3449 obj = * (const void **) ((const char *) obj + sdesc[pos].size);
3450
3451 return (const struct sized_memory_description *) obj;
3452 }
3453
3454 /* Compute the size of the data at RDATA, described by a single entry
3455 DESC1 in a description array. OBJ and DESC are used for
3456 XD_INDIRECT references. */
3457
3458 static Bytecount
3459 lispdesc_one_description_line_size (void *rdata,
3460 const struct memory_description *desc1,
3461 const void *obj,
3462 const struct memory_description *desc)
3463 {
3464 union_switcheroo:
3465 switch (desc1->type)
3466 {
3467 case XD_LISP_OBJECT_ARRAY:
3468 {
3469 EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj);
3470 return (val * sizeof (Lisp_Object));
3471 }
3472 case XD_LISP_OBJECT:
3473 case XD_LO_LINK:
3474 return sizeof (Lisp_Object);
3475 case XD_OPAQUE_PTR:
3476 return sizeof (void *);
3477 case XD_BLOCK_PTR:
3478 {
3479 EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj);
3480 return val * sizeof (void *);
3481 }
3482 case XD_BLOCK_ARRAY:
3483 {
3484 EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj);
3485
3486 return (val *
3487 lispdesc_block_size
3488 (rdata,
3489 lispdesc_indirect_description (obj, desc1->data2.descr)));
3490 }
3491 case XD_OPAQUE_DATA_PTR:
3492 return sizeof (void *);
3493 case XD_UNION_DYNAMIC_SIZE:
3494 {
3495 /* If an explicit size was given in the first-level structure
3496 description, use it; else compute size based on current union
3497 constant. */
3498 const struct sized_memory_description *sdesc =
3499 lispdesc_indirect_description (obj, desc1->data2.descr);
3500 if (sdesc->size)
3501 return sdesc->size;
3502 else
3503 {
3504 desc1 = lispdesc_process_xd_union (desc1, desc, obj);
3505 if (desc1)
3506 goto union_switcheroo;
3507 break;
3508 }
3509 }
3510 case XD_UNION:
3511 {
3512 /* If an explicit size was given in the first-level structure
3513 description, use it; else compute size based on maximum of all
3514 possible structures. */
3515 const struct sized_memory_description *sdesc =
3516 lispdesc_indirect_description (obj, desc1->data2.descr);
3517 if (sdesc->size)
3518 return sdesc->size;
3519 else
3520 {
3521 int count;
3522 Bytecount max_size = -1, size;
3523
3524 desc1 = sdesc->description;
3525
3526 for (count = 0; desc1[count].type != XD_END; count++)
3527 {
3528 size = lispdesc_one_description_line_size (rdata,
3529 &desc1[count],
3530 obj, desc);
3531 if (size > max_size)
3532 max_size = size;
3533 }
3534 return max_size;
3535 }
3536 }
3537 case XD_ASCII_STRING:
3538 return sizeof (void *);
3539 case XD_DOC_STRING:
3540 return sizeof (void *);
3541 case XD_INT_RESET:
3542 return sizeof (int);
3543 case XD_BYTECOUNT:
3544 return sizeof (Bytecount);
3545 case XD_ELEMCOUNT:
3546 return sizeof (Elemcount);
3547 case XD_HASHCODE:
3548 return sizeof (Hashcode);
3549 case XD_INT:
3550 return sizeof (int);
3551 case XD_LONG:
3552 return sizeof (long);
3553 default:
3554 stderr_out ("Unsupported dump type : %d\n", desc1->type);
3555 ABORT ();
3556 }
3557
3558 return 0;
3559 }
3560
3561
3562 /* Return the size of the memory block (NOT necessarily a structure!)
3563 described by SDESC and pointed to by OBJ. If SDESC records an
3564 explicit size (i.e. non-zero), it is simply returned; otherwise,
3565 the size is calculated by the maximum offset and the size of the
3566 object at that offset, rounded up to the maximum alignment. In
3567 this case, we may need the object, for example when retrieving an
3568 "indirect count" of an inlined array (the count is not constant,
3569 but is specified by one of the elements of the memory block). (It
3570 is generally not a problem if we return an overly large size -- we
3571 will simply end up reserving more space than necessary; but if the
3572 size is too small we could be in serious trouble, in particular
3573 with nested inlined structures, where there may be alignment
3574 padding in the middle of a block. #### In fact there is an (at
3575 least theoretical) problem with an overly large size -- we may
3576 trigger a protection fault when reading from invalid memory. We
3577 need to handle this -- perhaps in a stupid but dependable way,
3578 i.e. by trapping SIGSEGV and SIGBUS.) */
3579
3580 Bytecount
3581 lispdesc_block_size_1 (const void *obj, Bytecount size,
3582 const struct memory_description *desc)
3583 {
3584 EMACS_INT max_offset = -1;
3585 int max_offset_pos = -1;
3586 int pos;
3587
3588 if (size)
3589 return size;
3590
3591 for (pos = 0; desc[pos].type != XD_END; pos++)
3592 {
3593 EMACS_INT offset = lispdesc_indirect_count (desc[pos].offset, desc, obj);
3594 if (offset == max_offset)
3595 {
3596 stderr_out ("Two relocatable elements at same offset?\n");
3597 ABORT ();
3598 }
3599 else if (offset > max_offset)
3600 {
3601 max_offset = offset;
3602 max_offset_pos = pos;
3603 }
3604 }
3605
3606 if (max_offset_pos < 0)
3607 return 0;
3608
3609 {
3610 Bytecount size_at_max;
3611 size_at_max =
3612 lispdesc_one_description_line_size ((char *) obj + max_offset,
3613 &desc[max_offset_pos], obj, desc);
3614
3615 /* We have no way of knowing the required alignment for this structure,
3616 so just make it maximally aligned. */
3617 return MAX_ALIGN_SIZE (max_offset + size_at_max);
3618 }
3619 }
3620
3621 #endif /* defined (USE_KKCC) || defined (PDUMP) */
3622
3623 #ifdef MC_ALLOC
3624 #define GC_CHECK_NOT_FREE(lheader) \
3625 gc_checking_assert (! LRECORD_FREE_P (lheader));
3626 #else /* MC_ALLOC */
3627 #define GC_CHECK_NOT_FREE(lheader) \
3628 gc_checking_assert (! LRECORD_FREE_P (lheader)); \
3629 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || \
3630 ! ((struct old_lcrecord_header *) lheader)->free)
3631 #endif /* MC_ALLOC */
3632
3633 #ifdef USE_KKCC
3634 /* The following functions implement the new mark algorithm.
3635 They mark objects according to their descriptions. They
3636 are modeled on the corresponding pdumper procedures. */
3637
3638 #ifdef DEBUG_XEMACS
3639 /* The backtrace for the KKCC mark functions. */
3640 #define KKCC_INIT_BT_STACK_SIZE 4096
3641
3642 typedef struct
3643 {
3644 void *obj;
3645 const struct memory_description *desc;
3646 int pos;
3647 } kkcc_bt_stack_entry;
3648
3649 static kkcc_bt_stack_entry *kkcc_bt;
3650 static int kkcc_bt_stack_size;
3651 static int kkcc_bt_depth = 0;
3652
3653 static void
3654 kkcc_bt_init (void)
3655 {
3656 kkcc_bt_depth = 0;
3657 kkcc_bt_stack_size = KKCC_INIT_BT_STACK_SIZE;
3658 kkcc_bt = (kkcc_bt_stack_entry *)
3659 malloc (kkcc_bt_stack_size * sizeof (kkcc_bt_stack_entry));
3660 if (!kkcc_bt)
3661 {
3662 stderr_out ("KKCC backtrace stack init failed for size %d\n",
3663 kkcc_bt_stack_size);
3664 ABORT ();
3665 }
3666 }
3667
3668 void
3669 kkcc_backtrace (void)
3670 {
3671 int i;
3672 stderr_out ("KKCC mark stack backtrace :\n");
3673 for (i = kkcc_bt_depth - 1; i >= 0; i--)
3674 {
3675 Lisp_Object obj = wrap_pointer_1 (kkcc_bt[i].obj);
3676 stderr_out (" [%d]", i);
3677 #ifdef MC_ALLOC
3678 if ((XRECORD_LHEADER (obj)->type >= lrecord_type_last_built_in_type)
3679 #else /* not MC_ALLOC */
3680 if ((XRECORD_LHEADER (obj)->type >= lrecord_type_free)
3681 #endif /* not MC_ALLOC */
3682 || (!LRECORDP (obj))
3683 || (!XRECORD_LHEADER_IMPLEMENTATION (obj)))
3684 {
3685 stderr_out (" non Lisp Object");
3686 }
3687 else
3688 {
3689 stderr_out (" %s",
3690 XRECORD_LHEADER_IMPLEMENTATION (obj)->name);
3691 }
3692 stderr_out (" (addr: 0x%x, desc: 0x%x, ",
3693 (int) kkcc_bt[i].obj,
3694 (int) kkcc_bt[i].desc);
3695 if (kkcc_bt[i].pos >= 0)
3696 stderr_out ("pos: %d)\n", kkcc_bt[i].pos);
3697 else
3698 stderr_out ("root set)\n");
3699 }
3700 }
3701
3702 static void
3703 kkcc_bt_stack_realloc (void)
3704 {
3705 kkcc_bt_stack_size *= 2;
3706 kkcc_bt = (kkcc_bt_stack_entry *)
3707 realloc (kkcc_bt, kkcc_bt_stack_size * sizeof (kkcc_bt_stack_entry));
3708 if (!kkcc_bt)
3709 {
3710 stderr_out ("KKCC backtrace stack realloc failed for size %d\n",
3711 kkcc_bt_stack_size);
3712 ABORT ();
3713 }
3714 }
3715
3716 static void
3717 kkcc_bt_free (void)
3718 {
3719 free (kkcc_bt);
3720 kkcc_bt = 0;
3721 kkcc_bt_stack_size = 0;
3722 }
3723
3724 static void
3725 kkcc_bt_push (void *obj, const struct memory_description *desc,
3726 int level, int pos)
3727 {
3728 kkcc_bt_depth = level;
3729 kkcc_bt[kkcc_bt_depth].obj = obj;
3730 kkcc_bt[kkcc_bt_depth].desc = desc;
3731 kkcc_bt[kkcc_bt_depth].pos = pos;
3732 kkcc_bt_depth++;
3733 if (kkcc_bt_depth >= kkcc_bt_stack_size)
3734 kkcc_bt_stack_realloc ();
3735 }
3736
3737 #else /* not DEBUG_XEMACS */
3738 #define kkcc_bt_init()
3739 #define kkcc_bt_push(obj, desc, level, pos)
3740 #endif /* not DEBUG_XEMACS */
3741
3742 /* Object memory descriptions are in the lrecord_implementation structure.
3743 But copying them to a parallel array is much more cache-friendly. */
3744 const struct memory_description *lrecord_memory_descriptions[countof (lrecord_implementations_table)];
3745
3746 /* the initial stack size in kkcc_gc_stack_entries */
3747 #define KKCC_INIT_GC_STACK_SIZE 16384
3748
3749 typedef struct
3750 {
3751 void *data;
3752 const struct memory_description *desc;
3753 #ifdef DEBUG_XEMACS
3754 int level;
3755 int pos;
3756 #endif
3757 } kkcc_gc_stack_entry;
3758
3759 static kkcc_gc_stack_entry *kkcc_gc_stack_ptr;
3760 static kkcc_gc_stack_entry *kkcc_gc_stack_top;
3761 static kkcc_gc_stack_entry *kkcc_gc_stack_last_entry;
3762 static int kkcc_gc_stack_size;
3763
3764 static void
3765 kkcc_gc_stack_init (void)
3766 {
3767 kkcc_gc_stack_size = KKCC_INIT_GC_STACK_SIZE;
3768 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
3769 malloc (kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
3770 if (!kkcc_gc_stack_ptr)
3771 {
3772 stderr_out ("stack init failed for size %d\n", kkcc_gc_stack_size);
3773 ABORT ();
3774 }
3775 kkcc_gc_stack_top = kkcc_gc_stack_ptr - 1;
3776 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
3777 }
3778
3779 static void
3780 kkcc_gc_stack_free (void)
3781 {
3782 free (kkcc_gc_stack_ptr);
3783 kkcc_gc_stack_ptr = 0;
3784 kkcc_gc_stack_top = 0;
3785 kkcc_gc_stack_size = 0;
3786 }
3787
3788 static void
3789 kkcc_gc_stack_realloc (void)
3790 {
3791 int current_offset = (int)(kkcc_gc_stack_top - kkcc_gc_stack_ptr);
3792 kkcc_gc_stack_size *= 2;
3793 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
3794 realloc (kkcc_gc_stack_ptr,
3795 kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
3796 if (!kkcc_gc_stack_ptr)
3797 {
3798 stderr_out ("stack realloc failed for size %d\n", kkcc_gc_stack_size);
3799 ABORT ();
3800 }
3801 kkcc_gc_stack_top = kkcc_gc_stack_ptr + current_offset;
3802 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
3803 }
3804
3805 #define KKCC_GC_STACK_FULL (kkcc_gc_stack_top >= kkcc_gc_stack_last_entry)
3806 #define KKCC_GC_STACK_EMPTY (kkcc_gc_stack_top < kkcc_gc_stack_ptr)
3807
3808 static void
3809 #ifdef DEBUG_XEMACS
3810 kkcc_gc_stack_push_1 (void *data, const struct memory_description *desc,
3811 int level, int pos)
3812 #else
3813 kkcc_gc_stack_push_1 (void *data, const struct memory_description *desc)
3814 #endif
3815 {
3816 if (KKCC_GC_STACK_FULL)
3817 kkcc_gc_stack_realloc();
3818 kkcc_gc_stack_top++;
3819 kkcc_gc_stack_top->data = data;
3820 kkcc_gc_stack_top->desc = desc;
3821 #ifdef DEBUG_XEMACS
3822 kkcc_gc_stack_top->level = level;
3823 kkcc_gc_stack_top->pos = pos;
3824 #endif
3825 }
3826
3827 #ifdef DEBUG_XEMACS
3828 #define kkcc_gc_stack_push(data, desc, level, pos) \
3829 kkcc_gc_stack_push_1 (data, desc, level, pos)
3830 #else
3831 #define kkcc_gc_stack_push(data, desc, level, pos) \
3832 kkcc_gc_stack_push_1 (data, desc)
3833 #endif
3834
3835 static kkcc_gc_stack_entry *
3836 kkcc_gc_stack_pop (void)
3837 {
3838 if (KKCC_GC_STACK_EMPTY)
3839 return 0;
3840 kkcc_gc_stack_top--;
3841 return kkcc_gc_stack_top + 1;
3842 }
3843
3844 void
3845 #ifdef DEBUG_XEMACS
3846 kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj, int level, int pos)
3847 #else
3848 kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj)
3849 #endif
3850 {
3851 if (XTYPE (obj) == Lisp_Type_Record)
3852 {
3853 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3854 const struct memory_description *desc;
3855 GC_CHECK_LHEADER_INVARIANTS (lheader);
3856 desc = RECORD_DESCRIPTION (lheader);
3857 if (! MARKED_RECORD_HEADER_P (lheader))
3858 {
3859 MARK_RECORD_HEADER (lheader);
3860 kkcc_gc_stack_push ((void*) lheader, desc, level, pos);
3861 }
3862 }
3863 }
3864
3865 #ifdef DEBUG_XEMACS
3866 #define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
3867 kkcc_gc_stack_push_lisp_object_1 (obj, level, pos)
3868 #else
3869 #define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
3870 kkcc_gc_stack_push_lisp_object_1 (obj)
3871 #endif
3872
3873 #ifdef ERROR_CHECK_GC
3874 #define KKCC_DO_CHECK_FREE(obj, allow_free) \
3875 do \
3876 { \
3877 if (!allow_free && XTYPE (obj) == Lisp_Type_Record) \
3878 { \
3879 struct lrecord_header *lheader = XRECORD_LHEADER (obj); \
3880 GC_CHECK_NOT_FREE (lheader); \
3881 } \
3882 } while (0)
3883 #else
3884 #define KKCC_DO_CHECK_FREE(obj, allow_free)
3885 #endif
3886
3887 #ifdef ERROR_CHECK_GC
3888 #ifdef DEBUG_XEMACS
3889 static void
3890 mark_object_maybe_checking_free_1 (Lisp_Object obj, int allow_free,
3891 int level, int pos)
3892 #else
3893 static void
3894 mark_object_maybe_checking_free_1 (Lisp_Object obj, int allow_free)
3895 #endif
3896 {
3897 KKCC_DO_CHECK_FREE (obj, allow_free);
3898 kkcc_gc_stack_push_lisp_object (obj, level, pos);
3899 }
3900
3901 #ifdef DEBUG_XEMACS
3902 #define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
3903 mark_object_maybe_checking_free_1 (obj, allow_free, level, pos)
3904 #else
3905 #define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
3906 mark_object_maybe_checking_free_1 (obj, allow_free)
3907 #endif
3908 #else /* not ERROR_CHECK_GC */
3909 #define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
3910 kkcc_gc_stack_push_lisp_object (obj, level, pos)
3911 #endif /* not ERROR_CHECK_GC */
3912
3913
3914 /* This function loops all elements of a struct pointer and calls
3915 mark_with_description with each element. */
3916 static void
3917 #ifdef DEBUG_XEMACS
3918 mark_struct_contents_1 (const void *data,
3919 const struct sized_memory_description *sdesc,
3920 int count, int level, int pos)
3921 #else
3922 mark_struct_contents_1 (const void *data,
3923 const struct sized_memory_description *sdesc,
3924 int count)
3925 #endif
3926 {
3927 int i;
3928 Bytecount elsize;
3929 elsize = lispdesc_block_size (data, sdesc);
3930
3931 for (i = 0; i < count; i++)
3932 {
3933 kkcc_gc_stack_push (((char *) data) + elsize * i, sdesc->description,
3934 level, pos);
3935 }
3936 }
3937
3938 #ifdef DEBUG_XEMACS
3939 #define mark_struct_contents(data, sdesc, count, level, pos) \
3940 mark_struct_contents_1 (data, sdesc, count, level, pos)
3941 #else
3942 #define mark_struct_contents(data, sdesc, count, level, pos) \
3943 mark_struct_contents_1 (data, sdesc, count)
3944 #endif
3945
3946 /* This function implements the KKCC mark algorithm.
3947 Instead of calling mark_object, all the alive Lisp_Objects are pushed
3948 on the kkcc_gc_stack. This function processes all elements on the stack
3949 according to their descriptions. */
3950 static void
3951 kkcc_marking (void)
3952 {
3953 kkcc_gc_stack_entry *stack_entry = 0;
3954 void *data = 0;
3955 const struct memory_description *desc = 0;
3956 int pos;
3957 #ifdef DEBUG_XEMACS
3958 int level = 0;
3959 kkcc_bt_init ();
3960 #endif
3961
3962 while ((stack_entry = kkcc_gc_stack_pop ()) != 0)
3963 {
3964 data = stack_entry->data;
3965 desc = stack_entry->desc;
3966 #ifdef DEBUG_XEMACS
3967 level = stack_entry->level + 1;
3968 #endif
3969
3970 kkcc_bt_push (data, desc, stack_entry->level, stack_entry->pos);
3971
3972 gc_checking_assert (data);
3973 gc_checking_assert (desc);
3974
3975 for (pos = 0; desc[pos].type != XD_END; pos++)
3976 {
3977 const struct memory_description *desc1 = &desc[pos];
3978 const void *rdata =
3979 (const char *) data + lispdesc_indirect_count (desc1->offset,
3980 desc, data);
3981 union_switcheroo:
3982
3983 /* If the flag says don't mark, then don't mark. */
3984 if ((desc1->flags) & XD_FLAG_NO_KKCC)
3985 continue;
3986
3987 switch (desc1->type)
3988 {
3989 case XD_BYTECOUNT:
3990 case XD_ELEMCOUNT:
3991 case XD_HASHCODE:
3992 case XD_INT:
3993 case XD_LONG:
3994 case XD_INT_RESET:
3995 case XD_LO_LINK:
3996 case XD_OPAQUE_PTR:
3997 case XD_OPAQUE_DATA_PTR:
3998 case XD_ASCII_STRING:
3999 case XD_DOC_STRING:
4000 break;
4001 case XD_LISP_OBJECT:
4002 {
4003 const Lisp_Object *stored_obj = (const Lisp_Object *) rdata;
4004
4005 /* Because of the way that tagged objects work (pointers and
4006 Lisp_Objects have the same representation), XD_LISP_OBJECT
4007 can be used for untagged pointers. They might be NULL,
4008 though. */
4009 if (EQ (*stored_obj, Qnull_pointer))
4010 break;
4011 #ifdef MC_ALLOC
4012 mark_object_maybe_checking_free (*stored_obj, 0, level, pos);
4013 #else /* not MC_ALLOC */
4014 mark_object_maybe_checking_free
4015 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
4016 level, pos);
4017 #endif /* not MC_ALLOC */
4018 break;
4019 }
4020 case XD_LISP_OBJECT_ARRAY:
4021 {
4022 int i;
4023 EMACS_INT count =
4024 lispdesc_indirect_count (desc1->data1, desc, data);
4025
4026 for (i = 0; i < count; i++)
4027 {
4028 const Lisp_Object *stored_obj =
4029 (const Lisp_Object *) rdata + i;
4030
4031 if (EQ (*stored_obj, Qnull_pointer))
4032 break;
4033 #ifdef MC_ALLOC
4034 mark_object_maybe_checking_free (*stored_obj, 0, level, pos);
4035 #else /* not MC_ALLOC */
4036 mark_object_maybe_checking_free
4037 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
4038 level, pos);
4039 #endif /* not MC_ALLOC */
4040 }
4041 break;
4042 }
4043 case XD_BLOCK_PTR:
4044 {
4045 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
4046 data);
4047 const struct sized_memory_description *sdesc =
4048 lispdesc_indirect_description (data, desc1->data2.descr);
4049 const char *dobj = * (const char **) rdata;
4050 if (dobj)
4051 mark_struct_contents (dobj, sdesc, count, level, pos);
4052 break;
4053 }
4054 case XD_BLOCK_ARRAY:
4055 {
4056 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
4057 data);
4058 const struct sized_memory_description *sdesc =
4059 lispdesc_indirect_description (data, desc1->data2.descr);
4060
4061 mark_struct_contents (rdata, sdesc, count, level, pos);
4062 break;
4063 }
4064 case XD_UNION:
4065 case XD_UNION_DYNAMIC_SIZE:
4066 desc1 = lispdesc_process_xd_union (desc1, desc, data);
4067 if (desc1)
4068 goto union_switcheroo;
4069 break;
4070
4071 default:
4072 stderr_out ("Unsupported description type : %d\n", desc1->type);
4073 kkcc_backtrace ();
4074 ABORT ();
4075 }
4076 }
4077 }
4078 #ifdef DEBUG_XEMACS
4079 kkcc_bt_free ();
4080 #endif
4081 }
4082 #endif /* USE_KKCC */
4083
4084 /* Mark reference to a Lisp_Object. If the object referred to has not been
4085 seen yet, recursively mark all the references contained in it. */
4086
4087 void
4088 mark_object (
4089 #ifdef USE_KKCC
4090 Lisp_Object UNUSED (obj)
4091 #else
4092 Lisp_Object obj
4093 #endif
4094 )
4095 {
4096 #ifdef USE_KKCC
4097 /* this code should never be reached when configured for KKCC */
4098 stderr_out ("KKCC: Invalid mark_object call.\n");
4099 stderr_out ("Replace mark_object with kkcc_gc_stack_push_lisp_object.\n");
4100 ABORT ();
4101 #else /* not USE_KKCC */
4102
4103 tail_recurse:
4104
4105 /* Checks we used to perform */
4106 /* if (EQ (obj, Qnull_pointer)) return; */
4107 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */
4108 /* if (PURIFIED (XPNTR (obj))) return; */
4109
4110 if (XTYPE (obj) == Lisp_Type_Record)
4111 {
4112 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
4113
4114 GC_CHECK_LHEADER_INVARIANTS (lheader);
4115
4116 /* We handle this separately, above, so we can mark free objects */
4117 GC_CHECK_NOT_FREE (lheader);
4118
4119 /* All c_readonly objects have their mark bit set,
4120 so that we only need to check the mark bit here. */
4121 if (! MARKED_RECORD_HEADER_P (lheader))
4122 {
4123 MARK_RECORD_HEADER (lheader);
4124
4125 if (RECORD_MARKER (lheader))
4126 {
4127 obj = RECORD_MARKER (lheader) (obj);
4128 if (!NILP (obj)) goto tail_recurse;
4129 }
4130 }
4131 }
4132 #endif /* not KKCC */
4133 }
4134
4135
4136 #ifndef MC_ALLOC
4137 static int gc_count_num_short_string_in_use; 3446 static int gc_count_num_short_string_in_use;
4138 static Bytecount gc_count_string_total_size; 3447 static Bytecount gc_count_string_total_size;
4139 static Bytecount gc_count_short_string_total_size; 3448 static Bytecount gc_count_short_string_total_size;
4140 3449
4141 /* static int gc_count_total_records_used, gc_count_records_total_size; */ 3450 /* static int gc_count_total_records_used, gc_count_records_total_size; */
4148 int instances_in_use; 3457 int instances_in_use;
4149 int bytes_in_use; 3458 int bytes_in_use;
4150 int instances_freed; 3459 int instances_freed;
4151 int bytes_freed; 3460 int bytes_freed;
4152 int instances_on_free_list; 3461 int instances_on_free_list;
4153 } lcrecord_stats [countof (lrecord_implementations_table) 3462 } lcrecord_stats [countof (lrecord_implementations_table)];
4154 + MODULE_DEFINABLE_TYPE_COUNT];
4155 3463
4156 static void 3464 static void
4157 tick_lcrecord_stats (const struct lrecord_header *h, int free_p) 3465 tick_lcrecord_stats (const struct lrecord_header *h, int free_p)
4158 { 3466 {
4159 int type_index = h->type; 3467 int type_index = h->type;
4177 lcrecord_stats[type_index].instances_in_use++; 3485 lcrecord_stats[type_index].instances_in_use++;
4178 lcrecord_stats[type_index].bytes_in_use += sz; 3486 lcrecord_stats[type_index].bytes_in_use += sz;
4179 } 3487 }
4180 } 3488 }
4181 } 3489 }
4182 #endif /* not MC_ALLOC */ 3490 #endif /* not NEW_GC */
4183 3491
4184 3492
4185 #ifndef MC_ALLOC 3493 #ifndef NEW_GC
4186 /* Free all unmarked records */ 3494 /* Free all unmarked records */
4187 static void 3495 static void
4188 sweep_lcrecords_1 (struct old_lcrecord_header **prev, int *used) 3496 sweep_lcrecords_1 (struct old_lcrecord_header **prev, int *used)
4189 { 3497 {
4190 struct old_lcrecord_header *header; 3498 struct old_lcrecord_header *header;
4376 #endif /* !ERROR_CHECK_GC */ 3684 #endif /* !ERROR_CHECK_GC */
4377 3685
4378 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ 3686 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \
4379 SWEEP_FIXED_TYPE_BLOCK_1 (typename, obj_type, lheader) 3687 SWEEP_FIXED_TYPE_BLOCK_1 (typename, obj_type, lheader)
4380 3688
4381 #endif /* not MC_ALLOC */ 3689 #endif /* not NEW_GC */
4382 3690
4383 3691
4384 #ifndef MC_ALLOC 3692 #ifndef NEW_GC
4385 static void 3693 static void
4386 sweep_conses (void) 3694 sweep_conses (void)
4387 { 3695 {
4388 #define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3696 #define UNMARK_cons(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4389 #define ADDITIONAL_FREE_cons(ptr) 3697 #define ADDITIONAL_FREE_cons(ptr)
4390 3698
4391 SWEEP_FIXED_TYPE_BLOCK (cons, Lisp_Cons); 3699 SWEEP_FIXED_TYPE_BLOCK (cons, Lisp_Cons);
4392 } 3700 }
4393 #endif /* not MC_ALLOC */ 3701 #endif /* not NEW_GC */
4394 3702
4395 /* Explicitly free a cons cell. */ 3703 /* Explicitly free a cons cell. */
4396 void 3704 void
4397 free_cons (Lisp_Object cons) 3705 free_cons (Lisp_Object cons)
4398 { 3706 {
4399 #ifndef MC_ALLOC /* to avoid compiler warning */ 3707 #ifndef NEW_GC /* to avoid compiler warning */
4400 Lisp_Cons *ptr = XCONS (cons); 3708 Lisp_Cons *ptr = XCONS (cons);
4401 #endif /* MC_ALLOC */ 3709 #endif /* not NEW_GC */
4402 3710
4403 #ifdef ERROR_CHECK_GC 3711 #ifdef ERROR_CHECK_GC
4404 #ifdef MC_ALLOC 3712 #ifdef NEW_GC
4405 Lisp_Cons *ptr = XCONS (cons); 3713 Lisp_Cons *ptr = XCONS (cons);
4406 #endif /* MC_ALLOC */ 3714 #endif /* NEW_GC */
4407 /* If the CAR is not an int, then it will be a pointer, which will 3715 /* If the CAR is not an int, then it will be a pointer, which will
4408 always be four-byte aligned. If this cons cell has already been 3716 always be four-byte aligned. If this cons cell has already been
4409 placed on the free list, however, its car will probably contain 3717 placed on the free list, however, its car will probably contain
4410 a chain pointer to the next cons on the list, which has cleverly 3718 a chain pointer to the next cons on the list, which has cleverly
4411 had all its 0's and 1's inverted. This allows for a quick 3719 had all its 0's and 1's inverted. This allows for a quick
4416 well as a check in FREE_FIXED_TYPE(). */ 3724 well as a check in FREE_FIXED_TYPE(). */
4417 if (POINTER_TYPE_P (XTYPE (cons_car (ptr)))) 3725 if (POINTER_TYPE_P (XTYPE (cons_car (ptr))))
4418 ASSERT_VALID_POINTER (XPNTR (cons_car (ptr))); 3726 ASSERT_VALID_POINTER (XPNTR (cons_car (ptr)));
4419 #endif /* ERROR_CHECK_GC */ 3727 #endif /* ERROR_CHECK_GC */
4420 3728
4421 #ifdef MC_ALLOC 3729 #ifdef NEW_GC
4422 free_lrecord (cons); 3730 free_lrecord (cons);
4423 #else /* not MC_ALLOC */ 3731 #else /* not NEW_GC */
4424 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, Lisp_Cons, ptr); 3732 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (cons, Lisp_Cons, ptr);
4425 #endif /* not MC_ALLOC */ 3733 #endif /* not NEW_GC */
4426 } 3734 }
4427 3735
4428 /* explicitly free a list. You **must make sure** that you have 3736 /* explicitly free a list. You **must make sure** that you have
4429 created all the cons cells that make up this list and that there 3737 created all the cons cells that make up this list and that there
4430 are no pointers to any of these cons cells anywhere else. If there 3738 are no pointers to any of these cons cells anywhere else. If there
4458 free_cons (XCAR (rest)); 3766 free_cons (XCAR (rest));
4459 free_cons (rest); 3767 free_cons (rest);
4460 } 3768 }
4461 } 3769 }
4462 3770
4463 #ifndef MC_ALLOC 3771 #ifndef NEW_GC
4464 static void 3772 static void
4465 sweep_compiled_functions (void) 3773 sweep_compiled_functions (void)
4466 { 3774 {
4467 #define UNMARK_compiled_function(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3775 #define UNMARK_compiled_function(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4468 #define ADDITIONAL_FREE_compiled_function(ptr) \ 3776 #define ADDITIONAL_FREE_compiled_function(ptr) \
4537 #define UNMARK_event(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3845 #define UNMARK_event(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4538 #define ADDITIONAL_FREE_event(ptr) 3846 #define ADDITIONAL_FREE_event(ptr)
4539 3847
4540 SWEEP_FIXED_TYPE_BLOCK (event, Lisp_Event); 3848 SWEEP_FIXED_TYPE_BLOCK (event, Lisp_Event);
4541 } 3849 }
4542 #endif /* not MC_ALLOC */ 3850 #endif /* not NEW_GC */
4543 3851
4544 #ifdef EVENT_DATA_AS_OBJECTS 3852 #ifdef EVENT_DATA_AS_OBJECTS
4545 3853
4546 #ifndef MC_ALLOC 3854 #ifndef NEW_GC
4547 static void 3855 static void
4548 sweep_key_data (void) 3856 sweep_key_data (void)
4549 { 3857 {
4550 #define UNMARK_key_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3858 #define UNMARK_key_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4551 #define ADDITIONAL_FREE_key_data(ptr) 3859 #define ADDITIONAL_FREE_key_data(ptr)
4552 3860
4553 SWEEP_FIXED_TYPE_BLOCK (key_data, Lisp_Key_Data); 3861 SWEEP_FIXED_TYPE_BLOCK (key_data, Lisp_Key_Data);
4554 } 3862 }
4555 #endif /* not MC_ALLOC */ 3863 #endif /* not NEW_GC */
4556 3864
4557 void 3865 void
4558 free_key_data (Lisp_Object ptr) 3866 free_key_data (Lisp_Object ptr)
4559 { 3867 {
4560 #ifdef MC_ALLOC 3868 #ifdef NEW_GC
4561 free_lrecord (ptr); 3869 free_lrecord (ptr);
4562 #else /* not MC_ALLOC */ 3870 #else /* not NEW_GC */
4563 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (key_data, Lisp_Key_Data, XKEY_DATA (ptr)); 3871 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (key_data, Lisp_Key_Data, XKEY_DATA (ptr));
4564 #endif /* not MC_ALLOC */ 3872 #endif /* not NEW_GC */
4565 } 3873 }
4566 3874
4567 #ifndef MC_ALLOC 3875 #ifndef NEW_GC
4568 static void 3876 static void
4569 sweep_button_data (void) 3877 sweep_button_data (void)
4570 { 3878 {
4571 #define UNMARK_button_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3879 #define UNMARK_button_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4572 #define ADDITIONAL_FREE_button_data(ptr) 3880 #define ADDITIONAL_FREE_button_data(ptr)
4573 3881
4574 SWEEP_FIXED_TYPE_BLOCK (button_data, Lisp_Button_Data); 3882 SWEEP_FIXED_TYPE_BLOCK (button_data, Lisp_Button_Data);
4575 } 3883 }
4576 #endif /* not MC_ALLOC */ 3884 #endif /* not NEW_GC */
4577 3885
4578 void 3886 void
4579 free_button_data (Lisp_Object ptr) 3887 free_button_data (Lisp_Object ptr)
4580 { 3888 {
4581 #ifdef MC_ALLOC 3889 #ifdef NEW_GC
4582 free_lrecord (ptr); 3890 free_lrecord (ptr);
4583 #else /* not MC_ALLOC */ 3891 #else /* not NEW_GC */
4584 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (button_data, Lisp_Button_Data, XBUTTON_DATA (ptr)); 3892 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (button_data, Lisp_Button_Data, XBUTTON_DATA (ptr));
4585 #endif /* not MC_ALLOC */ 3893 #endif /* not NEW_GC */
4586 } 3894 }
4587 3895
4588 #ifndef MC_ALLOC 3896 #ifndef NEW_GC
4589 static void 3897 static void
4590 sweep_motion_data (void) 3898 sweep_motion_data (void)
4591 { 3899 {
4592 #define UNMARK_motion_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3900 #define UNMARK_motion_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4593 #define ADDITIONAL_FREE_motion_data(ptr) 3901 #define ADDITIONAL_FREE_motion_data(ptr)
4594 3902
4595 SWEEP_FIXED_TYPE_BLOCK (motion_data, Lisp_Motion_Data); 3903 SWEEP_FIXED_TYPE_BLOCK (motion_data, Lisp_Motion_Data);
4596 } 3904 }
4597 #endif /* not MC_ALLOC */ 3905 #endif /* not NEW_GC */
4598 3906
4599 void 3907 void
4600 free_motion_data (Lisp_Object ptr) 3908 free_motion_data (Lisp_Object ptr)
4601 { 3909 {
4602 #ifdef MC_ALLOC 3910 #ifdef NEW_GC
4603 free_lrecord (ptr); 3911 free_lrecord (ptr);
4604 #else /* not MC_ALLOC */ 3912 #else /* not NEW_GC */
4605 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (motion_data, Lisp_Motion_Data, XMOTION_DATA (ptr)); 3913 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (motion_data, Lisp_Motion_Data, XMOTION_DATA (ptr));
4606 #endif /* not MC_ALLOC */ 3914 #endif /* not NEW_GC */
4607 } 3915 }
4608 3916
4609 #ifndef MC_ALLOC 3917 #ifndef NEW_GC
4610 static void 3918 static void
4611 sweep_process_data (void) 3919 sweep_process_data (void)
4612 { 3920 {
4613 #define UNMARK_process_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3921 #define UNMARK_process_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4614 #define ADDITIONAL_FREE_process_data(ptr) 3922 #define ADDITIONAL_FREE_process_data(ptr)
4615 3923
4616 SWEEP_FIXED_TYPE_BLOCK (process_data, Lisp_Process_Data); 3924 SWEEP_FIXED_TYPE_BLOCK (process_data, Lisp_Process_Data);
4617 } 3925 }
4618 #endif /* not MC_ALLOC */ 3926 #endif /* not NEW_GC */
4619 3927
4620 void 3928 void
4621 free_process_data (Lisp_Object ptr) 3929 free_process_data (Lisp_Object ptr)
4622 { 3930 {
4623 #ifdef MC_ALLOC 3931 #ifdef NEW_GC
4624 free_lrecord (ptr); 3932 free_lrecord (ptr);
4625 #else /* not MC_ALLOC */ 3933 #else /* not NEW_GC */
4626 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (process_data, Lisp_Process_Data, XPROCESS_DATA (ptr)); 3934 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (process_data, Lisp_Process_Data, XPROCESS_DATA (ptr));
4627 #endif /* not MC_ALLOC */ 3935 #endif /* not NEW_GC */
4628 } 3936 }
4629 3937
4630 #ifndef MC_ALLOC 3938 #ifndef NEW_GC
4631 static void 3939 static void
4632 sweep_timeout_data (void) 3940 sweep_timeout_data (void)
4633 { 3941 {
4634 #define UNMARK_timeout_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3942 #define UNMARK_timeout_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4635 #define ADDITIONAL_FREE_timeout_data(ptr) 3943 #define ADDITIONAL_FREE_timeout_data(ptr)
4636 3944
4637 SWEEP_FIXED_TYPE_BLOCK (timeout_data, Lisp_Timeout_Data); 3945 SWEEP_FIXED_TYPE_BLOCK (timeout_data, Lisp_Timeout_Data);
4638 } 3946 }
4639 #endif /* not MC_ALLOC */ 3947 #endif /* not NEW_GC */
4640 3948
4641 void 3949 void
4642 free_timeout_data (Lisp_Object ptr) 3950 free_timeout_data (Lisp_Object ptr)
4643 { 3951 {
4644 #ifdef MC_ALLOC 3952 #ifdef NEW_GC
4645 free_lrecord (ptr); 3953 free_lrecord (ptr);
4646 #else /* not MC_ALLOC */ 3954 #else /* not NEW_GC */
4647 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (timeout_data, Lisp_Timeout_Data, XTIMEOUT_DATA (ptr)); 3955 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (timeout_data, Lisp_Timeout_Data, XTIMEOUT_DATA (ptr));
4648 #endif /* not MC_ALLOC */ 3956 #endif /* not NEW_GC */
4649 } 3957 }
4650 3958
4651 #ifndef MC_ALLOC 3959 #ifndef NEW_GC
4652 static void 3960 static void
4653 sweep_magic_data (void) 3961 sweep_magic_data (void)
4654 { 3962 {
4655 #define UNMARK_magic_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3963 #define UNMARK_magic_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4656 #define ADDITIONAL_FREE_magic_data(ptr) 3964 #define ADDITIONAL_FREE_magic_data(ptr)
4657 3965
4658 SWEEP_FIXED_TYPE_BLOCK (magic_data, Lisp_Magic_Data); 3966 SWEEP_FIXED_TYPE_BLOCK (magic_data, Lisp_Magic_Data);
4659 } 3967 }
4660 #endif /* not MC_ALLOC */ 3968 #endif /* not NEW_GC */
4661 3969
4662 void 3970 void
4663 free_magic_data (Lisp_Object ptr) 3971 free_magic_data (Lisp_Object ptr)
4664 { 3972 {
4665 #ifdef MC_ALLOC 3973 #ifdef NEW_GC
4666 free_lrecord (ptr); 3974 free_lrecord (ptr);
4667 #else /* not MC_ALLOC */ 3975 #else /* not NEW_GC */
4668 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_data, Lisp_Magic_Data, XMAGIC_DATA (ptr)); 3976 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_data, Lisp_Magic_Data, XMAGIC_DATA (ptr));
4669 #endif /* not MC_ALLOC */ 3977 #endif /* not NEW_GC */
4670 } 3978 }
4671 3979
4672 #ifndef MC_ALLOC 3980 #ifndef NEW_GC
4673 static void 3981 static void
4674 sweep_magic_eval_data (void) 3982 sweep_magic_eval_data (void)
4675 { 3983 {
4676 #define UNMARK_magic_eval_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 3984 #define UNMARK_magic_eval_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4677 #define ADDITIONAL_FREE_magic_eval_data(ptr) 3985 #define ADDITIONAL_FREE_magic_eval_data(ptr)
4678 3986
4679 SWEEP_FIXED_TYPE_BLOCK (magic_eval_data, Lisp_Magic_Eval_Data); 3987 SWEEP_FIXED_TYPE_BLOCK (magic_eval_data, Lisp_Magic_Eval_Data);
4680 } 3988 }
4681 #endif /* not MC_ALLOC */ 3989 #endif /* not NEW_GC */
4682 3990
4683 void 3991 void
4684 free_magic_eval_data (Lisp_Object ptr) 3992 free_magic_eval_data (Lisp_Object ptr)
4685 { 3993 {
4686 #ifdef MC_ALLOC 3994 #ifdef NEW_GC
4687 free_lrecord (ptr); 3995 free_lrecord (ptr);
4688 #else /* not MC_ALLOC */ 3996 #else /* not NEW_GC */
4689 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_eval_data, Lisp_Magic_Eval_Data, XMAGIC_EVAL_DATA (ptr)); 3997 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (magic_eval_data, Lisp_Magic_Eval_Data, XMAGIC_EVAL_DATA (ptr));
4690 #endif /* not MC_ALLOC */ 3998 #endif /* not NEW_GC */
4691 } 3999 }
4692 4000
4693 #ifndef MC_ALLOC 4001 #ifndef NEW_GC
4694 static void 4002 static void
4695 sweep_eval_data (void) 4003 sweep_eval_data (void)
4696 { 4004 {
4697 #define UNMARK_eval_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 4005 #define UNMARK_eval_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4698 #define ADDITIONAL_FREE_eval_data(ptr) 4006 #define ADDITIONAL_FREE_eval_data(ptr)
4699 4007
4700 SWEEP_FIXED_TYPE_BLOCK (eval_data, Lisp_Eval_Data); 4008 SWEEP_FIXED_TYPE_BLOCK (eval_data, Lisp_Eval_Data);
4701 } 4009 }
4702 #endif /* not MC_ALLOC */ 4010 #endif /* not NEW_GC */
4703 4011
4704 void 4012 void
4705 free_eval_data (Lisp_Object ptr) 4013 free_eval_data (Lisp_Object ptr)
4706 { 4014 {
4707 #ifdef MC_ALLOC 4015 #ifdef NEW_GC
4708 free_lrecord (ptr); 4016 free_lrecord (ptr);
4709 #else /* not MC_ALLOC */ 4017 #else /* not NEW_GC */
4710 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (eval_data, Lisp_Eval_Data, XEVAL_DATA (ptr)); 4018 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (eval_data, Lisp_Eval_Data, XEVAL_DATA (ptr));
4711 #endif /* not MC_ALLOC */ 4019 #endif /* not NEW_GC */
4712 } 4020 }
4713 4021
4714 #ifndef MC_ALLOC 4022 #ifndef NEW_GC
4715 static void 4023 static void
4716 sweep_misc_user_data (void) 4024 sweep_misc_user_data (void)
4717 { 4025 {
4718 #define UNMARK_misc_user_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 4026 #define UNMARK_misc_user_data(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4719 #define ADDITIONAL_FREE_misc_user_data(ptr) 4027 #define ADDITIONAL_FREE_misc_user_data(ptr)
4720 4028
4721 SWEEP_FIXED_TYPE_BLOCK (misc_user_data, Lisp_Misc_User_Data); 4029 SWEEP_FIXED_TYPE_BLOCK (misc_user_data, Lisp_Misc_User_Data);
4722 } 4030 }
4723 #endif /* not MC_ALLOC */ 4031 #endif /* not NEW_GC */
4724 4032
4725 void 4033 void
4726 free_misc_user_data (Lisp_Object ptr) 4034 free_misc_user_data (Lisp_Object ptr)
4727 { 4035 {
4728 #ifdef MC_ALLOC 4036 #ifdef NEW_GC
4729 free_lrecord (ptr); 4037 free_lrecord (ptr);
4730 #else /* not MC_ALLOC */ 4038 #else /* not NEW_GC */
4731 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (misc_user_data, Lisp_Misc_User_Data, XMISC_USER_DATA (ptr)); 4039 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (misc_user_data, Lisp_Misc_User_Data, XMISC_USER_DATA (ptr));
4732 #endif /* not MC_ALLOC */ 4040 #endif /* not NEW_GC */
4733 } 4041 }
4734 4042
4735 #endif /* EVENT_DATA_AS_OBJECTS */ 4043 #endif /* EVENT_DATA_AS_OBJECTS */
4736 4044
4737 #ifndef MC_ALLOC 4045 #ifndef NEW_GC
4738 static void 4046 static void
4739 sweep_markers (void) 4047 sweep_markers (void)
4740 { 4048 {
4741 #define UNMARK_marker(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader)) 4049 #define UNMARK_marker(ptr) UNMARK_RECORD_HEADER (&((ptr)->lheader))
4742 #define ADDITIONAL_FREE_marker(ptr) \ 4050 #define ADDITIONAL_FREE_marker(ptr) \
4745 unchain_marker (tem); \ 4053 unchain_marker (tem); \
4746 } while (0) 4054 } while (0)
4747 4055
4748 SWEEP_FIXED_TYPE_BLOCK (marker, Lisp_Marker); 4056 SWEEP_FIXED_TYPE_BLOCK (marker, Lisp_Marker);
4749 } 4057 }
4750 #endif /* not MC_ALLOC */ 4058 #endif /* not NEW_GC */
4751 4059
4752 /* Explicitly free a marker. */ 4060 /* Explicitly free a marker. */
4753 void 4061 void
4754 free_marker (Lisp_Object ptr) 4062 free_marker (Lisp_Object ptr)
4755 { 4063 {
4756 #ifdef MC_ALLOC 4064 #ifdef NEW_GC
4757 free_lrecord (ptr); 4065 free_lrecord (ptr);
4758 #else /* not MC_ALLOC */ 4066 #else /* not NEW_GC */
4759 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, XMARKER (ptr)); 4067 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, XMARKER (ptr));
4760 #endif /* not MC_ALLOC */ 4068 #endif /* not NEW_GC */
4761 } 4069 }
4762 4070
4763 4071
4764 #if defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) 4072 #if defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY)
4765 4073
4807 } 4115 }
4808 } 4116 }
4809 4117
4810 #endif /* defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) */ 4118 #endif /* defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) */
4811 4119
4120 #ifndef NEW_GC
4812 /* Compactify string chars, relocating the reference to each -- 4121 /* Compactify string chars, relocating the reference to each --
4813 free any empty string_chars_block we see. */ 4122 free any empty string_chars_block we see. */
4814 static void 4123 void
4815 compact_string_chars (void) 4124 compact_string_chars (void)
4816 { 4125 {
4817 struct string_chars_block *to_sb = first_string_chars_block; 4126 struct string_chars_block *to_sb = first_string_chars_block;
4818 int to_pos = 0; 4127 int to_pos = 0;
4819 struct string_chars_block *from_sb; 4128 struct string_chars_block *from_sb;
4905 current_string_chars_block = to_sb; 4214 current_string_chars_block = to_sb;
4906 current_string_chars_block->pos = to_pos; 4215 current_string_chars_block->pos = to_pos;
4907 current_string_chars_block->next = 0; 4216 current_string_chars_block->next = 0;
4908 } 4217 }
4909 } 4218 }
4910 4219 #endif /* not NEW_GC */
4911 #ifndef MC_ALLOC 4220
4221 #ifndef NEW_GC
4912 #if 1 /* Hack to debug missing purecopy's */ 4222 #if 1 /* Hack to debug missing purecopy's */
4913 static int debug_string_purity; 4223 static int debug_string_purity;
4914 4224
4915 static void 4225 static void
4916 debug_string_purity_print (Lisp_Object p) 4226 debug_string_purity_print (Lisp_Object p)
4929 stderr_out ("%c", ch); 4239 stderr_out ("%c", ch);
4930 } 4240 }
4931 stderr_out ("\"\n"); 4241 stderr_out ("\"\n");
4932 } 4242 }
4933 #endif /* 1 */ 4243 #endif /* 1 */
4934 #endif /* not MC_ALLOC */ 4244 #endif /* not NEW_GC */
4935 4245
4936 #ifndef MC_ALLOC 4246 #ifndef NEW_GC
4937 static void 4247 static void
4938 sweep_strings (void) 4248 sweep_strings (void)
4939 { 4249 {
4940 int num_small_used = 0; 4250 int num_small_used = 0;
4941 Bytecount num_small_bytes = 0, num_bytes = 0; 4251 Bytecount num_small_bytes = 0, num_bytes = 0;
4964 4274
4965 gc_count_num_short_string_in_use = num_small_used; 4275 gc_count_num_short_string_in_use = num_small_used;
4966 gc_count_string_total_size = num_bytes; 4276 gc_count_string_total_size = num_bytes;
4967 gc_count_short_string_total_size = num_small_bytes; 4277 gc_count_short_string_total_size = num_small_bytes;
4968 } 4278 }
4969 #endif /* not MC_ALLOC */ 4279 #endif /* not NEW_GC */
4970 4280
4971 /* I hate duplicating all this crap! */ 4281 #ifndef NEW_GC
4972 int 4282 void
4973 marked_p (Lisp_Object obj) 4283 gc_sweep_1 (void)
4974 { 4284 {
4975 /* Checks we used to perform. */
4976 /* if (EQ (obj, Qnull_pointer)) return 1; */
4977 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */
4978 /* if (PURIFIED (XPNTR (obj))) return 1; */
4979
4980 if (XTYPE (obj) == Lisp_Type_Record)
4981 {
4982 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
4983
4984 GC_CHECK_LHEADER_INVARIANTS (lheader);
4985
4986 return MARKED_RECORD_HEADER_P (lheader);
4987 }
4988 return 1;
4989 }
4990
4991 static void
4992 gc_sweep (void)
4993 {
4994 #ifdef MC_ALLOC
4995 compact_string_chars ();
4996 mc_finalize ();
4997 mc_sweep ();
4998 #else /* not MC_ALLOC */
4999 /* Free all unmarked records. Do this at the very beginning, 4285 /* Free all unmarked records. Do this at the very beginning,
5000 before anything else, so that the finalize methods can safely 4286 before anything else, so that the finalize methods can safely
5001 examine items in the objects. sweep_lcrecords_1() makes 4287 examine items in the objects. sweep_lcrecords_1() makes
5002 sure to call all the finalize methods *before* freeing anything, 4288 sure to call all the finalize methods *before* freeing anything,
5003 to complete the safety. */ 4289 to complete the safety. */
5068 sweep_magic_data (); 4354 sweep_magic_data ();
5069 sweep_magic_eval_data (); 4355 sweep_magic_eval_data ();
5070 sweep_eval_data (); 4356 sweep_eval_data ();
5071 sweep_misc_user_data (); 4357 sweep_misc_user_data ();
5072 #endif /* EVENT_DATA_AS_OBJECTS */ 4358 #endif /* EVENT_DATA_AS_OBJECTS */
5073 #endif /* not MC_ALLOC */ 4359 #endif /* not NEW_GC */
5074 4360
5075 #ifndef MC_ALLOC 4361 #ifndef NEW_GC
5076 #ifdef PDUMP 4362 #ifdef PDUMP
5077 pdump_objects_unmark (); 4363 pdump_objects_unmark ();
5078 #endif 4364 #endif
5079 #endif /* not MC_ALLOC */ 4365 }
5080 } 4366 #endif /* not NEW_GC */
5081 4367
5082 /* Clearing for disksave. */ 4368 /* Clearing for disksave. */
5083 4369
5084 void 4370 void
5085 disksave_object_finalization (void) 4371 disksave_object_finalization (void)
5113 defined(LOADHIST_BUILTIN)) 4399 defined(LOADHIST_BUILTIN))
5114 Vload_history = Qnil; 4400 Vload_history = Qnil;
5115 #endif 4401 #endif
5116 Vshell_file_name = Qnil; 4402 Vshell_file_name = Qnil;
5117 4403
4404 #ifdef NEW_GC
4405 gc_full ();
4406 #else /* not NEW_GC */
5118 garbage_collect_1 (); 4407 garbage_collect_1 ();
4408 #endif /* not NEW_GC */
5119 4409
5120 /* Run the disksave finalization methods of all live objects. */ 4410 /* Run the disksave finalization methods of all live objects. */
5121 disksave_object_finalization_1 (); 4411 disksave_object_finalization_1 ();
5122 4412
4413 #ifndef NEW_GC
5123 /* Zero out the uninitialized (really, unused) part of the containers 4414 /* Zero out the uninitialized (really, unused) part of the containers
5124 for the live strings. */ 4415 for the live strings. */
5125 { 4416 {
5126 struct string_chars_block *scb; 4417 struct string_chars_block *scb;
5127 for (scb = first_string_chars_block; scb; scb = scb->next) 4418 for (scb = first_string_chars_block; scb; scb = scb->next)
5134 /* from the block's fill ptr to the end */ 4425 /* from the block's fill ptr to the end */
5135 memset ((scb->string_chars + scb->pos), 0, count); 4426 memset ((scb->string_chars + scb->pos), 0, count);
5136 } 4427 }
5137 } 4428 }
5138 } 4429 }
4430 #endif /* not NEW_GC */
5139 4431
5140 /* There, that ought to be enough... */ 4432 /* There, that ought to be enough... */
5141 4433
5142 }
5143
5144
5145 int
5146 begin_gc_forbidden (void)
5147 {
5148 return internal_bind_int (&gc_currently_forbidden, 1);
5149 }
5150
5151 void
5152 end_gc_forbidden (int count)
5153 {
5154 unbind_to (count);
5155 }
5156
5157 /* Maybe we want to use this when doing a "panic" gc after memory_full()? */
5158 static int gc_hooks_inhibited;
5159
5160 struct post_gc_action
5161 {
5162 void (*fun) (void *);
5163 void *arg;
5164 };
5165
5166 typedef struct post_gc_action post_gc_action;
5167
5168 typedef struct
5169 {
5170 Dynarr_declare (post_gc_action);
5171 } post_gc_action_dynarr;
5172
5173 static post_gc_action_dynarr *post_gc_actions;
5174
5175 /* Register an action to be called at the end of GC.
5176 gc_in_progress is 0 when this is called.
5177 This is used when it is discovered that an action needs to be taken,
5178 but it's during GC, so it's not safe. (e.g. in a finalize method.)
5179
5180 As a general rule, do not use Lisp objects here.
5181 And NEVER signal an error.
5182 */
5183
5184 void
5185 register_post_gc_action (void (*fun) (void *), void *arg)
5186 {
5187 post_gc_action action;
5188
5189 if (!post_gc_actions)
5190 post_gc_actions = Dynarr_new (post_gc_action);
5191
5192 action.fun = fun;
5193 action.arg = arg;
5194
5195 Dynarr_add (post_gc_actions, action);
5196 }
5197
5198 static void
5199 run_post_gc_actions (void)
5200 {
5201 int i;
5202
5203 if (post_gc_actions)
5204 {
5205 for (i = 0; i < Dynarr_length (post_gc_actions); i++)
5206 {
5207 post_gc_action action = Dynarr_at (post_gc_actions, i);
5208 (action.fun) (action.arg);
5209 }
5210
5211 Dynarr_reset (post_gc_actions);
5212 }
5213 }
5214
5215
5216 void
5217 garbage_collect_1 (void)
5218 {
5219 #if MAX_SAVE_STACK > 0
5220 char stack_top_variable;
5221 extern char *stack_bottom;
5222 #endif
5223 struct frame *f;
5224 int speccount;
5225 int cursor_changed;
5226 Lisp_Object pre_gc_cursor;
5227 struct gcpro gcpro1;
5228 PROFILE_DECLARE ();
5229
5230 assert (!in_display || gc_currently_forbidden);
5231
5232 if (gc_in_progress
5233 || gc_currently_forbidden
5234 || in_display
5235 || preparing_for_armageddon)
5236 return;
5237
5238 PROFILE_RECORD_ENTERING_SECTION (QSin_garbage_collection);
5239
5240 /* We used to call selected_frame() here.
5241
5242 The following functions cannot be called inside GC
5243 so we move to after the above tests. */
5244 {
5245 Lisp_Object frame;
5246 Lisp_Object device = Fselected_device (Qnil);
5247 if (NILP (device)) /* Could happen during startup, eg. if always_gc */
5248 return;
5249 frame = Fselected_frame (device);
5250 if (NILP (frame))
5251 invalid_state ("No frames exist on device", device);
5252 f = XFRAME (frame);
5253 }
5254
5255 pre_gc_cursor = Qnil;
5256 cursor_changed = 0;
5257
5258 GCPRO1 (pre_gc_cursor);
5259
5260 /* Very important to prevent GC during any of the following
5261 stuff that might run Lisp code; otherwise, we'll likely
5262 have infinite GC recursion. */
5263 speccount = begin_gc_forbidden ();
5264
5265 need_to_signal_post_gc = 0;
5266 recompute_funcall_allocation_flag ();
5267
5268 if (!gc_hooks_inhibited)
5269 run_hook_trapping_problems
5270 (Qgarbage_collecting, Qpre_gc_hook,
5271 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION);
5272
5273 /* Now show the GC cursor/message. */
5274 if (!noninteractive)
5275 {
5276 if (FRAME_WIN_P (f))
5277 {
5278 Lisp_Object frame = wrap_frame (f);
5279 Lisp_Object cursor = glyph_image_instance (Vgc_pointer_glyph,
5280 FRAME_SELECTED_WINDOW (f),
5281 ERROR_ME_NOT, 1);
5282 pre_gc_cursor = f->pointer;
5283 if (POINTER_IMAGE_INSTANCEP (cursor)
5284 /* don't change if we don't know how to change back. */
5285 && POINTER_IMAGE_INSTANCEP (pre_gc_cursor))
5286 {
5287 cursor_changed = 1;
5288 Fset_frame_pointer (frame, cursor);
5289 }
5290 }
5291
5292 /* Don't print messages to the stream device. */
5293 if (!cursor_changed && !FRAME_STREAM_P (f))
5294 {
5295 if (garbage_collection_messages)
5296 {
5297 Lisp_Object args[2], whole_msg;
5298 args[0] = (STRINGP (Vgc_message) ? Vgc_message :
5299 build_msg_string (gc_default_message));
5300 args[1] = build_string ("...");
5301 whole_msg = Fconcat (2, args);
5302 echo_area_message (f, (Ibyte *) 0, whole_msg, 0, -1,
5303 Qgarbage_collecting);
5304 }
5305 }
5306 }
5307
5308 /***** Now we actually start the garbage collection. */
5309
5310 gc_in_progress = 1;
5311 inhibit_non_essential_conversion_operations = 1;
5312
5313 gc_generation_number[0]++;
5314
5315 #if MAX_SAVE_STACK > 0
5316
5317 /* Save a copy of the contents of the stack, for debugging. */
5318 if (!purify_flag)
5319 {
5320 /* Static buffer in which we save a copy of the C stack at each GC. */
5321 static char *stack_copy;
5322 static Bytecount stack_copy_size;
5323
5324 ptrdiff_t stack_diff = &stack_top_variable - stack_bottom;
5325 Bytecount stack_size = (stack_diff > 0 ? stack_diff : -stack_diff);
5326 if (stack_size < MAX_SAVE_STACK)
5327 {
5328 if (stack_copy_size < stack_size)
5329 {
5330 stack_copy = (char *) xrealloc (stack_copy, stack_size);
5331 stack_copy_size = stack_size;
5332 }
5333
5334 memcpy (stack_copy,
5335 stack_diff > 0 ? stack_bottom : &stack_top_variable,
5336 stack_size);
5337 }
5338 }
5339 #endif /* MAX_SAVE_STACK > 0 */
5340
5341 /* Do some totally ad-hoc resource clearing. */
5342 /* #### generalize this? */
5343 clear_event_resource ();
5344 cleanup_specifiers ();
5345 cleanup_buffer_undo_lists ();
5346
5347 /* Mark all the special slots that serve as the roots of accessibility. */
5348
5349 #ifdef USE_KKCC
5350 /* initialize kkcc stack */
5351 kkcc_gc_stack_init();
5352 #define mark_object(obj) kkcc_gc_stack_push_lisp_object (obj, 0, -1)
5353 #endif /* USE_KKCC */
5354
5355 { /* staticpro() */
5356 Lisp_Object **p = Dynarr_begin (staticpros);
5357 Elemcount count;
5358 for (count = Dynarr_length (staticpros); count; count--)
5359 mark_object (**p++);
5360 }
5361
5362 { /* staticpro_nodump() */
5363 Lisp_Object **p = Dynarr_begin (staticpros_nodump);
5364 Elemcount count;
5365 for (count = Dynarr_length (staticpros_nodump); count; count--)
5366 mark_object (**p++);
5367 }
5368
5369 #ifdef MC_ALLOC
5370 { /* mcpro () */
5371 Lisp_Object *p = Dynarr_begin (mcpros);
5372 Elemcount count;
5373 for (count = Dynarr_length (mcpros); count; count--)
5374 mark_object (*p++);
5375 }
5376 #endif /* MC_ALLOC */
5377
5378 { /* GCPRO() */
5379 struct gcpro *tail;
5380 int i;
5381 for (tail = gcprolist; tail; tail = tail->next)
5382 for (i = 0; i < tail->nvars; i++)
5383 mark_object (tail->var[i]);
5384 }
5385
5386 { /* specbind() */
5387 struct specbinding *bind;
5388 for (bind = specpdl; bind != specpdl_ptr; bind++)
5389 {
5390 mark_object (bind->symbol);
5391 mark_object (bind->old_value);
5392 }
5393 }
5394
5395 {
5396 struct catchtag *c;
5397 for (c = catchlist; c; c = c->next)
5398 {
5399 mark_object (c->tag);
5400 mark_object (c->val);
5401 mark_object (c->actual_tag);
5402 mark_object (c->backtrace);
5403 }
5404 }
5405
5406 {
5407 struct backtrace *backlist;
5408 for (backlist = backtrace_list; backlist; backlist = backlist->next)
5409 {
5410 int nargs = backlist->nargs;
5411 int i;
5412
5413 mark_object (*backlist->function);
5414 if (nargs < 0 /* nargs == UNEVALLED || nargs == MANY */
5415 /* might be fake (internal profiling entry) */
5416 && backlist->args)
5417 mark_object (backlist->args[0]);
5418 else
5419 for (i = 0; i < nargs; i++)
5420 mark_object (backlist->args[i]);
5421 }
5422 }
5423
5424 mark_profiling_info ();
5425
5426 /* OK, now do the after-mark stuff. This is for things that
5427 are only marked when something else is marked (e.g. weak hash tables).
5428 There may be complex dependencies between such objects -- e.g.
5429 a weak hash table might be unmarked, but after processing a later
5430 weak hash table, the former one might get marked. So we have to
5431 iterate until nothing more gets marked. */
5432 #ifdef USE_KKCC
5433 kkcc_marking ();
5434 #endif /* USE_KKCC */
5435 init_marking_ephemerons ();
5436 while (finish_marking_weak_hash_tables () > 0 ||
5437 finish_marking_weak_lists () > 0 ||
5438 continue_marking_ephemerons () > 0)
5439 #ifdef USE_KKCC
5440 {
5441 kkcc_marking ();
5442 }
5443 #else /* NOT USE_KKCC */
5444 ;
5445 #endif /* USE_KKCC */
5446
5447 /* At this point, we know which objects need to be finalized: we
5448 still need to resurrect them */
5449
5450 while (finish_marking_ephemerons () > 0 ||
5451 finish_marking_weak_lists () > 0 ||
5452 finish_marking_weak_hash_tables () > 0)
5453 #ifdef USE_KKCC
5454 {
5455 kkcc_marking ();
5456 }
5457 kkcc_gc_stack_free ();
5458 #undef mark_object
5459 #else /* NOT USE_KKCC */
5460 ;
5461 #endif /* USE_KKCC */
5462
5463 /* And prune (this needs to be called after everything else has been
5464 marked and before we do any sweeping). */
5465 /* #### this is somewhat ad-hoc and should probably be an object
5466 method */
5467 prune_weak_hash_tables ();
5468 prune_weak_lists ();
5469 prune_specifiers ();
5470 prune_syntax_tables ();
5471
5472 prune_ephemerons ();
5473 prune_weak_boxes ();
5474
5475 gc_sweep ();
5476
5477 consing_since_gc = 0;
5478 #ifndef DEBUG_XEMACS
5479 /* Allow you to set it really fucking low if you really want ... */
5480 if (gc_cons_threshold < 10000)
5481 gc_cons_threshold = 10000;
5482 #endif
5483 recompute_need_to_garbage_collect ();
5484
5485 inhibit_non_essential_conversion_operations = 0;
5486 gc_in_progress = 0;
5487
5488 run_post_gc_actions ();
5489
5490 /******* End of garbage collection ********/
5491
5492 /* Now remove the GC cursor/message */
5493 if (!noninteractive)
5494 {
5495 if (cursor_changed)
5496 Fset_frame_pointer (wrap_frame (f), pre_gc_cursor);
5497 else if (!FRAME_STREAM_P (f))
5498 {
5499 /* Show "...done" only if the echo area would otherwise be empty. */
5500 if (NILP (clear_echo_area (selected_frame (),
5501 Qgarbage_collecting, 0)))
5502 {
5503 if (garbage_collection_messages)
5504 {
5505 Lisp_Object args[2], whole_msg;
5506 args[0] = (STRINGP (Vgc_message) ? Vgc_message :
5507 build_msg_string (gc_default_message));
5508 args[1] = build_msg_string ("... done");
5509 whole_msg = Fconcat (2, args);
5510 echo_area_message (selected_frame (), (Ibyte *) 0,
5511 whole_msg, 0, -1,
5512 Qgarbage_collecting);
5513 }
5514 }
5515 }
5516 }
5517
5518 /* now stop inhibiting GC */
5519 unbind_to (speccount);
5520
5521 #ifndef MC_ALLOC
5522 if (!breathing_space)
5523 {
5524 breathing_space = malloc (4096 - MALLOC_OVERHEAD);
5525 }
5526 #endif /* not MC_ALLOC */
5527
5528 UNGCPRO;
5529
5530 need_to_signal_post_gc = 1;
5531 funcall_allocation_flag = 1;
5532
5533 PROFILE_RECORD_EXITING_SECTION (QSin_garbage_collection);
5534
5535 return;
5536 } 4434 }
5537 4435
5538 #ifdef ALLOC_TYPE_STATS 4436 #ifdef ALLOC_TYPE_STATS
5539 4437
5540 static Lisp_Object 4438 static Lisp_Object
5551 { 4449 {
5552 Lisp_Object pl = Qnil; 4450 Lisp_Object pl = Qnil;
5553 int i; 4451 int i;
5554 EMACS_INT tgu_val = 0; 4452 EMACS_INT tgu_val = 0;
5555 4453
5556 #ifdef MC_ALLOC 4454 #ifdef NEW_GC
5557 4455
5558 for (i = 0; i < (countof (lrecord_implementations_table) 4456 for (i = 0; i < countof (lrecord_implementations_table); i++)
5559 + MODULE_DEFINABLE_TYPE_COUNT); i++)
5560 { 4457 {
5561 if (lrecord_stats[i].instances_in_use != 0) 4458 if (lrecord_stats[i].instances_in_use != 0)
5562 { 4459 {
5563 char buf [255]; 4460 char buf [255];
5564 const char *name = lrecord_implementations_table[i]->name; 4461 const char *name = lrecord_implementations_table[i]->name;
5585 else 4482 else
5586 sprintf (buf, "%ss-used", name); 4483 sprintf (buf, "%ss-used", name);
5587 pl = gc_plist_hack (buf, lrecord_stats[i].instances_in_use, pl); 4484 pl = gc_plist_hack (buf, lrecord_stats[i].instances_in_use, pl);
5588 } 4485 }
5589 } 4486 }
5590 pl = gc_plist_hack ("string-data-storage-including-overhead", 4487
5591 lrecord_string_data_bytes_in_use_including_overhead, pl); 4488 #else /* not NEW_GC */
5592 pl = gc_plist_hack ("string-data-storage-additional",
5593 lrecord_string_data_bytes_in_use, pl);
5594 pl = gc_plist_hack ("string-data-used",
5595 lrecord_string_data_instances_in_use, pl);
5596 tgu_val += lrecord_string_data_bytes_in_use_including_overhead;
5597
5598 #else /* not MC_ALLOC */
5599 4489
5600 #define HACK_O_MATIC(type, name, pl) do { \ 4490 #define HACK_O_MATIC(type, name, pl) do { \
5601 EMACS_INT s = 0; \ 4491 EMACS_INT s = 0; \
5602 struct type##_block *x = current_##type##_block; \ 4492 struct type##_block *x = current_##type##_block; \
5603 while (x) { s += sizeof (*x) + MALLOC_OVERHEAD; x = x->prev; } \ 4493 while (x) { s += sizeof (*x) + MALLOC_OVERHEAD; x = x->prev; } \
5695 pl = gc_plist_hack ("conses-free", gc_count_num_cons_freelist, pl); 4585 pl = gc_plist_hack ("conses-free", gc_count_num_cons_freelist, pl);
5696 pl = gc_plist_hack ("conses-used", gc_count_num_cons_in_use, pl); 4586 pl = gc_plist_hack ("conses-used", gc_count_num_cons_in_use, pl);
5697 4587
5698 #undef HACK_O_MATIC 4588 #undef HACK_O_MATIC
5699 4589
5700 #endif /* MC_ALLOC */ 4590 #endif /* NEW_GC */
5701 4591
5702 if (set_total_gc_usage) 4592 if (set_total_gc_usage)
5703 { 4593 {
5704 total_gc_usage = tgu_val; 4594 total_gc_usage = tgu_val;
5705 total_gc_usage_set = 1; 4595 total_gc_usage_set = 1;
5732 `gc-cons-threshold' bytes of Lisp data since previous garbage collection. 4622 `gc-cons-threshold' bytes of Lisp data since previous garbage collection.
5733 */ 4623 */
5734 ()) 4624 ())
5735 { 4625 {
5736 /* Record total usage for purposes of determining next GC */ 4626 /* Record total usage for purposes of determining next GC */
4627 #ifdef NEW_GC
4628 gc_full ();
4629 #else /* not NEW_GC */
5737 garbage_collect_1 (); 4630 garbage_collect_1 ();
4631 #endif /* not NEW_GC */
5738 4632
5739 /* This will get set to 1, and total_gc_usage computed, as part of the 4633 /* This will get set to 1, and total_gc_usage computed, as part of the
5740 call to object_memory_usage_stats() -- if ALLOC_TYPE_STATS is enabled. */ 4634 call to object_memory_usage_stats() -- if ALLOC_TYPE_STATS is enabled. */
5741 total_gc_usage_set = 0; 4635 total_gc_usage_set = 0;
5742 #ifdef ALLOC_TYPE_STATS 4636 #ifdef ALLOC_TYPE_STATS
5743 /* The things we do for backwards-compatibility */ 4637 /* The things we do for backwards-compatibility */
5744 #ifdef MC_ALLOC 4638 #ifdef NEW_GC
5745 return 4639 return
5746 list6 4640 list6
5747 (Fcons (make_int (lrecord_stats[lrecord_type_cons].instances_in_use), 4641 (Fcons (make_int (lrecord_stats[lrecord_type_cons].instances_in_use),
5748 make_int (lrecord_stats[lrecord_type_cons] 4642 make_int (lrecord_stats[lrecord_type_cons]
5749 .bytes_in_use_including_overhead)), 4643 .bytes_in_use_including_overhead)),
5756 make_int (lrecord_stats[lrecord_type_string] 4650 make_int (lrecord_stats[lrecord_type_string]
5757 .bytes_in_use_including_overhead), 4651 .bytes_in_use_including_overhead),
5758 make_int (lrecord_stats[lrecord_type_vector] 4652 make_int (lrecord_stats[lrecord_type_vector]
5759 .bytes_in_use_including_overhead), 4653 .bytes_in_use_including_overhead),
5760 object_memory_usage_stats (1)); 4654 object_memory_usage_stats (1));
5761 #else /* not MC_ALLOC */ 4655 #else /* not NEW_GC */
5762 return 4656 return
5763 list6 (Fcons (make_int (gc_count_num_cons_in_use), 4657 list6 (Fcons (make_int (gc_count_num_cons_in_use),
5764 make_int (gc_count_num_cons_freelist)), 4658 make_int (gc_count_num_cons_freelist)),
5765 Fcons (make_int (gc_count_num_symbol_in_use), 4659 Fcons (make_int (gc_count_num_symbol_in_use),
5766 make_int (gc_count_num_symbol_freelist)), 4660 make_int (gc_count_num_symbol_freelist)),
5768 make_int (gc_count_num_marker_freelist)), 4662 make_int (gc_count_num_marker_freelist)),
5769 make_int (gc_count_string_total_size), 4663 make_int (gc_count_string_total_size),
5770 make_int (lcrecord_stats[lrecord_type_vector].bytes_in_use + 4664 make_int (lcrecord_stats[lrecord_type_vector].bytes_in_use +
5771 lcrecord_stats[lrecord_type_vector].bytes_freed), 4665 lcrecord_stats[lrecord_type_vector].bytes_freed),
5772 object_memory_usage_stats (1)); 4666 object_memory_usage_stats (1));
5773 #endif /* not MC_ALLOC */ 4667 #endif /* not NEW_GC */
5774 #else /* not ALLOC_TYPE_STATS */ 4668 #else /* not ALLOC_TYPE_STATS */
5775 return Qnil; 4669 return Qnil;
5776 #endif /* ALLOC_TYPE_STATS */ 4670 #endif /* ALLOC_TYPE_STATS */
5777 } 4671 }
5778 4672
5831 need_to_garbage_collect || 4725 need_to_garbage_collect ||
5832 need_to_check_c_alloca || 4726 need_to_check_c_alloca ||
5833 need_to_signal_post_gc; 4727 need_to_signal_post_gc;
5834 } 4728 }
5835 4729
5836 /* True if it's time to garbage collect now. */
5837 static void
5838 recompute_need_to_garbage_collect (void)
5839 {
5840 if (always_gc)
5841 need_to_garbage_collect = 1;
5842 else
5843 need_to_garbage_collect =
5844 (consing_since_gc > gc_cons_threshold
5845 &&
5846 #if 0 /* #### implement this better */
5847 (100 * consing_since_gc) / total_data_usage () >=
5848 gc_cons_percentage
5849 #else
5850 (!total_gc_usage_set ||
5851 (100 * consing_since_gc) / total_gc_usage >=
5852 gc_cons_percentage)
5853 #endif
5854 );
5855 recompute_funcall_allocation_flag ();
5856 }
5857
5858 4730
5859 int 4731 int
5860 object_dead_p (Lisp_Object obj) 4732 object_dead_p (Lisp_Object obj)
5861 { 4733 {
5862 return ((BUFFERP (obj) && !BUFFER_LIVE_P (XBUFFER (obj))) || 4734 return ((BUFFERP (obj) && !BUFFER_LIVE_P (XBUFFER (obj))) ||
5906 malloced_storage_size (void *UNUSED (ptr), Bytecount claimed_size, 4778 malloced_storage_size (void *UNUSED (ptr), Bytecount claimed_size,
5907 struct overhead_stats *stats) 4779 struct overhead_stats *stats)
5908 { 4780 {
5909 Bytecount orig_claimed_size = claimed_size; 4781 Bytecount orig_claimed_size = claimed_size;
5910 4782
5911 #ifdef GNU_MALLOC 4783 #ifndef SYSTEM_MALLOC
5912 if (claimed_size < (Bytecount) (2 * sizeof (void *))) 4784 if (claimed_size < (Bytecount) (2 * sizeof (void *)))
5913 claimed_size = 2 * sizeof (void *); 4785 claimed_size = 2 * sizeof (void *);
5914 # ifdef SUNOS_LOCALTIME_BUG 4786 # ifdef SUNOS_LOCALTIME_BUG
5915 if (claimed_size < 16) 4787 if (claimed_size < 16)
5916 claimed_size = 16; 4788 claimed_size = 16;
5943 claimed_size += 4095; 4815 claimed_size += 4095;
5944 claimed_size &= ~4095; 4816 claimed_size &= ~4095;
5945 claimed_size += (claimed_size / 4096) * 3 * sizeof (size_t); 4817 claimed_size += (claimed_size / 4096) * 3 * sizeof (size_t);
5946 } 4818 }
5947 4819
5948 #elif defined (SYSTEM_MALLOC) 4820 #else
5949 4821
5950 if (claimed_size < 16) 4822 if (claimed_size < 16)
5951 claimed_size = 16; 4823 claimed_size = 16;
5952 claimed_size += 2 * sizeof (void *); 4824 claimed_size += 2 * sizeof (void *);
5953 4825
5954 #else /* old GNU allocator */ 4826 #endif /* system allocator */
5955
5956 # ifdef rcheck /* #### may not be defined here */
5957 claimed_size += 20;
5958 # else
5959 claimed_size += 8;
5960 # endif
5961 {
5962 /* fxg: rename log->log2 to supress gcc3 shadow warning */
5963 int log2 = 1;
5964
5965 /* compute the log base two, more or less, then use it to compute
5966 the block size needed. */
5967 claimed_size--;
5968 /* It's big, it's heavy, it's wood! */
5969 while ((claimed_size /= 2) != 0)
5970 ++log2;
5971 claimed_size = 1;
5972 /* It's better than bad, it's good! */
5973 while (log2 > 0)
5974 {
5975 claimed_size *= 2;
5976 log2--;
5977 }
5978 }
5979
5980 #endif /* old GNU allocator */
5981 4827
5982 if (stats) 4828 if (stats)
5983 { 4829 {
5984 stats->was_requested += orig_claimed_size; 4830 stats->was_requested += orig_claimed_size;
5985 stats->malloc_overhead += claimed_size - orig_claimed_size; 4831 stats->malloc_overhead += claimed_size - orig_claimed_size;
5986 } 4832 }
5987 return claimed_size; 4833 return claimed_size;
5988 } 4834 }
5989 4835
5990 #ifndef MC_ALLOC 4836 #ifndef NEW_GC
5991 Bytecount 4837 Bytecount
5992 fixed_type_block_overhead (Bytecount size) 4838 fixed_type_block_overhead (Bytecount size)
5993 { 4839 {
5994 Bytecount per_block = TYPE_ALLOC_SIZE (cons, unsigned char); 4840 Bytecount per_block = TYPE_ALLOC_SIZE (cons, unsigned char);
5995 Bytecount overhead = 0; 4841 Bytecount overhead = 0;
6001 } 4847 }
6002 if (rand () % per_block < size) 4848 if (rand () % per_block < size)
6003 overhead += sizeof (void *) + per_block - storage_size; 4849 overhead += sizeof (void *) + per_block - storage_size;
6004 return overhead; 4850 return overhead;
6005 } 4851 }
6006 #endif /* not MC_ALLOC */ 4852 #endif /* not NEW_GC */
6007 #endif /* MEMORY_USAGE_STATS */ 4853 #endif /* MEMORY_USAGE_STATS */
6008 4854
6009 4855
6010 /* Initialization */ 4856 /* Initialization */
6011 static void 4857 static void
6019 /* C guarantees that Qnull_pointer will be initialized to all 0 bits, 4865 /* C guarantees that Qnull_pointer will be initialized to all 0 bits,
6020 so the following is actually a no-op. */ 4866 so the following is actually a no-op. */
6021 Qnull_pointer = wrap_pointer_1 (0); 4867 Qnull_pointer = wrap_pointer_1 (0);
6022 #endif 4868 #endif
6023 4869
6024 gc_generation_number[0] = 0; 4870 #ifndef NEW_GC
6025 #ifndef MC_ALLOC
6026 breathing_space = 0; 4871 breathing_space = 0;
6027 #endif /* not MC_ALLOC */
6028 Vgc_message = Qzero;
6029 #ifndef MC_ALLOC
6030 all_lcrecords = 0; 4872 all_lcrecords = 0;
6031 #endif /* not MC_ALLOC */ 4873 #endif /* not NEW_GC */
6032 ignore_malloc_warnings = 1; 4874 ignore_malloc_warnings = 1;
6033 #ifdef DOUG_LEA_MALLOC 4875 #ifdef DOUG_LEA_MALLOC
6034 mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ 4876 mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */
6035 mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */ 4877 mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */
6036 #if 0 /* Moved to emacs.c */ 4878 #if 0 /* Moved to emacs.c */
6037 mallopt (M_MMAP_MAX, 64); /* max. number of mmap'ed areas */ 4879 mallopt (M_MMAP_MAX, 64); /* max. number of mmap'ed areas */
6038 #endif 4880 #endif
6039 #endif 4881 #endif
4882 #ifndef NEW_GC
6040 init_string_chars_alloc (); 4883 init_string_chars_alloc ();
6041 #ifndef MC_ALLOC
6042 init_string_alloc (); 4884 init_string_alloc ();
6043 init_string_chars_alloc (); 4885 init_string_chars_alloc ();
6044 init_cons_alloc (); 4886 init_cons_alloc ();
6045 init_symbol_alloc (); 4887 init_symbol_alloc ();
6046 init_compiled_function_alloc (); 4888 init_compiled_function_alloc ();
6066 init_magic_data_alloc (); 4908 init_magic_data_alloc ();
6067 init_magic_eval_data_alloc (); 4909 init_magic_eval_data_alloc ();
6068 init_eval_data_alloc (); 4910 init_eval_data_alloc ();
6069 init_misc_user_data_alloc (); 4911 init_misc_user_data_alloc ();
6070 #endif /* EVENT_DATA_AS_OBJECTS */ 4912 #endif /* EVENT_DATA_AS_OBJECTS */
6071 #endif /* not MC_ALLOC */ 4913 #endif /* not NEW_GC */
6072 4914
6073 ignore_malloc_warnings = 0; 4915 ignore_malloc_warnings = 0;
6074 4916
6075 if (staticpros_nodump) 4917 if (staticpros_nodump)
6076 Dynarr_free (staticpros_nodump); 4918 Dynarr_free (staticpros_nodump);
6081 Dynarr_free (staticpro_nodump_names); 4923 Dynarr_free (staticpro_nodump_names);
6082 staticpro_nodump_names = Dynarr_new2 (char_ptr_dynarr, char *); 4924 staticpro_nodump_names = Dynarr_new2 (char_ptr_dynarr, char *);
6083 Dynarr_resize (staticpro_nodump_names, 100); /* ditto */ 4925 Dynarr_resize (staticpro_nodump_names, 100); /* ditto */
6084 #endif 4926 #endif
6085 4927
6086 #ifdef MC_ALLOC 4928 #ifdef NEW_GC
6087 mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object); 4929 mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object);
6088 Dynarr_resize (mcpros, 1410); /* merely a small optimization */ 4930 Dynarr_resize (mcpros, 1410); /* merely a small optimization */
6089 dump_add_root_block_ptr (&mcpros, &mcpros_description); 4931 dump_add_root_block_ptr (&mcpros, &mcpros_description);
6090 #ifdef DEBUG_XEMACS 4932 #ifdef DEBUG_XEMACS
6091 mcpro_names = Dynarr_new2 (char_ptr_dynarr, char *); 4933 mcpro_names = Dynarr_new2 (char_ptr_dynarr, char *);
6092 Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */ 4934 Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */
6093 dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description); 4935 dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description);
6094 #endif 4936 #endif
6095 #endif /* MC_ALLOC */ 4937 #endif /* NEW_GC */
6096 4938
6097 consing_since_gc = 0; 4939 consing_since_gc = 0;
6098 need_to_garbage_collect = always_gc;
6099 need_to_check_c_alloca = 0; 4940 need_to_check_c_alloca = 0;
6100 funcall_allocation_flag = 0; 4941 funcall_allocation_flag = 0;
6101 funcall_alloca_count = 0; 4942 funcall_alloca_count = 0;
6102 4943
6103 #if 1
6104 gc_cons_threshold = 2000000; /* XEmacs change */
6105 #else
6106 gc_cons_threshold = 15000; /* debugging */
6107 #endif
6108 gc_cons_percentage = 40; /* #### what is optimal? */
6109 total_gc_usage_set = 0;
6110 lrecord_uid_counter = 259; 4944 lrecord_uid_counter = 259;
6111 #ifndef MC_ALLOC 4945 #ifndef NEW_GC
6112 debug_string_purity = 0; 4946 debug_string_purity = 0;
6113 #endif /* not MC_ALLOC */ 4947 #endif /* not NEW_GC */
6114
6115 gc_currently_forbidden = 0;
6116 gc_hooks_inhibited = 0;
6117 4948
6118 #ifdef ERROR_CHECK_TYPES 4949 #ifdef ERROR_CHECK_TYPES
6119 ERROR_ME.really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 4950 ERROR_ME.really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
6120 666; 4951 666;
6121 ERROR_ME_NOT. 4952 ERROR_ME_NOT.
6127 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 4958 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
6128 8675309; 4959 8675309;
6129 #endif /* ERROR_CHECK_TYPES */ 4960 #endif /* ERROR_CHECK_TYPES */
6130 } 4961 }
6131 4962
6132 #ifndef MC_ALLOC 4963 #ifndef NEW_GC
6133 static void 4964 static void
6134 init_lcrecord_lists (void) 4965 init_lcrecord_lists (void)
6135 { 4966 {
6136 int i; 4967 int i;
6137 4968
6139 { 4970 {
6140 all_lcrecord_lists[i] = Qzero; /* Qnil not yet set */ 4971 all_lcrecord_lists[i] = Qzero; /* Qnil not yet set */
6141 staticpro_nodump (&all_lcrecord_lists[i]); 4972 staticpro_nodump (&all_lcrecord_lists[i]);
6142 } 4973 }
6143 } 4974 }
6144 #endif /* not MC_ALLOC */ 4975 #endif /* not NEW_GC */
6145 4976
6146 void 4977 void
6147 init_alloc_early (void) 4978 init_alloc_early (void)
6148 { 4979 {
6149 #if defined (__cplusplus) && defined (ERROR_CHECK_GC) 4980 #if defined (__cplusplus) && defined (ERROR_CHECK_GC)
6160 4991
6161 void 4992 void
6162 reinit_alloc_early (void) 4993 reinit_alloc_early (void)
6163 { 4994 {
6164 common_init_alloc_early (); 4995 common_init_alloc_early ();
6165 #ifndef MC_ALLOC 4996 #ifndef NEW_GC
6166 init_lcrecord_lists (); 4997 init_lcrecord_lists ();
6167 #endif /* not MC_ALLOC */ 4998 #endif /* not NEW_GC */
6168 } 4999 }
6169 5000
6170 void 5001 void
6171 init_alloc_once_early (void) 5002 init_alloc_once_early (void)
6172 { 5003 {
6179 } 5010 }
6180 5011
6181 INIT_LISP_OBJECT (cons); 5012 INIT_LISP_OBJECT (cons);
6182 INIT_LISP_OBJECT (vector); 5013 INIT_LISP_OBJECT (vector);
6183 INIT_LISP_OBJECT (string); 5014 INIT_LISP_OBJECT (string);
6184 #ifndef MC_ALLOC 5015 #ifdef NEW_GC
5016 INIT_LISP_OBJECT (string_indirect_data);
5017 INIT_LISP_OBJECT (string_direct_data);
5018 #endif /* NEW_GC */
5019 #ifndef NEW_GC
6185 INIT_LISP_OBJECT (lcrecord_list); 5020 INIT_LISP_OBJECT (lcrecord_list);
6186 INIT_LISP_OBJECT (free); 5021 INIT_LISP_OBJECT (free);
6187 #endif /* not MC_ALLOC */ 5022 #endif /* not NEW_GC */
6188 5023
6189 staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); 5024 staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
6190 Dynarr_resize (staticpros, 1410); /* merely a small optimization */ 5025 Dynarr_resize (staticpros, 1410); /* merely a small optimization */
6191 dump_add_root_block_ptr (&staticpros, &staticpros_description); 5026 dump_add_root_block_ptr (&staticpros, &staticpros_description);
6192 #ifdef DEBUG_XEMACS 5027 #ifdef DEBUG_XEMACS
6193 staticpro_names = Dynarr_new2 (char_ptr_dynarr, char *); 5028 staticpro_names = Dynarr_new2 (char_ptr_dynarr, char *);
6194 Dynarr_resize (staticpro_names, 1410); /* merely a small optimization */ 5029 Dynarr_resize (staticpro_names, 1410); /* merely a small optimization */
6195 dump_add_root_block_ptr (&staticpro_names, &staticpro_names_description); 5030 dump_add_root_block_ptr (&staticpro_names, &staticpro_names_description);
6196 #endif 5031 #endif
6197 5032
6198 #ifdef MC_ALLOC 5033 #ifdef NEW_GC
6199 mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object); 5034 mcpros = Dynarr_new2 (Lisp_Object_dynarr, Lisp_Object);
6200 Dynarr_resize (mcpros, 1410); /* merely a small optimization */ 5035 Dynarr_resize (mcpros, 1410); /* merely a small optimization */
6201 dump_add_root_block_ptr (&mcpros, &mcpros_description); 5036 dump_add_root_block_ptr (&mcpros, &mcpros_description);
6202 #ifdef DEBUG_XEMACS 5037 #ifdef DEBUG_XEMACS
6203 mcpro_names = Dynarr_new2 (char_ptr_dynarr, char *); 5038 mcpro_names = Dynarr_new2 (char_ptr_dynarr, char *);
6204 Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */ 5039 Dynarr_resize (mcpro_names, 1410); /* merely a small optimization */
6205 dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description); 5040 dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description);
6206 #endif 5041 #endif
6207 #endif /* MC_ALLOC */ 5042 #else /* not NEW_GC */
6208
6209 #ifndef MC_ALLOC
6210 init_lcrecord_lists (); 5043 init_lcrecord_lists ();
6211 #endif /* not MC_ALLOC */ 5044 #endif /* not NEW_GC */
6212 } 5045 }
6213 5046
6214 void 5047 void
6215 syms_of_alloc (void) 5048 syms_of_alloc (void)
6216 { 5049 {
6217 DEFSYMBOL (Qpre_gc_hook);
6218 DEFSYMBOL (Qpost_gc_hook);
6219 DEFSYMBOL (Qgarbage_collecting); 5050 DEFSYMBOL (Qgarbage_collecting);
6220 5051
6221 DEFSUBR (Fcons); 5052 DEFSUBR (Fcons);
6222 DEFSUBR (Flist); 5053 DEFSUBR (Flist);
6223 DEFSUBR (Fvector); 5054 DEFSUBR (Fvector);
6244 } 5075 }
6245 5076
6246 void 5077 void
6247 vars_of_alloc (void) 5078 vars_of_alloc (void)
6248 { 5079 {
6249 QSin_garbage_collection = build_msg_string ("(in garbage collection)");
6250 staticpro (&QSin_garbage_collection);
6251
6252 DEFVAR_INT ("gc-cons-threshold", &gc_cons_threshold /*
6253 *Number of bytes of consing between garbage collections.
6254 \"Consing\" is a misnomer in that this actually counts allocation
6255 of all different kinds of objects, not just conses.
6256 Garbage collection can happen automatically once this many bytes have been
6257 allocated since the last garbage collection. All data types count.
6258
6259 Garbage collection happens automatically when `eval' or `funcall' are
6260 called. (Note that `funcall' is called implicitly as part of evaluation.)
6261 By binding this temporarily to a large number, you can effectively
6262 prevent garbage collection during a part of the program.
6263
6264 Normally, you cannot set this value less than 10,000 (if you do, it is
6265 automatically reset during the next garbage collection). However, if
6266 XEmacs was compiled with DEBUG_XEMACS, this does not happen, allowing
6267 you to set this value very low to track down problems with insufficient
6268 GCPRO'ing. If you set this to a negative number, garbage collection will
6269 happen at *EVERY* call to `eval' or `funcall'. This is an extremely
6270 effective way to check GCPRO problems, but be warned that your XEmacs
6271 will be unusable! You almost certainly won't have the patience to wait
6272 long enough to be able to set it back.
6273
6274 See also `consing-since-gc' and `gc-cons-percentage'.
6275 */ );
6276
6277 DEFVAR_INT ("gc-cons-percentage", &gc_cons_percentage /*
6278 *Percentage of memory allocated between garbage collections.
6279
6280 Garbage collection will happen if this percentage of the total amount of
6281 memory used for data (see `lisp-object-memory-usage') has been allocated
6282 since the last garbage collection. However, it will not happen if less
6283 than `gc-cons-threshold' bytes have been allocated -- this sets an absolute
6284 minimum in case very little data has been allocated or the percentage is
6285 set very low. Set this to 0 to have garbage collection always happen after
6286 `gc-cons-threshold' bytes have been allocated, regardless of current memory
6287 usage.
6288
6289 See also `consing-since-gc' and `gc-cons-threshold'.
6290 */ );
6291
6292 #ifdef DEBUG_XEMACS 5080 #ifdef DEBUG_XEMACS
6293 DEFVAR_INT ("debug-allocation", &debug_allocation /* 5081 DEFVAR_INT ("debug-allocation", &debug_allocation /*
6294 If non-zero, print out information to stderr about all objects allocated. 5082 If non-zero, print out information to stderr about all objects allocated.
6295 See also `debug-allocation-backtrace-length'. 5083 See also `debug-allocation-backtrace-length'.
6296 */ ); 5084 */ );
6305 5093
6306 DEFVAR_BOOL ("purify-flag", &purify_flag /* 5094 DEFVAR_BOOL ("purify-flag", &purify_flag /*
6307 Non-nil means loading Lisp code in order to dump an executable. 5095 Non-nil means loading Lisp code in order to dump an executable.
6308 This means that certain objects should be allocated in readonly space. 5096 This means that certain objects should be allocated in readonly space.
6309 */ ); 5097 */ );
6310 5098 }
6311 DEFVAR_BOOL ("garbage-collection-messages", &garbage_collection_messages /*
6312 Non-nil means display messages at start and end of garbage collection.
6313 */ );
6314 garbage_collection_messages = 0;
6315
6316 DEFVAR_LISP ("pre-gc-hook", &Vpre_gc_hook /*
6317 Function or functions to be run just before each garbage collection.
6318 Interrupts, garbage collection, and errors are inhibited while this hook
6319 runs, so be extremely careful in what you add here. In particular, avoid
6320 consing, and do not interact with the user.
6321 */ );
6322 Vpre_gc_hook = Qnil;
6323
6324 DEFVAR_LISP ("post-gc-hook", &Vpost_gc_hook /*
6325 Function or functions to be run just after each garbage collection.
6326 Interrupts, garbage collection, and errors are inhibited while this hook
6327 runs. Each hook is called with one argument which is an alist with
6328 finalization data.
6329 */ );
6330 Vpost_gc_hook = Qnil;
6331
6332 DEFVAR_LISP ("gc-message", &Vgc_message /*
6333 String to print to indicate that a garbage collection is in progress.
6334 This is printed in the echo area. If the selected frame is on a
6335 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer
6336 image instance) in the domain of the selected frame, the mouse pointer
6337 will change instead of this message being printed.
6338 */ );
6339 Vgc_message = build_string (gc_default_message);
6340
6341 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /*
6342 Pointer glyph used to indicate that a garbage collection is in progress.
6343 If the selected window is on a window system and this glyph specifies a
6344 value (i.e. a pointer image instance) in the domain of the selected
6345 window, the pointer will be changed as specified during garbage collection.
6346 Otherwise, a message will be printed in the echo area, as controlled
6347 by `gc-message'.
6348 */ );
6349 }
6350
6351 void
6352 complex_vars_of_alloc (void)
6353 {
6354 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer);
6355 }