comparison src/alloc.c @ 3092:141c2920ea48

[xemacs-hg @ 2005-11-25 01:41:31 by crestani] Incremental Garbage Collector
author crestani
date Fri, 25 Nov 2005 01:42:08 +0000
parents d30cd499e445
children db0631f96757
comparison
equal deleted inserted replaced
3091:c22d8984148c 3092:141c2920ea48
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 */
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 MC_ALLOC
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)
280 249
281 /* Called if malloc returns zero */ 250 /* Called if malloc returns zero */
282 DOESNT_RETURN 251 DOESNT_RETURN
283 memory_full (void) 252 memory_full (void)
284 { 253 {
254 fprintf (stderr, "##### M E M O R Y F U L L #####\n");
285 /* Force a GC next time eval is called. 255 /* Force a GC next time eval is called.
286 It's better to loop garbage-collecting (we might reclaim enough 256 It's better to loop garbage-collecting (we might reclaim enough
287 to win) than to loop beeping and barfing "Memory exhausted" 257 to win) than to loop beeping and barfing "Memory exhausted"
288 */ 258 */
289 consing_since_gc = gc_cons_threshold + 1; 259 consing_since_gc = gc_cons_threshold + 1;
519 int bytes_in_use; 489 int bytes_in_use;
520 int bytes_in_use_including_overhead; 490 int bytes_in_use_including_overhead;
521 } lrecord_stats [countof (lrecord_implementations_table) 491 } lrecord_stats [countof (lrecord_implementations_table)
522 + MODULE_DEFINABLE_TYPE_COUNT]; 492 + MODULE_DEFINABLE_TYPE_COUNT];
523 493
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
528 void 494 void
529 init_lrecord_stats () 495 init_lrecord_stats ()
530 { 496 {
531 xzero (lrecord_stats); 497 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 } 498 }
552 499
553 void 500 void
554 inc_lrecord_stats (Bytecount size, const struct lrecord_header *h) 501 inc_lrecord_stats (Bytecount size, const struct lrecord_header *h)
555 { 502 {
579 lrecord_stats[type_index].bytes_in_use_including_overhead 526 lrecord_stats[type_index].bytes_in_use_including_overhead
580 -= size_including_overhead; 527 -= size_including_overhead;
581 528
582 DECREMENT_CONS_COUNTER (size); 529 DECREMENT_CONS_COUNTER (size);
583 } 530 }
531
532 int
533 lrecord_stats_heap_size (void)
534 {
535 int i;
536 int size = 0;
537 for (i = 0; i < (countof (lrecord_implementations_table)
538 + MODULE_DEFINABLE_TYPE_COUNT); i++)
539 size += lrecord_stats[i].bytes_in_use;
540 return size;
541 }
584 #endif /* not (MC_ALLOC && ALLOC_TYPE_STATS) */ 542 #endif /* not (MC_ALLOC && ALLOC_TYPE_STATS) */
585 543
586 #ifndef MC_ALLOC 544 #ifndef MC_ALLOC
587 /* lcrecords are chained together through their "next" field. 545 /* lcrecords are chained together through their "next" field.
588 After doing the mark phase, GC will walk this linked list 546 After doing the mark phase, GC will walk this linked list
611 #endif /* ALLOC_TYPE_STATS */ 569 #endif /* ALLOC_TYPE_STATS */
612 INCREMENT_CONS_COUNTER (size, implementation->name); 570 INCREMENT_CONS_COUNTER (size, implementation->name);
613 return lheader; 571 return lheader;
614 } 572 }
615 573
574
616 void * 575 void *
617 noseeum_alloc_lrecord (Bytecount size, 576 noseeum_alloc_lrecord (Bytecount size,
618 const struct lrecord_implementation *implementation) 577 const struct lrecord_implementation *implementation)
619 { 578 {
620 struct lrecord_header *lheader; 579 struct lrecord_header *lheader;
632 #endif /* ALLOC_TYPE_STATS */ 591 #endif /* ALLOC_TYPE_STATS */
633 NOSEEUM_INCREMENT_CONS_COUNTER (size, implementation->name); 592 NOSEEUM_INCREMENT_CONS_COUNTER (size, implementation->name);
634 return lheader; 593 return lheader;
635 } 594 }
636 595
596 #ifdef NEW_GC
597 void *
598 alloc_lrecord_array (Bytecount size, int elemcount,
599 const struct lrecord_implementation *implementation)
600 {
601 struct lrecord_header *lheader;
602 Rawbyte *start, *stop;
603
604 type_checking_assert
605 ((implementation->static_size == 0 ?
606 implementation->size_in_bytes_method != NULL :
607 implementation->static_size == size));
608
609 lheader = (struct lrecord_header *) mc_alloc_array (size, elemcount);
610 gc_checking_assert (LRECORD_FREE_P (lheader));
611
612 for (start = (Rawbyte *) lheader,
613 stop = ((Rawbyte *) lheader) + (size * elemcount -1);
614 start < stop; start += size)
615 {
616 struct lrecord_header *lh = (struct lrecord_header *) start;
617 set_lheader_implementation (lh, implementation);
618 lh->uid = lrecord_uid_counter++;
619 #ifdef ALLOC_TYPE_STATS
620 inc_lrecord_stats (size, lh);
621 #endif /* not ALLOC_TYPE_STATS */
622 }
623 INCREMENT_CONS_COUNTER (size * elemcount, implementation->name);
624 return lheader;
625 }
626 #endif /* NEW_GC */
627
637 void 628 void
638 free_lrecord (Lisp_Object lrecord) 629 free_lrecord (Lisp_Object lrecord)
639 { 630 {
631 #ifndef NEW_GC
640 gc_checking_assert (!gc_in_progress); 632 gc_checking_assert (!gc_in_progress);
633 #endif /* not NEW_GC */
641 gc_checking_assert (!LRECORD_FREE_P (XRECORD_LHEADER (lrecord))); 634 gc_checking_assert (!LRECORD_FREE_P (XRECORD_LHEADER (lrecord)));
642 gc_checking_assert (!XRECORD_LHEADER (lrecord)->free); 635 gc_checking_assert (!XRECORD_LHEADER (lrecord)->free);
643 636
637 #ifdef NEW_GC
638 GC_STAT_EXPLICITLY_TRIED_FREED;
639 /* Ignore requests to manual free objects while in garbage collection. */
640 if (write_barrier_enabled || gc_in_progress)
641 return;
642
643 GC_STAT_EXPLICITLY_FREED;
644 #endif /* NEW_GC */
645
644 MC_ALLOC_CALL_FINALIZER (XPNTR (lrecord)); 646 MC_ALLOC_CALL_FINALIZER (XPNTR (lrecord));
645 mc_free (XPNTR (lrecord)); 647 mc_free (XPNTR (lrecord));
648 recompute_need_to_garbage_collect ();
646 } 649 }
647 #else /* not MC_ALLOC */ 650 #else /* not MC_ALLOC */
648 651
649 /* The most basic of the lcrecord allocation functions. Not usually called 652 /* The most basic of the lcrecord allocation functions. Not usually called
650 directly. Allocates an lrecord not managed by any lcrecord-list, of a 653 directly. Allocates an lrecord not managed by any lcrecord-list, of a
952 unless there's a large number (usually 1000, but 955 unless there's a large number (usually 1000, but
953 varies depending on type) of them already on the list. 956 varies depending on type) of them already on the list.
954 This way, we ensure that an object that gets freed will 957 This way, we ensure that an object that gets freed will
955 remain free for the next 1000 (or whatever) times that 958 remain free for the next 1000 (or whatever) times that
956 an object of that type is allocated. */ 959 an object of that type is allocated. */
957
958 #ifndef MALLOC_OVERHEAD
959 #ifdef GNU_MALLOC
960 #define MALLOC_OVERHEAD 0
961 #elif defined (rcheck)
962 #define MALLOC_OVERHEAD 20
963 #else
964 #define MALLOC_OVERHEAD 8
965 #endif
966 #endif /* MALLOC_OVERHEAD */
967 960
968 #if !defined(HAVE_MMAP) || defined(DOUG_LEA_MALLOC) 961 #if !defined(HAVE_MMAP) || defined(DOUG_LEA_MALLOC)
969 /* If we released our reserve (due to running out of memory), 962 /* If we released our reserve (due to running out of memory),
970 and we have a fair amount free once again, 963 and we have a fair amount free once again,
971 try to set aside another reserve in case we run out once more. 964 try to set aside another reserve in case we run out once more.
1830 f->flags.interactivep = 0; 1823 f->flags.interactivep = 0;
1831 f->flags.domainp = 0; /* I18N3 */ 1824 f->flags.domainp = 0; /* I18N3 */
1832 f->instructions = Qzero; 1825 f->instructions = Qzero;
1833 f->constants = Qzero; 1826 f->constants = Qzero;
1834 f->arglist = Qnil; 1827 f->arglist = Qnil;
1828 #ifdef NEW_GC
1829 f->arguments = Qnil;
1830 #else /* not NEW_GC */
1835 f->args = NULL; 1831 f->args = NULL;
1832 #endif /* not NEW_GC */
1836 f->max_args = f->min_args = f->args_in_array = 0; 1833 f->max_args = f->min_args = f->args_in_array = 0;
1837 f->doc_and_interactive = Qnil; 1834 f->doc_and_interactive = Qnil;
1838 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK 1835 #ifdef COMPILED_FUNCTION_ANNOTATION_HACK
1839 f->annotated = Qnil; 1836 f->annotated = Qnil;
1840 #endif 1837 #endif
2236 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) && 2233 return (((len = XSTRING_LENGTH (obj1)) == XSTRING_LENGTH (obj2)) &&
2237 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len)); 2234 !memcmp (XSTRING_DATA (obj1), XSTRING_DATA (obj2), len));
2238 } 2235 }
2239 2236
2240 static const struct memory_description string_description[] = { 2237 static const struct memory_description string_description[] = {
2238 #ifdef NEW_GC
2239 { XD_LISP_OBJECT, offsetof (Lisp_String, data_object) },
2240 #else /* not NEW_GC */
2241 { XD_BYTECOUNT, offsetof (Lisp_String, size_) }, 2241 { XD_BYTECOUNT, offsetof (Lisp_String, size_) },
2242 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data_), XD_INDIRECT(0, 1) }, 2242 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String, data_), XD_INDIRECT(0, 1) },
2243 #endif /* not NEW_GC */
2243 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) }, 2244 { XD_LISP_OBJECT, offsetof (Lisp_String, plist) },
2244 { XD_END } 2245 { XD_END }
2245 }; 2246 };
2246 2247
2247 /* We store the string's extent info as the first element of the string's 2248 /* We store the string's extent info as the first element of the string's
2308 string_remprop, 2309 string_remprop,
2309 string_plist, 2310 string_plist,
2310 Lisp_String); 2311 Lisp_String);
2311 #endif /* not MC_ALLOC */ 2312 #endif /* not MC_ALLOC */
2312 2313
2314 #ifdef NEW_GC
2315 #define STRING_FULLSIZE(size) \
2316 ALIGN_SIZE (FLEXIBLE_ARRAY_STRUCT_SIZEOF (Lisp_String_Direct_Data, Lisp_Object, data, (size) + 1), sizeof (Lisp_Object *));
2317 #else /* not NEW_GC */
2313 /* String blocks contain this many useful bytes. */ 2318 /* String blocks contain this many useful bytes. */
2314 #define STRING_CHARS_BLOCK_SIZE \ 2319 #define STRING_CHARS_BLOCK_SIZE \
2315 ((Bytecount) (8192 - MALLOC_OVERHEAD - \ 2320 ((Bytecount) (8192 - MALLOC_OVERHEAD - \
2316 ((2 * sizeof (struct string_chars_block *)) \ 2321 ((2 * sizeof (struct string_chars_block *)) \
2317 + sizeof (EMACS_INT)))) 2322 + sizeof (EMACS_INT))))
2339 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) 2344 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE)
2340 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) 2345 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size)))
2341 2346
2342 #define STRING_CHARS_FREE_P(ptr) ((ptr)->string == NULL) 2347 #define STRING_CHARS_FREE_P(ptr) ((ptr)->string == NULL)
2343 #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL)) 2348 #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL))
2349 #endif /* not NEW_GC */
2344 2350
2345 #ifdef MC_ALLOC 2351 #ifdef MC_ALLOC
2352 #ifndef NEW_GC
2346 static void 2353 static void
2347 finalize_string (void *header, int for_disksave) 2354 finalize_string (void *header, int for_disksave)
2348 { 2355 {
2349 if (!for_disksave) 2356 if (!for_disksave)
2350 { 2357 {
2351 Lisp_String *s = (Lisp_String *) header; 2358 Lisp_String *s = (Lisp_String *) header;
2352 Bytecount size = s->size_; 2359 Bytecount size = s->size_;
2353 #ifdef ALLOC_TYPE_STATS
2354 dec_lrecord_string_data_stats (size);
2355 #endif /* ALLOC_TYPE_STATS */
2356 if (BIG_STRING_SIZE_P (size)) 2360 if (BIG_STRING_SIZE_P (size))
2357 xfree (s->data_, Ibyte *); 2361 xfree (s->data_, Ibyte *);
2358 } 2362 }
2359 } 2363 }
2360 2364
2367 string_getprop, 2371 string_getprop,
2368 string_putprop, 2372 string_putprop,
2369 string_remprop, 2373 string_remprop,
2370 string_plist, 2374 string_plist,
2371 Lisp_String); 2375 Lisp_String);
2372 2376 #else /* NEW_GC */
2377 DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("string", string,
2378 1, /*dumpable-flag*/
2379 mark_string, print_string,
2380 0,
2381 string_equal, 0,
2382 string_description,
2383 string_getprop,
2384 string_putprop,
2385 string_remprop,
2386 string_plist,
2387 Lisp_String);
2388
2389
2390 static const struct memory_description string_direct_data_description[] = {
2391 { XD_BYTECOUNT, offsetof (Lisp_String_Indirect_Data, size) },
2392 { XD_END }
2393 };
2394
2395 static Bytecount
2396 size_string_direct_data (const void *lheader)
2397 {
2398 return STRING_FULLSIZE (((Lisp_String_Direct_Data *) lheader)->size);
2399 }
2400
2401
2402 DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("string-direct-data",
2403 string_direct_data,
2404 1, /*dumpable-flag*/
2405 0, 0, 0, 0, 0,
2406 string_direct_data_description,
2407 size_string_direct_data,
2408 Lisp_String_Direct_Data);
2409
2410
2411 static const struct memory_description string_indirect_data_description[] = {
2412 { XD_BYTECOUNT, offsetof (Lisp_String_Indirect_Data, size) },
2413 { XD_OPAQUE_DATA_PTR, offsetof (Lisp_String_Indirect_Data, data),
2414 XD_INDIRECT(0, 1) },
2415 { XD_END }
2416 };
2417
2418 DEFINE_LRECORD_IMPLEMENTATION ("string-indirect-data",
2419 string_indirect_data,
2420 1, /*dumpable-flag*/
2421 0, 0, 0, 0, 0,
2422 string_indirect_data_description,
2423 Lisp_String_Indirect_Data);
2424 #endif /* NEW_GC */
2373 #endif /* MC_ALLOC */ 2425 #endif /* MC_ALLOC */
2374 2426
2427 #ifndef NEW_GC
2375 struct string_chars 2428 struct string_chars
2376 { 2429 {
2377 Lisp_String *string; 2430 Lisp_String *string;
2378 unsigned char chars[1]; 2431 unsigned char chars[1];
2379 }; 2432 };
2436 2489
2437 INCREMENT_CONS_COUNTER (fullsize, "string chars"); 2490 INCREMENT_CONS_COUNTER (fullsize, "string chars");
2438 2491
2439 return s_chars; 2492 return s_chars;
2440 } 2493 }
2494 #endif /* not NEW_GC */
2441 2495
2442 #ifdef SLEDGEHAMMER_CHECK_ASCII_BEGIN 2496 #ifdef SLEDGEHAMMER_CHECK_ASCII_BEGIN
2443 void 2497 void
2444 sledgehammer_check_ascii_begin (Lisp_Object str) 2498 sledgehammer_check_ascii_begin (Lisp_Object str)
2445 { 2499 {
2470 2524
2471 assert (length >= 0 && fullsize > 0); 2525 assert (length >= 0 && fullsize > 0);
2472 2526
2473 #ifdef MC_ALLOC 2527 #ifdef MC_ALLOC
2474 s = alloc_lrecord_type (Lisp_String, &lrecord_string); 2528 s = alloc_lrecord_type (Lisp_String, &lrecord_string);
2475 #ifdef ALLOC_TYPE_STATS
2476 inc_lrecord_string_data_stats (length);
2477 #endif /* ALLOC_TYPE_STATS */
2478 #else /* not MC_ALLOC */ 2529 #else /* not MC_ALLOC */
2479 /* Allocate the string header */ 2530 /* Allocate the string header */
2480 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); 2531 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
2481 xzero (*s); 2532 xzero (*s);
2482 set_lheader_implementation (&s->u.lheader, &lrecord_string); 2533 set_lheader_implementation (&s->u.lheader, &lrecord_string);
2484 2535
2485 /* The above allocations set the UID field, which overlaps with the 2536 /* The above allocations set the UID field, which overlaps with the
2486 ascii-length field, to some non-zero value. We need to zero it. */ 2537 ascii-length field, to some non-zero value. We need to zero it. */
2487 XSET_STRING_ASCII_BEGIN (wrap_string (s), 0); 2538 XSET_STRING_ASCII_BEGIN (wrap_string (s), 0);
2488 2539
2540 #ifdef NEW_GC
2541 STRING_DATA_OBJECT (s) =
2542 wrap_string_direct_data (alloc_lrecord (fullsize,
2543 &lrecord_string_direct_data));
2544 #else /* not NEW_GC */
2489 set_lispstringp_data (s, BIG_STRING_FULLSIZE_P (fullsize) 2545 set_lispstringp_data (s, BIG_STRING_FULLSIZE_P (fullsize)
2490 ? allocate_big_string_chars (length + 1) 2546 ? allocate_big_string_chars (length + 1)
2491 : allocate_string_chars_struct (wrap_string (s), 2547 : allocate_string_chars_struct (wrap_string (s),
2492 fullsize)->chars); 2548 fullsize)->chars);
2549 #endif /* not NEW_GC */
2493 2550
2494 set_lispstringp_length (s, length); 2551 set_lispstringp_length (s, length);
2495 s->plist = Qnil; 2552 s->plist = Qnil;
2496 set_string_byte (wrap_string (s), length, 0); 2553 set_string_byte (wrap_string (s), length, 0);
2497 2554
2509 */ 2566 */
2510 2567
2511 void 2568 void
2512 resize_string (Lisp_Object s, Bytecount pos, Bytecount delta) 2569 resize_string (Lisp_Object s, Bytecount pos, Bytecount delta)
2513 { 2570 {
2571 #ifdef NEW_GC
2572 Bytecount newfullsize, len;
2573 #else /* not NEW_GC */
2514 Bytecount oldfullsize, newfullsize; 2574 Bytecount oldfullsize, newfullsize;
2575 #endif /* not NEW_GC */
2515 #ifdef VERIFY_STRING_CHARS_INTEGRITY 2576 #ifdef VERIFY_STRING_CHARS_INTEGRITY
2516 verify_string_chars_integrity (); 2577 verify_string_chars_integrity ();
2517 #endif 2578 #endif
2518 #ifdef ERROR_CHECK_TEXT 2579 #ifdef ERROR_CHECK_TEXT
2519 if (pos >= 0) 2580 if (pos >= 0)
2537 /* If DELTA < 0, the functions below will delete the characters 2598 /* If DELTA < 0, the functions below will delete the characters
2538 before POS. We want to delete characters *after* POS, however, 2599 before POS. We want to delete characters *after* POS, however,
2539 so convert this to the appropriate form. */ 2600 so convert this to the appropriate form. */
2540 pos += -delta; 2601 pos += -delta;
2541 2602
2603 #ifdef NEW_GC
2604 newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta);
2605
2606 len = XSTRING_LENGTH (s) + 1 - pos;
2607
2608 if (delta < 0 && pos >= 0)
2609 memmove (XSTRING_DATA (s) + pos + delta,
2610 XSTRING_DATA (s) + pos, len);
2611
2612 XSTRING_DATA_OBJECT (s) =
2613 wrap_string_direct_data (mc_realloc (XPNTR (XSTRING_DATA_OBJECT (s)),
2614 newfullsize));
2615 if (delta > 0 && pos >= 0)
2616 memmove (XSTRING_DATA (s) + pos + delta, XSTRING_DATA (s) + pos,
2617 len);
2618
2619 #else /* NEW_GC */
2542 oldfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s)); 2620 oldfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s));
2543 newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta); 2621 newfullsize = STRING_FULLSIZE (XSTRING_LENGTH (s) + delta);
2544 2622
2545 if (BIG_STRING_FULLSIZE_P (oldfullsize)) 2623 if (BIG_STRING_FULLSIZE_P (oldfullsize))
2546 { 2624 {
2629 ((struct unused_string_chars *) old_s_chars)->fullsize = 2707 ((struct unused_string_chars *) old_s_chars)->fullsize =
2630 oldfullsize; 2708 oldfullsize;
2631 } 2709 }
2632 } 2710 }
2633 } 2711 }
2712 #endif /* not NEW_GC */
2634 2713
2635 XSET_STRING_LENGTH (s, XSTRING_LENGTH (s) + delta); 2714 XSET_STRING_LENGTH (s, XSTRING_LENGTH (s) + delta);
2636 /* If pos < 0, the string won't be zero-terminated. 2715 /* If pos < 0, the string won't be zero-terminated.
2637 Terminate now just to make sure. */ 2716 Terminate now just to make sure. */
2638 XSTRING_DATA (s)[XSTRING_LENGTH (s)] = '\0'; 2717 XSTRING_DATA (s)[XSTRING_LENGTH (s)] = '\0';
2850 bytecount_to_charcount (contents, length); /* Just for the assertions */ 2929 bytecount_to_charcount (contents, length); /* Just for the assertions */
2851 #endif 2930 #endif
2852 2931
2853 #ifdef MC_ALLOC 2932 #ifdef MC_ALLOC
2854 s = alloc_lrecord_type (Lisp_String, &lrecord_string); 2933 s = alloc_lrecord_type (Lisp_String, &lrecord_string);
2855 #ifdef ALLOC_TYPE_STATS
2856 inc_lrecord_string_data_stats (length);
2857 #endif /* ALLOC_TYPE_STATS */
2858 mcpro (wrap_pointer_1 (s)); /* otherwise nocopy_strings get 2934 mcpro (wrap_pointer_1 (s)); /* otherwise nocopy_strings get
2859 collected and static data is tried to 2935 collected and static data is tried to
2860 be freed. */ 2936 be freed. */
2861 #else /* not MC_ALLOC */ 2937 #else /* not MC_ALLOC */
2862 /* Allocate the string header */ 2938 /* Allocate the string header */
2865 SET_C_READONLY_RECORD_HEADER (&s->u.lheader); 2941 SET_C_READONLY_RECORD_HEADER (&s->u.lheader);
2866 #endif /* not MC_ALLOC */ 2942 #endif /* not MC_ALLOC */
2867 /* Don't need to XSET_STRING_ASCII_BEGIN() here because it happens in 2943 /* Don't need to XSET_STRING_ASCII_BEGIN() here because it happens in
2868 init_string_ascii_begin(). */ 2944 init_string_ascii_begin(). */
2869 s->plist = Qnil; 2945 s->plist = Qnil;
2946 #ifdef NEW_GC
2947 set_lispstringp_indirect (s);
2948 STRING_DATA_OBJECT (s) =
2949 wrap_string_indirect_data
2950 (alloc_lrecord_type (Lisp_String_Indirect_Data,
2951 &lrecord_string_indirect_data));
2952 XSTRING_INDIRECT_DATA_DATA (STRING_DATA_OBJECT (s)) = (Ibyte *) contents;
2953 XSTRING_INDIRECT_DATA_SIZE (STRING_DATA_OBJECT (s)) = length;
2954 #else /* not NEW_GC */
2870 set_lispstringp_data (s, (Ibyte *) contents); 2955 set_lispstringp_data (s, (Ibyte *) contents);
2871 set_lispstringp_length (s, length); 2956 set_lispstringp_length (s, length);
2957 #endif /* not NEW_GC */
2872 val = wrap_string (s); 2958 val = wrap_string (s);
2873 init_string_ascii_begin (val); 2959 init_string_ascii_begin (val);
2874 sledgehammer_check_ascii_begin (val); 2960 sledgehammer_check_ascii_begin (val);
2875 2961
2876 return val; 2962 return val;
3334 Dynarr_add (mcpros, varaddress); 3420 Dynarr_add (mcpros, varaddress);
3335 } 3421 }
3336 3422
3337 #endif /* not DEBUG_XEMACS */ 3423 #endif /* not DEBUG_XEMACS */
3338 #endif /* MC_ALLOC */ 3424 #endif /* MC_ALLOC */
3339
3340 #ifdef ERROR_CHECK_GC
3341 #ifdef MC_ALLOC
3342 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \
3343 struct lrecord_header * GCLI_lh = (lheader); \
3344 assert (GCLI_lh != 0); \
3345 assert (GCLI_lh->type < (unsigned int) lrecord_type_count); \
3346 } while (0)
3347 #else /* not MC_ALLOC */
3348 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \
3349 struct lrecord_header * GCLI_lh = (lheader); \
3350 assert (GCLI_lh != 0); \
3351 assert (GCLI_lh->type < (unsigned int) lrecord_type_count); \
3352 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) || \
3353 (MARKED_RECORD_HEADER_P (GCLI_lh) && \
3354 LISP_READONLY_RECORD_HEADER_P (GCLI_lh))); \
3355 } while (0)
3356 #endif /* not MC_ALLOC */
3357 #else
3358 #define GC_CHECK_LHEADER_INVARIANTS(lheader)
3359 #endif
3360
3361
3362 static const struct memory_description lisp_object_description_1[] = {
3363 { XD_LISP_OBJECT, 0 },
3364 { XD_END }
3365 };
3366
3367 const struct sized_memory_description lisp_object_description = {
3368 sizeof (Lisp_Object),
3369 lisp_object_description_1
3370 };
3371
3372 #if defined (USE_KKCC) || defined (PDUMP)
3373
3374 /* This function extracts the value of a count variable described somewhere
3375 else in the description. It is converted corresponding to the type */
3376 EMACS_INT
3377 lispdesc_indirect_count_1 (EMACS_INT code,
3378 const struct memory_description *idesc,
3379 const void *idata)
3380 {
3381 EMACS_INT count;
3382 const void *irdata;
3383
3384 int line = XD_INDIRECT_VAL (code);
3385 int delta = XD_INDIRECT_DELTA (code);
3386
3387 irdata = ((char *) idata) +
3388 lispdesc_indirect_count (idesc[line].offset, idesc, idata);
3389 switch (idesc[line].type)
3390 {
3391 case XD_BYTECOUNT:
3392 count = * (Bytecount *) irdata;
3393 break;
3394 case XD_ELEMCOUNT:
3395 count = * (Elemcount *) irdata;
3396 break;
3397 case XD_HASHCODE:
3398 count = * (Hashcode *) irdata;
3399 break;
3400 case XD_INT:
3401 count = * (int *) irdata;
3402 break;
3403 case XD_LONG:
3404 count = * (long *) irdata;
3405 break;
3406 default:
3407 stderr_out ("Unsupported count type : %d (line = %d, code = %ld)\n",
3408 idesc[line].type, line, (long) code);
3409 #if defined(USE_KKCC) && defined(DEBUG_XEMACS)
3410 if (gc_in_progress)
3411 kkcc_backtrace ();
3412 #endif
3413 #ifdef PDUMP
3414 if (in_pdump)
3415 pdump_backtrace ();
3416 #endif
3417 count = 0; /* warning suppression */
3418 ABORT ();
3419 }
3420 count += delta;
3421 return count;
3422 }
3423
3424 /* SDESC is a "description map" (basically, a list of offsets used for
3425 successive indirections) and OBJ is the first object to indirect off of.
3426 Return the description ultimately found. */
3427
3428 const struct sized_memory_description *
3429 lispdesc_indirect_description_1 (const void *obj,
3430 const struct sized_memory_description *sdesc)
3431 {
3432 int pos;
3433
3434 for (pos = 0; sdesc[pos].size >= 0; pos++)
3435 obj = * (const void **) ((const char *) obj + sdesc[pos].size);
3436
3437 return (const struct sized_memory_description *) obj;
3438 }
3439
3440 /* Compute the size of the data at RDATA, described by a single entry
3441 DESC1 in a description array. OBJ and DESC are used for
3442 XD_INDIRECT references. */
3443
3444 static Bytecount
3445 lispdesc_one_description_line_size (void *rdata,
3446 const struct memory_description *desc1,
3447 const void *obj,
3448 const struct memory_description *desc)
3449 {
3450 union_switcheroo:
3451 switch (desc1->type)
3452 {
3453 case XD_LISP_OBJECT_ARRAY:
3454 {
3455 EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj);
3456 return (val * sizeof (Lisp_Object));
3457 }
3458 case XD_LISP_OBJECT:
3459 case XD_LO_LINK:
3460 return sizeof (Lisp_Object);
3461 case XD_OPAQUE_PTR:
3462 return sizeof (void *);
3463 case XD_BLOCK_PTR:
3464 {
3465 EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj);
3466 return val * sizeof (void *);
3467 }
3468 case XD_BLOCK_ARRAY:
3469 {
3470 EMACS_INT val = lispdesc_indirect_count (desc1->data1, desc, obj);
3471
3472 return (val *
3473 lispdesc_block_size
3474 (rdata,
3475 lispdesc_indirect_description (obj, desc1->data2.descr)));
3476 }
3477 case XD_OPAQUE_DATA_PTR:
3478 return sizeof (void *);
3479 case XD_UNION_DYNAMIC_SIZE:
3480 {
3481 /* If an explicit size was given in the first-level structure
3482 description, use it; else compute size based on current union
3483 constant. */
3484 const struct sized_memory_description *sdesc =
3485 lispdesc_indirect_description (obj, desc1->data2.descr);
3486 if (sdesc->size)
3487 return sdesc->size;
3488 else
3489 {
3490 desc1 = lispdesc_process_xd_union (desc1, desc, obj);
3491 if (desc1)
3492 goto union_switcheroo;
3493 break;
3494 }
3495 }
3496 case XD_UNION:
3497 {
3498 /* If an explicit size was given in the first-level structure
3499 description, use it; else compute size based on maximum of all
3500 possible structures. */
3501 const struct sized_memory_description *sdesc =
3502 lispdesc_indirect_description (obj, desc1->data2.descr);
3503 if (sdesc->size)
3504 return sdesc->size;
3505 else
3506 {
3507 int count;
3508 Bytecount max_size = -1, size;
3509
3510 desc1 = sdesc->description;
3511
3512 for (count = 0; desc1[count].type != XD_END; count++)
3513 {
3514 size = lispdesc_one_description_line_size (rdata,
3515 &desc1[count],
3516 obj, desc);
3517 if (size > max_size)
3518 max_size = size;
3519 }
3520 return max_size;
3521 }
3522 }
3523 case XD_ASCII_STRING:
3524 return sizeof (void *);
3525 case XD_DOC_STRING:
3526 return sizeof (void *);
3527 case XD_INT_RESET:
3528 return sizeof (int);
3529 case XD_BYTECOUNT:
3530 return sizeof (Bytecount);
3531 case XD_ELEMCOUNT:
3532 return sizeof (Elemcount);
3533 case XD_HASHCODE:
3534 return sizeof (Hashcode);
3535 case XD_INT:
3536 return sizeof (int);
3537 case XD_LONG:
3538 return sizeof (long);
3539 default:
3540 stderr_out ("Unsupported dump type : %d\n", desc1->type);
3541 ABORT ();
3542 }
3543
3544 return 0;
3545 }
3546
3547
3548 /* Return the size of the memory block (NOT necessarily a structure!)
3549 described by SDESC and pointed to by OBJ. If SDESC records an
3550 explicit size (i.e. non-zero), it is simply returned; otherwise,
3551 the size is calculated by the maximum offset and the size of the
3552 object at that offset, rounded up to the maximum alignment. In
3553 this case, we may need the object, for example when retrieving an
3554 "indirect count" of an inlined array (the count is not constant,
3555 but is specified by one of the elements of the memory block). (It
3556 is generally not a problem if we return an overly large size -- we
3557 will simply end up reserving more space than necessary; but if the
3558 size is too small we could be in serious trouble, in particular
3559 with nested inlined structures, where there may be alignment
3560 padding in the middle of a block. #### In fact there is an (at
3561 least theoretical) problem with an overly large size -- we may
3562 trigger a protection fault when reading from invalid memory. We
3563 need to handle this -- perhaps in a stupid but dependable way,
3564 i.e. by trapping SIGSEGV and SIGBUS.) */
3565
3566 Bytecount
3567 lispdesc_block_size_1 (const void *obj, Bytecount size,
3568 const struct memory_description *desc)
3569 {
3570 EMACS_INT max_offset = -1;
3571 int max_offset_pos = -1;
3572 int pos;
3573
3574 if (size)
3575 return size;
3576
3577 for (pos = 0; desc[pos].type != XD_END; pos++)
3578 {
3579 EMACS_INT offset = lispdesc_indirect_count (desc[pos].offset, desc, obj);
3580 if (offset == max_offset)
3581 {
3582 stderr_out ("Two relocatable elements at same offset?\n");
3583 ABORT ();
3584 }
3585 else if (offset > max_offset)
3586 {
3587 max_offset = offset;
3588 max_offset_pos = pos;
3589 }
3590 }
3591
3592 if (max_offset_pos < 0)
3593 return 0;
3594
3595 {
3596 Bytecount size_at_max;
3597 size_at_max =
3598 lispdesc_one_description_line_size ((char *) obj + max_offset,
3599 &desc[max_offset_pos], obj, desc);
3600
3601 /* We have no way of knowing the required alignment for this structure,
3602 so just make it maximally aligned. */
3603 return MAX_ALIGN_SIZE (max_offset + size_at_max);
3604 }
3605 }
3606
3607 #endif /* defined (USE_KKCC) || defined (PDUMP) */
3608
3609 #ifdef MC_ALLOC
3610 #define GC_CHECK_NOT_FREE(lheader) \
3611 gc_checking_assert (! LRECORD_FREE_P (lheader));
3612 #else /* MC_ALLOC */
3613 #define GC_CHECK_NOT_FREE(lheader) \
3614 gc_checking_assert (! LRECORD_FREE_P (lheader)); \
3615 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || \
3616 ! ((struct old_lcrecord_header *) lheader)->free)
3617 #endif /* MC_ALLOC */
3618
3619 #ifdef USE_KKCC
3620 /* The following functions implement the new mark algorithm.
3621 They mark objects according to their descriptions. They
3622 are modeled on the corresponding pdumper procedures. */
3623
3624 #ifdef DEBUG_XEMACS
3625 /* The backtrace for the KKCC mark functions. */
3626 #define KKCC_INIT_BT_STACK_SIZE 4096
3627
3628 typedef struct
3629 {
3630 void *obj;
3631 const struct memory_description *desc;
3632 int pos;
3633 } kkcc_bt_stack_entry;
3634
3635 static kkcc_bt_stack_entry *kkcc_bt;
3636 static int kkcc_bt_stack_size;
3637 static int kkcc_bt_depth = 0;
3638
3639 static void
3640 kkcc_bt_init (void)
3641 {
3642 kkcc_bt_depth = 0;
3643 kkcc_bt_stack_size = KKCC_INIT_BT_STACK_SIZE;
3644 kkcc_bt = (kkcc_bt_stack_entry *)
3645 malloc (kkcc_bt_stack_size * sizeof (kkcc_bt_stack_entry));
3646 if (!kkcc_bt)
3647 {
3648 stderr_out ("KKCC backtrace stack init failed for size %d\n",
3649 kkcc_bt_stack_size);
3650 ABORT ();
3651 }
3652 }
3653
3654 void
3655 kkcc_backtrace (void)
3656 {
3657 int i;
3658 stderr_out ("KKCC mark stack backtrace :\n");
3659 for (i = kkcc_bt_depth - 1; i >= 0; i--)
3660 {
3661 Lisp_Object obj = wrap_pointer_1 (kkcc_bt[i].obj);
3662 stderr_out (" [%d]", i);
3663 #ifdef MC_ALLOC
3664 if ((XRECORD_LHEADER (obj)->type >= lrecord_type_last_built_in_type)
3665 #else /* not MC_ALLOC */
3666 if ((XRECORD_LHEADER (obj)->type >= lrecord_type_free)
3667 #endif /* not MC_ALLOC */
3668 || (!LRECORDP (obj))
3669 || (!XRECORD_LHEADER_IMPLEMENTATION (obj)))
3670 {
3671 stderr_out (" non Lisp Object");
3672 }
3673 else
3674 {
3675 stderr_out (" %s",
3676 XRECORD_LHEADER_IMPLEMENTATION (obj)->name);
3677 }
3678 stderr_out (" (addr: 0x%x, desc: 0x%x, ",
3679 (int) kkcc_bt[i].obj,
3680 (int) kkcc_bt[i].desc);
3681 if (kkcc_bt[i].pos >= 0)
3682 stderr_out ("pos: %d)\n", kkcc_bt[i].pos);
3683 else
3684 stderr_out ("root set)\n");
3685 }
3686 }
3687
3688 static void
3689 kkcc_bt_stack_realloc (void)
3690 {
3691 kkcc_bt_stack_size *= 2;
3692 kkcc_bt = (kkcc_bt_stack_entry *)
3693 realloc (kkcc_bt, kkcc_bt_stack_size * sizeof (kkcc_bt_stack_entry));
3694 if (!kkcc_bt)
3695 {
3696 stderr_out ("KKCC backtrace stack realloc failed for size %d\n",
3697 kkcc_bt_stack_size);
3698 ABORT ();
3699 }
3700 }
3701
3702 static void
3703 kkcc_bt_free (void)
3704 {
3705 free (kkcc_bt);
3706 kkcc_bt = 0;
3707 kkcc_bt_stack_size = 0;
3708 }
3709
3710 static void
3711 kkcc_bt_push (void *obj, const struct memory_description *desc,
3712 int level, int pos)
3713 {
3714 kkcc_bt_depth = level;
3715 kkcc_bt[kkcc_bt_depth].obj = obj;
3716 kkcc_bt[kkcc_bt_depth].desc = desc;
3717 kkcc_bt[kkcc_bt_depth].pos = pos;
3718 kkcc_bt_depth++;
3719 if (kkcc_bt_depth >= kkcc_bt_stack_size)
3720 kkcc_bt_stack_realloc ();
3721 }
3722
3723 #else /* not DEBUG_XEMACS */
3724 #define kkcc_bt_init()
3725 #define kkcc_bt_push(obj, desc, level, pos)
3726 #endif /* not DEBUG_XEMACS */
3727
3728 /* Object memory descriptions are in the lrecord_implementation structure.
3729 But copying them to a parallel array is much more cache-friendly. */
3730 const struct memory_description *lrecord_memory_descriptions[countof (lrecord_implementations_table)];
3731
3732 /* the initial stack size in kkcc_gc_stack_entries */
3733 #define KKCC_INIT_GC_STACK_SIZE 16384
3734
3735 typedef struct
3736 {
3737 void *data;
3738 const struct memory_description *desc;
3739 #ifdef DEBUG_XEMACS
3740 int level;
3741 int pos;
3742 #endif
3743 } kkcc_gc_stack_entry;
3744
3745 static kkcc_gc_stack_entry *kkcc_gc_stack_ptr;
3746 static kkcc_gc_stack_entry *kkcc_gc_stack_top;
3747 static kkcc_gc_stack_entry *kkcc_gc_stack_last_entry;
3748 static int kkcc_gc_stack_size;
3749
3750 static void
3751 kkcc_gc_stack_init (void)
3752 {
3753 kkcc_gc_stack_size = KKCC_INIT_GC_STACK_SIZE;
3754 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
3755 malloc (kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
3756 if (!kkcc_gc_stack_ptr)
3757 {
3758 stderr_out ("stack init failed for size %d\n", kkcc_gc_stack_size);
3759 ABORT ();
3760 }
3761 kkcc_gc_stack_top = kkcc_gc_stack_ptr - 1;
3762 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
3763 }
3764
3765 static void
3766 kkcc_gc_stack_free (void)
3767 {
3768 free (kkcc_gc_stack_ptr);
3769 kkcc_gc_stack_ptr = 0;
3770 kkcc_gc_stack_top = 0;
3771 kkcc_gc_stack_size = 0;
3772 }
3773
3774 static void
3775 kkcc_gc_stack_realloc (void)
3776 {
3777 int current_offset = (int)(kkcc_gc_stack_top - kkcc_gc_stack_ptr);
3778 kkcc_gc_stack_size *= 2;
3779 kkcc_gc_stack_ptr = (kkcc_gc_stack_entry *)
3780 realloc (kkcc_gc_stack_ptr,
3781 kkcc_gc_stack_size * sizeof (kkcc_gc_stack_entry));
3782 if (!kkcc_gc_stack_ptr)
3783 {
3784 stderr_out ("stack realloc failed for size %d\n", kkcc_gc_stack_size);
3785 ABORT ();
3786 }
3787 kkcc_gc_stack_top = kkcc_gc_stack_ptr + current_offset;
3788 kkcc_gc_stack_last_entry = kkcc_gc_stack_ptr + kkcc_gc_stack_size - 1;
3789 }
3790
3791 #define KKCC_GC_STACK_FULL (kkcc_gc_stack_top >= kkcc_gc_stack_last_entry)
3792 #define KKCC_GC_STACK_EMPTY (kkcc_gc_stack_top < kkcc_gc_stack_ptr)
3793
3794 static void
3795 #ifdef DEBUG_XEMACS
3796 kkcc_gc_stack_push_1 (void *data, const struct memory_description *desc,
3797 int level, int pos)
3798 #else
3799 kkcc_gc_stack_push_1 (void *data, const struct memory_description *desc)
3800 #endif
3801 {
3802 if (KKCC_GC_STACK_FULL)
3803 kkcc_gc_stack_realloc();
3804 kkcc_gc_stack_top++;
3805 kkcc_gc_stack_top->data = data;
3806 kkcc_gc_stack_top->desc = desc;
3807 #ifdef DEBUG_XEMACS
3808 kkcc_gc_stack_top->level = level;
3809 kkcc_gc_stack_top->pos = pos;
3810 #endif
3811 }
3812
3813 #ifdef DEBUG_XEMACS
3814 #define kkcc_gc_stack_push(data, desc, level, pos) \
3815 kkcc_gc_stack_push_1 (data, desc, level, pos)
3816 #else
3817 #define kkcc_gc_stack_push(data, desc, level, pos) \
3818 kkcc_gc_stack_push_1 (data, desc)
3819 #endif
3820
3821 static kkcc_gc_stack_entry *
3822 kkcc_gc_stack_pop (void)
3823 {
3824 if (KKCC_GC_STACK_EMPTY)
3825 return 0;
3826 kkcc_gc_stack_top--;
3827 return kkcc_gc_stack_top + 1;
3828 }
3829
3830 void
3831 #ifdef DEBUG_XEMACS
3832 kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj, int level, int pos)
3833 #else
3834 kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj)
3835 #endif
3836 {
3837 if (XTYPE (obj) == Lisp_Type_Record)
3838 {
3839 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
3840 const struct memory_description *desc;
3841 GC_CHECK_LHEADER_INVARIANTS (lheader);
3842 desc = RECORD_DESCRIPTION (lheader);
3843 if (! MARKED_RECORD_HEADER_P (lheader))
3844 {
3845 MARK_RECORD_HEADER (lheader);
3846 kkcc_gc_stack_push ((void*) lheader, desc, level, pos);
3847 }
3848 }
3849 }
3850
3851 #ifdef DEBUG_XEMACS
3852 #define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
3853 kkcc_gc_stack_push_lisp_object_1 (obj, level, pos)
3854 #else
3855 #define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
3856 kkcc_gc_stack_push_lisp_object_1 (obj)
3857 #endif
3858
3859 #ifdef ERROR_CHECK_GC
3860 #define KKCC_DO_CHECK_FREE(obj, allow_free) \
3861 do \
3862 { \
3863 if (!allow_free && XTYPE (obj) == Lisp_Type_Record) \
3864 { \
3865 struct lrecord_header *lheader = XRECORD_LHEADER (obj); \
3866 GC_CHECK_NOT_FREE (lheader); \
3867 } \
3868 } while (0)
3869 #else
3870 #define KKCC_DO_CHECK_FREE(obj, allow_free)
3871 #endif
3872
3873 #ifdef ERROR_CHECK_GC
3874 #ifdef DEBUG_XEMACS
3875 static void
3876 mark_object_maybe_checking_free_1 (Lisp_Object obj, int allow_free,
3877 int level, int pos)
3878 #else
3879 static void
3880 mark_object_maybe_checking_free_1 (Lisp_Object obj, int allow_free)
3881 #endif
3882 {
3883 KKCC_DO_CHECK_FREE (obj, allow_free);
3884 kkcc_gc_stack_push_lisp_object (obj, level, pos);
3885 }
3886
3887 #ifdef DEBUG_XEMACS
3888 #define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
3889 mark_object_maybe_checking_free_1 (obj, allow_free, level, pos)
3890 #else
3891 #define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
3892 mark_object_maybe_checking_free_1 (obj, allow_free)
3893 #endif
3894 #else /* not ERROR_CHECK_GC */
3895 #define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
3896 kkcc_gc_stack_push_lisp_object (obj, level, pos)
3897 #endif /* not ERROR_CHECK_GC */
3898
3899
3900 /* This function loops all elements of a struct pointer and calls
3901 mark_with_description with each element. */
3902 static void
3903 #ifdef DEBUG_XEMACS
3904 mark_struct_contents_1 (const void *data,
3905 const struct sized_memory_description *sdesc,
3906 int count, int level, int pos)
3907 #else
3908 mark_struct_contents_1 (const void *data,
3909 const struct sized_memory_description *sdesc,
3910 int count)
3911 #endif
3912 {
3913 int i;
3914 Bytecount elsize;
3915 elsize = lispdesc_block_size (data, sdesc);
3916
3917 for (i = 0; i < count; i++)
3918 {
3919 kkcc_gc_stack_push (((char *) data) + elsize * i, sdesc->description,
3920 level, pos);
3921 }
3922 }
3923
3924 #ifdef DEBUG_XEMACS
3925 #define mark_struct_contents(data, sdesc, count, level, pos) \
3926 mark_struct_contents_1 (data, sdesc, count, level, pos)
3927 #else
3928 #define mark_struct_contents(data, sdesc, count, level, pos) \
3929 mark_struct_contents_1 (data, sdesc, count)
3930 #endif
3931
3932 /* This function implements the KKCC mark algorithm.
3933 Instead of calling mark_object, all the alive Lisp_Objects are pushed
3934 on the kkcc_gc_stack. This function processes all elements on the stack
3935 according to their descriptions. */
3936 static void
3937 kkcc_marking (void)
3938 {
3939 kkcc_gc_stack_entry *stack_entry = 0;
3940 void *data = 0;
3941 const struct memory_description *desc = 0;
3942 int pos;
3943 #ifdef DEBUG_XEMACS
3944 int level = 0;
3945 kkcc_bt_init ();
3946 #endif
3947
3948 while ((stack_entry = kkcc_gc_stack_pop ()) != 0)
3949 {
3950 data = stack_entry->data;
3951 desc = stack_entry->desc;
3952 #ifdef DEBUG_XEMACS
3953 level = stack_entry->level + 1;
3954 #endif
3955
3956 kkcc_bt_push (data, desc, stack_entry->level, stack_entry->pos);
3957
3958 gc_checking_assert (data);
3959 gc_checking_assert (desc);
3960
3961 for (pos = 0; desc[pos].type != XD_END; pos++)
3962 {
3963 const struct memory_description *desc1 = &desc[pos];
3964 const void *rdata =
3965 (const char *) data + lispdesc_indirect_count (desc1->offset,
3966 desc, data);
3967 union_switcheroo:
3968
3969 /* If the flag says don't mark, then don't mark. */
3970 if ((desc1->flags) & XD_FLAG_NO_KKCC)
3971 continue;
3972
3973 switch (desc1->type)
3974 {
3975 case XD_BYTECOUNT:
3976 case XD_ELEMCOUNT:
3977 case XD_HASHCODE:
3978 case XD_INT:
3979 case XD_LONG:
3980 case XD_INT_RESET:
3981 case XD_LO_LINK:
3982 case XD_OPAQUE_PTR:
3983 case XD_OPAQUE_DATA_PTR:
3984 case XD_ASCII_STRING:
3985 case XD_DOC_STRING:
3986 break;
3987 case XD_LISP_OBJECT:
3988 {
3989 const Lisp_Object *stored_obj = (const Lisp_Object *) rdata;
3990
3991 /* Because of the way that tagged objects work (pointers and
3992 Lisp_Objects have the same representation), XD_LISP_OBJECT
3993 can be used for untagged pointers. They might be NULL,
3994 though. */
3995 if (EQ (*stored_obj, Qnull_pointer))
3996 break;
3997 #ifdef MC_ALLOC
3998 mark_object_maybe_checking_free (*stored_obj, 0, level, pos);
3999 #else /* not MC_ALLOC */
4000 mark_object_maybe_checking_free
4001 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
4002 level, pos);
4003 #endif /* not MC_ALLOC */
4004 break;
4005 }
4006 case XD_LISP_OBJECT_ARRAY:
4007 {
4008 int i;
4009 EMACS_INT count =
4010 lispdesc_indirect_count (desc1->data1, desc, data);
4011
4012 for (i = 0; i < count; i++)
4013 {
4014 const Lisp_Object *stored_obj =
4015 (const Lisp_Object *) rdata + i;
4016
4017 if (EQ (*stored_obj, Qnull_pointer))
4018 break;
4019 #ifdef MC_ALLOC
4020 mark_object_maybe_checking_free (*stored_obj, 0, level, pos);
4021 #else /* not MC_ALLOC */
4022 mark_object_maybe_checking_free
4023 (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
4024 level, pos);
4025 #endif /* not MC_ALLOC */
4026 }
4027 break;
4028 }
4029 case XD_BLOCK_PTR:
4030 {
4031 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
4032 data);
4033 const struct sized_memory_description *sdesc =
4034 lispdesc_indirect_description (data, desc1->data2.descr);
4035 const char *dobj = * (const char **) rdata;
4036 if (dobj)
4037 mark_struct_contents (dobj, sdesc, count, level, pos);
4038 break;
4039 }
4040 case XD_BLOCK_ARRAY:
4041 {
4042 EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
4043 data);
4044 const struct sized_memory_description *sdesc =
4045 lispdesc_indirect_description (data, desc1->data2.descr);
4046
4047 mark_struct_contents (rdata, sdesc, count, level, pos);
4048 break;
4049 }
4050 case XD_UNION:
4051 case XD_UNION_DYNAMIC_SIZE:
4052 desc1 = lispdesc_process_xd_union (desc1, desc, data);
4053 if (desc1)
4054 goto union_switcheroo;
4055 break;
4056
4057 default:
4058 stderr_out ("Unsupported description type : %d\n", desc1->type);
4059 kkcc_backtrace ();
4060 ABORT ();
4061 }
4062 }
4063 }
4064 #ifdef DEBUG_XEMACS
4065 kkcc_bt_free ();
4066 #endif
4067 }
4068 #endif /* USE_KKCC */
4069
4070 /* Mark reference to a Lisp_Object. If the object referred to has not been
4071 seen yet, recursively mark all the references contained in it. */
4072
4073 void
4074 mark_object (
4075 #ifdef USE_KKCC
4076 Lisp_Object UNUSED (obj)
4077 #else
4078 Lisp_Object obj
4079 #endif
4080 )
4081 {
4082 #ifdef USE_KKCC
4083 /* this code should never be reached when configured for KKCC */
4084 stderr_out ("KKCC: Invalid mark_object call.\n");
4085 stderr_out ("Replace mark_object with kkcc_gc_stack_push_lisp_object.\n");
4086 ABORT ();
4087 #else /* not USE_KKCC */
4088
4089 tail_recurse:
4090
4091 /* Checks we used to perform */
4092 /* if (EQ (obj, Qnull_pointer)) return; */
4093 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */
4094 /* if (PURIFIED (XPNTR (obj))) return; */
4095
4096 if (XTYPE (obj) == Lisp_Type_Record)
4097 {
4098 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
4099
4100 GC_CHECK_LHEADER_INVARIANTS (lheader);
4101
4102 /* We handle this separately, above, so we can mark free objects */
4103 GC_CHECK_NOT_FREE (lheader);
4104
4105 /* All c_readonly objects have their mark bit set,
4106 so that we only need to check the mark bit here. */
4107 if (! MARKED_RECORD_HEADER_P (lheader))
4108 {
4109 MARK_RECORD_HEADER (lheader);
4110
4111 if (RECORD_MARKER (lheader))
4112 {
4113 obj = RECORD_MARKER (lheader) (obj);
4114 if (!NILP (obj)) goto tail_recurse;
4115 }
4116 }
4117 }
4118 #endif /* not KKCC */
4119 }
4120 3425
4121 3426
4122 #ifndef MC_ALLOC 3427 #ifndef MC_ALLOC
4123 static int gc_count_num_short_string_in_use; 3428 static int gc_count_num_short_string_in_use;
4124 static Bytecount gc_count_string_total_size; 3429 static Bytecount gc_count_string_total_size;
4793 } 4098 }
4794 } 4099 }
4795 4100
4796 #endif /* defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) */ 4101 #endif /* defined (MULE) && defined (VERIFY_STRING_CHARS_INTEGRITY) */
4797 4102
4103 #ifndef NEW_GC
4798 /* Compactify string chars, relocating the reference to each -- 4104 /* Compactify string chars, relocating the reference to each --
4799 free any empty string_chars_block we see. */ 4105 free any empty string_chars_block we see. */
4800 static void 4106 void
4801 compact_string_chars (void) 4107 compact_string_chars (void)
4802 { 4108 {
4803 struct string_chars_block *to_sb = first_string_chars_block; 4109 struct string_chars_block *to_sb = first_string_chars_block;
4804 int to_pos = 0; 4110 int to_pos = 0;
4805 struct string_chars_block *from_sb; 4111 struct string_chars_block *from_sb;
4891 current_string_chars_block = to_sb; 4197 current_string_chars_block = to_sb;
4892 current_string_chars_block->pos = to_pos; 4198 current_string_chars_block->pos = to_pos;
4893 current_string_chars_block->next = 0; 4199 current_string_chars_block->next = 0;
4894 } 4200 }
4895 } 4201 }
4202 #endif /* not NEW_GC */
4896 4203
4897 #ifndef MC_ALLOC 4204 #ifndef MC_ALLOC
4898 #if 1 /* Hack to debug missing purecopy's */ 4205 #if 1 /* Hack to debug missing purecopy's */
4899 static int debug_string_purity; 4206 static int debug_string_purity;
4900 4207
4952 gc_count_string_total_size = num_bytes; 4259 gc_count_string_total_size = num_bytes;
4953 gc_count_short_string_total_size = num_small_bytes; 4260 gc_count_short_string_total_size = num_small_bytes;
4954 } 4261 }
4955 #endif /* not MC_ALLOC */ 4262 #endif /* not MC_ALLOC */
4956 4263
4957 /* I hate duplicating all this crap! */ 4264 #ifndef NEW_GC
4958 int 4265 void
4959 marked_p (Lisp_Object obj) 4266 gc_sweep_1 (void)
4960 {
4961 /* Checks we used to perform. */
4962 /* if (EQ (obj, Qnull_pointer)) return 1; */
4963 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */
4964 /* if (PURIFIED (XPNTR (obj))) return 1; */
4965
4966 if (XTYPE (obj) == Lisp_Type_Record)
4967 {
4968 struct lrecord_header *lheader = XRECORD_LHEADER (obj);
4969
4970 GC_CHECK_LHEADER_INVARIANTS (lheader);
4971
4972 return MARKED_RECORD_HEADER_P (lheader);
4973 }
4974 return 1;
4975 }
4976
4977 static void
4978 gc_sweep (void)
4979 { 4267 {
4980 #ifdef MC_ALLOC 4268 #ifdef MC_ALLOC
4981 compact_string_chars (); 4269 compact_string_chars ();
4982 mc_finalize (); 4270 mc_finalize ();
4983 mc_sweep (); 4271 mc_sweep ();
5062 #ifdef PDUMP 4350 #ifdef PDUMP
5063 pdump_objects_unmark (); 4351 pdump_objects_unmark ();
5064 #endif 4352 #endif
5065 #endif /* not MC_ALLOC */ 4353 #endif /* not MC_ALLOC */
5066 } 4354 }
4355 #endif /* not NEW_GC */
5067 4356
5068 /* Clearing for disksave. */ 4357 /* Clearing for disksave. */
5069 4358
5070 void 4359 void
5071 disksave_object_finalization (void) 4360 disksave_object_finalization (void)
5099 defined(LOADHIST_BUILTIN)) 4388 defined(LOADHIST_BUILTIN))
5100 Vload_history = Qnil; 4389 Vload_history = Qnil;
5101 #endif 4390 #endif
5102 Vshell_file_name = Qnil; 4391 Vshell_file_name = Qnil;
5103 4392
4393 #ifdef NEW_GC
4394 gc_full ();
4395 #else /* not NEW_GC */
5104 garbage_collect_1 (); 4396 garbage_collect_1 ();
4397 #endif /* not NEW_GC */
5105 4398
5106 /* Run the disksave finalization methods of all live objects. */ 4399 /* Run the disksave finalization methods of all live objects. */
5107 disksave_object_finalization_1 (); 4400 disksave_object_finalization_1 ();
5108 4401
4402 #ifndef NEW_GC
5109 /* Zero out the uninitialized (really, unused) part of the containers 4403 /* Zero out the uninitialized (really, unused) part of the containers
5110 for the live strings. */ 4404 for the live strings. */
5111 { 4405 {
5112 struct string_chars_block *scb; 4406 struct string_chars_block *scb;
5113 for (scb = first_string_chars_block; scb; scb = scb->next) 4407 for (scb = first_string_chars_block; scb; scb = scb->next)
5120 /* from the block's fill ptr to the end */ 4414 /* from the block's fill ptr to the end */
5121 memset ((scb->string_chars + scb->pos), 0, count); 4415 memset ((scb->string_chars + scb->pos), 0, count);
5122 } 4416 }
5123 } 4417 }
5124 } 4418 }
4419 #endif /* not NEW_GC */
5125 4420
5126 /* There, that ought to be enough... */ 4421 /* There, that ought to be enough... */
5127 4422
5128 }
5129
5130
5131 int
5132 begin_gc_forbidden (void)
5133 {
5134 return internal_bind_int (&gc_currently_forbidden, 1);
5135 }
5136
5137 void
5138 end_gc_forbidden (int count)
5139 {
5140 unbind_to (count);
5141 }
5142
5143 /* Maybe we want to use this when doing a "panic" gc after memory_full()? */
5144 static int gc_hooks_inhibited;
5145
5146 struct post_gc_action
5147 {
5148 void (*fun) (void *);
5149 void *arg;
5150 };
5151
5152 typedef struct post_gc_action post_gc_action;
5153
5154 typedef struct
5155 {
5156 Dynarr_declare (post_gc_action);
5157 } post_gc_action_dynarr;
5158
5159 static post_gc_action_dynarr *post_gc_actions;
5160
5161 /* Register an action to be called at the end of GC.
5162 gc_in_progress is 0 when this is called.
5163 This is used when it is discovered that an action needs to be taken,
5164 but it's during GC, so it's not safe. (e.g. in a finalize method.)
5165
5166 As a general rule, do not use Lisp objects here.
5167 And NEVER signal an error.
5168 */
5169
5170 void
5171 register_post_gc_action (void (*fun) (void *), void *arg)
5172 {
5173 post_gc_action action;
5174
5175 if (!post_gc_actions)
5176 post_gc_actions = Dynarr_new (post_gc_action);
5177
5178 action.fun = fun;
5179 action.arg = arg;
5180
5181 Dynarr_add (post_gc_actions, action);
5182 }
5183
5184 static void
5185 run_post_gc_actions (void)
5186 {
5187 int i;
5188
5189 if (post_gc_actions)
5190 {
5191 for (i = 0; i < Dynarr_length (post_gc_actions); i++)
5192 {
5193 post_gc_action action = Dynarr_at (post_gc_actions, i);
5194 (action.fun) (action.arg);
5195 }
5196
5197 Dynarr_reset (post_gc_actions);
5198 }
5199 }
5200
5201
5202 void
5203 garbage_collect_1 (void)
5204 {
5205 #if MAX_SAVE_STACK > 0
5206 char stack_top_variable;
5207 extern char *stack_bottom;
5208 #endif
5209 struct frame *f;
5210 int speccount;
5211 int cursor_changed;
5212 Lisp_Object pre_gc_cursor;
5213 struct gcpro gcpro1;
5214 PROFILE_DECLARE ();
5215
5216 assert (!in_display || gc_currently_forbidden);
5217
5218 if (gc_in_progress
5219 || gc_currently_forbidden
5220 || in_display
5221 || preparing_for_armageddon)
5222 return;
5223
5224 PROFILE_RECORD_ENTERING_SECTION (QSin_garbage_collection);
5225
5226 /* We used to call selected_frame() here.
5227
5228 The following functions cannot be called inside GC
5229 so we move to after the above tests. */
5230 {
5231 Lisp_Object frame;
5232 Lisp_Object device = Fselected_device (Qnil);
5233 if (NILP (device)) /* Could happen during startup, eg. if always_gc */
5234 return;
5235 frame = Fselected_frame (device);
5236 if (NILP (frame))
5237 invalid_state ("No frames exist on device", device);
5238 f = XFRAME (frame);
5239 }
5240
5241 pre_gc_cursor = Qnil;
5242 cursor_changed = 0;
5243
5244 GCPRO1 (pre_gc_cursor);
5245
5246 /* Very important to prevent GC during any of the following
5247 stuff that might run Lisp code; otherwise, we'll likely
5248 have infinite GC recursion. */
5249 speccount = begin_gc_forbidden ();
5250
5251 need_to_signal_post_gc = 0;
5252 recompute_funcall_allocation_flag ();
5253
5254 if (!gc_hooks_inhibited)
5255 run_hook_trapping_problems
5256 (Qgarbage_collecting, Qpre_gc_hook,
5257 INHIBIT_EXISTING_PERMANENT_DISPLAY_OBJECT_DELETION);
5258
5259 /* Now show the GC cursor/message. */
5260 if (!noninteractive)
5261 {
5262 if (FRAME_WIN_P (f))
5263 {
5264 Lisp_Object frame = wrap_frame (f);
5265 Lisp_Object cursor = glyph_image_instance (Vgc_pointer_glyph,
5266 FRAME_SELECTED_WINDOW (f),
5267 ERROR_ME_NOT, 1);
5268 pre_gc_cursor = f->pointer;
5269 if (POINTER_IMAGE_INSTANCEP (cursor)
5270 /* don't change if we don't know how to change back. */
5271 && POINTER_IMAGE_INSTANCEP (pre_gc_cursor))
5272 {
5273 cursor_changed = 1;
5274 Fset_frame_pointer (frame, cursor);
5275 }
5276 }
5277
5278 /* Don't print messages to the stream device. */
5279 if (!cursor_changed && !FRAME_STREAM_P (f))
5280 {
5281 if (garbage_collection_messages)
5282 {
5283 Lisp_Object args[2], whole_msg;
5284 args[0] = (STRINGP (Vgc_message) ? Vgc_message :
5285 build_msg_string (gc_default_message));
5286 args[1] = build_string ("...");
5287 whole_msg = Fconcat (2, args);
5288 echo_area_message (f, (Ibyte *) 0, whole_msg, 0, -1,
5289 Qgarbage_collecting);
5290 }
5291 }
5292 }
5293
5294 /***** Now we actually start the garbage collection. */
5295
5296 gc_in_progress = 1;
5297 inhibit_non_essential_conversion_operations = 1;
5298
5299 gc_generation_number[0]++;
5300
5301 #if MAX_SAVE_STACK > 0
5302
5303 /* Save a copy of the contents of the stack, for debugging. */
5304 if (!purify_flag)
5305 {
5306 /* Static buffer in which we save a copy of the C stack at each GC. */
5307 static char *stack_copy;
5308 static Bytecount stack_copy_size;
5309
5310 ptrdiff_t stack_diff = &stack_top_variable - stack_bottom;
5311 Bytecount stack_size = (stack_diff > 0 ? stack_diff : -stack_diff);
5312 if (stack_size < MAX_SAVE_STACK)
5313 {
5314 if (stack_copy_size < stack_size)
5315 {
5316 stack_copy = (char *) xrealloc (stack_copy, stack_size);
5317 stack_copy_size = stack_size;
5318 }
5319
5320 memcpy (stack_copy,
5321 stack_diff > 0 ? stack_bottom : &stack_top_variable,
5322 stack_size);
5323 }
5324 }
5325 #endif /* MAX_SAVE_STACK > 0 */
5326
5327 /* Do some totally ad-hoc resource clearing. */
5328 /* #### generalize this? */
5329 clear_event_resource ();
5330 cleanup_specifiers ();
5331 cleanup_buffer_undo_lists ();
5332
5333 /* Mark all the special slots that serve as the roots of accessibility. */
5334
5335 #ifdef USE_KKCC
5336 /* initialize kkcc stack */
5337 kkcc_gc_stack_init();
5338 #define mark_object(obj) kkcc_gc_stack_push_lisp_object (obj, 0, -1)
5339 #endif /* USE_KKCC */
5340
5341 { /* staticpro() */
5342 Lisp_Object **p = Dynarr_begin (staticpros);
5343 Elemcount count;
5344 for (count = Dynarr_length (staticpros); count; count--)
5345 mark_object (**p++);
5346 }
5347
5348 { /* staticpro_nodump() */
5349 Lisp_Object **p = Dynarr_begin (staticpros_nodump);
5350 Elemcount count;
5351 for (count = Dynarr_length (staticpros_nodump); count; count--)
5352 mark_object (**p++);
5353 }
5354
5355 #ifdef MC_ALLOC
5356 { /* mcpro () */
5357 Lisp_Object *p = Dynarr_begin (mcpros);
5358 Elemcount count;
5359 for (count = Dynarr_length (mcpros); count; count--)
5360 mark_object (*p++);
5361 }
5362 #endif /* MC_ALLOC */
5363
5364 { /* GCPRO() */
5365 struct gcpro *tail;
5366 int i;
5367 for (tail = gcprolist; tail; tail = tail->next)
5368 for (i = 0; i < tail->nvars; i++)
5369 mark_object (tail->var[i]);
5370 }
5371
5372 { /* specbind() */
5373 struct specbinding *bind;
5374 for (bind = specpdl; bind != specpdl_ptr; bind++)
5375 {
5376 mark_object (bind->symbol);
5377 mark_object (bind->old_value);
5378 }
5379 }
5380
5381 {
5382 struct catchtag *c;
5383 for (c = catchlist; c; c = c->next)
5384 {
5385 mark_object (c->tag);
5386 mark_object (c->val);
5387 mark_object (c->actual_tag);
5388 mark_object (c->backtrace);
5389 }
5390 }
5391
5392 {
5393 struct backtrace *backlist;
5394 for (backlist = backtrace_list; backlist; backlist = backlist->next)
5395 {
5396 int nargs = backlist->nargs;
5397 int i;
5398
5399 mark_object (*backlist->function);
5400 if (nargs < 0 /* nargs == UNEVALLED || nargs == MANY */
5401 /* might be fake (internal profiling entry) */
5402 && backlist->args)
5403 mark_object (backlist->args[0]);
5404 else
5405 for (i = 0; i < nargs; i++)
5406 mark_object (backlist->args[i]);
5407 }
5408 }
5409
5410 mark_profiling_info ();
5411
5412 /* OK, now do the after-mark stuff. This is for things that
5413 are only marked when something else is marked (e.g. weak hash tables).
5414 There may be complex dependencies between such objects -- e.g.
5415 a weak hash table might be unmarked, but after processing a later
5416 weak hash table, the former one might get marked. So we have to
5417 iterate until nothing more gets marked. */
5418 #ifdef USE_KKCC
5419 kkcc_marking ();
5420 #endif /* USE_KKCC */
5421 init_marking_ephemerons ();
5422 while (finish_marking_weak_hash_tables () > 0 ||
5423 finish_marking_weak_lists () > 0 ||
5424 continue_marking_ephemerons () > 0)
5425 #ifdef USE_KKCC
5426 {
5427 kkcc_marking ();
5428 }
5429 #else /* NOT USE_KKCC */
5430 ;
5431 #endif /* USE_KKCC */
5432
5433 /* At this point, we know which objects need to be finalized: we
5434 still need to resurrect them */
5435
5436 while (finish_marking_ephemerons () > 0 ||
5437 finish_marking_weak_lists () > 0 ||
5438 finish_marking_weak_hash_tables () > 0)
5439 #ifdef USE_KKCC
5440 {
5441 kkcc_marking ();
5442 }
5443 kkcc_gc_stack_free ();
5444 #undef mark_object
5445 #else /* NOT USE_KKCC */
5446 ;
5447 #endif /* USE_KKCC */
5448
5449 /* And prune (this needs to be called after everything else has been
5450 marked and before we do any sweeping). */
5451 /* #### this is somewhat ad-hoc and should probably be an object
5452 method */
5453 prune_weak_hash_tables ();
5454 prune_weak_lists ();
5455 prune_specifiers ();
5456 prune_syntax_tables ();
5457
5458 prune_ephemerons ();
5459 prune_weak_boxes ();
5460
5461 gc_sweep ();
5462
5463 consing_since_gc = 0;
5464 #ifndef DEBUG_XEMACS
5465 /* Allow you to set it really fucking low if you really want ... */
5466 if (gc_cons_threshold < 10000)
5467 gc_cons_threshold = 10000;
5468 #endif
5469 recompute_need_to_garbage_collect ();
5470
5471 inhibit_non_essential_conversion_operations = 0;
5472 gc_in_progress = 0;
5473
5474 run_post_gc_actions ();
5475
5476 /******* End of garbage collection ********/
5477
5478 /* Now remove the GC cursor/message */
5479 if (!noninteractive)
5480 {
5481 if (cursor_changed)
5482 Fset_frame_pointer (wrap_frame (f), pre_gc_cursor);
5483 else if (!FRAME_STREAM_P (f))
5484 {
5485 /* Show "...done" only if the echo area would otherwise be empty. */
5486 if (NILP (clear_echo_area (selected_frame (),
5487 Qgarbage_collecting, 0)))
5488 {
5489 if (garbage_collection_messages)
5490 {
5491 Lisp_Object args[2], whole_msg;
5492 args[0] = (STRINGP (Vgc_message) ? Vgc_message :
5493 build_msg_string (gc_default_message));
5494 args[1] = build_msg_string ("... done");
5495 whole_msg = Fconcat (2, args);
5496 echo_area_message (selected_frame (), (Ibyte *) 0,
5497 whole_msg, 0, -1,
5498 Qgarbage_collecting);
5499 }
5500 }
5501 }
5502 }
5503
5504 /* now stop inhibiting GC */
5505 unbind_to (speccount);
5506
5507 #ifndef MC_ALLOC
5508 if (!breathing_space)
5509 {
5510 breathing_space = malloc (4096 - MALLOC_OVERHEAD);
5511 }
5512 #endif /* not MC_ALLOC */
5513
5514 UNGCPRO;
5515
5516 need_to_signal_post_gc = 1;
5517 funcall_allocation_flag = 1;
5518
5519 PROFILE_RECORD_EXITING_SECTION (QSin_garbage_collection);
5520
5521 return;
5522 } 4423 }
5523 4424
5524 #ifdef ALLOC_TYPE_STATS 4425 #ifdef ALLOC_TYPE_STATS
5525 4426
5526 static Lisp_Object 4427 static Lisp_Object
5571 else 4472 else
5572 sprintf (buf, "%ss-used", name); 4473 sprintf (buf, "%ss-used", name);
5573 pl = gc_plist_hack (buf, lrecord_stats[i].instances_in_use, pl); 4474 pl = gc_plist_hack (buf, lrecord_stats[i].instances_in_use, pl);
5574 } 4475 }
5575 } 4476 }
5576 pl = gc_plist_hack ("string-data-storage-including-overhead",
5577 lrecord_string_data_bytes_in_use_including_overhead, pl);
5578 pl = gc_plist_hack ("string-data-storage-additional",
5579 lrecord_string_data_bytes_in_use, pl);
5580 pl = gc_plist_hack ("string-data-used",
5581 lrecord_string_data_instances_in_use, pl);
5582 tgu_val += lrecord_string_data_bytes_in_use_including_overhead;
5583 4477
5584 #else /* not MC_ALLOC */ 4478 #else /* not MC_ALLOC */
5585 4479
5586 #define HACK_O_MATIC(type, name, pl) do { \ 4480 #define HACK_O_MATIC(type, name, pl) do { \
5587 EMACS_INT s = 0; \ 4481 EMACS_INT s = 0; \
5718 `gc-cons-threshold' bytes of Lisp data since previous garbage collection. 4612 `gc-cons-threshold' bytes of Lisp data since previous garbage collection.
5719 */ 4613 */
5720 ()) 4614 ())
5721 { 4615 {
5722 /* Record total usage for purposes of determining next GC */ 4616 /* Record total usage for purposes of determining next GC */
4617 #ifdef NEW_GC
4618 gc_full ();
4619 #else /* not NEW_GC */
5723 garbage_collect_1 (); 4620 garbage_collect_1 ();
4621 #endif /* not NEW_GC */
5724 4622
5725 /* This will get set to 1, and total_gc_usage computed, as part of the 4623 /* This will get set to 1, and total_gc_usage computed, as part of the
5726 call to object_memory_usage_stats() -- if ALLOC_TYPE_STATS is enabled. */ 4624 call to object_memory_usage_stats() -- if ALLOC_TYPE_STATS is enabled. */
5727 total_gc_usage_set = 0; 4625 total_gc_usage_set = 0;
5728 #ifdef ALLOC_TYPE_STATS 4626 #ifdef ALLOC_TYPE_STATS
5817 need_to_garbage_collect || 4715 need_to_garbage_collect ||
5818 need_to_check_c_alloca || 4716 need_to_check_c_alloca ||
5819 need_to_signal_post_gc; 4717 need_to_signal_post_gc;
5820 } 4718 }
5821 4719
5822 /* True if it's time to garbage collect now. */
5823 static void
5824 recompute_need_to_garbage_collect (void)
5825 {
5826 if (always_gc)
5827 need_to_garbage_collect = 1;
5828 else
5829 need_to_garbage_collect =
5830 (consing_since_gc > gc_cons_threshold
5831 &&
5832 #if 0 /* #### implement this better */
5833 (100 * consing_since_gc) / total_data_usage () >=
5834 gc_cons_percentage
5835 #else
5836 (!total_gc_usage_set ||
5837 (100 * consing_since_gc) / total_gc_usage >=
5838 gc_cons_percentage)
5839 #endif
5840 );
5841 recompute_funcall_allocation_flag ();
5842 }
5843
5844 4720
5845 int 4721 int
5846 object_dead_p (Lisp_Object obj) 4722 object_dead_p (Lisp_Object obj)
5847 { 4723 {
5848 return ((BUFFERP (obj) && !BUFFER_LIVE_P (XBUFFER (obj))) || 4724 return ((BUFFERP (obj) && !BUFFER_LIVE_P (XBUFFER (obj))) ||
6005 /* C guarantees that Qnull_pointer will be initialized to all 0 bits, 4881 /* C guarantees that Qnull_pointer will be initialized to all 0 bits,
6006 so the following is actually a no-op. */ 4882 so the following is actually a no-op. */
6007 Qnull_pointer = wrap_pointer_1 (0); 4883 Qnull_pointer = wrap_pointer_1 (0);
6008 #endif 4884 #endif
6009 4885
6010 gc_generation_number[0] = 0;
6011 #ifndef MC_ALLOC 4886 #ifndef MC_ALLOC
6012 breathing_space = 0; 4887 breathing_space = 0;
6013 #endif /* not MC_ALLOC */ 4888 #endif /* not MC_ALLOC */
6014 Vgc_message = Qzero;
6015 #ifndef MC_ALLOC 4889 #ifndef MC_ALLOC
6016 all_lcrecords = 0; 4890 all_lcrecords = 0;
6017 #endif /* not MC_ALLOC */ 4891 #endif /* not MC_ALLOC */
6018 ignore_malloc_warnings = 1; 4892 ignore_malloc_warnings = 1;
6019 #ifdef DOUG_LEA_MALLOC 4893 #ifdef DOUG_LEA_MALLOC
6021 mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */ 4895 mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */
6022 #if 0 /* Moved to emacs.c */ 4896 #if 0 /* Moved to emacs.c */
6023 mallopt (M_MMAP_MAX, 64); /* max. number of mmap'ed areas */ 4897 mallopt (M_MMAP_MAX, 64); /* max. number of mmap'ed areas */
6024 #endif 4898 #endif
6025 #endif 4899 #endif
4900 #ifndef NEW_GC
6026 init_string_chars_alloc (); 4901 init_string_chars_alloc ();
4902 #endif /* not NEW_GC */
6027 #ifndef MC_ALLOC 4903 #ifndef MC_ALLOC
6028 init_string_alloc (); 4904 init_string_alloc ();
6029 init_string_chars_alloc (); 4905 init_string_chars_alloc ();
6030 init_cons_alloc (); 4906 init_cons_alloc ();
6031 init_symbol_alloc (); 4907 init_symbol_alloc ();
6079 dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description); 4955 dump_add_root_block_ptr (&mcpro_names, &mcpro_names_description);
6080 #endif 4956 #endif
6081 #endif /* MC_ALLOC */ 4957 #endif /* MC_ALLOC */
6082 4958
6083 consing_since_gc = 0; 4959 consing_since_gc = 0;
6084 need_to_garbage_collect = always_gc;
6085 need_to_check_c_alloca = 0; 4960 need_to_check_c_alloca = 0;
6086 funcall_allocation_flag = 0; 4961 funcall_allocation_flag = 0;
6087 funcall_alloca_count = 0; 4962 funcall_alloca_count = 0;
6088 4963
6089 #if 1
6090 gc_cons_threshold = 2000000; /* XEmacs change */
6091 #else
6092 gc_cons_threshold = 15000; /* debugging */
6093 #endif
6094 gc_cons_percentage = 40; /* #### what is optimal? */
6095 total_gc_usage_set = 0;
6096 lrecord_uid_counter = 259; 4964 lrecord_uid_counter = 259;
6097 #ifndef MC_ALLOC 4965 #ifndef MC_ALLOC
6098 debug_string_purity = 0; 4966 debug_string_purity = 0;
6099 #endif /* not MC_ALLOC */ 4967 #endif /* not MC_ALLOC */
6100
6101 gc_currently_forbidden = 0;
6102 gc_hooks_inhibited = 0;
6103 4968
6104 #ifdef ERROR_CHECK_TYPES 4969 #ifdef ERROR_CHECK_TYPES
6105 ERROR_ME.really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 4970 ERROR_ME.really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
6106 666; 4971 666;
6107 ERROR_ME_NOT. 4972 ERROR_ME_NOT.
6165 } 5030 }
6166 5031
6167 INIT_LRECORD_IMPLEMENTATION (cons); 5032 INIT_LRECORD_IMPLEMENTATION (cons);
6168 INIT_LRECORD_IMPLEMENTATION (vector); 5033 INIT_LRECORD_IMPLEMENTATION (vector);
6169 INIT_LRECORD_IMPLEMENTATION (string); 5034 INIT_LRECORD_IMPLEMENTATION (string);
5035 #ifdef NEW_GC
5036 INIT_LRECORD_IMPLEMENTATION (string_indirect_data);
5037 INIT_LRECORD_IMPLEMENTATION (string_direct_data);
5038 #endif /* NEW_GC */
6170 #ifndef MC_ALLOC 5039 #ifndef MC_ALLOC
6171 INIT_LRECORD_IMPLEMENTATION (lcrecord_list); 5040 INIT_LRECORD_IMPLEMENTATION (lcrecord_list);
6172 INIT_LRECORD_IMPLEMENTATION (free); 5041 INIT_LRECORD_IMPLEMENTATION (free);
6173 #endif /* not MC_ALLOC */ 5042 #endif /* not MC_ALLOC */
6174 5043
6198 } 5067 }
6199 5068
6200 void 5069 void
6201 syms_of_alloc (void) 5070 syms_of_alloc (void)
6202 { 5071 {
6203 DEFSYMBOL (Qpre_gc_hook);
6204 DEFSYMBOL (Qpost_gc_hook);
6205 DEFSYMBOL (Qgarbage_collecting); 5072 DEFSYMBOL (Qgarbage_collecting);
6206 5073
6207 DEFSUBR (Fcons); 5074 DEFSUBR (Fcons);
6208 DEFSUBR (Flist); 5075 DEFSUBR (Flist);
6209 DEFSUBR (Fvector); 5076 DEFSUBR (Fvector);
6230 } 5097 }
6231 5098
6232 void 5099 void
6233 vars_of_alloc (void) 5100 vars_of_alloc (void)
6234 { 5101 {
6235 QSin_garbage_collection = build_msg_string ("(in garbage collection)");
6236 staticpro (&QSin_garbage_collection);
6237
6238 DEFVAR_INT ("gc-cons-threshold", &gc_cons_threshold /*
6239 *Number of bytes of consing between garbage collections.
6240 \"Consing\" is a misnomer in that this actually counts allocation
6241 of all different kinds of objects, not just conses.
6242 Garbage collection can happen automatically once this many bytes have been
6243 allocated since the last garbage collection. All data types count.
6244
6245 Garbage collection happens automatically when `eval' or `funcall' are
6246 called. (Note that `funcall' is called implicitly as part of evaluation.)
6247 By binding this temporarily to a large number, you can effectively
6248 prevent garbage collection during a part of the program.
6249
6250 Normally, you cannot set this value less than 10,000 (if you do, it is
6251 automatically reset during the next garbage collection). However, if
6252 XEmacs was compiled with DEBUG_XEMACS, this does not happen, allowing
6253 you to set this value very low to track down problems with insufficient
6254 GCPRO'ing. If you set this to a negative number, garbage collection will
6255 happen at *EVERY* call to `eval' or `funcall'. This is an extremely
6256 effective way to check GCPRO problems, but be warned that your XEmacs
6257 will be unusable! You almost certainly won't have the patience to wait
6258 long enough to be able to set it back.
6259
6260 See also `consing-since-gc' and `gc-cons-percentage'.
6261 */ );
6262
6263 DEFVAR_INT ("gc-cons-percentage", &gc_cons_percentage /*
6264 *Percentage of memory allocated between garbage collections.
6265
6266 Garbage collection will happen if this percentage of the total amount of
6267 memory used for data (see `lisp-object-memory-usage') has been allocated
6268 since the last garbage collection. However, it will not happen if less
6269 than `gc-cons-threshold' bytes have been allocated -- this sets an absolute
6270 minimum in case very little data has been allocated or the percentage is
6271 set very low. Set this to 0 to have garbage collection always happen after
6272 `gc-cons-threshold' bytes have been allocated, regardless of current memory
6273 usage.
6274
6275 See also `consing-since-gc' and `gc-cons-threshold'.
6276 */ );
6277
6278 #ifdef DEBUG_XEMACS 5102 #ifdef DEBUG_XEMACS
6279 DEFVAR_INT ("debug-allocation", &debug_allocation /* 5103 DEFVAR_INT ("debug-allocation", &debug_allocation /*
6280 If non-zero, print out information to stderr about all objects allocated. 5104 If non-zero, print out information to stderr about all objects allocated.
6281 See also `debug-allocation-backtrace-length'. 5105 See also `debug-allocation-backtrace-length'.
6282 */ ); 5106 */ );
6291 5115
6292 DEFVAR_BOOL ("purify-flag", &purify_flag /* 5116 DEFVAR_BOOL ("purify-flag", &purify_flag /*
6293 Non-nil means loading Lisp code in order to dump an executable. 5117 Non-nil means loading Lisp code in order to dump an executable.
6294 This means that certain objects should be allocated in readonly space. 5118 This means that certain objects should be allocated in readonly space.
6295 */ ); 5119 */ );
6296 5120 }
6297 DEFVAR_BOOL ("garbage-collection-messages", &garbage_collection_messages /*
6298 Non-nil means display messages at start and end of garbage collection.
6299 */ );
6300 garbage_collection_messages = 0;
6301
6302 DEFVAR_LISP ("pre-gc-hook", &Vpre_gc_hook /*
6303 Function or functions to be run just before each garbage collection.
6304 Interrupts, garbage collection, and errors are inhibited while this hook
6305 runs, so be extremely careful in what you add here. In particular, avoid
6306 consing, and do not interact with the user.
6307 */ );
6308 Vpre_gc_hook = Qnil;
6309
6310 DEFVAR_LISP ("post-gc-hook", &Vpost_gc_hook /*
6311 Function or functions to be run just after each garbage collection.
6312 Interrupts, garbage collection, and errors are inhibited while this hook
6313 runs. Each hook is called with one argument which is an alist with
6314 finalization data.
6315 */ );
6316 Vpost_gc_hook = Qnil;
6317
6318 DEFVAR_LISP ("gc-message", &Vgc_message /*
6319 String to print to indicate that a garbage collection is in progress.
6320 This is printed in the echo area. If the selected frame is on a
6321 window system and `gc-pointer-glyph' specifies a value (i.e. a pointer
6322 image instance) in the domain of the selected frame, the mouse pointer
6323 will change instead of this message being printed.
6324 */ );
6325 Vgc_message = build_string (gc_default_message);
6326
6327 DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /*
6328 Pointer glyph used to indicate that a garbage collection is in progress.
6329 If the selected window is on a window system and this glyph specifies a
6330 value (i.e. a pointer image instance) in the domain of the selected
6331 window, the pointer will be changed as specified during garbage collection.
6332 Otherwise, a message will be printed in the echo area, as controlled
6333 by `gc-message'.
6334 */ );
6335 }
6336
6337 void
6338 complex_vars_of_alloc (void)
6339 {
6340 Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer);
6341 }