comparison src/alloc.c @ 771:943eaba38521

[xemacs-hg @ 2002-03-13 08:51:24 by ben] The big ben-mule-21-5 check-in! Various files were added and deleted. See CHANGES-ben-mule. There are still some test suite failures. No crashes, though. Many of the failures have to do with problems in the test suite itself rather than in the actual code. I'll be addressing these in the next day or so -- none of the test suite failures are at all critical. Meanwhile I'll be trying to address the biggest issues -- i.e. build or run failures, which will almost certainly happen on various platforms. All comments should be sent to ben@xemacs.org -- use a Cc: if necessary when sending to mailing lists. There will be pre- and post- tags, something like pre-ben-mule-21-5-merge-in, and post-ben-mule-21-5-merge-in.
author ben
date Wed, 13 Mar 2002 08:54:06 +0000
parents a307f9a2021d
children 79940b592197
comparison
equal deleted inserted replaced
770:336a418893b5 771:943eaba38521
1 /* Storage allocation and gc for XEmacs Lisp interpreter. 1 /* Storage allocation and gc for XEmacs Lisp interpreter.
2 Copyright (C) 1985-1998 Free Software Foundation, Inc. 2 Copyright (C) 1985-1998 Free Software Foundation, Inc.
3 Copyright (C) 1995 Sun Microsystems, Inc. 3 Copyright (C) 1995 Sun Microsystems, Inc.
4 Copyright (C) 1995, 1996 Ben Wing. 4 Copyright (C) 1995, 1996, 2001, 2002 Ben Wing.
5 5
6 This file is part of XEmacs. 6 This file is part of XEmacs.
7 7
8 XEmacs is free software; you can redistribute it and/or modify it 8 XEmacs is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the 9 under the terms of the GNU General Public License as published by the
153 Lisp_Object Vpost_gc_hook, Qpost_gc_hook; 153 Lisp_Object Vpost_gc_hook, Qpost_gc_hook;
154 154
155 /* "Garbage collecting" */ 155 /* "Garbage collecting" */
156 Lisp_Object Vgc_message; 156 Lisp_Object Vgc_message;
157 Lisp_Object Vgc_pointer_glyph; 157 Lisp_Object Vgc_pointer_glyph;
158 static const char gc_default_message[] = "Garbage collecting"; 158 static const Char_ASCII gc_default_message[] = "Garbage collecting";
159 Lisp_Object Qgarbage_collecting; 159 Lisp_Object Qgarbage_collecting;
160 160
161 /* Non-zero means we're in the process of doing the dump */ 161 /* Non-zero means we're in the process of doing the dump */
162 int purify_flag; 162 int purify_flag;
163 163
327 #undef xstrdup 327 #undef xstrdup
328 char * 328 char *
329 xstrdup (const char *str) 329 xstrdup (const char *str)
330 { 330 {
331 int len = strlen (str) + 1; /* for stupid terminating 0 */ 331 int len = strlen (str) + 1; /* for stupid terminating 0 */
332
333 void *val = xmalloc (len); 332 void *val = xmalloc (len);
333
334 if (val == 0) return 0; 334 if (val == 0) return 0;
335 return (char *) memcpy (val, str, len); 335 return (char *) memcpy (val, str, len);
336 } 336 }
337 337
338 #ifdef NEED_STRDUP 338 #ifdef NEED_STRDUP
355 After doing the mark phase, GC will walk this linked list 355 After doing the mark phase, GC will walk this linked list
356 and free any lcrecord which hasn't been marked. */ 356 and free any lcrecord which hasn't been marked. */
357 static struct lcrecord_header *all_lcrecords; 357 static struct lcrecord_header *all_lcrecords;
358 358
359 void * 359 void *
360 alloc_lcrecord (Bytecount size, const struct lrecord_implementation *implementation) 360 alloc_lcrecord (Bytecount size,
361 const struct lrecord_implementation *implementation)
361 { 362 {
362 struct lcrecord_header *lcheader; 363 struct lcrecord_header *lcheader;
363 364
364 type_checking_assert 365 type_checking_assert
365 ((implementation->static_size == 0 ? 366 ((implementation->static_size == 0 ?
390 * Only call it if you really feel you must (and if the 391 * Only call it if you really feel you must (and if the
391 * lrecord was fairly recently allocated). 392 * lrecord was fairly recently allocated).
392 * Otherwise, just let the GC do its job -- that's what it's there for 393 * Otherwise, just let the GC do its job -- that's what it's there for
393 */ 394 */
394 void 395 void
395 free_lcrecord (struct lcrecord_header *lcrecord) 396 very_old_free_lcrecord (struct lcrecord_header *lcrecord)
396 { 397 {
397 if (all_lcrecords == lcrecord) 398 if (all_lcrecords == lcrecord)
398 { 399 {
399 all_lcrecords = lcrecord->next; 400 all_lcrecords = lcrecord->next;
400 } 401 }
761 struct lrecord_header lheader; 762 struct lrecord_header lheader;
762 struct Lisp_Free *chain; 763 struct Lisp_Free *chain;
763 } Lisp_Free; 764 } Lisp_Free;
764 765
765 #define LRECORD_FREE_P(ptr) \ 766 #define LRECORD_FREE_P(ptr) \
766 ((ptr)->lheader.type == lrecord_type_free) 767 (((struct lrecord_header *) ptr)->type == lrecord_type_free)
767 768
768 #define MARK_LRECORD_AS_FREE(ptr) \ 769 #define MARK_LRECORD_AS_FREE(ptr) \
769 ((void) ((ptr)->lheader.type = lrecord_type_free)) 770 ((void) (((struct lrecord_header *) ptr)->type = lrecord_type_free))
770 771
771 #ifdef ERROR_CHECK_GC 772 #ifdef ERROR_CHECK_GC
772 #define MARK_LRECORD_AS_NOT_FREE(ptr) \ 773 #define MARK_LRECORD_AS_NOT_FREE(ptr) \
773 ((void) ((ptr)->lheader.type = lrecord_type_undefined)) 774 ((void) (((struct lrecord_header *) ptr)->type = lrecord_type_undefined))
774 #else 775 #else
775 #define MARK_LRECORD_AS_NOT_FREE(ptr) DO_NOTHING 776 #define MARK_LRECORD_AS_NOT_FREE(ptr) DO_NOTHING
776 #endif 777 #endif
777 778
778 #ifdef ERROR_CHECK_GC 779 #ifdef ERROR_CHECK_GC
1826 INCREMENT_CONS_COUNTER (fullsize, "string chars"); 1827 INCREMENT_CONS_COUNTER (fullsize, "string chars");
1827 1828
1828 return s_chars; 1829 return s_chars;
1829 } 1830 }
1830 1831
1832 #ifdef SLEDGEHAMMER_CHECK_ASCII_BEGIN
1833 void
1834 sledgehammer_check_ascii_begin (Lisp_Object str)
1835 {
1836 Bytecount i;
1837
1838 for (i = 0; i < XSTRING_LENGTH (str); i++)
1839 {
1840 if (!BYTE_ASCII_P (XSTRING_BYTE (str, i)))
1841 break;
1842 }
1843
1844 assert (i == (Bytecount) XSTRING_ASCII_BEGIN (str) ||
1845 (i > MAX_STRING_ASCII_BEGIN &&
1846 (Bytecount) XSTRING_ASCII_BEGIN (str) ==
1847 (Bytecount) MAX_STRING_ASCII_BEGIN));
1848 }
1849 #endif
1850
1851 /* You do NOT want to be calling this! (And if you do, you must call
1852 set_string_ascii_begin() after modifying the string.) Use alloca()
1853 instead and then call make_string() like the rest of the world. */
1854
1831 Lisp_Object 1855 Lisp_Object
1832 make_uninit_string (Bytecount length) 1856 make_uninit_string (Bytecount length)
1833 { 1857 {
1834 Lisp_String *s; 1858 Lisp_String *s;
1835 EMACS_INT fullsize = STRING_FULLSIZE (length); 1859 EMACS_INT fullsize = STRING_FULLSIZE (length);
1837 1861
1838 assert (length >= 0 && fullsize > 0); 1862 assert (length >= 0 && fullsize > 0);
1839 1863
1840 /* Allocate the string header */ 1864 /* Allocate the string header */
1841 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); 1865 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
1842 set_lheader_implementation (&s->lheader, &lrecord_string); 1866 set_lheader_implementation (&s->u.lheader, &lrecord_string);
1843 1867
1844 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize) 1868 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize)
1845 ? xnew_array (Intbyte, length + 1) 1869 ? xnew_array (Intbyte, length + 1)
1846 : allocate_string_chars_struct (s, fullsize)->chars); 1870 : allocate_string_chars_struct (s, fullsize)->chars);
1847 1871
1848 set_string_length (s, length); 1872 set_string_length (s, length);
1849 s->plist = Qnil; 1873 s->plist = Qnil;
1874 set_string_ascii_begin (s, 0);
1850 1875
1851 set_string_byte (s, length, 0); 1876 set_string_byte (s, length, 0);
1852 1877
1853 XSETSTRING (val, s); 1878 XSETSTRING (val, s);
1854 return val; 1879 return val;
2006 #endif 2031 #endif
2007 } 2032 }
2008 2033
2009 #ifdef MULE 2034 #ifdef MULE
2010 2035
2036 /* WARNING: If you modify an existing string, you must call
2037 CHECK_LISP_WRITEABLE() before and bump_string_modiff() afterwards. */
2011 void 2038 void
2012 set_string_char (Lisp_String *s, Charcount i, Emchar c) 2039 set_string_char (Lisp_String *s, Charcount i, Emchar c)
2013 { 2040 {
2014 Intbyte newstr[MAX_EMCHAR_LEN]; 2041 Intbyte newstr[MAX_EMCHAR_LEN];
2015 Bytecount bytoff = charcount_to_bytecount (string_data (s), i); 2042 Bytecount bytoff = string_index_char_to_byte (s, i);
2016 Bytecount oldlen = charcount_to_bytecount (string_data (s) + bytoff, 1); 2043 Bytecount oldlen = charcount_to_bytecount (string_data (s) + bytoff, 1);
2017 Bytecount newlen = set_charptr_emchar (newstr, c); 2044 Bytecount newlen = set_charptr_emchar (newstr, c);
2018 2045
2046 sledgehammer_check_ascii_begin (wrap_string (s));
2019 if (oldlen != newlen) 2047 if (oldlen != newlen)
2020 resize_string (s, bytoff, newlen - oldlen); 2048 resize_string (s, bytoff, newlen - oldlen);
2021 /* Remember, string_data (s) might have changed so we can't cache it. */ 2049 /* Remember, string_data (s) might have changed so we can't cache it. */
2022 memcpy (string_data (s) + bytoff, newstr, newlen); 2050 memcpy (string_data (s) + bytoff, newstr, newlen);
2051 if (oldlen != newlen)
2052 {
2053 if (newlen > 1 && i <= (Charcount) string_ascii_begin (s))
2054 /* Everything starting with the new char is no longer part of
2055 ascii_begin */
2056 set_string_ascii_begin (s, i);
2057 else if (newlen == 1 && i == (Charcount) string_ascii_begin (s))
2058 /* We've extended ascii_begin, and we have to figure out how much by */
2059 {
2060 Bytecount j;
2061 for (j = i + 1; j < string_length (s); j++)
2062 {
2063 if (!BYTE_ASCII_P (string_data (s)[j]))
2064 break;
2065 }
2066 set_string_ascii_begin (s, min (j, MAX_STRING_ASCII_BEGIN));
2067 }
2068 }
2069 sledgehammer_check_ascii_begin (wrap_string (s));
2023 } 2070 }
2024 2071
2025 #endif /* MULE */ 2072 #endif /* MULE */
2026 2073
2027 DEFUN ("make-string", Fmake_string, 2, 2, 0, /* 2074 DEFUN ("make-string", Fmake_string, 2, 2, 0, /*
2036 Intbyte init_str[MAX_EMCHAR_LEN]; 2083 Intbyte init_str[MAX_EMCHAR_LEN];
2037 int len = set_charptr_emchar (init_str, XCHAR (character)); 2084 int len = set_charptr_emchar (init_str, XCHAR (character));
2038 Lisp_Object val = make_uninit_string (len * XINT (length)); 2085 Lisp_Object val = make_uninit_string (len * XINT (length));
2039 2086
2040 if (len == 1) 2087 if (len == 1)
2041 /* Optimize the single-byte case */ 2088 {
2042 memset (XSTRING_DATA (val), XCHAR (character), XSTRING_LENGTH (val)); 2089 /* Optimize the single-byte case */
2090 memset (XSTRING_DATA (val), XCHAR (character), XSTRING_LENGTH (val));
2091 set_string_ascii_begin (XSTRING (val), min (MAX_STRING_ASCII_BEGIN,
2092 len * XINT (length)));
2093 }
2043 else 2094 else
2044 { 2095 {
2045 EMACS_INT i; 2096 EMACS_INT i;
2046 Intbyte *ptr = XSTRING_DATA (val); 2097 Intbyte *ptr = XSTRING_DATA (val);
2047 2098
2055 case 2: *ptr++ = *init_ptr++; 2106 case 2: *ptr++ = *init_ptr++;
2056 case 1: *ptr++ = *init_ptr++; 2107 case 1: *ptr++ = *init_ptr++;
2057 } 2108 }
2058 } 2109 }
2059 } 2110 }
2111 sledgehammer_check_ascii_begin (val);
2060 return val; 2112 return val;
2061 } 2113 }
2062 } 2114 }
2063 2115
2064 DEFUN ("string", Fstring, 0, MANY, 0, /* 2116 DEFUN ("string", Fstring, 0, MANY, 0, /*
2076 p += set_charptr_emchar (p, XCHAR (lisp_char)); 2128 p += set_charptr_emchar (p, XCHAR (lisp_char));
2077 } 2129 }
2078 return make_string (storage, p - storage); 2130 return make_string (storage, p - storage);
2079 } 2131 }
2080 2132
2133 /* Initialize the ascii_begin member of a string to the correct value. */
2134
2135 void
2136 init_string_ascii_begin (Lisp_Object string)
2137 {
2138 #ifdef MULE
2139 int i;
2140 Bytecount length = XSTRING_LENGTH (string);
2141 Intbyte *contents = XSTRING_DATA (string);
2142
2143 for (i = 0; i < length; i++)
2144 {
2145 if (!BYTE_ASCII_P (contents[i]))
2146 break;
2147 }
2148 set_string_ascii_begin (XSTRING (string), min (i, MAX_STRING_ASCII_BEGIN));
2149 #else
2150 set_string_ascii_begin (XSTRING (string), min (XSTRING_LENGTH (string),
2151 MAX_STRING_ASCII_BEGIN));
2152 #endif
2153 sledgehammer_check_ascii_begin (string);
2154 }
2081 2155
2082 /* Take some raw memory, which MUST already be in internal format, 2156 /* Take some raw memory, which MUST already be in internal format,
2083 and package it up into a Lisp string. */ 2157 and package it up into a Lisp string. */
2084 Lisp_Object 2158 Lisp_Object
2085 make_string (const Intbyte *contents, Bytecount length) 2159 make_string (const Intbyte *contents, Bytecount length)
2091 bytecount_to_charcount (contents, length); /* Just for the assertions */ 2165 bytecount_to_charcount (contents, length); /* Just for the assertions */
2092 #endif 2166 #endif
2093 2167
2094 val = make_uninit_string (length); 2168 val = make_uninit_string (length);
2095 memcpy (XSTRING_DATA (val), contents, length); 2169 memcpy (XSTRING_DATA (val), contents, length);
2170 init_string_ascii_begin (val);
2171 sledgehammer_check_ascii_begin (val);
2096 return val; 2172 return val;
2097 } 2173 }
2098 2174
2099 /* Take some raw memory, encoded in some external data format, 2175 /* Take some raw memory, encoded in some external data format,
2100 and convert it into a Lisp string. */ 2176 and convert it into a Lisp string. */
2108 coding_system); 2184 coding_system);
2109 return string; 2185 return string;
2110 } 2186 }
2111 2187
2112 Lisp_Object 2188 Lisp_Object
2189 build_intstring (const Intbyte *str)
2190 {
2191 /* Some strlen's crash and burn if passed null. */
2192 return make_string (str, (str ? qxestrlen (str) : 0));
2193 }
2194
2195 Lisp_Object
2113 build_string (const CIntbyte *str) 2196 build_string (const CIntbyte *str)
2114 { 2197 {
2115 /* Some strlen's crash and burn if passed null. */ 2198 /* Some strlen's crash and burn if passed null. */
2116 return make_string ((const Intbyte *) str, (str ? strlen(str) : 0)); 2199 return make_string ((const Intbyte *) str, (str ? strlen (str) : 0));
2117 } 2200 }
2118 2201
2119 Lisp_Object 2202 Lisp_Object
2120 build_ext_string (const Extbyte *str, Lisp_Object coding_system) 2203 build_ext_string (const Extbyte *str, Lisp_Object coding_system)
2121 { 2204 {
2123 return make_ext_string ((const Extbyte *) str, (str ? strlen(str) : 0), 2206 return make_ext_string ((const Extbyte *) str, (str ? strlen(str) : 0),
2124 coding_system); 2207 coding_system);
2125 } 2208 }
2126 2209
2127 Lisp_Object 2210 Lisp_Object
2128 build_translated_string (const CIntbyte *str) 2211 build_msg_intstring (const Intbyte *str)
2129 { 2212 {
2130 return build_string (GETTEXT (str)); 2213 return build_intstring (GETTEXT (str));
2214 }
2215
2216 Lisp_Object
2217 build_msg_string (const CIntbyte *str)
2218 {
2219 return build_string (CGETTEXT (str));
2131 } 2220 }
2132 2221
2133 Lisp_Object 2222 Lisp_Object
2134 make_string_nocopy (const Intbyte *contents, Bytecount length) 2223 make_string_nocopy (const Intbyte *contents, Bytecount length)
2135 { 2224 {
2141 bytecount_to_charcount (contents, length); /* Just for the assertions */ 2230 bytecount_to_charcount (contents, length); /* Just for the assertions */
2142 #endif 2231 #endif
2143 2232
2144 /* Allocate the string header */ 2233 /* Allocate the string header */
2145 ALLOCATE_FIXED_TYPE (string, Lisp_String, s); 2234 ALLOCATE_FIXED_TYPE (string, Lisp_String, s);
2146 set_lheader_implementation (&s->lheader, &lrecord_string); 2235 set_lheader_implementation (&s->u.lheader, &lrecord_string);
2147 SET_C_READONLY_RECORD_HEADER (&s->lheader); 2236 SET_C_READONLY_RECORD_HEADER (&s->u.lheader);
2148 s->plist = Qnil; 2237 s->plist = Qnil;
2149 set_string_data (s, (Intbyte *)contents); 2238 set_string_data (s, (Intbyte *) contents);
2150 set_string_length (s, length); 2239 set_string_length (s, length);
2151
2152 XSETSTRING (val, s); 2240 XSETSTRING (val, s);
2241 init_string_ascii_begin (val);
2242 sledgehammer_check_ascii_begin (val);
2243
2153 return val; 2244 return val;
2154 } 2245 }
2155 2246
2156 2247
2157 /************************************************************************/ 2248 /************************************************************************/
2228 0, 0, 0, 0, struct lcrecord_list); 2319 0, 0, 0, 0, struct lcrecord_list);
2229 Lisp_Object 2320 Lisp_Object
2230 make_lcrecord_list (Elemcount size, 2321 make_lcrecord_list (Elemcount size,
2231 const struct lrecord_implementation *implementation) 2322 const struct lrecord_implementation *implementation)
2232 { 2323 {
2233 struct lcrecord_list *p = alloc_lcrecord_type (struct lcrecord_list, 2324 struct lcrecord_list *p =
2234 &lrecord_lcrecord_list); 2325 /* Avoid infinite recursion allocating this */
2326 alloc_unmanaged_lcrecord_type (struct lcrecord_list,
2327 &lrecord_lcrecord_list);
2235 Lisp_Object val; 2328 Lisp_Object val;
2236 2329
2237 p->implementation = implementation; 2330 p->implementation = implementation;
2238 p->size = size; 2331 p->size = size;
2239 p->free = Qnil; 2332 p->free = Qnil;
2278 XSETOBJ (val, alloc_lcrecord (list->size, list->implementation)); 2371 XSETOBJ (val, alloc_lcrecord (list->size, list->implementation));
2279 return val; 2372 return val;
2280 } 2373 }
2281 } 2374 }
2282 2375
2376 /* "Free" a Lisp object LCRECORD by placing it on its associated free list
2377 LCRECORD_LIST; next time allocate_managed_lcrecord() is called with the
2378 same LCRECORD_LIST as its parameter, it will return an object from the
2379 free list, which may be this one. Be VERY VERY SURE there are no
2380 pointers to this object hanging around anywhere where they might be
2381 used!
2382
2383 The first thing this does before making any global state change is to
2384 call the finalize method of the object, if it exists. */
2385
2283 void 2386 void
2284 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord) 2387 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord)
2285 { 2388 {
2286 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list); 2389 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list);
2287 struct free_lcrecord_header *free_header = 2390 struct free_lcrecord_header *free_header =
2288 (struct free_lcrecord_header *) XPNTR (lcrecord); 2391 (struct free_lcrecord_header *) XPNTR (lcrecord);
2289 struct lrecord_header *lheader = &free_header->lcheader.lheader; 2392 struct lrecord_header *lheader = &free_header->lcheader.lheader;
2290 const struct lrecord_implementation *implementation 2393 const struct lrecord_implementation *implementation
2291 = LHEADER_IMPLEMENTATION (lheader); 2394 = LHEADER_IMPLEMENTATION (lheader);
2292 2395
2396 /* Finalizer methods may try to free objects within them, which typically
2397 won't be marked and thus are scheduled for demolition. Putting them
2398 on the free list would be very bad, as we'd have xfree()d memory in
2399 the list. Even if for some reason the objects are still live
2400 (generally a logic error!), we still will have problems putting such
2401 an object on the free list right now (e.g. we'd have to avoid calling
2402 the finalizer twice, etc.). So basically, those finalizers should not
2403 be freeing any objects if during GC. Abort now to catch those
2404 problems. */
2405 gc_checking_assert (!gc_in_progress);
2406
2293 /* Make sure the size is correct. This will catch, for example, 2407 /* Make sure the size is correct. This will catch, for example,
2294 putting a window configuration on the wrong free list. */ 2408 putting a window configuration on the wrong free list. */
2295 gc_checking_assert ((implementation->size_in_bytes_method ? 2409 gc_checking_assert ((implementation->size_in_bytes_method ?
2296 implementation->size_in_bytes_method (lheader) : 2410 implementation->size_in_bytes_method (lheader) :
2297 implementation->static_size) 2411 implementation->static_size)
2298 == list->size); 2412 == list->size);
2299 2413 /* Make sure the object isn't already freed. */
2414 gc_checking_assert (!free_header->lcheader.free);
2415
2300 if (implementation->finalizer) 2416 if (implementation->finalizer)
2301 implementation->finalizer (lheader, 0); 2417 implementation->finalizer (lheader, 0);
2302 free_header->chain = list->free; 2418 free_header->chain = list->free;
2303 free_header->lcheader.free = 1; 2419 free_header->lcheader.free = 1;
2304 list->free = lcrecord; 2420 list->free = lcrecord;
2305 } 2421 }
2306 2422
2307 2423 static Lisp_Object all_lcrecord_lists[countof (lrecord_implementations_table)];
2424
2425 void *
2426 alloc_automanaged_lcrecord (Bytecount size,
2427 const struct lrecord_implementation *imp)
2428 {
2429 if (EQ (all_lcrecord_lists[imp->lrecord_type_index], Qzero))
2430 all_lcrecord_lists[imp->lrecord_type_index] =
2431 make_lcrecord_list (size, imp);
2432
2433 return XPNTR (allocate_managed_lcrecord
2434 (all_lcrecord_lists[imp->lrecord_type_index]));
2435 }
2436
2437 void
2438 free_lcrecord (Lisp_Object rec)
2439 {
2440 int type = XRECORD_LHEADER (rec)->type;
2441
2442 assert (!EQ (all_lcrecord_lists[type], Qzero));
2443
2444 free_managed_lcrecord (all_lcrecord_lists[type], rec);
2445 }
2308 2446
2309 2447
2310 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /* 2448 DEFUN ("purecopy", Fpurecopy, 1, 1, 0, /*
2311 Kept for compatibility, returns its argument. 2449 Kept for compatibility, returns its argument.
2312 Old: 2450 Old:
2334 This hack speeds up (garbage-collect) by about 5%. */ 2472 This hack speeds up (garbage-collect) by about 5%. */
2335 Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object); 2473 Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object);
2336 2474
2337 struct gcpro *gcprolist; 2475 struct gcpro *gcprolist;
2338 2476
2339 /* We want the staticpros relocated, but not the pointers found therein. 2477 /* We want the staticpro list relocated, but not the pointers found
2340 Hence we use a trivial description, as for pointerless objects. */ 2478 therein, because they refer to locations in the global data segment, not
2479 in the heap; we only dump heap objects. Hence we use a trivial
2480 description, as for pointerless objects. (Note that the data segment
2481 objects, which are global variables like Qfoo or Vbar, themselves are
2482 pointers to heap objects. Each needs to be described to pdump as a
2483 "root pointer"; this happens in the call to staticpro(). */
2341 static const struct lrecord_description staticpro_description_1[] = { 2484 static const struct lrecord_description staticpro_description_1[] = {
2342 { XD_END } 2485 { XD_END }
2343 }; 2486 };
2344 2487
2345 static const struct struct_description staticpro_description = { 2488 static const struct struct_description staticpro_description = {
2355 static const struct struct_description staticpros_description = { 2498 static const struct struct_description staticpros_description = {
2356 sizeof (Lisp_Object_ptr_dynarr), 2499 sizeof (Lisp_Object_ptr_dynarr),
2357 staticpros_description_1 2500 staticpros_description_1
2358 }; 2501 };
2359 2502
2503 #ifdef DEBUG_XEMACS
2504
2505 static const struct lrecord_description staticpro_one_name_description_1[] = {
2506 { XD_C_STRING, 0 },
2507 { XD_END }
2508 };
2509
2510 static const struct struct_description staticpro_one_name_description = {
2511 sizeof (char *),
2512 staticpro_one_name_description_1
2513 };
2514
2515 static const struct lrecord_description staticpro_names_description_1[] = {
2516 XD_DYNARR_DESC (char_ptr_dynarr, &staticpro_one_name_description),
2517 { XD_END }
2518 };
2519
2520 static const struct struct_description staticpro_names_description = {
2521 sizeof (char_ptr_dynarr),
2522 staticpro_names_description_1
2523 };
2524
2525 /* Help debug crashes gc-marking a staticpro'ed object. */
2526
2527 Lisp_Object_ptr_dynarr *staticpros;
2528 char_ptr_dynarr *staticpro_names;
2529
2530 /* Mark the Lisp_Object at non-heap VARADDRESS as a root object for
2531 garbage collection, and for dumping. */
2532 void
2533 staticpro_1 (Lisp_Object *varaddress, char *varname)
2534 {
2535 Dynarr_add (staticpros, varaddress);
2536 Dynarr_add (staticpro_names, varname);
2537 dump_add_root_object (varaddress);
2538 }
2539
2540
2541 Lisp_Object_ptr_dynarr *staticpros_nodump;
2542 char_ptr_dynarr *staticpro_nodump_names;
2543
2544 /* Mark the Lisp_Object at heap VARADDRESS as a root object for
2545 garbage collection, but not for dumping. (See below.) */
2546 void
2547 staticpro_nodump_1 (Lisp_Object *varaddress, char *varname)
2548 {
2549 Dynarr_add (staticpros_nodump, varaddress);
2550 Dynarr_add (staticpro_nodump_names, varname);
2551 }
2552
2553 #else /* not DEBUG_XEMACS */
2554
2360 Lisp_Object_ptr_dynarr *staticpros; 2555 Lisp_Object_ptr_dynarr *staticpros;
2361 2556
2362 /* Mark the Lisp_Object at non-heap VARADDRESS as a root object for 2557 /* Mark the Lisp_Object at non-heap VARADDRESS as a root object for
2363 garbage collection, and for dumping. */ 2558 garbage collection, and for dumping. */
2364 void 2559 void
2369 } 2564 }
2370 2565
2371 2566
2372 Lisp_Object_ptr_dynarr *staticpros_nodump; 2567 Lisp_Object_ptr_dynarr *staticpros_nodump;
2373 2568
2374 /* Mark the Lisp_Object at non-heap VARADDRESS as a root object for 2569 /* Mark the Lisp_Object at heap VARADDRESS as a root object for garbage
2375 garbage collection, but not for dumping. */ 2570 collection, but not for dumping. This is used for objects where the
2571 only sure pointer is in the heap (rather than in the global data
2572 segment, as must be the case for pdump root pointers), but not inside of
2573 another Lisp object (where it will be marked as a result of that Lisp
2574 object's mark method). The call to staticpro_nodump() must occur *BOTH*
2575 at initialization time and at "reinitialization" time (startup, after
2576 pdump load.) (For example, this is the case with the predicate symbols
2577 for specifier and coding system types. The pointer to this symbol is
2578 inside of a methods structure, which is allocated on the heap. The
2579 methods structure will be written out to the pdump data file, and may be
2580 reloaded at a different address.)
2581
2582 #### The necessity for reinitialization is a bug in pdump. Pdump should
2583 automatically regenerate the staticpro()s for these symbols when it
2584 loads the data in. */
2585
2376 void 2586 void
2377 staticpro_nodump (Lisp_Object *varaddress) 2587 staticpro_nodump (Lisp_Object *varaddress)
2378 { 2588 {
2379 Dynarr_add (staticpros_nodump, varaddress); 2589 Dynarr_add (staticpros_nodump, varaddress);
2380 } 2590 }
2591
2592 #endif /* not DEBUG_XEMACS */
2381 2593
2382 #ifdef ERROR_CHECK_GC 2594 #ifdef ERROR_CHECK_GC
2383 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \ 2595 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \
2384 struct lrecord_header * GCLI_lh = (lheader); \ 2596 struct lrecord_header * GCLI_lh = (lheader); \
2385 assert (GCLI_lh != 0); \ 2597 assert (GCLI_lh != 0); \
2614 /* And the Lord said: Thou shalt use the `c-backslash-region' command 2826 /* And the Lord said: Thou shalt use the `c-backslash-region' command
2615 to make macros prettier. */ 2827 to make macros prettier. */
2616 2828
2617 #ifdef ERROR_CHECK_GC 2829 #ifdef ERROR_CHECK_GC
2618 2830
2619 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ 2831 #define SWEEP_FIXED_TYPE_BLOCK_1(typename, obj_type, lheader) \
2620 do { \ 2832 do { \
2621 struct typename##_block *SFTB_current; \ 2833 struct typename##_block *SFTB_current; \
2622 int SFTB_limit; \ 2834 int SFTB_limit; \
2623 int num_free = 0, num_used = 0; \ 2835 int num_free = 0, num_used = 0; \
2624 \ 2836 \
2660 gc_count_num_##typename##_freelist = num_free; \ 2872 gc_count_num_##typename##_freelist = num_free; \
2661 } while (0) 2873 } while (0)
2662 2874
2663 #else /* !ERROR_CHECK_GC */ 2875 #else /* !ERROR_CHECK_GC */
2664 2876
2665 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \ 2877 #define SWEEP_FIXED_TYPE_BLOCK_1(typename, obj_type, lheader) \
2666 do { \ 2878 do { \
2667 struct typename##_block *SFTB_current; \ 2879 struct typename##_block *SFTB_current; \
2668 struct typename##_block **SFTB_prev; \ 2880 struct typename##_block **SFTB_prev; \
2669 int SFTB_limit; \ 2881 int SFTB_limit; \
2670 int num_free = 0, num_used = 0; \ 2882 int num_free = 0, num_used = 0; \
2671 \ 2883 \
2672 typename##_free_list = 0; \ 2884 typename##_free_list = 0; \
2673 \ 2885 \
2674 for (SFTB_prev = &current_##typename##_block, \ 2886 for (SFTB_prev = &current_##typename##_block, \
2675 SFTB_current = current_##typename##_block, \ 2887 SFTB_current = current_##typename##_block, \
2676 SFTB_limit = current_##typename##_block_index; \ 2888 SFTB_limit = current_##typename##_block_index; \
2677 SFTB_current; \ 2889 SFTB_current; \
2678 ) \ 2890 ) \
2679 { \ 2891 { \
2680 int SFTB_iii; \ 2892 int SFTB_iii; \
2681 int SFTB_empty = 1; \ 2893 int SFTB_empty = 1; \
2682 Lisp_Free *SFTB_old_free_list = typename##_free_list; \ 2894 Lisp_Free *SFTB_old_free_list = typename##_free_list; \
2683 \ 2895 \
2684 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ 2896 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \
2685 { \ 2897 { \
2686 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ 2898 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \
2687 \ 2899 \
2688 if (LRECORD_FREE_P (SFTB_victim)) \ 2900 if (LRECORD_FREE_P (SFTB_victim)) \
2689 { \ 2901 { \
2690 num_free++; \ 2902 num_free++; \
2691 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \ 2903 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \
2692 } \ 2904 } \
2693 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ 2905 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2694 { \ 2906 { \
2695 SFTB_empty = 0; \ 2907 SFTB_empty = 0; \
2696 num_used++; \ 2908 num_used++; \
2697 } \ 2909 } \
2698 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ 2910 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \
2699 { \ 2911 { \
2700 num_free++; \ 2912 num_free++; \
2701 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ 2913 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \
2702 } \ 2914 } \
2703 else \ 2915 else \
2704 { \ 2916 { \
2705 SFTB_empty = 0; \ 2917 SFTB_empty = 0; \
2706 num_used++; \ 2918 num_used++; \
2707 UNMARK_##typename (SFTB_victim); \ 2919 UNMARK_##typename (SFTB_victim); \
2708 } \ 2920 } \
2709 } \ 2921 } \
2710 if (!SFTB_empty) \ 2922 if (!SFTB_empty) \
2711 { \ 2923 { \
2712 SFTB_prev = &(SFTB_current->prev); \ 2924 SFTB_prev = &(SFTB_current->prev); \
2713 SFTB_current = SFTB_current->prev; \ 2925 SFTB_current = SFTB_current->prev; \
2714 } \ 2926 } \
2715 else if (SFTB_current == current_##typename##_block \ 2927 else if (SFTB_current == current_##typename##_block \
2716 && !SFTB_current->prev) \ 2928 && !SFTB_current->prev) \
2717 { \ 2929 { \
2718 /* No real point in freeing sole allocation block */ \ 2930 /* No real point in freeing sole allocation block */ \
2719 break; \ 2931 break; \
2720 } \ 2932 } \
2721 else \ 2933 else \
2722 { \ 2934 { \
2723 struct typename##_block *SFTB_victim_block = SFTB_current; \ 2935 struct typename##_block *SFTB_victim_block = SFTB_current; \
2724 if (SFTB_victim_block == current_##typename##_block) \ 2936 if (SFTB_victim_block == current_##typename##_block) \
2725 current_##typename##_block_index \ 2937 current_##typename##_block_index \
2726 = countof (current_##typename##_block->block); \ 2938 = countof (current_##typename##_block->block); \
2727 SFTB_current = SFTB_current->prev; \ 2939 SFTB_current = SFTB_current->prev; \
2728 { \ 2940 { \
2729 *SFTB_prev = SFTB_current; \ 2941 *SFTB_prev = SFTB_current; \
2730 xfree (SFTB_victim_block); \ 2942 xfree (SFTB_victim_block); \
2731 /* Restore free list to what it was before victim was swept */ \ 2943 /* Restore free list to what it was before victim was swept */ \
2732 typename##_free_list = SFTB_old_free_list; \ 2944 typename##_free_list = SFTB_old_free_list; \
2733 num_free -= SFTB_limit; \ 2945 num_free -= SFTB_limit; \
2734 } \ 2946 } \
2735 } \ 2947 } \
2736 SFTB_limit = countof (current_##typename##_block->block); \ 2948 SFTB_limit = countof (current_##typename##_block->block); \
2737 } \ 2949 } \
2738 \ 2950 \
2739 gc_count_num_##typename##_in_use = num_used; \ 2951 gc_count_num_##typename##_in_use = num_used; \
2740 gc_count_num_##typename##_freelist = num_free; \ 2952 gc_count_num_##typename##_freelist = num_free; \
2741 } while (0) 2953 } while (0)
2742 2954
2743 #endif /* !ERROR_CHECK_GC */ 2955 #endif /* !ERROR_CHECK_GC */
2956
2957 #define SWEEP_FIXED_TYPE_BLOCK(typename, obj_type) \
2958 SWEEP_FIXED_TYPE_BLOCK_1 (typename, obj_type, lheader)
2744 2959
2745 2960
2746 2961
2747 2962
2748 static void 2963 static void
2977 fullsize = STRING_FULLSIZE (size); 3192 fullsize = STRING_FULLSIZE (size);
2978 3193
2979 gc_checking_assert (! BIG_STRING_FULLSIZE_P (fullsize)); 3194 gc_checking_assert (! BIG_STRING_FULLSIZE_P (fullsize));
2980 3195
2981 /* Just skip it if it isn't marked. */ 3196 /* Just skip it if it isn't marked. */
2982 if (! MARKED_RECORD_HEADER_P (&(string->lheader))) 3197 if (! MARKED_RECORD_HEADER_P (&(string->u.lheader)))
2983 { 3198 {
2984 from_pos += fullsize; 3199 from_pos += fullsize;
2985 continue; 3200 continue;
2986 } 3201 }
2987 3202
3062 int debug = debug_string_purity; 3277 int debug = debug_string_purity;
3063 3278
3064 #define UNMARK_string(ptr) do { \ 3279 #define UNMARK_string(ptr) do { \
3065 Lisp_String *p = (ptr); \ 3280 Lisp_String *p = (ptr); \
3066 Bytecount size = string_length (p); \ 3281 Bytecount size = string_length (p); \
3067 UNMARK_RECORD_HEADER (&(p->lheader)); \ 3282 UNMARK_RECORD_HEADER (&(p->u.lheader)); \
3068 num_bytes += size; \ 3283 num_bytes += size; \
3069 if (!BIG_STRING_SIZE_P (size)) \ 3284 if (!BIG_STRING_SIZE_P (size)) \
3070 { \ 3285 { \
3071 num_small_bytes += size; \ 3286 num_small_bytes += size; \
3072 num_small_used++; \ 3287 num_small_used++; \
3078 Bytecount size = string_length (ptr); \ 3293 Bytecount size = string_length (ptr); \
3079 if (BIG_STRING_SIZE_P (size)) \ 3294 if (BIG_STRING_SIZE_P (size)) \
3080 xfree (ptr->data); \ 3295 xfree (ptr->data); \
3081 } while (0) 3296 } while (0)
3082 3297
3083 SWEEP_FIXED_TYPE_BLOCK (string, Lisp_String); 3298 SWEEP_FIXED_TYPE_BLOCK_1 (string, Lisp_String, u.lheader);
3084 3299
3085 gc_count_num_short_string_in_use = num_small_used; 3300 gc_count_num_short_string_in_use = num_small_used;
3086 gc_count_string_total_size = num_bytes; 3301 gc_count_string_total_size = num_bytes;
3087 gc_count_short_string_total_size = num_small_bytes; 3302 gc_count_short_string_total_size = num_small_bytes;
3088 } 3303 }
3186 to turn those strings into garbage. 3401 to turn those strings into garbage.
3187 */ 3402 */
3188 3403
3189 /* Yeah, this list is pretty ad-hoc... */ 3404 /* Yeah, this list is pretty ad-hoc... */
3190 Vprocess_environment = Qnil; 3405 Vprocess_environment = Qnil;
3406 env_initted = 0;
3191 Vexec_directory = Qnil; 3407 Vexec_directory = Qnil;
3192 Vdata_directory = Qnil; 3408 Vdata_directory = Qnil;
3193 Vsite_directory = Qnil; 3409 Vsite_directory = Qnil;
3194 Vdoc_directory = Qnil; 3410 Vdoc_directory = Qnil;
3195 Vconfigure_info_directory = Qnil; 3411 Vconfigure_info_directory = Qnil;
3196 Vexec_path = Qnil; 3412 Vexec_path = Qnil;
3197 Vload_path = Qnil; 3413 Vload_path = Qnil;
3198 /* Vdump_load_path = Qnil; */ 3414 /* Vdump_load_path = Qnil; */
3199 /* Release hash tables for locate_file */ 3415 /* Release hash tables for locate_file */
3200 Flocate_file_clear_hashing (Qt); 3416 Flocate_file_clear_hashing (Qt);
3201 uncache_home_directory(); 3417 uncache_home_directory ();
3202 3418
3203 #if defined(LOADHIST) && !(defined(LOADHIST_DUMPED) || \ 3419 #if defined(LOADHIST) && !(defined(LOADHIST_DUMPED) || \
3204 defined(LOADHIST_BUILTIN)) 3420 defined(LOADHIST_BUILTIN))
3205 Vload_history = Qnil; 3421 Vload_history = Qnil;
3206 #endif 3422 #endif
3231 /* There, that ought to be enough... */ 3447 /* There, that ought to be enough... */
3232 3448
3233 } 3449 }
3234 3450
3235 3451
3236 Lisp_Object 3452 static Lisp_Object
3237 restore_gc_inhibit (Lisp_Object val) 3453 restore_gc_inhibit (Lisp_Object val)
3238 { 3454 {
3239 gc_currently_forbidden = XINT (val); 3455 gc_currently_forbidden = XINT (val);
3240 return val; 3456 return val;
3457 }
3458
3459 int
3460 begin_gc_forbidden (void)
3461 {
3462 int speccount = record_unwind_protect (restore_gc_inhibit,
3463 make_int (gc_currently_forbidden));
3464 gc_currently_forbidden = 1;
3465 return speccount;
3466 }
3467
3468 void
3469 end_gc_forbidden (int count)
3470 {
3471 unbind_to (count);
3241 } 3472 }
3242 3473
3243 /* Maybe we want to use this when doing a "panic" gc after memory_full()? */ 3474 /* Maybe we want to use this when doing a "panic" gc after memory_full()? */
3244 static int gc_hooks_inhibited; 3475 static int gc_hooks_inhibited;
3245 3476
3339 GCPRO1 (pre_gc_cursor); 3570 GCPRO1 (pre_gc_cursor);
3340 3571
3341 /* Very important to prevent GC during any of the following 3572 /* Very important to prevent GC during any of the following
3342 stuff that might run Lisp code; otherwise, we'll likely 3573 stuff that might run Lisp code; otherwise, we'll likely
3343 have infinite GC recursion. */ 3574 have infinite GC recursion. */
3344 speccount = specpdl_depth (); 3575 speccount = begin_gc_forbidden ();
3345 record_unwind_protect (restore_gc_inhibit,
3346 make_int (gc_currently_forbidden));
3347 gc_currently_forbidden = 1;
3348 3576
3349 if (!gc_hooks_inhibited) 3577 if (!gc_hooks_inhibited)
3350 run_hook_trapping_errors ("Error in pre-gc-hook", Qpre_gc_hook); 3578 run_hook_trapping_errors ("Error in pre-gc-hook", Qpre_gc_hook);
3351 3579
3352 /* Now show the GC cursor/message. */ 3580 /* Now show the GC cursor/message. */
3353 if (!noninteractive) 3581 if (!noninteractive)
3354 { 3582 {
3355 if (FRAME_WIN_P (f)) 3583 if (FRAME_WIN_P (f))
3356 { 3584 {
3357 Lisp_Object frame = make_frame (f); 3585 Lisp_Object frame = wrap_frame (f);
3358 Lisp_Object cursor = glyph_image_instance (Vgc_pointer_glyph, 3586 Lisp_Object cursor = glyph_image_instance (Vgc_pointer_glyph,
3359 FRAME_SELECTED_WINDOW (f), 3587 FRAME_SELECTED_WINDOW (f),
3360 ERROR_ME_NOT, 1); 3588 ERROR_ME_NOT, 1);
3361 pre_gc_cursor = f->pointer; 3589 pre_gc_cursor = f->pointer;
3362 if (POINTER_IMAGE_INSTANCEP (cursor) 3590 if (POINTER_IMAGE_INSTANCEP (cursor)
3369 } 3597 }
3370 3598
3371 /* Don't print messages to the stream device. */ 3599 /* Don't print messages to the stream device. */
3372 if (!cursor_changed && !FRAME_STREAM_P (f)) 3600 if (!cursor_changed && !FRAME_STREAM_P (f))
3373 { 3601 {
3374 char *msg = (STRINGP (Vgc_message)
3375 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message))
3376 : 0);
3377 Lisp_Object args[2], whole_msg; 3602 Lisp_Object args[2], whole_msg;
3378 args[0] = build_string (msg ? msg : 3603 args[0] = (STRINGP (Vgc_message) ? Vgc_message :
3379 GETTEXT ((const char *) gc_default_message)); 3604 build_msg_string (gc_default_message));
3380 args[1] = build_string ("..."); 3605 args[1] = build_string ("...");
3381 whole_msg = Fconcat (2, args); 3606 whole_msg = Fconcat (2, args);
3382 echo_area_message (f, (Intbyte *) 0, whole_msg, 0, -1, 3607 echo_area_message (f, (Intbyte *) 0, whole_msg, 0, -1,
3383 Qgarbage_collecting); 3608 Qgarbage_collecting);
3384 } 3609 }
3385 } 3610 }
3386 3611
3387 /***** Now we actually start the garbage collection. */ 3612 /***** Now we actually start the garbage collection. */
3388 3613
3389 gc_in_progress = 1; 3614 gc_in_progress = 1;
3615 inhibit_non_essential_printing_operations = 1;
3390 3616
3391 gc_generation_number[0]++; 3617 gc_generation_number[0]++;
3392 3618
3393 #if MAX_SAVE_STACK > 0 3619 #if MAX_SAVE_STACK > 0
3394 3620
3508 /* Allow you to set it really fucking low if you really want ... */ 3734 /* Allow you to set it really fucking low if you really want ... */
3509 if (gc_cons_threshold < 10000) 3735 if (gc_cons_threshold < 10000)
3510 gc_cons_threshold = 10000; 3736 gc_cons_threshold = 10000;
3511 #endif 3737 #endif
3512 3738
3739 inhibit_non_essential_printing_operations = 0;
3513 gc_in_progress = 0; 3740 gc_in_progress = 0;
3514 3741
3515 run_post_gc_actions (); 3742 run_post_gc_actions ();
3516 3743
3517 /******* End of garbage collection ********/ 3744 /******* End of garbage collection ********/
3520 3747
3521 /* Now remove the GC cursor/message */ 3748 /* Now remove the GC cursor/message */
3522 if (!noninteractive) 3749 if (!noninteractive)
3523 { 3750 {
3524 if (cursor_changed) 3751 if (cursor_changed)
3525 Fset_frame_pointer (make_frame (f), pre_gc_cursor); 3752 Fset_frame_pointer (wrap_frame (f), pre_gc_cursor);
3526 else if (!FRAME_STREAM_P (f)) 3753 else if (!FRAME_STREAM_P (f))
3527 { 3754 {
3528 char *msg = (STRINGP (Vgc_message)
3529 ? GETTEXT ((char *) XSTRING_DATA (Vgc_message))
3530 : 0);
3531
3532 /* Show "...done" only if the echo area would otherwise be empty. */ 3755 /* Show "...done" only if the echo area would otherwise be empty. */
3533 if (NILP (clear_echo_area (selected_frame (), 3756 if (NILP (clear_echo_area (selected_frame (),
3534 Qgarbage_collecting, 0))) 3757 Qgarbage_collecting, 0)))
3535 { 3758 {
3536 Lisp_Object args[2], whole_msg; 3759 Lisp_Object args[2], whole_msg;
3537 args[0] = build_string (msg ? msg : 3760 args[0] = (STRINGP (Vgc_message) ? Vgc_message :
3538 GETTEXT ((const char *) 3761 build_msg_string (gc_default_message));
3539 gc_default_message)); 3762 args[1] = build_msg_string ("... done");
3540 args[1] = build_string ("... done");
3541 whole_msg = Fconcat (2, args); 3763 whole_msg = Fconcat (2, args);
3542 echo_area_message (selected_frame (), (Intbyte *) 0, 3764 echo_area_message (selected_frame (), (Intbyte *) 0,
3543 whole_msg, 0, -1, 3765 whole_msg, 0, -1,
3544 Qgarbage_collecting); 3766 Qgarbage_collecting);
3545 } 3767 }
3546 } 3768 }
3547 } 3769 }
3548 3770
3549 /* now stop inhibiting GC */ 3771 /* now stop inhibiting GC */
3550 unbind_to (speccount, Qnil); 3772 unbind_to (speccount);
3551 3773
3552 if (!breathing_space) 3774 if (!breathing_space)
3553 { 3775 {
3554 breathing_space = malloc (4096 - MALLOC_OVERHEAD); 3776 breathing_space = malloc (4096 - MALLOC_OVERHEAD);
3555 } 3777 }
3559 } 3781 }
3560 3782
3561 /* Debugging aids. */ 3783 /* Debugging aids. */
3562 3784
3563 static Lisp_Object 3785 static Lisp_Object
3564 gc_plist_hack (const char *name, int value, Lisp_Object tail) 3786 gc_plist_hack (const Char_ASCII *name, int value, Lisp_Object tail)
3565 { 3787 {
3566 /* C doesn't have local functions (or closures, or GC, or readable syntax, 3788 /* C doesn't have local functions (or closures, or GC, or readable syntax,
3567 or portable numeric datatypes, or bit-vectors, or characters, or 3789 or portable numeric datatypes, or bit-vectors, or characters, or
3568 arrays, or exceptions, or ...) */ 3790 arrays, or exceptions, or ...) */
3569 return cons3 (intern (name), make_int (value), tail); 3791 return cons3 (intern (name), make_int (value), tail);
3866 4088
3867 #endif /* MEMORY_USAGE_STATS */ 4089 #endif /* MEMORY_USAGE_STATS */
3868 4090
3869 4091
3870 /* Initialization */ 4092 /* Initialization */
3871 void 4093 static void
3872 reinit_alloc_once_early (void) 4094 common_init_alloc_once_early (void)
3873 { 4095 {
4096 #ifndef Qzero
4097 Qzero = make_int (0); /* Only used if Lisp_Object is a union type */
4098 #endif
4099
4100 #ifndef Qnull_pointer
4101 /* C guarantees that Qnull_pointer will be initialized to all 0 bits,
4102 so the following is actually a no-op. */
4103 XSETOBJ (Qnull_pointer, 0);
4104 #endif
4105
3874 gc_generation_number[0] = 0; 4106 gc_generation_number[0] = 0;
3875 breathing_space = 0; 4107 breathing_space = 0;
3876 XSETINT (all_bit_vectors, 0); /* Qzero may not be set yet. */ 4108 all_bit_vectors = Qzero;
3877 XSETINT (Vgc_message, 0); 4109 Vgc_message = Qzero;
3878 all_lcrecords = 0; 4110 all_lcrecords = 0;
3879 ignore_malloc_warnings = 1; 4111 ignore_malloc_warnings = 1;
3880 #ifdef DOUG_LEA_MALLOC 4112 #ifdef DOUG_LEA_MALLOC
3881 mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ 4113 mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */
3882 mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */ 4114 mallopt (M_MMAP_THRESHOLD, 64*1024); /* mmap threshold */
3900 4132
3901 if (staticpros_nodump) 4133 if (staticpros_nodump)
3902 Dynarr_free (staticpros_nodump); 4134 Dynarr_free (staticpros_nodump);
3903 staticpros_nodump = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); 4135 staticpros_nodump = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
3904 Dynarr_resize (staticpros_nodump, 100); /* merely a small optimization */ 4136 Dynarr_resize (staticpros_nodump, 100); /* merely a small optimization */
4137 #ifdef DEBUG_XEMACS
4138 if (staticpro_nodump_names)
4139 Dynarr_free (staticpro_nodump_names);
4140 staticpro_nodump_names = Dynarr_new2 (char_ptr_dynarr, char *);
4141 Dynarr_resize (staticpro_nodump_names, 100); /* ditto */
4142 #endif
3905 4143
3906 consing_since_gc = 0; 4144 consing_since_gc = 0;
3907 #if 1 4145 #if 1
3908 gc_cons_threshold = 500000; /* XEmacs change */ 4146 gc_cons_threshold = 500000; /* XEmacs change */
3909 #else 4147 #else
3925 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure = 4163 really_unlikely_name_to_have_accidentally_in_a_non_errb_structure =
3926 3333632; 4164 3333632;
3927 #endif /* ERROR_CHECK_TYPECHECK */ 4165 #endif /* ERROR_CHECK_TYPECHECK */
3928 } 4166 }
3929 4167
4168 static void
4169 init_lcrecord_lists (void)
4170 {
4171 int i;
4172
4173 for (i = 0; i < countof (lrecord_implementations_table); i++)
4174 {
4175 all_lcrecord_lists[i] = Qzero; /* Qnil not yet set */
4176 staticpro_nodump (&all_lcrecord_lists[i]);
4177 }
4178 }
4179
4180 void
4181 reinit_alloc_once_early (void)
4182 {
4183 common_init_alloc_once_early ();
4184 init_lcrecord_lists ();
4185 }
4186
3930 void 4187 void
3931 init_alloc_once_early (void) 4188 init_alloc_once_early (void)
3932 { 4189 {
3933 reinit_alloc_once_early (); 4190 common_init_alloc_once_early ();
3934 4191
3935 { 4192 {
3936 int i; 4193 int i;
3937 for (i = 0; i < countof (lrecord_implementations_table); i++) 4194 for (i = 0; i < countof (lrecord_implementations_table); i++)
3938 lrecord_implementations_table[i] = 0; 4195 lrecord_implementations_table[i] = 0;
3944 INIT_LRECORD_IMPLEMENTATION (lcrecord_list); 4201 INIT_LRECORD_IMPLEMENTATION (lcrecord_list);
3945 4202
3946 staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *); 4203 staticpros = Dynarr_new2 (Lisp_Object_ptr_dynarr, Lisp_Object *);
3947 Dynarr_resize (staticpros, 1410); /* merely a small optimization */ 4204 Dynarr_resize (staticpros, 1410); /* merely a small optimization */
3948 dump_add_root_struct_ptr (&staticpros, &staticpros_description); 4205 dump_add_root_struct_ptr (&staticpros, &staticpros_description);
4206 #ifdef DEBUG_XEMACS
4207 staticpro_names = Dynarr_new2 (char_ptr_dynarr, char *);
4208 Dynarr_resize (staticpro_names, 1410); /* merely a small optimization */
4209 dump_add_root_struct_ptr (&staticpro_names, &staticpro_names_description);
4210 #endif
4211
4212 init_lcrecord_lists ();
3949 } 4213 }
3950 4214
3951 void 4215 void
3952 reinit_alloc (void) 4216 init_alloc_early (void)
3953 { 4217 {
3954 gcprolist = 0; 4218 gcprolist = 0;
3955 } 4219 }
3956 4220
3957 void 4221 void