Mercurial > hg > xemacs-beta
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 = ¤t_##typename##_block, \ | 2886 for (SFTB_prev = ¤t_##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 |