diff options
| author | Kenichi Handa | 2012-08-16 21:25:17 +0900 |
|---|---|---|
| committer | Kenichi Handa | 2012-08-16 21:25:17 +0900 |
| commit | d75ffb4ed0b2e72a9361a07d16a5c884a9459728 (patch) | |
| tree | 8ac5a6a8ae033fef7fbc7fb7b09a703ef4b0ed5b /src/alloc.c | |
| parent | 69c41c4070c86baac11a627e9c3d366420aeb7cc (diff) | |
| parent | 250c8ab9b8f6322959fa3122db83944c30c3894b (diff) | |
| download | emacs-d75ffb4ed0b2e72a9361a07d16a5c884a9459728.tar.gz emacs-d75ffb4ed0b2e72a9361a07d16a5c884a9459728.zip | |
merge trunk
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 720 |
1 files changed, 404 insertions, 316 deletions
diff --git a/src/alloc.c b/src/alloc.c index 39c360a67e7..1d484d4a322 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -19,6 +19,9 @@ You should have received a copy of the GNU General Public License | |||
| 19 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | 19 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ |
| 20 | 20 | ||
| 21 | #include <config.h> | 21 | #include <config.h> |
| 22 | |||
| 23 | #define LISP_INLINE EXTERN_INLINE | ||
| 24 | |||
| 22 | #include <stdio.h> | 25 | #include <stdio.h> |
| 23 | #include <limits.h> /* For CHAR_BIT. */ | 26 | #include <limits.h> /* For CHAR_BIT. */ |
| 24 | #include <setjmp.h> | 27 | #include <setjmp.h> |
| @@ -29,11 +32,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | |||
| 29 | #include <pthread.h> | 32 | #include <pthread.h> |
| 30 | #endif | 33 | #endif |
| 31 | 34 | ||
| 32 | /* This file is part of the core Lisp implementation, and thus must | ||
| 33 | deal with the real data structures. If the Lisp implementation is | ||
| 34 | replaced, this file likely will not be used. */ | ||
| 35 | |||
| 36 | #undef HIDE_LISP_IMPLEMENTATION | ||
| 37 | #include "lisp.h" | 35 | #include "lisp.h" |
| 38 | #include "process.h" | 36 | #include "process.h" |
| 39 | #include "intervals.h" | 37 | #include "intervals.h" |
| @@ -155,11 +153,9 @@ static pthread_mutex_t alloc_mutex; | |||
| 155 | #define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG) | 153 | #define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG) |
| 156 | #define VECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0) | 154 | #define VECTOR_MARKED_P(V) (((V)->header.size & ARRAY_MARK_FLAG) != 0) |
| 157 | 155 | ||
| 158 | /* Value is the number of bytes of S, a pointer to a struct Lisp_String. | 156 | /* Default value of gc_cons_threshold (see below). */ |
| 159 | Be careful during GC, because S->size contains the mark bit for | ||
| 160 | strings. */ | ||
| 161 | 157 | ||
| 162 | #define GC_STRING_BYTES(S) (STRING_BYTES (S)) | 158 | #define GC_DEFAULT_THRESHOLD (100000 * word_size) |
| 163 | 159 | ||
| 164 | /* Global variables. */ | 160 | /* Global variables. */ |
| 165 | struct emacs_globals globals; | 161 | struct emacs_globals globals; |
| @@ -189,7 +185,7 @@ int abort_on_gc; | |||
| 189 | 185 | ||
| 190 | /* Number of live and free conses etc. */ | 186 | /* Number of live and free conses etc. */ |
| 191 | 187 | ||
| 192 | static EMACS_INT total_conses, total_markers, total_symbols, total_vector_size; | 188 | static EMACS_INT total_conses, total_markers, total_symbols, total_buffers; |
| 193 | static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; | 189 | static EMACS_INT total_free_conses, total_free_markers, total_free_symbols; |
| 194 | static EMACS_INT total_free_floats, total_floats; | 190 | static EMACS_INT total_free_floats, total_floats; |
| 195 | 191 | ||
| @@ -232,7 +228,7 @@ static ptrdiff_t pure_bytes_used_before_overflow; | |||
| 232 | #define PURE_POINTER_P(P) \ | 228 | #define PURE_POINTER_P(P) \ |
| 233 | ((uintptr_t) (P) - (uintptr_t) purebeg <= pure_size) | 229 | ((uintptr_t) (P) - (uintptr_t) purebeg <= pure_size) |
| 234 | 230 | ||
| 235 | /* Index in pure at which next pure Lisp object will be allocated.. */ | 231 | /* Index in pure at which next pure Lisp object will be allocated.. */ |
| 236 | 232 | ||
| 237 | static ptrdiff_t pure_bytes_used_lisp; | 233 | static ptrdiff_t pure_bytes_used_lisp; |
| 238 | 234 | ||
| @@ -258,6 +254,15 @@ static char *stack_copy; | |||
| 258 | static ptrdiff_t stack_copy_size; | 254 | static ptrdiff_t stack_copy_size; |
| 259 | #endif | 255 | #endif |
| 260 | 256 | ||
| 257 | static Lisp_Object Qconses; | ||
| 258 | static Lisp_Object Qsymbols; | ||
| 259 | static Lisp_Object Qmiscs; | ||
| 260 | static Lisp_Object Qstrings; | ||
| 261 | static Lisp_Object Qvectors; | ||
| 262 | static Lisp_Object Qfloats; | ||
| 263 | static Lisp_Object Qintervals; | ||
| 264 | static Lisp_Object Qbuffers; | ||
| 265 | static Lisp_Object Qstring_bytes, Qvector_slots, Qheap; | ||
| 261 | static Lisp_Object Qgc_cons_threshold; | 266 | static Lisp_Object Qgc_cons_threshold; |
| 262 | Lisp_Object Qchar_table_extra_slots; | 267 | Lisp_Object Qchar_table_extra_slots; |
| 263 | 268 | ||
| @@ -520,16 +525,11 @@ buffer_memory_full (ptrdiff_t nbytes) | |||
| 520 | hold a size_t value and (2) the header size is a multiple of the | 525 | hold a size_t value and (2) the header size is a multiple of the |
| 521 | alignment that Emacs needs for C types and for USE_LSB_TAG. */ | 526 | alignment that Emacs needs for C types and for USE_LSB_TAG. */ |
| 522 | #define XMALLOC_BASE_ALIGNMENT \ | 527 | #define XMALLOC_BASE_ALIGNMENT \ |
| 523 | offsetof ( \ | 528 | alignof (union { long double d; intmax_t i; void *p; }) |
| 524 | struct { \ | ||
| 525 | union { long double d; intmax_t i; void *p; } u; \ | ||
| 526 | char c; \ | ||
| 527 | }, \ | ||
| 528 | c) | ||
| 529 | 529 | ||
| 530 | #if USE_LSB_TAG | 530 | #if USE_LSB_TAG |
| 531 | # define XMALLOC_HEADER_ALIGNMENT \ | 531 | # define XMALLOC_HEADER_ALIGNMENT \ |
| 532 | COMMON_MULTIPLE (1 << GCTYPEBITS, XMALLOC_BASE_ALIGNMENT) | 532 | COMMON_MULTIPLE (GCALIGNMENT, XMALLOC_BASE_ALIGNMENT) |
| 533 | #else | 533 | #else |
| 534 | # define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT | 534 | # define XMALLOC_HEADER_ALIGNMENT XMALLOC_BASE_ALIGNMENT |
| 535 | #endif | 535 | #endif |
| @@ -898,6 +898,16 @@ safe_alloca_unwind (Lisp_Object arg) | |||
| 898 | return Qnil; | 898 | return Qnil; |
| 899 | } | 899 | } |
| 900 | 900 | ||
| 901 | /* Return a newly allocated memory block of SIZE bytes, remembering | ||
| 902 | to free it when unwinding. */ | ||
| 903 | void * | ||
| 904 | record_xmalloc (size_t size) | ||
| 905 | { | ||
| 906 | void *p = xmalloc (size); | ||
| 907 | record_unwind_protect (safe_alloca_unwind, make_save_value (p, 0)); | ||
| 908 | return p; | ||
| 909 | } | ||
| 910 | |||
| 901 | 911 | ||
| 902 | /* Like malloc but used for allocating Lisp data. NBYTES is the | 912 | /* Like malloc but used for allocating Lisp data. NBYTES is the |
| 903 | number of bytes to allocate, TYPE describes the intended use of the | 913 | number of bytes to allocate, TYPE describes the intended use of the |
| @@ -1512,6 +1522,7 @@ make_interval (void) | |||
| 1512 | newi->next = interval_block; | 1522 | newi->next = interval_block; |
| 1513 | interval_block = newi; | 1523 | interval_block = newi; |
| 1514 | interval_block_index = 0; | 1524 | interval_block_index = 0; |
| 1525 | total_free_intervals += INTERVAL_BLOCK_SIZE; | ||
| 1515 | } | 1526 | } |
| 1516 | val = &interval_block->intervals[interval_block_index++]; | 1527 | val = &interval_block->intervals[interval_block_index++]; |
| 1517 | } | 1528 | } |
| @@ -1520,6 +1531,7 @@ make_interval (void) | |||
| 1520 | 1531 | ||
| 1521 | consing_since_gc += sizeof (struct interval); | 1532 | consing_since_gc += sizeof (struct interval); |
| 1522 | intervals_consed++; | 1533 | intervals_consed++; |
| 1534 | total_free_intervals--; | ||
| 1523 | RESET_INTERVAL (val); | 1535 | RESET_INTERVAL (val); |
| 1524 | val->gcmarkbit = 0; | 1536 | val->gcmarkbit = 0; |
| 1525 | return val; | 1537 | return val; |
| @@ -1531,41 +1543,21 @@ make_interval (void) | |||
| 1531 | static void | 1543 | static void |
| 1532 | mark_interval (register INTERVAL i, Lisp_Object dummy) | 1544 | mark_interval (register INTERVAL i, Lisp_Object dummy) |
| 1533 | { | 1545 | { |
| 1534 | eassert (!i->gcmarkbit); /* Intervals are never shared. */ | 1546 | /* Intervals should never be shared. So, if extra internal checking is |
| 1547 | enabled, GC aborts if it seems to have visited an interval twice. */ | ||
| 1548 | eassert (!i->gcmarkbit); | ||
| 1535 | i->gcmarkbit = 1; | 1549 | i->gcmarkbit = 1; |
| 1536 | mark_object (i->plist); | 1550 | mark_object (i->plist); |
| 1537 | } | 1551 | } |
| 1538 | 1552 | ||
| 1539 | |||
| 1540 | /* Mark the interval tree rooted in TREE. Don't call this directly; | ||
| 1541 | use the macro MARK_INTERVAL_TREE instead. */ | ||
| 1542 | |||
| 1543 | static void | ||
| 1544 | mark_interval_tree (register INTERVAL tree) | ||
| 1545 | { | ||
| 1546 | /* No need to test if this tree has been marked already; this | ||
| 1547 | function is always called through the MARK_INTERVAL_TREE macro, | ||
| 1548 | which takes care of that. */ | ||
| 1549 | |||
| 1550 | traverse_intervals_noorder (tree, mark_interval, Qnil); | ||
| 1551 | } | ||
| 1552 | |||
| 1553 | |||
| 1554 | /* Mark the interval tree rooted in I. */ | 1553 | /* Mark the interval tree rooted in I. */ |
| 1555 | 1554 | ||
| 1556 | #define MARK_INTERVAL_TREE(i) \ | 1555 | #define MARK_INTERVAL_TREE(i) \ |
| 1557 | do { \ | 1556 | do { \ |
| 1558 | if (!NULL_INTERVAL_P (i) && !i->gcmarkbit) \ | 1557 | if (i && !i->gcmarkbit) \ |
| 1559 | mark_interval_tree (i); \ | 1558 | traverse_intervals_noorder (i, mark_interval, Qnil); \ |
| 1560 | } while (0) | 1559 | } while (0) |
| 1561 | 1560 | ||
| 1562 | |||
| 1563 | #define UNMARK_BALANCE_INTERVALS(i) \ | ||
| 1564 | do { \ | ||
| 1565 | if (! NULL_INTERVAL_P (i)) \ | ||
| 1566 | (i) = balance_intervals (i); \ | ||
| 1567 | } while (0) | ||
| 1568 | |||
| 1569 | /*********************************************************************** | 1561 | /*********************************************************************** |
| 1570 | String Allocation | 1562 | String Allocation |
| 1571 | ***********************************************************************/ | 1563 | ***********************************************************************/ |
| @@ -1704,7 +1696,7 @@ static EMACS_INT total_strings, total_free_strings; | |||
| 1704 | 1696 | ||
| 1705 | /* Number of bytes used by live strings. */ | 1697 | /* Number of bytes used by live strings. */ |
| 1706 | 1698 | ||
| 1707 | static EMACS_INT total_string_size; | 1699 | static EMACS_INT total_string_bytes; |
| 1708 | 1700 | ||
| 1709 | /* Given a pointer to a Lisp_String S which is on the free-list | 1701 | /* Given a pointer to a Lisp_String S which is on the free-list |
| 1710 | string_free_list, return a pointer to its successor in the | 1702 | string_free_list, return a pointer to its successor in the |
| @@ -1773,13 +1765,13 @@ static char const string_overrun_cookie[GC_STRING_OVERRUN_COOKIE_SIZE] = | |||
| 1773 | STRING_BYTES_BOUND, nor can it be so long that the size_t | 1765 | STRING_BYTES_BOUND, nor can it be so long that the size_t |
| 1774 | arithmetic in allocate_string_data would overflow while it is | 1766 | arithmetic in allocate_string_data would overflow while it is |
| 1775 | calculating a value to be passed to malloc. */ | 1767 | calculating a value to be passed to malloc. */ |
| 1776 | #define STRING_BYTES_MAX \ | 1768 | static ptrdiff_t const STRING_BYTES_MAX = |
| 1777 | min (STRING_BYTES_BOUND, \ | 1769 | min (STRING_BYTES_BOUND, |
| 1778 | ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD \ | 1770 | ((SIZE_MAX - XMALLOC_OVERRUN_CHECK_OVERHEAD |
| 1779 | - GC_STRING_EXTRA \ | 1771 | - GC_STRING_EXTRA |
| 1780 | - offsetof (struct sblock, first_data) \ | 1772 | - offsetof (struct sblock, first_data) |
| 1781 | - SDATA_DATA_OFFSET) \ | 1773 | - SDATA_DATA_OFFSET) |
| 1782 | & ~(sizeof (EMACS_INT) - 1))) | 1774 | & ~(sizeof (EMACS_INT) - 1))); |
| 1783 | 1775 | ||
| 1784 | /* Initialize string allocation. Called from init_alloc_once. */ | 1776 | /* Initialize string allocation. Called from init_alloc_once. */ |
| 1785 | 1777 | ||
| @@ -1795,10 +1787,8 @@ init_strings (void) | |||
| 1795 | 1787 | ||
| 1796 | static int check_string_bytes_count; | 1788 | static int check_string_bytes_count; |
| 1797 | 1789 | ||
| 1798 | #define CHECK_STRING_BYTES(S) STRING_BYTES (S) | 1790 | /* Like STRING_BYTES, but with debugging check. Can be |
| 1799 | 1791 | called during GC, so pay attention to the mark bit. */ | |
| 1800 | |||
| 1801 | /* Like GC_STRING_BYTES, but with debugging check. */ | ||
| 1802 | 1792 | ||
| 1803 | ptrdiff_t | 1793 | ptrdiff_t |
| 1804 | string_bytes (struct Lisp_String *s) | 1794 | string_bytes (struct Lisp_String *s) |
| @@ -1830,15 +1820,8 @@ check_sblock (struct sblock *b) | |||
| 1830 | 1820 | ||
| 1831 | /* Check that the string size recorded in the string is the | 1821 | /* Check that the string size recorded in the string is the |
| 1832 | same as the one recorded in the sdata structure. */ | 1822 | same as the one recorded in the sdata structure. */ |
| 1833 | if (from->string) | 1823 | nbytes = SDATA_SIZE (from->string ? string_bytes (from->string) |
| 1834 | CHECK_STRING_BYTES (from->string); | 1824 | : SDATA_NBYTES (from)); |
| 1835 | |||
| 1836 | if (from->string) | ||
| 1837 | nbytes = GC_STRING_BYTES (from->string); | ||
| 1838 | else | ||
| 1839 | nbytes = SDATA_NBYTES (from); | ||
| 1840 | |||
| 1841 | nbytes = SDATA_SIZE (nbytes); | ||
| 1842 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 1825 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| 1843 | } | 1826 | } |
| 1844 | } | 1827 | } |
| @@ -1859,7 +1842,7 @@ check_string_bytes (int all_p) | |||
| 1859 | { | 1842 | { |
| 1860 | struct Lisp_String *s = b->first_data.string; | 1843 | struct Lisp_String *s = b->first_data.string; |
| 1861 | if (s) | 1844 | if (s) |
| 1862 | CHECK_STRING_BYTES (s); | 1845 | string_bytes (s); |
| 1863 | } | 1846 | } |
| 1864 | 1847 | ||
| 1865 | for (b = oldest_sblock; b; b = b->next) | 1848 | for (b = oldest_sblock; b; b = b->next) |
| @@ -1869,6 +1852,10 @@ check_string_bytes (int all_p) | |||
| 1869 | check_sblock (current_sblock); | 1852 | check_sblock (current_sblock); |
| 1870 | } | 1853 | } |
| 1871 | 1854 | ||
| 1855 | #else /* not GC_CHECK_STRING_BYTES */ | ||
| 1856 | |||
| 1857 | #define check_string_bytes(all) ((void) 0) | ||
| 1858 | |||
| 1872 | #endif /* GC_CHECK_STRING_BYTES */ | 1859 | #endif /* GC_CHECK_STRING_BYTES */ |
| 1873 | 1860 | ||
| 1874 | #ifdef GC_CHECK_STRING_FREE_LIST | 1861 | #ifdef GC_CHECK_STRING_FREE_LIST |
| @@ -1967,9 +1954,9 @@ void | |||
| 1967 | allocate_string_data (struct Lisp_String *s, | 1954 | allocate_string_data (struct Lisp_String *s, |
| 1968 | EMACS_INT nchars, EMACS_INT nbytes) | 1955 | EMACS_INT nchars, EMACS_INT nbytes) |
| 1969 | { | 1956 | { |
| 1970 | struct sdata *data; | 1957 | struct sdata *data, *old_data; |
| 1971 | struct sblock *b; | 1958 | struct sblock *b; |
| 1972 | ptrdiff_t needed; | 1959 | ptrdiff_t needed, old_nbytes; |
| 1973 | 1960 | ||
| 1974 | if (STRING_BYTES_MAX < nbytes) | 1961 | if (STRING_BYTES_MAX < nbytes) |
| 1975 | string_overflow (); | 1962 | string_overflow (); |
| @@ -1977,6 +1964,13 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1977 | /* Determine the number of bytes needed to store NBYTES bytes | 1964 | /* Determine the number of bytes needed to store NBYTES bytes |
| 1978 | of string data. */ | 1965 | of string data. */ |
| 1979 | needed = SDATA_SIZE (nbytes); | 1966 | needed = SDATA_SIZE (nbytes); |
| 1967 | if (s->data) | ||
| 1968 | { | ||
| 1969 | old_data = SDATA_OF_STRING (s); | ||
| 1970 | old_nbytes = STRING_BYTES (s); | ||
| 1971 | } | ||
| 1972 | else | ||
| 1973 | old_data = NULL; | ||
| 1980 | 1974 | ||
| 1981 | MALLOC_BLOCK_INPUT; | 1975 | MALLOC_BLOCK_INPUT; |
| 1982 | 1976 | ||
| @@ -2046,6 +2040,16 @@ allocate_string_data (struct Lisp_String *s, | |||
| 2046 | memcpy ((char *) data + needed, string_overrun_cookie, | 2040 | memcpy ((char *) data + needed, string_overrun_cookie, |
| 2047 | GC_STRING_OVERRUN_COOKIE_SIZE); | 2041 | GC_STRING_OVERRUN_COOKIE_SIZE); |
| 2048 | #endif | 2042 | #endif |
| 2043 | |||
| 2044 | /* Note that Faset may call to this function when S has already data | ||
| 2045 | assigned. In this case, mark data as free by setting it's string | ||
| 2046 | back-pointer to null, and record the size of the data in it. */ | ||
| 2047 | if (old_data) | ||
| 2048 | { | ||
| 2049 | SDATA_NBYTES (old_data) = old_nbytes; | ||
| 2050 | old_data->string = NULL; | ||
| 2051 | } | ||
| 2052 | |||
| 2049 | consing_since_gc += needed; | 2053 | consing_since_gc += needed; |
| 2050 | } | 2054 | } |
| 2051 | 2055 | ||
| @@ -2060,7 +2064,7 @@ sweep_strings (void) | |||
| 2060 | 2064 | ||
| 2061 | string_free_list = NULL; | 2065 | string_free_list = NULL; |
| 2062 | total_strings = total_free_strings = 0; | 2066 | total_strings = total_free_strings = 0; |
| 2063 | total_string_size = 0; | 2067 | total_string_bytes = 0; |
| 2064 | 2068 | ||
| 2065 | /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ | 2069 | /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ |
| 2066 | for (b = string_blocks; b; b = next) | 2070 | for (b = string_blocks; b; b = next) |
| @@ -2082,11 +2086,11 @@ sweep_strings (void) | |||
| 2082 | /* String is live; unmark it and its intervals. */ | 2086 | /* String is live; unmark it and its intervals. */ |
| 2083 | UNMARK_STRING (s); | 2087 | UNMARK_STRING (s); |
| 2084 | 2088 | ||
| 2085 | if (!NULL_INTERVAL_P (s->intervals)) | 2089 | /* Do not use string_(set|get)_intervals here. */ |
| 2086 | UNMARK_BALANCE_INTERVALS (s->intervals); | 2090 | s->intervals = balance_intervals (s->intervals); |
| 2087 | 2091 | ||
| 2088 | ++total_strings; | 2092 | ++total_strings; |
| 2089 | total_string_size += STRING_BYTES (s); | 2093 | total_string_bytes += STRING_BYTES (s); |
| 2090 | } | 2094 | } |
| 2091 | else | 2095 | else |
| 2092 | { | 2096 | { |
| @@ -2097,10 +2101,10 @@ sweep_strings (void) | |||
| 2097 | how large that is. Reset the sdata's string | 2101 | how large that is. Reset the sdata's string |
| 2098 | back-pointer so that we know it's free. */ | 2102 | back-pointer so that we know it's free. */ |
| 2099 | #ifdef GC_CHECK_STRING_BYTES | 2103 | #ifdef GC_CHECK_STRING_BYTES |
| 2100 | if (GC_STRING_BYTES (s) != SDATA_NBYTES (data)) | 2104 | if (string_bytes (s) != SDATA_NBYTES (data)) |
| 2101 | abort (); | 2105 | abort (); |
| 2102 | #else | 2106 | #else |
| 2103 | data->u.nbytes = GC_STRING_BYTES (s); | 2107 | data->u.nbytes = STRING_BYTES (s); |
| 2104 | #endif | 2108 | #endif |
| 2105 | data->string = NULL; | 2109 | data->string = NULL; |
| 2106 | 2110 | ||
| @@ -2203,22 +2207,17 @@ compact_small_strings (void) | |||
| 2203 | /* Compute the next FROM here because copying below may | 2207 | /* Compute the next FROM here because copying below may |
| 2204 | overwrite data we need to compute it. */ | 2208 | overwrite data we need to compute it. */ |
| 2205 | ptrdiff_t nbytes; | 2209 | ptrdiff_t nbytes; |
| 2210 | struct Lisp_String *s = from->string; | ||
| 2206 | 2211 | ||
| 2207 | #ifdef GC_CHECK_STRING_BYTES | 2212 | #ifdef GC_CHECK_STRING_BYTES |
| 2208 | /* Check that the string size recorded in the string is the | 2213 | /* Check that the string size recorded in the string is the |
| 2209 | same as the one recorded in the sdata structure. */ | 2214 | same as the one recorded in the sdata structure. */ |
| 2210 | if (from->string | 2215 | if (s && string_bytes (s) != SDATA_NBYTES (from)) |
| 2211 | && GC_STRING_BYTES (from->string) != SDATA_NBYTES (from)) | ||
| 2212 | abort (); | 2216 | abort (); |
| 2213 | #endif /* GC_CHECK_STRING_BYTES */ | 2217 | #endif /* GC_CHECK_STRING_BYTES */ |
| 2214 | 2218 | ||
| 2215 | if (from->string) | 2219 | nbytes = s ? STRING_BYTES (s) : SDATA_NBYTES (from); |
| 2216 | nbytes = GC_STRING_BYTES (from->string); | 2220 | eassert (nbytes <= LARGE_STRING_BYTES); |
| 2217 | else | ||
| 2218 | nbytes = SDATA_NBYTES (from); | ||
| 2219 | |||
| 2220 | if (nbytes > LARGE_STRING_BYTES) | ||
| 2221 | abort (); | ||
| 2222 | 2221 | ||
| 2223 | nbytes = SDATA_SIZE (nbytes); | 2222 | nbytes = SDATA_SIZE (nbytes); |
| 2224 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); | 2223 | from_end = (struct sdata *) ((char *) from + nbytes + GC_STRING_EXTRA); |
| @@ -2230,8 +2229,8 @@ compact_small_strings (void) | |||
| 2230 | abort (); | 2229 | abort (); |
| 2231 | #endif | 2230 | #endif |
| 2232 | 2231 | ||
| 2233 | /* FROM->string non-null means it's alive. Copy its data. */ | 2232 | /* Non-NULL S means it's alive. Copy its data. */ |
| 2234 | if (from->string) | 2233 | if (s) |
| 2235 | { | 2234 | { |
| 2236 | /* If TB is full, proceed with the next sblock. */ | 2235 | /* If TB is full, proceed with the next sblock. */ |
| 2237 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); | 2236 | to_end = (struct sdata *) ((char *) to + nbytes + GC_STRING_EXTRA); |
| @@ -2335,6 +2334,8 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2335 | ptrdiff_t length_in_chars; | 2334 | ptrdiff_t length_in_chars; |
| 2336 | EMACS_INT length_in_elts; | 2335 | EMACS_INT length_in_elts; |
| 2337 | int bits_per_value; | 2336 | int bits_per_value; |
| 2337 | int extra_bool_elts = ((bool_header_size - header_size + word_size - 1) | ||
| 2338 | / word_size); | ||
| 2338 | 2339 | ||
| 2339 | CHECK_NATNUM (length); | 2340 | CHECK_NATNUM (length); |
| 2340 | 2341 | ||
| @@ -2342,9 +2343,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2342 | 2343 | ||
| 2343 | length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value; | 2344 | length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value; |
| 2344 | 2345 | ||
| 2345 | /* We must allocate one more elements than LENGTH_IN_ELTS for the | 2346 | val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); |
| 2346 | slot `size' of the struct Lisp_Bool_Vector. */ | ||
| 2347 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); | ||
| 2348 | 2347 | ||
| 2349 | /* No Lisp_Object to trace in there. */ | 2348 | /* No Lisp_Object to trace in there. */ |
| 2350 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0); | 2349 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0); |
| @@ -2360,7 +2359,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2360 | 2359 | ||
| 2361 | /* Clear any extraneous bits in the last byte. */ | 2360 | /* Clear any extraneous bits in the last byte. */ |
| 2362 | p->data[length_in_chars - 1] | 2361 | p->data[length_in_chars - 1] |
| 2363 | &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1; | 2362 | &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1; |
| 2364 | } | 2363 | } |
| 2365 | 2364 | ||
| 2366 | return val; | 2365 | return val; |
| @@ -2489,7 +2488,7 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | |||
| 2489 | return empty_multibyte_string; | 2488 | return empty_multibyte_string; |
| 2490 | 2489 | ||
| 2491 | s = allocate_string (); | 2490 | s = allocate_string (); |
| 2492 | s->intervals = NULL_INTERVAL; | 2491 | s->intervals = NULL; |
| 2493 | allocate_string_data (s, nchars, nbytes); | 2492 | allocate_string_data (s, nchars, nbytes); |
| 2494 | XSETSTRING (string, s); | 2493 | XSETSTRING (string, s); |
| 2495 | string_chars_consed += nbytes; | 2494 | string_chars_consed += nbytes; |
| @@ -2603,6 +2602,7 @@ make_float (double float_value) | |||
| 2603 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); | 2602 | memset (new->gcmarkbits, 0, sizeof new->gcmarkbits); |
| 2604 | float_block = new; | 2603 | float_block = new; |
| 2605 | float_block_index = 0; | 2604 | float_block_index = 0; |
| 2605 | total_free_floats += FLOAT_BLOCK_SIZE; | ||
| 2606 | } | 2606 | } |
| 2607 | XSETFLOAT (val, &float_block->floats[float_block_index]); | 2607 | XSETFLOAT (val, &float_block->floats[float_block_index]); |
| 2608 | float_block_index++; | 2608 | float_block_index++; |
| @@ -2614,6 +2614,7 @@ make_float (double float_value) | |||
| 2614 | eassert (!FLOAT_MARKED_P (XFLOAT (val))); | 2614 | eassert (!FLOAT_MARKED_P (XFLOAT (val))); |
| 2615 | consing_since_gc += sizeof (struct Lisp_Float); | 2615 | consing_since_gc += sizeof (struct Lisp_Float); |
| 2616 | floats_consed++; | 2616 | floats_consed++; |
| 2617 | total_free_floats--; | ||
| 2617 | return val; | 2618 | return val; |
| 2618 | } | 2619 | } |
| 2619 | 2620 | ||
| @@ -2679,6 +2680,8 @@ free_cons (struct Lisp_Cons *ptr) | |||
| 2679 | ptr->car = Vdead; | 2680 | ptr->car = Vdead; |
| 2680 | #endif | 2681 | #endif |
| 2681 | cons_free_list = ptr; | 2682 | cons_free_list = ptr; |
| 2683 | consing_since_gc -= sizeof *ptr; | ||
| 2684 | total_free_conses++; | ||
| 2682 | } | 2685 | } |
| 2683 | 2686 | ||
| 2684 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, | 2687 | DEFUN ("cons", Fcons, Scons, 2, 2, 0, |
| @@ -2708,6 +2711,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2708 | new->next = cons_block; | 2711 | new->next = cons_block; |
| 2709 | cons_block = new; | 2712 | cons_block = new; |
| 2710 | cons_block_index = 0; | 2713 | cons_block_index = 0; |
| 2714 | total_free_conses += CONS_BLOCK_SIZE; | ||
| 2711 | } | 2715 | } |
| 2712 | XSETCONS (val, &cons_block->conses[cons_block_index]); | 2716 | XSETCONS (val, &cons_block->conses[cons_block_index]); |
| 2713 | cons_block_index++; | 2717 | cons_block_index++; |
| @@ -2719,6 +2723,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2719 | XSETCDR (val, cdr); | 2723 | XSETCDR (val, cdr); |
| 2720 | eassert (!CONS_MARKED_P (XCONS (val))); | 2724 | eassert (!CONS_MARKED_P (XCONS (val))); |
| 2721 | consing_since_gc += sizeof (struct Lisp_Cons); | 2725 | consing_since_gc += sizeof (struct Lisp_Cons); |
| 2726 | total_free_conses--; | ||
| 2722 | cons_cells_consed++; | 2727 | cons_cells_consed++; |
| 2723 | return val; | 2728 | return val; |
| 2724 | } | 2729 | } |
| @@ -2771,6 +2776,38 @@ list5 (Lisp_Object arg1, Lisp_Object arg2, Lisp_Object arg3, Lisp_Object arg4, L | |||
| 2771 | Fcons (arg5, Qnil))))); | 2776 | Fcons (arg5, Qnil))))); |
| 2772 | } | 2777 | } |
| 2773 | 2778 | ||
| 2779 | /* Make a list of COUNT Lisp_Objects, where ARG is the | ||
| 2780 | first one. Allocate conses from pure space if TYPE | ||
| 2781 | is CONSTYPE_PURE, or allocate as usual if type is CONSTYPE_HEAP. */ | ||
| 2782 | |||
| 2783 | Lisp_Object | ||
| 2784 | listn (enum constype type, ptrdiff_t count, Lisp_Object arg, ...) | ||
| 2785 | { | ||
| 2786 | va_list ap; | ||
| 2787 | ptrdiff_t i; | ||
| 2788 | Lisp_Object val, *objp; | ||
| 2789 | |||
| 2790 | /* Change to SAFE_ALLOCA if you hit this eassert. */ | ||
| 2791 | eassert (count <= MAX_ALLOCA / word_size); | ||
| 2792 | |||
| 2793 | objp = alloca (count * word_size); | ||
| 2794 | objp[0] = arg; | ||
| 2795 | va_start (ap, arg); | ||
| 2796 | for (i = 1; i < count; i++) | ||
| 2797 | objp[i] = va_arg (ap, Lisp_Object); | ||
| 2798 | va_end (ap); | ||
| 2799 | |||
| 2800 | for (val = Qnil, i = count - 1; i >= 0; i--) | ||
| 2801 | { | ||
| 2802 | if (type == CONSTYPE_PURE) | ||
| 2803 | val = pure_cons (objp[i], val); | ||
| 2804 | else if (type == CONSTYPE_HEAP) | ||
| 2805 | val = Fcons (objp[i], val); | ||
| 2806 | else | ||
| 2807 | abort (); | ||
| 2808 | } | ||
| 2809 | return val; | ||
| 2810 | } | ||
| 2774 | 2811 | ||
| 2775 | DEFUN ("list", Flist, Slist, 0, MANY, 0, | 2812 | DEFUN ("list", Flist, Slist, 0, MANY, 0, |
| 2776 | doc: /* Return a newly created list with specified arguments as elements. | 2813 | doc: /* Return a newly created list with specified arguments as elements. |
| @@ -2848,13 +2885,10 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | |||
| 2848 | 2885 | ||
| 2849 | #define VECTOR_BLOCK_SIZE 4096 | 2886 | #define VECTOR_BLOCK_SIZE 4096 |
| 2850 | 2887 | ||
| 2851 | /* Handy constants for vectorlike objects. */ | 2888 | /* Align allocation request sizes to be a multiple of ROUNDUP_SIZE. */ |
| 2852 | enum | 2889 | enum |
| 2853 | { | 2890 | { |
| 2854 | header_size = offsetof (struct Lisp_Vector, contents), | 2891 | roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1) |
| 2855 | word_size = sizeof (Lisp_Object), | ||
| 2856 | roundup_size = COMMON_MULTIPLE (sizeof (Lisp_Object), | ||
| 2857 | USE_LSB_TAG ? 1 << GCTYPEBITS : 1) | ||
| 2858 | }; | 2892 | }; |
| 2859 | 2893 | ||
| 2860 | /* ROUNDUP_SIZE must be a power of 2. */ | 2894 | /* ROUNDUP_SIZE must be a power of 2. */ |
| @@ -2879,7 +2913,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2879 | /* Size of the largest vector allocated from block. */ | 2913 | /* Size of the largest vector allocated from block. */ |
| 2880 | 2914 | ||
| 2881 | #define VBLOCK_BYTES_MAX \ | 2915 | #define VBLOCK_BYTES_MAX \ |
| 2882 | vroundup ((VECTOR_BLOCK_BYTES / 2) - sizeof (Lisp_Object)) | 2916 | vroundup ((VECTOR_BLOCK_BYTES / 2) - word_size) |
| 2883 | 2917 | ||
| 2884 | /* We maintain one free list for each possible block-allocated | 2918 | /* We maintain one free list for each possible block-allocated |
| 2885 | vector size, and this is the number of free lists we have. */ | 2919 | vector size, and this is the number of free lists we have. */ |
| @@ -2905,6 +2939,7 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2905 | eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ | 2939 | eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ |
| 2906 | (v)->header.next.vector = vector_free_lists[index]; \ | 2940 | (v)->header.next.vector = vector_free_lists[index]; \ |
| 2907 | vector_free_lists[index] = (v); \ | 2941 | vector_free_lists[index] = (v); \ |
| 2942 | total_free_vector_slots += (nbytes) / word_size; \ | ||
| 2908 | } while (0) | 2943 | } while (0) |
| 2909 | 2944 | ||
| 2910 | struct vector_block | 2945 | struct vector_block |
| @@ -2930,6 +2965,14 @@ static struct Lisp_Vector *large_vectors; | |||
| 2930 | 2965 | ||
| 2931 | Lisp_Object zero_vector; | 2966 | Lisp_Object zero_vector; |
| 2932 | 2967 | ||
| 2968 | /* Number of live vectors. */ | ||
| 2969 | |||
| 2970 | static EMACS_INT total_vectors; | ||
| 2971 | |||
| 2972 | /* Total size of live and free vectors, in Lisp_Object units. */ | ||
| 2973 | |||
| 2974 | static EMACS_INT total_vector_slots, total_free_vector_slots; | ||
| 2975 | |||
| 2933 | /* Get a new vector block. */ | 2976 | /* Get a new vector block. */ |
| 2934 | 2977 | ||
| 2935 | static struct vector_block * | 2978 | static struct vector_block * |
| @@ -2975,6 +3018,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2975 | vector = vector_free_lists[index]; | 3018 | vector = vector_free_lists[index]; |
| 2976 | vector_free_lists[index] = vector->header.next.vector; | 3019 | vector_free_lists[index] = vector->header.next.vector; |
| 2977 | vector->header.next.nbytes = nbytes; | 3020 | vector->header.next.nbytes = nbytes; |
| 3021 | total_free_vector_slots -= nbytes / word_size; | ||
| 2978 | return vector; | 3022 | return vector; |
| 2979 | } | 3023 | } |
| 2980 | 3024 | ||
| @@ -2989,6 +3033,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2989 | vector = vector_free_lists[index]; | 3033 | vector = vector_free_lists[index]; |
| 2990 | vector_free_lists[index] = vector->header.next.vector; | 3034 | vector_free_lists[index] = vector->header.next.vector; |
| 2991 | vector->header.next.nbytes = nbytes; | 3035 | vector->header.next.nbytes = nbytes; |
| 3036 | total_free_vector_slots -= nbytes / word_size; | ||
| 2992 | 3037 | ||
| 2993 | /* Excess bytes are used for the smaller vector, | 3038 | /* Excess bytes are used for the smaller vector, |
| 2994 | which should be set on an appropriate free list. */ | 3039 | which should be set on an appropriate free list. */ |
| @@ -3018,12 +3063,6 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3018 | return vector; | 3063 | return vector; |
| 3019 | } | 3064 | } |
| 3020 | 3065 | ||
| 3021 | /* Return how many Lisp_Objects can be stored in V. */ | ||
| 3022 | |||
| 3023 | #define VECTOR_SIZE(v) ((v)->header.size & PSEUDOVECTOR_FLAG ? \ | ||
| 3024 | (PSEUDOVECTOR_SIZE_MASK & (v)->header.size) : \ | ||
| 3025 | (v)->header.size) | ||
| 3026 | |||
| 3027 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ | 3066 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ |
| 3028 | 3067 | ||
| 3029 | #define VECTOR_IN_BLOCK(vector, block) \ | 3068 | #define VECTOR_IN_BLOCK(vector, block) \ |
| @@ -3048,7 +3087,7 @@ sweep_vectors (void) | |||
| 3048 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; | 3087 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; |
| 3049 | struct Lisp_Vector *vector, *next, **vprev = &large_vectors; | 3088 | struct Lisp_Vector *vector, *next, **vprev = &large_vectors; |
| 3050 | 3089 | ||
| 3051 | total_vector_size = 0; | 3090 | total_vectors = total_vector_slots = total_free_vector_slots = 0; |
| 3052 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); | 3091 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); |
| 3053 | 3092 | ||
| 3054 | /* Looking through vector blocks. */ | 3093 | /* Looking through vector blocks. */ |
| @@ -3063,7 +3102,8 @@ sweep_vectors (void) | |||
| 3063 | if (VECTOR_MARKED_P (vector)) | 3102 | if (VECTOR_MARKED_P (vector)) |
| 3064 | { | 3103 | { |
| 3065 | VECTOR_UNMARK (vector); | 3104 | VECTOR_UNMARK (vector); |
| 3066 | total_vector_size += VECTOR_SIZE (vector); | 3105 | total_vectors++; |
| 3106 | total_vector_slots += vector->header.next.nbytes / word_size; | ||
| 3067 | next = ADVANCE (vector, vector->header.next.nbytes); | 3107 | next = ADVANCE (vector, vector->header.next.nbytes); |
| 3068 | } | 3108 | } |
| 3069 | else | 3109 | else |
| @@ -3119,7 +3159,24 @@ sweep_vectors (void) | |||
| 3119 | if (VECTOR_MARKED_P (vector)) | 3159 | if (VECTOR_MARKED_P (vector)) |
| 3120 | { | 3160 | { |
| 3121 | VECTOR_UNMARK (vector); | 3161 | VECTOR_UNMARK (vector); |
| 3122 | total_vector_size += VECTOR_SIZE (vector); | 3162 | total_vectors++; |
| 3163 | if (vector->header.size & PSEUDOVECTOR_FLAG) | ||
| 3164 | { | ||
| 3165 | struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) vector; | ||
| 3166 | |||
| 3167 | /* All non-bool pseudovectors are small enough to be allocated | ||
| 3168 | from vector blocks. This code should be redesigned if some | ||
| 3169 | pseudovector type grows beyond VBLOCK_BYTES_MAX. */ | ||
| 3170 | eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)); | ||
| 3171 | |||
| 3172 | total_vector_slots | ||
| 3173 | += (bool_header_size | ||
| 3174 | + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1) | ||
| 3175 | / BOOL_VECTOR_BITS_PER_CHAR)) / word_size; | ||
| 3176 | } | ||
| 3177 | else | ||
| 3178 | total_vector_slots | ||
| 3179 | += header_size / word_size + vector->header.size; | ||
| 3123 | vprev = &vector->header.next.vector; | 3180 | vprev = &vector->header.next.vector; |
| 3124 | } | 3181 | } |
| 3125 | else | 3182 | else |
| @@ -3385,8 +3442,8 @@ union aligned_Lisp_Symbol | |||
| 3385 | { | 3442 | { |
| 3386 | struct Lisp_Symbol s; | 3443 | struct Lisp_Symbol s; |
| 3387 | #if USE_LSB_TAG | 3444 | #if USE_LSB_TAG |
| 3388 | unsigned char c[(sizeof (struct Lisp_Symbol) + (1 << GCTYPEBITS) - 1) | 3445 | unsigned char c[(sizeof (struct Lisp_Symbol) + GCALIGNMENT - 1) |
| 3389 | & -(1 << GCTYPEBITS)]; | 3446 | & -GCALIGNMENT]; |
| 3390 | #endif | 3447 | #endif |
| 3391 | }; | 3448 | }; |
| 3392 | 3449 | ||
| @@ -3442,6 +3499,7 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3442 | new->next = symbol_block; | 3499 | new->next = symbol_block; |
| 3443 | symbol_block = new; | 3500 | symbol_block = new; |
| 3444 | symbol_block_index = 0; | 3501 | symbol_block_index = 0; |
| 3502 | total_free_symbols += SYMBOL_BLOCK_SIZE; | ||
| 3445 | } | 3503 | } |
| 3446 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index].s); | 3504 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index].s); |
| 3447 | symbol_block_index++; | 3505 | symbol_block_index++; |
| @@ -3450,18 +3508,19 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3450 | MALLOC_UNBLOCK_INPUT; | 3508 | MALLOC_UNBLOCK_INPUT; |
| 3451 | 3509 | ||
| 3452 | p = XSYMBOL (val); | 3510 | p = XSYMBOL (val); |
| 3453 | p->xname = name; | 3511 | set_symbol_name (val, name); |
| 3454 | p->plist = Qnil; | 3512 | set_symbol_plist (val, Qnil); |
| 3455 | p->redirect = SYMBOL_PLAINVAL; | 3513 | p->redirect = SYMBOL_PLAINVAL; |
| 3456 | SET_SYMBOL_VAL (p, Qunbound); | 3514 | SET_SYMBOL_VAL (p, Qunbound); |
| 3457 | p->function = Qunbound; | 3515 | set_symbol_function (val, Qunbound); |
| 3458 | p->next = NULL; | 3516 | set_symbol_next (val, NULL); |
| 3459 | p->gcmarkbit = 0; | 3517 | p->gcmarkbit = 0; |
| 3460 | p->interned = SYMBOL_UNINTERNED; | 3518 | p->interned = SYMBOL_UNINTERNED; |
| 3461 | p->constant = 0; | 3519 | p->constant = 0; |
| 3462 | p->declared_special = 0; | 3520 | p->declared_special = 0; |
| 3463 | consing_since_gc += sizeof (struct Lisp_Symbol); | 3521 | consing_since_gc += sizeof (struct Lisp_Symbol); |
| 3464 | symbols_consed++; | 3522 | symbols_consed++; |
| 3523 | total_free_symbols--; | ||
| 3465 | return val; | 3524 | return val; |
| 3466 | } | 3525 | } |
| 3467 | 3526 | ||
| @@ -3478,8 +3537,8 @@ union aligned_Lisp_Misc | |||
| 3478 | { | 3537 | { |
| 3479 | union Lisp_Misc m; | 3538 | union Lisp_Misc m; |
| 3480 | #if USE_LSB_TAG | 3539 | #if USE_LSB_TAG |
| 3481 | unsigned char c[(sizeof (union Lisp_Misc) + (1 << GCTYPEBITS) - 1) | 3540 | unsigned char c[(sizeof (union Lisp_Misc) + GCALIGNMENT - 1) |
| 3482 | & -(1 << GCTYPEBITS)]; | 3541 | & -GCALIGNMENT]; |
| 3483 | #endif | 3542 | #endif |
| 3484 | }; | 3543 | }; |
| 3485 | 3544 | ||
| @@ -3501,10 +3560,10 @@ static int marker_block_index = MARKER_BLOCK_SIZE; | |||
| 3501 | 3560 | ||
| 3502 | static union Lisp_Misc *marker_free_list; | 3561 | static union Lisp_Misc *marker_free_list; |
| 3503 | 3562 | ||
| 3504 | /* Return a newly allocated Lisp_Misc object, with no substructure. */ | 3563 | /* Return a newly allocated Lisp_Misc object of specified TYPE. */ |
| 3505 | 3564 | ||
| 3506 | Lisp_Object | 3565 | static Lisp_Object |
| 3507 | allocate_misc (void) | 3566 | allocate_misc (enum Lisp_Misc_Type type) |
| 3508 | { | 3567 | { |
| 3509 | Lisp_Object val; | 3568 | Lisp_Object val; |
| 3510 | 3569 | ||
| @@ -3536,6 +3595,7 @@ allocate_misc (void) | |||
| 3536 | --total_free_markers; | 3595 | --total_free_markers; |
| 3537 | consing_since_gc += sizeof (union Lisp_Misc); | 3596 | consing_since_gc += sizeof (union Lisp_Misc); |
| 3538 | misc_objects_consed++; | 3597 | misc_objects_consed++; |
| 3598 | XMISCTYPE (val) = type; | ||
| 3539 | XMISCANY (val)->gcmarkbit = 0; | 3599 | XMISCANY (val)->gcmarkbit = 0; |
| 3540 | return val; | 3600 | return val; |
| 3541 | } | 3601 | } |
| @@ -3548,7 +3608,7 @@ free_misc (Lisp_Object misc) | |||
| 3548 | XMISCTYPE (misc) = Lisp_Misc_Free; | 3608 | XMISCTYPE (misc) = Lisp_Misc_Free; |
| 3549 | XMISC (misc)->u_free.chain = marker_free_list; | 3609 | XMISC (misc)->u_free.chain = marker_free_list; |
| 3550 | marker_free_list = XMISC (misc); | 3610 | marker_free_list = XMISC (misc); |
| 3551 | 3611 | consing_since_gc -= sizeof (union Lisp_Misc); | |
| 3552 | total_free_markers++; | 3612 | total_free_markers++; |
| 3553 | } | 3613 | } |
| 3554 | 3614 | ||
| @@ -3562,8 +3622,7 @@ make_save_value (void *pointer, ptrdiff_t integer) | |||
| 3562 | register Lisp_Object val; | 3622 | register Lisp_Object val; |
| 3563 | register struct Lisp_Save_Value *p; | 3623 | register struct Lisp_Save_Value *p; |
| 3564 | 3624 | ||
| 3565 | val = allocate_misc (); | 3625 | val = allocate_misc (Lisp_Misc_Save_Value); |
| 3566 | XMISCTYPE (val) = Lisp_Misc_Save_Value; | ||
| 3567 | p = XSAVE_VALUE (val); | 3626 | p = XSAVE_VALUE (val); |
| 3568 | p->pointer = pointer; | 3627 | p->pointer = pointer; |
| 3569 | p->integer = integer; | 3628 | p->integer = integer; |
| @@ -3571,6 +3630,21 @@ make_save_value (void *pointer, ptrdiff_t integer) | |||
| 3571 | return val; | 3630 | return val; |
| 3572 | } | 3631 | } |
| 3573 | 3632 | ||
| 3633 | /* Return a Lisp_Misc_Overlay object with specified START, END and PLIST. */ | ||
| 3634 | |||
| 3635 | Lisp_Object | ||
| 3636 | build_overlay (Lisp_Object start, Lisp_Object end, Lisp_Object plist) | ||
| 3637 | { | ||
| 3638 | register Lisp_Object overlay; | ||
| 3639 | |||
| 3640 | overlay = allocate_misc (Lisp_Misc_Overlay); | ||
| 3641 | OVERLAY_START (overlay) = start; | ||
| 3642 | OVERLAY_END (overlay) = end; | ||
| 3643 | set_overlay_plist (overlay, plist); | ||
| 3644 | XOVERLAY (overlay)->next = NULL; | ||
| 3645 | return overlay; | ||
| 3646 | } | ||
| 3647 | |||
| 3574 | DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, | 3648 | DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, |
| 3575 | doc: /* Return a newly allocated marker which does not point at any place. */) | 3649 | doc: /* Return a newly allocated marker which does not point at any place. */) |
| 3576 | (void) | 3650 | (void) |
| @@ -3578,8 +3652,7 @@ DEFUN ("make-marker", Fmake_marker, Smake_marker, 0, 0, 0, | |||
| 3578 | register Lisp_Object val; | 3652 | register Lisp_Object val; |
| 3579 | register struct Lisp_Marker *p; | 3653 | register struct Lisp_Marker *p; |
| 3580 | 3654 | ||
| 3581 | val = allocate_misc (); | 3655 | val = allocate_misc (Lisp_Misc_Marker); |
| 3582 | XMISCTYPE (val) = Lisp_Misc_Marker; | ||
| 3583 | p = XMARKER (val); | 3656 | p = XMARKER (val); |
| 3584 | p->buffer = 0; | 3657 | p->buffer = 0; |
| 3585 | p->bytepos = 0; | 3658 | p->bytepos = 0; |
| @@ -3604,8 +3677,7 @@ build_marker (struct buffer *buf, ptrdiff_t charpos, ptrdiff_t bytepos) | |||
| 3604 | /* Every character is at least one byte. */ | 3677 | /* Every character is at least one byte. */ |
| 3605 | eassert (charpos <= bytepos); | 3678 | eassert (charpos <= bytepos); |
| 3606 | 3679 | ||
| 3607 | obj = allocate_misc (); | 3680 | obj = allocate_misc (Lisp_Misc_Marker); |
| 3608 | XMISCTYPE (obj) = Lisp_Misc_Marker; | ||
| 3609 | m = XMARKER (obj); | 3681 | m = XMARKER (obj); |
| 3610 | m->buffer = buf; | 3682 | m->buffer = buf; |
| 3611 | m->charpos = charpos; | 3683 | m->charpos = charpos; |
| @@ -4239,7 +4311,7 @@ live_symbol_p (struct mem_node *m, void *p) | |||
| 4239 | && offset < (SYMBOL_BLOCK_SIZE * sizeof b->symbols[0]) | 4311 | && offset < (SYMBOL_BLOCK_SIZE * sizeof b->symbols[0]) |
| 4240 | && (b != symbol_block | 4312 | && (b != symbol_block |
| 4241 | || offset / sizeof b->symbols[0] < symbol_block_index) | 4313 | || offset / sizeof b->symbols[0] < symbol_block_index) |
| 4242 | && !EQ (((struct Lisp_Symbol *) p)->function, Vdead)); | 4314 | && !EQ (((struct Lisp_Symbol *)p)->function, Vdead)); |
| 4243 | } | 4315 | } |
| 4244 | else | 4316 | else |
| 4245 | return 0; | 4317 | return 0; |
| @@ -4342,7 +4414,7 @@ live_buffer_p (struct mem_node *m, void *p) | |||
| 4342 | must not have been killed. */ | 4414 | must not have been killed. */ |
| 4343 | return (m->type == MEM_TYPE_BUFFER | 4415 | return (m->type == MEM_TYPE_BUFFER |
| 4344 | && p == m->start | 4416 | && p == m->start |
| 4345 | && !NILP (((struct buffer *) p)->BUFFER_INTERNAL_FIELD (name))); | 4417 | && !NILP (((struct buffer *) p)->INTERNAL_FIELD (name))); |
| 4346 | } | 4418 | } |
| 4347 | 4419 | ||
| 4348 | #endif /* GC_MARK_STACK || defined GC_MALLOC_CHECK */ | 4420 | #endif /* GC_MARK_STACK || defined GC_MALLOC_CHECK */ |
| @@ -4476,9 +4548,9 @@ mark_maybe_pointer (void *p) | |||
| 4476 | struct mem_node *m; | 4548 | struct mem_node *m; |
| 4477 | 4549 | ||
| 4478 | /* Quickly rule out some values which can't point to Lisp data. | 4550 | /* Quickly rule out some values which can't point to Lisp data. |
| 4479 | USE_LSB_TAG needs Lisp data to be aligned on multiples of 1 << GCTYPEBITS. | 4551 | USE_LSB_TAG needs Lisp data to be aligned on multiples of GCALIGNMENT. |
| 4480 | Otherwise, assume that Lisp data is aligned on even addresses. */ | 4552 | Otherwise, assume that Lisp data is aligned on even addresses. */ |
| 4481 | if ((intptr_t) p % (USE_LSB_TAG ? 1 << GCTYPEBITS : 2)) | 4553 | if ((intptr_t) p % (USE_LSB_TAG ? GCALIGNMENT : 2)) |
| 4482 | return; | 4554 | return; |
| 4483 | 4555 | ||
| 4484 | m = mem_find (p); | 4556 | m = mem_find (p); |
| @@ -4544,10 +4616,10 @@ mark_maybe_pointer (void *p) | |||
| 4544 | } | 4616 | } |
| 4545 | 4617 | ||
| 4546 | 4618 | ||
| 4547 | /* Alignment of pointer values. Use offsetof, as it sometimes returns | 4619 | /* Alignment of pointer values. Use alignof, as it sometimes returns |
| 4548 | a smaller alignment than GCC's __alignof__ and mark_memory might | 4620 | a smaller alignment than GCC's __alignof__ and mark_memory might |
| 4549 | miss objects if __alignof__ were used. */ | 4621 | miss objects if __alignof__ were used. */ |
| 4550 | #define GC_POINTER_ALIGNMENT offsetof (struct {char a; void *b;}, b) | 4622 | #define GC_POINTER_ALIGNMENT alignof (void *) |
| 4551 | 4623 | ||
| 4552 | /* Define POINTERS_MIGHT_HIDE_IN_OBJECTS to 1 if marking via C pointers does | 4624 | /* Define POINTERS_MIGHT_HIDE_IN_OBJECTS to 1 if marking via C pointers does |
| 4553 | not suffice, which is the typical case. A host where a Lisp_Object is | 4625 | not suffice, which is the typical case. A host where a Lisp_Object is |
| @@ -4993,19 +5065,13 @@ pure_alloc (size_t size, int type) | |||
| 4993 | { | 5065 | { |
| 4994 | void *result; | 5066 | void *result; |
| 4995 | #if USE_LSB_TAG | 5067 | #if USE_LSB_TAG |
| 4996 | size_t alignment = (1 << GCTYPEBITS); | 5068 | size_t alignment = GCALIGNMENT; |
| 4997 | #else | 5069 | #else |
| 4998 | size_t alignment = sizeof (EMACS_INT); | 5070 | size_t alignment = alignof (EMACS_INT); |
| 4999 | 5071 | ||
| 5000 | /* Give Lisp_Floats an extra alignment. */ | 5072 | /* Give Lisp_Floats an extra alignment. */ |
| 5001 | if (type == Lisp_Float) | 5073 | if (type == Lisp_Float) |
| 5002 | { | 5074 | alignment = alignof (struct Lisp_Float); |
| 5003 | #if defined __GNUC__ && __GNUC__ >= 2 | ||
| 5004 | alignment = __alignof (struct Lisp_Float); | ||
| 5005 | #else | ||
| 5006 | alignment = sizeof (struct Lisp_Float); | ||
| 5007 | #endif | ||
| 5008 | } | ||
| 5009 | #endif | 5075 | #endif |
| 5010 | 5076 | ||
| 5011 | again: | 5077 | again: |
| @@ -5131,19 +5197,17 @@ make_pure_string (const char *data, | |||
| 5131 | ptrdiff_t nchars, ptrdiff_t nbytes, int multibyte) | 5197 | ptrdiff_t nchars, ptrdiff_t nbytes, int multibyte) |
| 5132 | { | 5198 | { |
| 5133 | Lisp_Object string; | 5199 | Lisp_Object string; |
| 5134 | struct Lisp_String *s; | 5200 | struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); |
| 5135 | |||
| 5136 | s = (struct Lisp_String *) pure_alloc (sizeof *s, Lisp_String); | ||
| 5137 | s->data = (unsigned char *) find_string_data_in_pure (data, nbytes); | 5201 | s->data = (unsigned char *) find_string_data_in_pure (data, nbytes); |
| 5138 | if (s->data == NULL) | 5202 | if (s->data == NULL) |
| 5139 | { | 5203 | { |
| 5140 | s->data = (unsigned char *) pure_alloc (nbytes + 1, -1); | 5204 | s->data = pure_alloc (nbytes + 1, -1); |
| 5141 | memcpy (s->data, data, nbytes); | 5205 | memcpy (s->data, data, nbytes); |
| 5142 | s->data[nbytes] = '\0'; | 5206 | s->data[nbytes] = '\0'; |
| 5143 | } | 5207 | } |
| 5144 | s->size = nchars; | 5208 | s->size = nchars; |
| 5145 | s->size_byte = multibyte ? nbytes : -1; | 5209 | s->size_byte = multibyte ? nbytes : -1; |
| 5146 | s->intervals = NULL_INTERVAL; | 5210 | s->intervals = NULL; |
| 5147 | XSETSTRING (string, s); | 5211 | XSETSTRING (string, s); |
| 5148 | return string; | 5212 | return string; |
| 5149 | } | 5213 | } |
| @@ -5155,13 +5219,11 @@ Lisp_Object | |||
| 5155 | make_pure_c_string (const char *data, ptrdiff_t nchars) | 5219 | make_pure_c_string (const char *data, ptrdiff_t nchars) |
| 5156 | { | 5220 | { |
| 5157 | Lisp_Object string; | 5221 | Lisp_Object string; |
| 5158 | struct Lisp_String *s; | 5222 | struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); |
| 5159 | |||
| 5160 | s = (struct Lisp_String *) pure_alloc (sizeof *s, Lisp_String); | ||
| 5161 | s->size = nchars; | 5223 | s->size = nchars; |
| 5162 | s->size_byte = -1; | 5224 | s->size_byte = -1; |
| 5163 | s->data = (unsigned char *) data; | 5225 | s->data = (unsigned char *) data; |
| 5164 | s->intervals = NULL_INTERVAL; | 5226 | s->intervals = NULL; |
| 5165 | XSETSTRING (string, s); | 5227 | XSETSTRING (string, s); |
| 5166 | return string; | 5228 | return string; |
| 5167 | } | 5229 | } |
| @@ -5172,10 +5234,8 @@ make_pure_c_string (const char *data, ptrdiff_t nchars) | |||
| 5172 | Lisp_Object | 5234 | Lisp_Object |
| 5173 | pure_cons (Lisp_Object car, Lisp_Object cdr) | 5235 | pure_cons (Lisp_Object car, Lisp_Object cdr) |
| 5174 | { | 5236 | { |
| 5175 | register Lisp_Object new; | 5237 | Lisp_Object new; |
| 5176 | struct Lisp_Cons *p; | 5238 | struct Lisp_Cons *p = pure_alloc (sizeof *p, Lisp_Cons); |
| 5177 | |||
| 5178 | p = (struct Lisp_Cons *) pure_alloc (sizeof *p, Lisp_Cons); | ||
| 5179 | XSETCONS (new, p); | 5239 | XSETCONS (new, p); |
| 5180 | XSETCAR (new, Fpurecopy (car)); | 5240 | XSETCAR (new, Fpurecopy (car)); |
| 5181 | XSETCDR (new, Fpurecopy (cdr)); | 5241 | XSETCDR (new, Fpurecopy (cdr)); |
| @@ -5188,10 +5248,8 @@ pure_cons (Lisp_Object car, Lisp_Object cdr) | |||
| 5188 | static Lisp_Object | 5248 | static Lisp_Object |
| 5189 | make_pure_float (double num) | 5249 | make_pure_float (double num) |
| 5190 | { | 5250 | { |
| 5191 | register Lisp_Object new; | 5251 | Lisp_Object new; |
| 5192 | struct Lisp_Float *p; | 5252 | struct Lisp_Float *p = pure_alloc (sizeof *p, Lisp_Float); |
| 5193 | |||
| 5194 | p = (struct Lisp_Float *) pure_alloc (sizeof *p, Lisp_Float); | ||
| 5195 | XSETFLOAT (new, p); | 5253 | XSETFLOAT (new, p); |
| 5196 | XFLOAT_INIT (new, num); | 5254 | XFLOAT_INIT (new, num); |
| 5197 | return new; | 5255 | return new; |
| @@ -5205,11 +5263,8 @@ static Lisp_Object | |||
| 5205 | make_pure_vector (ptrdiff_t len) | 5263 | make_pure_vector (ptrdiff_t len) |
| 5206 | { | 5264 | { |
| 5207 | Lisp_Object new; | 5265 | Lisp_Object new; |
| 5208 | struct Lisp_Vector *p; | 5266 | size_t size = header_size + len * word_size; |
| 5209 | size_t size = (offsetof (struct Lisp_Vector, contents) | 5267 | struct Lisp_Vector *p = pure_alloc (size, Lisp_Vectorlike); |
| 5210 | + len * sizeof (Lisp_Object)); | ||
| 5211 | |||
| 5212 | p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike); | ||
| 5213 | XSETVECTOR (new, p); | 5268 | XSETVECTOR (new, p); |
| 5214 | XVECTOR (new)->header.size = len; | 5269 | XVECTOR (new)->header.size = len; |
| 5215 | return new; | 5270 | return new; |
| @@ -5308,28 +5363,40 @@ inhibit_garbage_collection (void) | |||
| 5308 | return count; | 5363 | return count; |
| 5309 | } | 5364 | } |
| 5310 | 5365 | ||
| 5366 | /* Used to avoid possible overflows when | ||
| 5367 | converting from C to Lisp integers. */ | ||
| 5368 | |||
| 5369 | static inline Lisp_Object | ||
| 5370 | bounded_number (EMACS_INT number) | ||
| 5371 | { | ||
| 5372 | return make_number (min (MOST_POSITIVE_FIXNUM, number)); | ||
| 5373 | } | ||
| 5311 | 5374 | ||
| 5312 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | 5375 | DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", |
| 5313 | doc: /* Reclaim storage for Lisp objects no longer needed. | 5376 | doc: /* Reclaim storage for Lisp objects no longer needed. |
| 5314 | Garbage collection happens automatically if you cons more than | 5377 | Garbage collection happens automatically if you cons more than |
| 5315 | `gc-cons-threshold' bytes of Lisp data since previous garbage collection. | 5378 | `gc-cons-threshold' bytes of Lisp data since previous garbage collection. |
| 5316 | `garbage-collect' normally returns a list with info on amount of space in use: | 5379 | `garbage-collect' normally returns a list with info on amount of space in use, |
| 5317 | ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS) | 5380 | where each entry has the form (NAME SIZE USED FREE), where: |
| 5318 | (USED-MISCS . FREE-MISCS) USED-STRING-CHARS USED-VECTOR-SLOTS | 5381 | - NAME is a symbol describing the kind of objects this entry represents, |
| 5319 | (USED-FLOATS . FREE-FLOATS) (USED-INTERVALS . FREE-INTERVALS) | 5382 | - SIZE is the number of bytes used by each one, |
| 5320 | (USED-STRINGS . FREE-STRINGS)) | 5383 | - USED is the number of those objects that were found live in the heap, |
| 5384 | - FREE is the number of those objects that are not live but that Emacs | ||
| 5385 | keeps around for future allocations (maybe because it does not know how | ||
| 5386 | to return them to the OS). | ||
| 5321 | However, if there was overflow in pure space, `garbage-collect' | 5387 | However, if there was overflow in pure space, `garbage-collect' |
| 5322 | returns nil, because real GC can't be done. | 5388 | returns nil, because real GC can't be done. |
| 5323 | See Info node `(elisp)Garbage Collection'. */) | 5389 | See Info node `(elisp)Garbage Collection'. */) |
| 5324 | (void) | 5390 | (void) |
| 5325 | { | 5391 | { |
| 5326 | register struct specbinding *bind; | 5392 | register struct specbinding *bind; |
| 5393 | register struct buffer *nextb; | ||
| 5327 | char stack_top_variable; | 5394 | char stack_top_variable; |
| 5328 | ptrdiff_t i; | 5395 | ptrdiff_t i; |
| 5329 | int message_p; | 5396 | int message_p; |
| 5330 | Lisp_Object total[8]; | ||
| 5331 | ptrdiff_t count = SPECPDL_INDEX (); | 5397 | ptrdiff_t count = SPECPDL_INDEX (); |
| 5332 | EMACS_TIME t1; | 5398 | EMACS_TIME start; |
| 5399 | Lisp_Object retval = Qnil; | ||
| 5333 | 5400 | ||
| 5334 | if (abort_on_gc) | 5401 | if (abort_on_gc) |
| 5335 | abort (); | 5402 | abort (); |
| @@ -5339,46 +5406,14 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5339 | if (pure_bytes_used_before_overflow) | 5406 | if (pure_bytes_used_before_overflow) |
| 5340 | return Qnil; | 5407 | return Qnil; |
| 5341 | 5408 | ||
| 5342 | CHECK_CONS_LIST (); | 5409 | check_cons_list (); |
| 5343 | 5410 | ||
| 5344 | /* Don't keep undo information around forever. | 5411 | /* Don't keep undo information around forever. |
| 5345 | Do this early on, so it is no problem if the user quits. */ | 5412 | Do this early on, so it is no problem if the user quits. */ |
| 5346 | { | 5413 | FOR_EACH_BUFFER (nextb) |
| 5347 | register struct buffer *nextb = all_buffers; | 5414 | compact_buffer (nextb); |
| 5348 | 5415 | ||
| 5349 | while (nextb) | 5416 | start = current_emacs_time (); |
| 5350 | { | ||
| 5351 | /* If a buffer's undo list is Qt, that means that undo is | ||
| 5352 | turned off in that buffer. Calling truncate_undo_list on | ||
| 5353 | Qt tends to return NULL, which effectively turns undo back on. | ||
| 5354 | So don't call truncate_undo_list if undo_list is Qt. */ | ||
| 5355 | if (! NILP (nextb->BUFFER_INTERNAL_FIELD (name)) | ||
| 5356 | && ! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) | ||
| 5357 | truncate_undo_list (nextb); | ||
| 5358 | |||
| 5359 | /* Shrink buffer gaps, but skip indirect and dead buffers. */ | ||
| 5360 | if (nextb->base_buffer == 0 && !NILP (nextb->BUFFER_INTERNAL_FIELD (name)) | ||
| 5361 | && ! nextb->text->inhibit_shrinking) | ||
| 5362 | { | ||
| 5363 | /* If a buffer's gap size is more than 10% of the buffer | ||
| 5364 | size, or larger than 2000 bytes, then shrink it | ||
| 5365 | accordingly. Keep a minimum size of 20 bytes. */ | ||
| 5366 | int size = min (2000, max (20, (nextb->text->z_byte / 10))); | ||
| 5367 | |||
| 5368 | if (nextb->text->gap_size > size) | ||
| 5369 | { | ||
| 5370 | struct buffer *save_current = current_buffer; | ||
| 5371 | current_buffer = nextb; | ||
| 5372 | make_gap (-(nextb->text->gap_size - size)); | ||
| 5373 | current_buffer = save_current; | ||
| 5374 | } | ||
| 5375 | } | ||
| 5376 | |||
| 5377 | nextb = nextb->header.next.buffer; | ||
| 5378 | } | ||
| 5379 | } | ||
| 5380 | |||
| 5381 | t1 = current_emacs_time (); | ||
| 5382 | 5417 | ||
| 5383 | /* In case user calls debug_print during GC, | 5418 | /* In case user calls debug_print during GC, |
| 5384 | don't let that cause a recursive GC. */ | 5419 | don't let that cause a recursive GC. */ |
| @@ -5425,8 +5460,6 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5425 | 5460 | ||
| 5426 | gc_in_progress = 1; | 5461 | gc_in_progress = 1; |
| 5427 | 5462 | ||
| 5428 | /* clear_marks (); */ | ||
| 5429 | |||
| 5430 | /* Mark all the special slots that serve as the roots of accessibility. */ | 5463 | /* Mark all the special slots that serve as the roots of accessibility. */ |
| 5431 | 5464 | ||
| 5432 | for (i = 0; i < staticidx; i++) | 5465 | for (i = 0; i < staticidx; i++) |
| @@ -5490,48 +5523,42 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5490 | Look thru every buffer's undo list | 5523 | Look thru every buffer's undo list |
| 5491 | for elements that update markers that were not marked, | 5524 | for elements that update markers that were not marked, |
| 5492 | and delete them. */ | 5525 | and delete them. */ |
| 5493 | { | 5526 | FOR_EACH_BUFFER (nextb) |
| 5494 | register struct buffer *nextb = all_buffers; | 5527 | { |
| 5495 | 5528 | /* If a buffer's undo list is Qt, that means that undo is | |
| 5496 | while (nextb) | 5529 | turned off in that buffer. Calling truncate_undo_list on |
| 5497 | { | 5530 | Qt tends to return NULL, which effectively turns undo back on. |
| 5498 | /* If a buffer's undo list is Qt, that means that undo is | 5531 | So don't call truncate_undo_list if undo_list is Qt. */ |
| 5499 | turned off in that buffer. Calling truncate_undo_list on | 5532 | if (! EQ (nextb->INTERNAL_FIELD (undo_list), Qt)) |
| 5500 | Qt tends to return NULL, which effectively turns undo back on. | 5533 | { |
| 5501 | So don't call truncate_undo_list if undo_list is Qt. */ | 5534 | Lisp_Object tail, prev; |
| 5502 | if (! EQ (nextb->BUFFER_INTERNAL_FIELD (undo_list), Qt)) | 5535 | tail = nextb->INTERNAL_FIELD (undo_list); |
| 5503 | { | 5536 | prev = Qnil; |
| 5504 | Lisp_Object tail, prev; | 5537 | while (CONSP (tail)) |
| 5505 | tail = nextb->BUFFER_INTERNAL_FIELD (undo_list); | 5538 | { |
| 5506 | prev = Qnil; | 5539 | if (CONSP (XCAR (tail)) |
| 5507 | while (CONSP (tail)) | 5540 | && MARKERP (XCAR (XCAR (tail))) |
| 5508 | { | 5541 | && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) |
| 5509 | if (CONSP (XCAR (tail)) | 5542 | { |
| 5510 | && MARKERP (XCAR (XCAR (tail))) | 5543 | if (NILP (prev)) |
| 5511 | && !XMARKER (XCAR (XCAR (tail)))->gcmarkbit) | 5544 | nextb->INTERNAL_FIELD (undo_list) = tail = XCDR (tail); |
| 5512 | { | 5545 | else |
| 5513 | if (NILP (prev)) | 5546 | { |
| 5514 | nextb->BUFFER_INTERNAL_FIELD (undo_list) = tail = XCDR (tail); | 5547 | tail = XCDR (tail); |
| 5515 | else | 5548 | XSETCDR (prev, tail); |
| 5516 | { | 5549 | } |
| 5517 | tail = XCDR (tail); | 5550 | } |
| 5518 | XSETCDR (prev, tail); | 5551 | else |
| 5519 | } | 5552 | { |
| 5520 | } | 5553 | prev = tail; |
| 5521 | else | 5554 | tail = XCDR (tail); |
| 5522 | { | 5555 | } |
| 5523 | prev = tail; | 5556 | } |
| 5524 | tail = XCDR (tail); | 5557 | } |
| 5525 | } | 5558 | /* Now that we have stripped the elements that need not be in the |
| 5526 | } | 5559 | undo_list any more, we can finally mark the list. */ |
| 5527 | } | 5560 | mark_object (nextb->INTERNAL_FIELD (undo_list)); |
| 5528 | /* Now that we have stripped the elements that need not be in the | 5561 | } |
| 5529 | undo_list any more, we can finally mark the list. */ | ||
| 5530 | mark_object (nextb->BUFFER_INTERNAL_FIELD (undo_list)); | ||
| 5531 | |||
| 5532 | nextb = nextb->header.next.buffer; | ||
| 5533 | } | ||
| 5534 | } | ||
| 5535 | 5562 | ||
| 5536 | gc_sweep (); | 5563 | gc_sweep (); |
| 5537 | 5564 | ||
| @@ -5547,14 +5574,13 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5547 | 5574 | ||
| 5548 | UNBLOCK_INPUT; | 5575 | UNBLOCK_INPUT; |
| 5549 | 5576 | ||
| 5550 | CHECK_CONS_LIST (); | 5577 | check_cons_list (); |
| 5551 | 5578 | ||
| 5552 | /* clear_marks (); */ | ||
| 5553 | gc_in_progress = 0; | 5579 | gc_in_progress = 0; |
| 5554 | 5580 | ||
| 5555 | consing_since_gc = 0; | 5581 | consing_since_gc = 0; |
| 5556 | if (gc_cons_threshold < 10000) | 5582 | if (gc_cons_threshold < GC_DEFAULT_THRESHOLD / 10) |
| 5557 | gc_cons_threshold = 10000; | 5583 | gc_cons_threshold = GC_DEFAULT_THRESHOLD / 10; |
| 5558 | 5584 | ||
| 5559 | gc_relative_threshold = 0; | 5585 | gc_relative_threshold = 0; |
| 5560 | if (FLOATP (Vgc_cons_percentage)) | 5586 | if (FLOATP (Vgc_cons_percentage)) |
| @@ -5564,8 +5590,8 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5564 | tot += total_conses * sizeof (struct Lisp_Cons); | 5590 | tot += total_conses * sizeof (struct Lisp_Cons); |
| 5565 | tot += total_symbols * sizeof (struct Lisp_Symbol); | 5591 | tot += total_symbols * sizeof (struct Lisp_Symbol); |
| 5566 | tot += total_markers * sizeof (union Lisp_Misc); | 5592 | tot += total_markers * sizeof (union Lisp_Misc); |
| 5567 | tot += total_string_size; | 5593 | tot += total_string_bytes; |
| 5568 | tot += total_vector_size * sizeof (Lisp_Object); | 5594 | tot += total_vector_slots * word_size; |
| 5569 | tot += total_floats * sizeof (struct Lisp_Float); | 5595 | tot += total_floats * sizeof (struct Lisp_Float); |
| 5570 | tot += total_intervals * sizeof (struct interval); | 5596 | tot += total_intervals * sizeof (struct interval); |
| 5571 | tot += total_strings * sizeof (struct Lisp_String); | 5597 | tot += total_strings * sizeof (struct Lisp_String); |
| @@ -5589,37 +5615,69 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5589 | } | 5615 | } |
| 5590 | 5616 | ||
| 5591 | unbind_to (count, Qnil); | 5617 | unbind_to (count, Qnil); |
| 5618 | { | ||
| 5619 | Lisp_Object total[11]; | ||
| 5620 | int total_size = 10; | ||
| 5621 | |||
| 5622 | total[0] = list4 (Qconses, make_number (sizeof (struct Lisp_Cons)), | ||
| 5623 | bounded_number (total_conses), | ||
| 5624 | bounded_number (total_free_conses)); | ||
| 5592 | 5625 | ||
| 5593 | total[0] = Fcons (make_number (total_conses), | 5626 | total[1] = list4 (Qsymbols, make_number (sizeof (struct Lisp_Symbol)), |
| 5594 | make_number (total_free_conses)); | 5627 | bounded_number (total_symbols), |
| 5595 | total[1] = Fcons (make_number (total_symbols), | 5628 | bounded_number (total_free_symbols)); |
| 5596 | make_number (total_free_symbols)); | 5629 | |
| 5597 | total[2] = Fcons (make_number (total_markers), | 5630 | total[2] = list4 (Qmiscs, make_number (sizeof (union Lisp_Misc)), |
| 5598 | make_number (total_free_markers)); | 5631 | bounded_number (total_markers), |
| 5599 | total[3] = make_number (total_string_size); | 5632 | bounded_number (total_free_markers)); |
| 5600 | total[4] = make_number (total_vector_size); | 5633 | |
| 5601 | total[5] = Fcons (make_number (total_floats), | 5634 | total[3] = list4 (Qstrings, make_number (sizeof (struct Lisp_String)), |
| 5602 | make_number (total_free_floats)); | 5635 | bounded_number (total_strings), |
| 5603 | total[6] = Fcons (make_number (total_intervals), | 5636 | bounded_number (total_free_strings)); |
| 5604 | make_number (total_free_intervals)); | 5637 | |
| 5605 | total[7] = Fcons (make_number (total_strings), | 5638 | total[4] = list3 (Qstring_bytes, make_number (1), |
| 5606 | make_number (total_free_strings)); | 5639 | bounded_number (total_string_bytes)); |
| 5640 | |||
| 5641 | total[5] = list3 (Qvectors, make_number (sizeof (struct Lisp_Vector)), | ||
| 5642 | bounded_number (total_vectors)); | ||
| 5643 | |||
| 5644 | total[6] = list4 (Qvector_slots, make_number (word_size), | ||
| 5645 | bounded_number (total_vector_slots), | ||
| 5646 | bounded_number (total_free_vector_slots)); | ||
| 5647 | |||
| 5648 | total[7] = list4 (Qfloats, make_number (sizeof (struct Lisp_Float)), | ||
| 5649 | bounded_number (total_floats), | ||
| 5650 | bounded_number (total_free_floats)); | ||
| 5651 | |||
| 5652 | total[8] = list4 (Qintervals, make_number (sizeof (struct interval)), | ||
| 5653 | bounded_number (total_intervals), | ||
| 5654 | bounded_number (total_free_intervals)); | ||
| 5655 | |||
| 5656 | total[9] = list3 (Qbuffers, make_number (sizeof (struct buffer)), | ||
| 5657 | bounded_number (total_buffers)); | ||
| 5658 | |||
| 5659 | #ifdef DOUG_LEA_MALLOC | ||
| 5660 | total_size++; | ||
| 5661 | total[10] = list4 (Qheap, make_number (1024), | ||
| 5662 | bounded_number ((mallinfo ().uordblks + 1023) >> 10), | ||
| 5663 | bounded_number ((mallinfo ().fordblks + 1023) >> 10)); | ||
| 5664 | #endif | ||
| 5665 | retval = Flist (total_size, total); | ||
| 5666 | } | ||
| 5607 | 5667 | ||
| 5608 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 5668 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 5609 | { | 5669 | { |
| 5610 | /* Compute average percentage of zombies. */ | 5670 | /* Compute average percentage of zombies. */ |
| 5611 | double nlive = 0; | 5671 | double nlive |
| 5612 | 5672 | = (total_conses + total_symbols + total_markers + total_strings | |
| 5613 | for (i = 0; i < 7; ++i) | 5673 | + total_vectors + total_floats + total_intervals + total_buffers); |
| 5614 | if (CONSP (total[i])) | ||
| 5615 | nlive += XFASTINT (XCAR (total[i])); | ||
| 5616 | 5674 | ||
| 5617 | avg_live = (avg_live * ngcs + nlive) / (ngcs + 1); | 5675 | avg_live = (avg_live * ngcs + nlive) / (ngcs + 1); |
| 5618 | max_live = max (nlive, max_live); | 5676 | max_live = max (nlive, max_live); |
| 5619 | avg_zombies = (avg_zombies * ngcs + nzombies) / (ngcs + 1); | 5677 | avg_zombies = (avg_zombies * ngcs + nzombies) / (ngcs + 1); |
| 5620 | max_zombies = max (nzombies, max_zombies); | 5678 | max_zombies = max (nzombies, max_zombies); |
| 5621 | ++ngcs; | 5679 | ++ngcs; |
| 5622 | } | 5680 | } |
| 5623 | #endif | 5681 | #endif |
| 5624 | 5682 | ||
| 5625 | if (!NILP (Vpost_gc_hook)) | 5683 | if (!NILP (Vpost_gc_hook)) |
| @@ -5632,15 +5690,14 @@ See Info node `(elisp)Garbage Collection'. */) | |||
| 5632 | /* Accumulate statistics. */ | 5690 | /* Accumulate statistics. */ |
| 5633 | if (FLOATP (Vgc_elapsed)) | 5691 | if (FLOATP (Vgc_elapsed)) |
| 5634 | { | 5692 | { |
| 5635 | EMACS_TIME t2 = current_emacs_time (); | 5693 | EMACS_TIME since_start = sub_emacs_time (current_emacs_time (), start); |
| 5636 | EMACS_TIME t3 = sub_emacs_time (t2, t1); | ||
| 5637 | Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) | 5694 | Vgc_elapsed = make_float (XFLOAT_DATA (Vgc_elapsed) |
| 5638 | + EMACS_TIME_TO_DOUBLE (t3)); | 5695 | + EMACS_TIME_TO_DOUBLE (since_start)); |
| 5639 | } | 5696 | } |
| 5640 | 5697 | ||
| 5641 | gcs_done++; | 5698 | gcs_done++; |
| 5642 | 5699 | ||
| 5643 | return Flist (sizeof total / sizeof *total, total); | 5700 | return retval; |
| 5644 | } | 5701 | } |
| 5645 | 5702 | ||
| 5646 | 5703 | ||
| @@ -5779,7 +5836,7 @@ mark_buffer (struct buffer *buffer) | |||
| 5779 | 5836 | ||
| 5780 | /* ...but there are some buffer-specific things. */ | 5837 | /* ...but there are some buffer-specific things. */ |
| 5781 | 5838 | ||
| 5782 | MARK_INTERVAL_TREE (BUF_INTERVALS (buffer)); | 5839 | MARK_INTERVAL_TREE (buffer_get_intervals (buffer)); |
| 5783 | 5840 | ||
| 5784 | /* For now, we just don't mark the undo_list. It's done later in | 5841 | /* For now, we just don't mark the undo_list. It's done later in |
| 5785 | a special way just before the sweep phase, and after stripping | 5842 | a special way just before the sweep phase, and after stripping |
| @@ -5852,7 +5909,7 @@ mark_object (Lisp_Object arg) | |||
| 5852 | 5909 | ||
| 5853 | #endif /* not GC_CHECK_MARKED_OBJECTS */ | 5910 | #endif /* not GC_CHECK_MARKED_OBJECTS */ |
| 5854 | 5911 | ||
| 5855 | switch (SWITCH_ENUM_CAST (XTYPE (obj))) | 5912 | switch (XTYPE (obj)) |
| 5856 | { | 5913 | { |
| 5857 | case Lisp_String: | 5914 | case Lisp_String: |
| 5858 | { | 5915 | { |
| @@ -5865,7 +5922,7 @@ mark_object (Lisp_Object arg) | |||
| 5865 | #ifdef GC_CHECK_STRING_BYTES | 5922 | #ifdef GC_CHECK_STRING_BYTES |
| 5866 | /* Check that the string size recorded in the string is the | 5923 | /* Check that the string size recorded in the string is the |
| 5867 | same as the one recorded in the sdata structure. */ | 5924 | same as the one recorded in the sdata structure. */ |
| 5868 | CHECK_STRING_BYTES (ptr); | 5925 | string_bytes (ptr); |
| 5869 | #endif /* GC_CHECK_STRING_BYTES */ | 5926 | #endif /* GC_CHECK_STRING_BYTES */ |
| 5870 | } | 5927 | } |
| 5871 | break; | 5928 | break; |
| @@ -5901,9 +5958,10 @@ mark_object (Lisp_Object arg) | |||
| 5901 | #ifdef GC_CHECK_MARKED_OBJECTS | 5958 | #ifdef GC_CHECK_MARKED_OBJECTS |
| 5902 | if (po != &buffer_defaults && po != &buffer_local_symbols) | 5959 | if (po != &buffer_defaults && po != &buffer_local_symbols) |
| 5903 | { | 5960 | { |
| 5904 | struct buffer *b = all_buffers; | 5961 | struct buffer *b; |
| 5905 | for (; b && b != po; b = b->header.next.buffer) | 5962 | FOR_EACH_BUFFER (b) |
| 5906 | ; | 5963 | if (b == po) |
| 5964 | break; | ||
| 5907 | if (b == NULL) | 5965 | if (b == NULL) |
| 5908 | abort (); | 5966 | abort (); |
| 5909 | } | 5967 | } |
| @@ -5945,7 +6003,8 @@ mark_object (Lisp_Object arg) | |||
| 5945 | /* Mark glyphs for leaf windows. Marking window | 6003 | /* Mark glyphs for leaf windows. Marking window |
| 5946 | matrices is sufficient because frame matrices | 6004 | matrices is sufficient because frame matrices |
| 5947 | use the same glyph memory. */ | 6005 | use the same glyph memory. */ |
| 5948 | if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) | 6006 | if (NILP (w->hchild) && NILP (w->vchild) |
| 6007 | && w->current_matrix) | ||
| 5949 | { | 6008 | { |
| 5950 | mark_glyph_matrix (w->current_matrix); | 6009 | mark_glyph_matrix (w->current_matrix); |
| 5951 | mark_glyph_matrix (w->desired_matrix); | 6010 | mark_glyph_matrix (w->desired_matrix); |
| @@ -6029,9 +6088,9 @@ mark_object (Lisp_Object arg) | |||
| 6029 | break; | 6088 | break; |
| 6030 | default: abort (); | 6089 | default: abort (); |
| 6031 | } | 6090 | } |
| 6032 | if (!PURE_POINTER_P (XSTRING (ptr->xname))) | 6091 | if (!PURE_POINTER_P (XSTRING (ptr->name))) |
| 6033 | MARK_STRING (XSTRING (ptr->xname)); | 6092 | MARK_STRING (XSTRING (ptr->name)); |
| 6034 | MARK_INTERVAL_TREE (STRING_INTERVALS (ptr->xname)); | 6093 | MARK_INTERVAL_TREE (string_get_intervals (ptr->name)); |
| 6035 | 6094 | ||
| 6036 | ptr = ptr->next; | 6095 | ptr = ptr->next; |
| 6037 | if (ptr) | 6096 | if (ptr) |
| @@ -6203,10 +6262,7 @@ gc_sweep (void) | |||
| 6203 | sweep_weak_hash_tables (); | 6262 | sweep_weak_hash_tables (); |
| 6204 | 6263 | ||
| 6205 | sweep_strings (); | 6264 | sweep_strings (); |
| 6206 | #ifdef GC_CHECK_STRING_BYTES | 6265 | check_string_bytes (!noninteractive); |
| 6207 | if (!noninteractive) | ||
| 6208 | check_string_bytes (1); | ||
| 6209 | #endif | ||
| 6210 | 6266 | ||
| 6211 | /* Put all unmarked conses on free list */ | 6267 | /* Put all unmarked conses on free list */ |
| 6212 | { | 6268 | { |
| @@ -6349,7 +6405,7 @@ gc_sweep (void) | |||
| 6349 | { | 6405 | { |
| 6350 | if (!iblk->intervals[i].gcmarkbit) | 6406 | if (!iblk->intervals[i].gcmarkbit) |
| 6351 | { | 6407 | { |
| 6352 | SET_INTERVAL_PARENT (&iblk->intervals[i], interval_free_list); | 6408 | interval_set_parent (&iblk->intervals[i], interval_free_list); |
| 6353 | interval_free_list = &iblk->intervals[i]; | 6409 | interval_free_list = &iblk->intervals[i]; |
| 6354 | this_free++; | 6410 | this_free++; |
| 6355 | } | 6411 | } |
| @@ -6400,7 +6456,7 @@ gc_sweep (void) | |||
| 6400 | /* Check if the symbol was created during loadup. In such a case | 6456 | /* Check if the symbol was created during loadup. In such a case |
| 6401 | it might be pointed to by pure bytecode which we don't trace, | 6457 | it might be pointed to by pure bytecode which we don't trace, |
| 6402 | so we conservatively assume that it is live. */ | 6458 | so we conservatively assume that it is live. */ |
| 6403 | int pure_p = PURE_POINTER_P (XSTRING (sym->s.xname)); | 6459 | int pure_p = PURE_POINTER_P (XSTRING (sym->s.name)); |
| 6404 | 6460 | ||
| 6405 | if (!sym->s.gcmarkbit && !pure_p) | 6461 | if (!sym->s.gcmarkbit && !pure_p) |
| 6406 | { | 6462 | { |
| @@ -6417,7 +6473,7 @@ gc_sweep (void) | |||
| 6417 | { | 6473 | { |
| 6418 | ++num_used; | 6474 | ++num_used; |
| 6419 | if (!pure_p) | 6475 | if (!pure_p) |
| 6420 | UNMARK_STRING (XSTRING (sym->s.xname)); | 6476 | UNMARK_STRING (XSTRING (sym->s.name)); |
| 6421 | sym->s.gcmarkbit = 0; | 6477 | sym->s.gcmarkbit = 0; |
| 6422 | } | 6478 | } |
| 6423 | } | 6479 | } |
| @@ -6504,6 +6560,7 @@ gc_sweep (void) | |||
| 6504 | { | 6560 | { |
| 6505 | register struct buffer *buffer = all_buffers, *prev = 0, *next; | 6561 | register struct buffer *buffer = all_buffers, *prev = 0, *next; |
| 6506 | 6562 | ||
| 6563 | total_buffers = 0; | ||
| 6507 | while (buffer) | 6564 | while (buffer) |
| 6508 | if (!VECTOR_MARKED_P (buffer)) | 6565 | if (!VECTOR_MARKED_P (buffer)) |
| 6509 | { | 6566 | { |
| @@ -6518,17 +6575,15 @@ gc_sweep (void) | |||
| 6518 | else | 6575 | else |
| 6519 | { | 6576 | { |
| 6520 | VECTOR_UNMARK (buffer); | 6577 | VECTOR_UNMARK (buffer); |
| 6521 | UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); | 6578 | /* Do not use buffer_(set|get)_intervals here. */ |
| 6579 | buffer->text->intervals = balance_intervals (buffer->text->intervals); | ||
| 6580 | total_buffers++; | ||
| 6522 | prev = buffer, buffer = buffer->header.next.buffer; | 6581 | prev = buffer, buffer = buffer->header.next.buffer; |
| 6523 | } | 6582 | } |
| 6524 | } | 6583 | } |
| 6525 | 6584 | ||
| 6526 | sweep_vectors (); | 6585 | sweep_vectors (); |
| 6527 | 6586 | check_string_bytes (!noninteractive); | |
| 6528 | #ifdef GC_CHECK_STRING_BYTES | ||
| 6529 | if (!noninteractive) | ||
| 6530 | check_string_bytes (1); | ||
| 6531 | #endif | ||
| 6532 | } | 6587 | } |
| 6533 | 6588 | ||
| 6534 | 6589 | ||
| @@ -6564,18 +6619,15 @@ Frames, windows, buffers, and subprocesses count as vectors | |||
| 6564 | (but the contents of a buffer's text do not count here). */) | 6619 | (but the contents of a buffer's text do not count here). */) |
| 6565 | (void) | 6620 | (void) |
| 6566 | { | 6621 | { |
| 6567 | Lisp_Object consed[8]; | 6622 | return listn (CONSTYPE_HEAP, 8, |
| 6568 | 6623 | bounded_number (cons_cells_consed), | |
| 6569 | consed[0] = make_number (min (MOST_POSITIVE_FIXNUM, cons_cells_consed)); | 6624 | bounded_number (floats_consed), |
| 6570 | consed[1] = make_number (min (MOST_POSITIVE_FIXNUM, floats_consed)); | 6625 | bounded_number (vector_cells_consed), |
| 6571 | consed[2] = make_number (min (MOST_POSITIVE_FIXNUM, vector_cells_consed)); | 6626 | bounded_number (symbols_consed), |
| 6572 | consed[3] = make_number (min (MOST_POSITIVE_FIXNUM, symbols_consed)); | 6627 | bounded_number (string_chars_consed), |
| 6573 | consed[4] = make_number (min (MOST_POSITIVE_FIXNUM, string_chars_consed)); | 6628 | bounded_number (misc_objects_consed), |
| 6574 | consed[5] = make_number (min (MOST_POSITIVE_FIXNUM, misc_objects_consed)); | 6629 | bounded_number (intervals_consed), |
| 6575 | consed[6] = make_number (min (MOST_POSITIVE_FIXNUM, intervals_consed)); | 6630 | bounded_number (strings_consed)); |
| 6576 | consed[7] = make_number (min (MOST_POSITIVE_FIXNUM, strings_consed)); | ||
| 6577 | |||
| 6578 | return Flist (8, consed); | ||
| 6579 | } | 6631 | } |
| 6580 | 6632 | ||
| 6581 | /* Find at most FIND_MAX symbols which have OBJ as their value or | 6633 | /* Find at most FIND_MAX symbols which have OBJ as their value or |
| @@ -6669,7 +6721,7 @@ init_alloc_once (void) | |||
| 6669 | #endif | 6721 | #endif |
| 6670 | 6722 | ||
| 6671 | refill_memory_reserve (); | 6723 | refill_memory_reserve (); |
| 6672 | gc_cons_threshold = 100000 * sizeof (Lisp_Object); | 6724 | gc_cons_threshold = GC_DEFAULT_THRESHOLD; |
| 6673 | } | 6725 | } |
| 6674 | 6726 | ||
| 6675 | void | 6727 | void |
| @@ -6756,13 +6808,25 @@ do hash-consing of the objects allocated to pure space. */); | |||
| 6756 | /* We build this in advance because if we wait until we need it, we might | 6808 | /* We build this in advance because if we wait until we need it, we might |
| 6757 | not be able to allocate the memory to hold it. */ | 6809 | not be able to allocate the memory to hold it. */ |
| 6758 | Vmemory_signal_data | 6810 | Vmemory_signal_data |
| 6759 | = pure_cons (Qerror, | 6811 | = listn (CONSTYPE_PURE, 2, Qerror, |
| 6760 | pure_cons (build_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs"), Qnil)); | 6812 | build_pure_c_string ("Memory exhausted--use M-x save-some-buffers then exit and restart Emacs")); |
| 6761 | 6813 | ||
| 6762 | DEFVAR_LISP ("memory-full", Vmemory_full, | 6814 | DEFVAR_LISP ("memory-full", Vmemory_full, |
| 6763 | doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); | 6815 | doc: /* Non-nil means Emacs cannot get much more Lisp memory. */); |
| 6764 | Vmemory_full = Qnil; | 6816 | Vmemory_full = Qnil; |
| 6765 | 6817 | ||
| 6818 | DEFSYM (Qconses, "conses"); | ||
| 6819 | DEFSYM (Qsymbols, "symbols"); | ||
| 6820 | DEFSYM (Qmiscs, "miscs"); | ||
| 6821 | DEFSYM (Qstrings, "strings"); | ||
| 6822 | DEFSYM (Qvectors, "vectors"); | ||
| 6823 | DEFSYM (Qfloats, "floats"); | ||
| 6824 | DEFSYM (Qintervals, "intervals"); | ||
| 6825 | DEFSYM (Qbuffers, "buffers"); | ||
| 6826 | DEFSYM (Qstring_bytes, "string-bytes"); | ||
| 6827 | DEFSYM (Qvector_slots, "vector-slots"); | ||
| 6828 | DEFSYM (Qheap, "heap"); | ||
| 6829 | |||
| 6766 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); | 6830 | DEFSYM (Qgc_cons_threshold, "gc-cons-threshold"); |
| 6767 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); | 6831 | DEFSYM (Qchar_table_extra_slots, "char-table-extra-slots"); |
| 6768 | 6832 | ||
| @@ -6791,3 +6855,27 @@ The time is in seconds as a floating point value. */); | |||
| 6791 | defsubr (&Sgc_status); | 6855 | defsubr (&Sgc_status); |
| 6792 | #endif | 6856 | #endif |
| 6793 | } | 6857 | } |
| 6858 | |||
| 6859 | /* When compiled with GCC, GDB might say "No enum type named | ||
| 6860 | pvec_type" if we don't have at least one symbol with that type, and | ||
| 6861 | then xbacktrace could fail. Similarly for the other enums and | ||
| 6862 | their values. */ | ||
| 6863 | union | ||
| 6864 | { | ||
| 6865 | enum CHARTAB_SIZE_BITS CHARTAB_SIZE_BITS; | ||
| 6866 | enum CHAR_TABLE_STANDARD_SLOTS CHAR_TABLE_STANDARD_SLOTS; | ||
| 6867 | enum char_bits char_bits; | ||
| 6868 | enum CHECK_LISP_OBJECT_TYPE CHECK_LISP_OBJECT_TYPE; | ||
| 6869 | enum DEFAULT_HASH_SIZE DEFAULT_HASH_SIZE; | ||
| 6870 | enum enum_USE_LSB_TAG enum_USE_LSB_TAG; | ||
| 6871 | enum FLOAT_TO_STRING_BUFSIZE FLOAT_TO_STRING_BUFSIZE; | ||
| 6872 | enum Lisp_Bits Lisp_Bits; | ||
| 6873 | enum Lisp_Compiled Lisp_Compiled; | ||
| 6874 | enum maxargs maxargs; | ||
| 6875 | enum MAX_ALLOCA MAX_ALLOCA; | ||
| 6876 | enum More_Lisp_Bits More_Lisp_Bits; | ||
| 6877 | enum pvec_type pvec_type; | ||
| 6878 | #if USE_LSB_TAG | ||
| 6879 | enum lsb_bits lsb_bits; | ||
| 6880 | #endif | ||
| 6881 | } const EXTERNALLY_VISIBLE gdb_make_enums_visible = {0}; | ||