diff options
| author | Paul Eggert | 2017-11-13 08:51:41 -0800 |
|---|---|---|
| committer | Paul Eggert | 2017-11-13 10:16:51 -0800 |
| commit | b1573a97e17b518723ab3f906eb6d521caed196d (patch) | |
| tree | 2bcfe8f47a99d7ba9b46e75ed5bffd2ba37970e0 /src/alloc.c | |
| parent | 5d68dc9a2fd1b9b883db6bc1c226541b50de8bb1 (diff) | |
| download | emacs-b1573a97e17b518723ab3f906eb6d521caed196d.tar.gz emacs-b1573a97e17b518723ab3f906eb6d521caed196d.zip | |
Use alignas to fix GCALIGN-related bugs
Use alignas and unions to specify alignments of objects needing
addresses that are at least a multiple of GCALIGNMENT. Using
these standard C facilities should be safer than relying on ad hoc
and poorly-understood features like GCC’s __attribute__
((aligned (N))), the root cause for recent porting bugs like
Bug#29040. The alignas macro was standardized by C11 and Gnulib
supports alignas for pre-C11 platforms. I have tested this on Sun
Studio 12 sparc (2007) and GCC 4.4.7 x86-64 (2012) as well as on
more recent platforms like GCC 7.2.1 (2017) on Fedora 26 (both
x86-64 and x86).
* lib-src/make-docfile.c (close_emacs_globals): lispsym is now
just an array of struct Lisp_Symbol, since struct Lisp_Symbol is
now properly aligned. All uses changed.
* src/alloc.c (NEXT_FREE_LISP_STRING): Just use the new u.next
member; this is simpler and safer than casting a pointer that
might not be aligned properly.
(aligned_Lisp_Symbol): Remove. No longer needed, now that struct
Lisp_Symbol is aligned properly. All uses replaced with struct
Lisp_Symbol.
* src/lisp.h (GCALIGNED): Remove, as it does not work as expected:
it can cause the natural alignment to be ignored. All uses
replaced by unions with a ‘char alignas (GCALIGNMENT)’ member as
described below.
(struct Lisp_Symbol, struct Lisp_Cons, struct Lisp_String):
Change definition from ‘struct TAG { MEMBERS };’ to
‘struct TAG { union { struct { MEMBERS } s; char alignas
(GCALIGNMENT) gcaligned; } u; };’. This guarantees ‘struct TAG’
to have an alignment that at least max (GCALIGNMENT, N) where N is
its old alignment. All uses like ‘PTR->MEMBER’ changed to
‘PTR->u.s.MEMBER’; these uses were supposed to be mostly private
anyway. Verify that the resulting ‘struct TAG’ is properly
aligned for Emacs.
(union vectorlike_header): New member ‘gcaligned’ to guarantee
that this type, and its containing types like ‘struct Lisp_Subr’,
‘struct buffer’ and ‘struct thread_state’, are all properly
aligned for Emacs.
(struct Lisp_String): New union member ‘next’, for the benefit
of NEXT_FREE_LISP_STRING.
(union Aligned_Cons, union Aligned_String): Remove. All uses
replaced by struct Lisp_Cons and struct Lisp_String, since they
are now properly aligned.
(USE_STACK_CONS, USE_STACK_STRING): Simplify now that we can
assume struct Lisp_Cons and struct Lisp_String are properly
aligned.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 211 |
1 files changed, 101 insertions, 110 deletions
diff --git a/src/alloc.c b/src/alloc.c index 5a44d7a9fc2..3b87195b707 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -211,9 +211,9 @@ alloc_unexec_post (void) | |||
| 211 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer | 211 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer |
| 212 | to a struct Lisp_String. */ | 212 | to a struct Lisp_String. */ |
| 213 | 213 | ||
| 214 | #define MARK_STRING(S) ((S)->size |= ARRAY_MARK_FLAG) | 214 | #define MARK_STRING(S) ((S)->u.s.size |= ARRAY_MARK_FLAG) |
| 215 | #define UNMARK_STRING(S) ((S)->size &= ~ARRAY_MARK_FLAG) | 215 | #define UNMARK_STRING(S) ((S)->u.s.size &= ~ARRAY_MARK_FLAG) |
| 216 | #define STRING_MARKED_P(S) (((S)->size & ARRAY_MARK_FLAG) != 0) | 216 | #define STRING_MARKED_P(S) (((S)->u.s.size & ARRAY_MARK_FLAG) != 0) |
| 217 | 217 | ||
| 218 | #define VECTOR_MARK(V) ((V)->header.size |= ARRAY_MARK_FLAG) | 218 | #define VECTOR_MARK(V) ((V)->header.size |= ARRAY_MARK_FLAG) |
| 219 | #define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG) | 219 | #define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG) |
| @@ -1730,14 +1730,14 @@ static EMACS_INT total_string_bytes; | |||
| 1730 | string_free_list, return a pointer to its successor in the | 1730 | string_free_list, return a pointer to its successor in the |
| 1731 | free-list. */ | 1731 | free-list. */ |
| 1732 | 1732 | ||
| 1733 | #define NEXT_FREE_LISP_STRING(S) (*(struct Lisp_String **) (S)) | 1733 | #define NEXT_FREE_LISP_STRING(S) ((S)->u.next) |
| 1734 | 1734 | ||
| 1735 | /* Return a pointer to the sdata structure belonging to Lisp string S. | 1735 | /* Return a pointer to the sdata structure belonging to Lisp string S. |
| 1736 | S must be live, i.e. S->data must not be null. S->data is actually | 1736 | S must be live, i.e. S->data must not be null. S->data is actually |
| 1737 | a pointer to the `u.data' member of its sdata structure; the | 1737 | a pointer to the `u.data' member of its sdata structure; the |
| 1738 | structure starts at a constant offset in front of that. */ | 1738 | structure starts at a constant offset in front of that. */ |
| 1739 | 1739 | ||
| 1740 | #define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET)) | 1740 | #define SDATA_OF_STRING(S) ((sdata *) ((S)->u.s.data - SDATA_DATA_OFFSET)) |
| 1741 | 1741 | ||
| 1742 | 1742 | ||
| 1743 | #ifdef GC_CHECK_STRING_OVERRUN | 1743 | #ifdef GC_CHECK_STRING_OVERRUN |
| @@ -1818,9 +1818,10 @@ ptrdiff_t | |||
| 1818 | string_bytes (struct Lisp_String *s) | 1818 | string_bytes (struct Lisp_String *s) |
| 1819 | { | 1819 | { |
| 1820 | ptrdiff_t nbytes = | 1820 | ptrdiff_t nbytes = |
| 1821 | (s->size_byte < 0 ? s->size & ~ARRAY_MARK_FLAG : s->size_byte); | 1821 | (s->u.s.size_byte < 0 ? s->u.s.size & ~ARRAY_MARK_FLAG : s->u.s.size_byte); |
| 1822 | 1822 | ||
| 1823 | if (!PURE_P (s) && s->data && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) | 1823 | if (!PURE_P (s) && s->u.s.data |
| 1824 | && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) | ||
| 1824 | emacs_abort (); | 1825 | emacs_abort (); |
| 1825 | return nbytes; | 1826 | return nbytes; |
| 1826 | } | 1827 | } |
| @@ -1926,7 +1927,7 @@ allocate_string (void) | |||
| 1926 | { | 1927 | { |
| 1927 | s = b->strings + i; | 1928 | s = b->strings + i; |
| 1928 | /* Every string on a free list should have NULL data pointer. */ | 1929 | /* Every string on a free list should have NULL data pointer. */ |
| 1929 | s->data = NULL; | 1930 | s->u.s.data = NULL; |
| 1930 | NEXT_FREE_LISP_STRING (s) = string_free_list; | 1931 | NEXT_FREE_LISP_STRING (s) = string_free_list; |
| 1931 | string_free_list = s; | 1932 | string_free_list = s; |
| 1932 | } | 1933 | } |
| @@ -1965,10 +1966,10 @@ allocate_string (void) | |||
| 1965 | 1966 | ||
| 1966 | 1967 | ||
| 1967 | /* Set up Lisp_String S for holding NCHARS characters, NBYTES bytes, | 1968 | /* Set up Lisp_String S for holding NCHARS characters, NBYTES bytes, |
| 1968 | plus a NUL byte at the end. Allocate an sdata structure for S, and | 1969 | plus a NUL byte at the end. Allocate an sdata structure DATA for |
| 1969 | set S->data to its `u.data' member. Store a NUL byte at the end of | 1970 | S, and set S->u.s.data to SDATA->u.data. Store a NUL byte at the |
| 1970 | S->data. Set S->size to NCHARS and S->size_byte to NBYTES. Free | 1971 | end of S->u.s.data. Set S->u.s.size to NCHARS and S->u.s.size_byte |
| 1971 | S->data if it was initially non-null. */ | 1972 | to NBYTES. Free S->u.s.data if it was initially non-null. */ |
| 1972 | 1973 | ||
| 1973 | void | 1974 | void |
| 1974 | allocate_string_data (struct Lisp_String *s, | 1975 | allocate_string_data (struct Lisp_String *s, |
| @@ -1984,7 +1985,7 @@ allocate_string_data (struct Lisp_String *s, | |||
| 1984 | /* Determine the number of bytes needed to store NBYTES bytes | 1985 | /* Determine the number of bytes needed to store NBYTES bytes |
| 1985 | of string data. */ | 1986 | of string data. */ |
| 1986 | needed = SDATA_SIZE (nbytes); | 1987 | needed = SDATA_SIZE (nbytes); |
| 1987 | if (s->data) | 1988 | if (s->u.s.data) |
| 1988 | { | 1989 | { |
| 1989 | old_data = SDATA_OF_STRING (s); | 1990 | old_data = SDATA_OF_STRING (s); |
| 1990 | old_nbytes = STRING_BYTES (s); | 1991 | old_nbytes = STRING_BYTES (s); |
| @@ -2043,13 +2044,13 @@ allocate_string_data (struct Lisp_String *s, | |||
| 2043 | 2044 | ||
| 2044 | MALLOC_UNBLOCK_INPUT; | 2045 | MALLOC_UNBLOCK_INPUT; |
| 2045 | 2046 | ||
| 2046 | s->data = SDATA_DATA (data); | 2047 | s->u.s.data = SDATA_DATA (data); |
| 2047 | #ifdef GC_CHECK_STRING_BYTES | 2048 | #ifdef GC_CHECK_STRING_BYTES |
| 2048 | SDATA_NBYTES (data) = nbytes; | 2049 | SDATA_NBYTES (data) = nbytes; |
| 2049 | #endif | 2050 | #endif |
| 2050 | s->size = nchars; | 2051 | s->u.s.size = nchars; |
| 2051 | s->size_byte = nbytes; | 2052 | s->u.s.size_byte = nbytes; |
| 2052 | s->data[nbytes] = '\0'; | 2053 | s->u.s.data[nbytes] = '\0'; |
| 2053 | #ifdef GC_CHECK_STRING_OVERRUN | 2054 | #ifdef GC_CHECK_STRING_OVERRUN |
| 2054 | memcpy ((char *) data + needed, string_overrun_cookie, | 2055 | memcpy ((char *) data + needed, string_overrun_cookie, |
| 2055 | GC_STRING_OVERRUN_COOKIE_SIZE); | 2056 | GC_STRING_OVERRUN_COOKIE_SIZE); |
| @@ -2093,7 +2094,7 @@ sweep_strings (void) | |||
| 2093 | { | 2094 | { |
| 2094 | struct Lisp_String *s = b->strings + i; | 2095 | struct Lisp_String *s = b->strings + i; |
| 2095 | 2096 | ||
| 2096 | if (s->data) | 2097 | if (s->u.s.data) |
| 2097 | { | 2098 | { |
| 2098 | /* String was not on free-list before. */ | 2099 | /* String was not on free-list before. */ |
| 2099 | if (STRING_MARKED_P (s)) | 2100 | if (STRING_MARKED_P (s)) |
| @@ -2102,7 +2103,7 @@ sweep_strings (void) | |||
| 2102 | UNMARK_STRING (s); | 2103 | UNMARK_STRING (s); |
| 2103 | 2104 | ||
| 2104 | /* Do not use string_(set|get)_intervals here. */ | 2105 | /* Do not use string_(set|get)_intervals here. */ |
| 2105 | s->intervals = balance_intervals (s->intervals); | 2106 | s->u.s.intervals = balance_intervals (s->u.s.intervals); |
| 2106 | 2107 | ||
| 2107 | ++total_strings; | 2108 | ++total_strings; |
| 2108 | total_string_bytes += STRING_BYTES (s); | 2109 | total_string_bytes += STRING_BYTES (s); |
| @@ -2125,7 +2126,7 @@ sweep_strings (void) | |||
| 2125 | 2126 | ||
| 2126 | /* Reset the strings's `data' member so that we | 2127 | /* Reset the strings's `data' member so that we |
| 2127 | know it's free. */ | 2128 | know it's free. */ |
| 2128 | s->data = NULL; | 2129 | s->u.s.data = NULL; |
| 2129 | 2130 | ||
| 2130 | /* Put the string on the free-list. */ | 2131 | /* Put the string on the free-list. */ |
| 2131 | NEXT_FREE_LISP_STRING (s) = string_free_list; | 2132 | NEXT_FREE_LISP_STRING (s) = string_free_list; |
| @@ -2264,7 +2265,7 @@ compact_small_strings (void) | |||
| 2264 | { | 2265 | { |
| 2265 | eassert (tb != b || to < from); | 2266 | eassert (tb != b || to < from); |
| 2266 | memmove (to, from, nbytes + GC_STRING_EXTRA); | 2267 | memmove (to, from, nbytes + GC_STRING_EXTRA); |
| 2267 | to->string->data = SDATA_DATA (to); | 2268 | to->string->u.s.data = SDATA_DATA (to); |
| 2268 | } | 2269 | } |
| 2269 | 2270 | ||
| 2270 | /* Advance past the sdata we copied to. */ | 2271 | /* Advance past the sdata we copied to. */ |
| @@ -2544,7 +2545,7 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) | |||
| 2544 | return empty_multibyte_string; | 2545 | return empty_multibyte_string; |
| 2545 | 2546 | ||
| 2546 | s = allocate_string (); | 2547 | s = allocate_string (); |
| 2547 | s->intervals = NULL; | 2548 | s->u.s.intervals = NULL; |
| 2548 | allocate_string_data (s, nchars, nbytes); | 2549 | allocate_string_data (s, nchars, nbytes); |
| 2549 | XSETSTRING (string, s); | 2550 | XSETSTRING (string, s); |
| 2550 | string_chars_consed += nbytes; | 2551 | string_chars_consed += nbytes; |
| @@ -2729,8 +2730,8 @@ static struct Lisp_Cons *cons_free_list; | |||
| 2729 | void | 2730 | void |
| 2730 | free_cons (struct Lisp_Cons *ptr) | 2731 | free_cons (struct Lisp_Cons *ptr) |
| 2731 | { | 2732 | { |
| 2732 | ptr->u.chain = cons_free_list; | 2733 | ptr->u.s.u.chain = cons_free_list; |
| 2733 | ptr->car = Vdead; | 2734 | ptr->u.s.car = Vdead; |
| 2734 | cons_free_list = ptr; | 2735 | cons_free_list = ptr; |
| 2735 | consing_since_gc -= sizeof *ptr; | 2736 | consing_since_gc -= sizeof *ptr; |
| 2736 | total_free_conses++; | 2737 | total_free_conses++; |
| @@ -2749,7 +2750,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 2749 | /* We use the cdr for chaining the free list | 2750 | /* We use the cdr for chaining the free list |
| 2750 | so that we won't use the same field that has the mark bit. */ | 2751 | so that we won't use the same field that has the mark bit. */ |
| 2751 | XSETCONS (val, cons_free_list); | 2752 | XSETCONS (val, cons_free_list); |
| 2752 | cons_free_list = cons_free_list->u.chain; | 2753 | cons_free_list = cons_free_list->u.s.u.chain; |
| 2753 | } | 2754 | } |
| 2754 | else | 2755 | else |
| 2755 | { | 2756 | { |
| @@ -2786,7 +2787,7 @@ check_cons_list (void) | |||
| 2786 | struct Lisp_Cons *tail = cons_free_list; | 2787 | struct Lisp_Cons *tail = cons_free_list; |
| 2787 | 2788 | ||
| 2788 | while (tail) | 2789 | while (tail) |
| 2789 | tail = tail->u.chain; | 2790 | tail = tail->u.s.u.chain; |
| 2790 | } | 2791 | } |
| 2791 | #endif | 2792 | #endif |
| 2792 | 2793 | ||
| @@ -3543,27 +3544,17 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3543 | Symbol Allocation | 3544 | Symbol Allocation |
| 3544 | ***********************************************************************/ | 3545 | ***********************************************************************/ |
| 3545 | 3546 | ||
| 3546 | /* Like struct Lisp_Symbol, but padded so that the size is a multiple | ||
| 3547 | of the required alignment. */ | ||
| 3548 | |||
| 3549 | union aligned_Lisp_Symbol | ||
| 3550 | { | ||
| 3551 | struct Lisp_Symbol s; | ||
| 3552 | unsigned char c[(sizeof (struct Lisp_Symbol) + GCALIGNMENT - 1) | ||
| 3553 | & -GCALIGNMENT]; | ||
| 3554 | }; | ||
| 3555 | |||
| 3556 | /* Each symbol_block is just under 1020 bytes long, since malloc | 3547 | /* Each symbol_block is just under 1020 bytes long, since malloc |
| 3557 | really allocates in units of powers of two and uses 4 bytes for its | 3548 | really allocates in units of powers of two and uses 4 bytes for its |
| 3558 | own overhead. */ | 3549 | own overhead. */ |
| 3559 | 3550 | ||
| 3560 | #define SYMBOL_BLOCK_SIZE \ | 3551 | #define SYMBOL_BLOCK_SIZE \ |
| 3561 | ((1020 - sizeof (struct symbol_block *)) / sizeof (union aligned_Lisp_Symbol)) | 3552 | ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol)) |
| 3562 | 3553 | ||
| 3563 | struct symbol_block | 3554 | struct symbol_block |
| 3564 | { | 3555 | { |
| 3565 | /* Place `symbols' first, to preserve alignment. */ | 3556 | /* Place `symbols' first, to preserve alignment. */ |
| 3566 | union aligned_Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; | 3557 | struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; |
| 3567 | struct symbol_block *next; | 3558 | struct symbol_block *next; |
| 3568 | }; | 3559 | }; |
| 3569 | 3560 | ||
| @@ -3587,7 +3578,7 @@ static struct Lisp_Symbol *symbol_free_list; | |||
| 3587 | static void | 3578 | static void |
| 3588 | set_symbol_name (Lisp_Object sym, Lisp_Object name) | 3579 | set_symbol_name (Lisp_Object sym, Lisp_Object name) |
| 3589 | { | 3580 | { |
| 3590 | XSYMBOL (sym)->name = name; | 3581 | XSYMBOL (sym)->u.s.name = name; |
| 3591 | } | 3582 | } |
| 3592 | 3583 | ||
| 3593 | void | 3584 | void |
| @@ -3596,15 +3587,15 @@ init_symbol (Lisp_Object val, Lisp_Object name) | |||
| 3596 | struct Lisp_Symbol *p = XSYMBOL (val); | 3587 | struct Lisp_Symbol *p = XSYMBOL (val); |
| 3597 | set_symbol_name (val, name); | 3588 | set_symbol_name (val, name); |
| 3598 | set_symbol_plist (val, Qnil); | 3589 | set_symbol_plist (val, Qnil); |
| 3599 | p->redirect = SYMBOL_PLAINVAL; | 3590 | p->u.s.redirect = SYMBOL_PLAINVAL; |
| 3600 | SET_SYMBOL_VAL (p, Qunbound); | 3591 | SET_SYMBOL_VAL (p, Qunbound); |
| 3601 | set_symbol_function (val, Qnil); | 3592 | set_symbol_function (val, Qnil); |
| 3602 | set_symbol_next (val, NULL); | 3593 | set_symbol_next (val, NULL); |
| 3603 | p->gcmarkbit = false; | 3594 | p->u.s.gcmarkbit = false; |
| 3604 | p->interned = SYMBOL_UNINTERNED; | 3595 | p->u.s.interned = SYMBOL_UNINTERNED; |
| 3605 | p->trapped_write = SYMBOL_UNTRAPPED_WRITE; | 3596 | p->u.s.trapped_write = SYMBOL_UNTRAPPED_WRITE; |
| 3606 | p->declared_special = false; | 3597 | p->u.s.declared_special = false; |
| 3607 | p->pinned = false; | 3598 | p->u.s.pinned = false; |
| 3608 | } | 3599 | } |
| 3609 | 3600 | ||
| 3610 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, | 3601 | DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, |
| @@ -3621,7 +3612,7 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3621 | if (symbol_free_list) | 3612 | if (symbol_free_list) |
| 3622 | { | 3613 | { |
| 3623 | XSETSYMBOL (val, symbol_free_list); | 3614 | XSETSYMBOL (val, symbol_free_list); |
| 3624 | symbol_free_list = symbol_free_list->next; | 3615 | symbol_free_list = symbol_free_list->u.s.next; |
| 3625 | } | 3616 | } |
| 3626 | else | 3617 | else |
| 3627 | { | 3618 | { |
| @@ -3634,7 +3625,7 @@ Its value is void, and its function definition and property list are nil. */) | |||
| 3634 | symbol_block_index = 0; | 3625 | symbol_block_index = 0; |
| 3635 | total_free_symbols += SYMBOL_BLOCK_SIZE; | 3626 | total_free_symbols += SYMBOL_BLOCK_SIZE; |
| 3636 | } | 3627 | } |
| 3637 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index].s); | 3628 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); |
| 3638 | symbol_block_index++; | 3629 | symbol_block_index++; |
| 3639 | } | 3630 | } |
| 3640 | 3631 | ||
| @@ -4587,7 +4578,7 @@ live_string_holding (struct mem_node *m, void *p) | |||
| 4587 | if (0 <= offset && offset < STRING_BLOCK_SIZE * sizeof b->strings[0]) | 4578 | if (0 <= offset && offset < STRING_BLOCK_SIZE * sizeof b->strings[0]) |
| 4588 | { | 4579 | { |
| 4589 | struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0]; | 4580 | struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0]; |
| 4590 | if (s->data) | 4581 | if (s->u.s.data) |
| 4591 | return make_lisp_ptr (s, Lisp_String); | 4582 | return make_lisp_ptr (s, Lisp_String); |
| 4592 | } | 4583 | } |
| 4593 | } | 4584 | } |
| @@ -4621,7 +4612,7 @@ live_cons_holding (struct mem_node *m, void *p) | |||
| 4621 | || offset / sizeof b->conses[0] < cons_block_index)) | 4612 | || offset / sizeof b->conses[0] < cons_block_index)) |
| 4622 | { | 4613 | { |
| 4623 | struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0]; | 4614 | struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0]; |
| 4624 | if (!EQ (s->car, Vdead)) | 4615 | if (!EQ (s->u.s.car, Vdead)) |
| 4625 | return make_lisp_ptr (s, Lisp_Cons); | 4616 | return make_lisp_ptr (s, Lisp_Cons); |
| 4626 | } | 4617 | } |
| 4627 | } | 4618 | } |
| @@ -4656,7 +4647,7 @@ live_symbol_holding (struct mem_node *m, void *p) | |||
| 4656 | || offset / sizeof b->symbols[0] < symbol_block_index)) | 4647 | || offset / sizeof b->symbols[0] < symbol_block_index)) |
| 4657 | { | 4648 | { |
| 4658 | struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0]; | 4649 | struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0]; |
| 4659 | if (!EQ (s->function, Vdead)) | 4650 | if (!EQ (s->u.s.function, Vdead)) |
| 4660 | return make_lisp_symbol (s); | 4651 | return make_lisp_symbol (s); |
| 4661 | } | 4652 | } |
| 4662 | } | 4653 | } |
| @@ -4984,7 +4975,7 @@ mark_memory (void *start, void *end) | |||
| 4984 | Lisp_Object obj = build_string ("test"); | 4975 | Lisp_Object obj = build_string ("test"); |
| 4985 | struct Lisp_String *s = XSTRING (obj); | 4976 | struct Lisp_String *s = XSTRING (obj); |
| 4986 | Fgarbage_collect (); | 4977 | Fgarbage_collect (); |
| 4987 | fprintf (stderr, "test '%s'\n", s->data); | 4978 | fprintf (stderr, "test '%s'\n", s->u.s.data); |
| 4988 | return Qnil; | 4979 | return Qnil; |
| 4989 | } | 4980 | } |
| 4990 | 4981 | ||
| @@ -5484,16 +5475,16 @@ make_pure_string (const char *data, | |||
| 5484 | { | 5475 | { |
| 5485 | Lisp_Object string; | 5476 | Lisp_Object string; |
| 5486 | struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); | 5477 | struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); |
| 5487 | s->data = (unsigned char *) find_string_data_in_pure (data, nbytes); | 5478 | s->u.s.data = (unsigned char *) find_string_data_in_pure (data, nbytes); |
| 5488 | if (s->data == NULL) | 5479 | if (s->u.s.data == NULL) |
| 5489 | { | 5480 | { |
| 5490 | s->data = pure_alloc (nbytes + 1, -1); | 5481 | s->u.s.data = pure_alloc (nbytes + 1, -1); |
| 5491 | memcpy (s->data, data, nbytes); | 5482 | memcpy (s->u.s.data, data, nbytes); |
| 5492 | s->data[nbytes] = '\0'; | 5483 | s->u.s.data[nbytes] = '\0'; |
| 5493 | } | 5484 | } |
| 5494 | s->size = nchars; | 5485 | s->u.s.size = nchars; |
| 5495 | s->size_byte = multibyte ? nbytes : -1; | 5486 | s->u.s.size_byte = multibyte ? nbytes : -1; |
| 5496 | s->intervals = NULL; | 5487 | s->u.s.intervals = NULL; |
| 5497 | XSETSTRING (string, s); | 5488 | XSETSTRING (string, s); |
| 5498 | return string; | 5489 | return string; |
| 5499 | } | 5490 | } |
| @@ -5506,10 +5497,10 @@ make_pure_c_string (const char *data, ptrdiff_t nchars) | |||
| 5506 | { | 5497 | { |
| 5507 | Lisp_Object string; | 5498 | Lisp_Object string; |
| 5508 | struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); | 5499 | struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); |
| 5509 | s->size = nchars; | 5500 | s->u.s.size = nchars; |
| 5510 | s->size_byte = -1; | 5501 | s->u.s.size_byte = -1; |
| 5511 | s->data = (unsigned char *) data; | 5502 | s->u.s.data = (unsigned char *) data; |
| 5512 | s->intervals = NULL; | 5503 | s->u.s.intervals = NULL; |
| 5513 | XSETSTRING (string, s); | 5504 | XSETSTRING (string, s); |
| 5514 | return string; | 5505 | return string; |
| 5515 | } | 5506 | } |
| @@ -5620,7 +5611,7 @@ purecopy (Lisp_Object obj) | |||
| 5620 | || SUBRP (obj)) | 5611 | || SUBRP (obj)) |
| 5621 | return obj; /* Already pure. */ | 5612 | return obj; /* Already pure. */ |
| 5622 | 5613 | ||
| 5623 | if (STRINGP (obj) && XSTRING (obj)->intervals) | 5614 | if (STRINGP (obj) && XSTRING (obj)->u.s.intervals) |
| 5624 | message_with_string ("Dropping text-properties while making string `%s' pure", | 5615 | message_with_string ("Dropping text-properties while making string `%s' pure", |
| 5625 | obj, true); | 5616 | obj, true); |
| 5626 | 5617 | ||
| @@ -5675,10 +5666,10 @@ purecopy (Lisp_Object obj) | |||
| 5675 | } | 5666 | } |
| 5676 | else if (SYMBOLP (obj)) | 5667 | else if (SYMBOLP (obj)) |
| 5677 | { | 5668 | { |
| 5678 | if (!XSYMBOL (obj)->pinned && !c_symbol_p (XSYMBOL (obj))) | 5669 | if (!XSYMBOL (obj)->u.s.pinned && !c_symbol_p (XSYMBOL (obj))) |
| 5679 | { /* We can't purify them, but they appear in many pure objects. | 5670 | { /* We can't purify them, but they appear in many pure objects. |
| 5680 | Mark them as `pinned' so we know to mark them at every GC cycle. */ | 5671 | Mark them as `pinned' so we know to mark them at every GC cycle. */ |
| 5681 | XSYMBOL (obj)->pinned = true; | 5672 | XSYMBOL (obj)->u.s.pinned = true; |
| 5682 | symbol_block_pinned = symbol_block; | 5673 | symbol_block_pinned = symbol_block; |
| 5683 | } | 5674 | } |
| 5684 | /* Don't hash-cons it. */ | 5675 | /* Don't hash-cons it. */ |
| @@ -5891,10 +5882,10 @@ mark_pinned_symbols (void) | |||
| 5891 | 5882 | ||
| 5892 | for (sblk = symbol_block_pinned; sblk; sblk = sblk->next) | 5883 | for (sblk = symbol_block_pinned; sblk; sblk = sblk->next) |
| 5893 | { | 5884 | { |
| 5894 | union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim; | 5885 | struct Lisp_Symbol *sym = sblk->symbols, *end = sym + lim; |
| 5895 | for (; sym < end; ++sym) | 5886 | for (; sym < end; ++sym) |
| 5896 | if (sym->s.pinned) | 5887 | if (sym->u.s.pinned) |
| 5897 | mark_object (make_lisp_symbol (&sym->s)); | 5888 | mark_object (make_lisp_symbol (sym)); |
| 5898 | 5889 | ||
| 5899 | lim = SYMBOL_BLOCK_SIZE; | 5890 | lim = SYMBOL_BLOCK_SIZE; |
| 5900 | } | 5891 | } |
| @@ -6256,7 +6247,7 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype) | |||
| 6256 | { | 6247 | { |
| 6257 | Lisp_Object val = ptr->contents[i]; | 6248 | Lisp_Object val = ptr->contents[i]; |
| 6258 | 6249 | ||
| 6259 | if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->gcmarkbit)) | 6250 | if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->u.s.gcmarkbit)) |
| 6260 | continue; | 6251 | continue; |
| 6261 | if (SUB_CHAR_TABLE_P (val)) | 6252 | if (SUB_CHAR_TABLE_P (val)) |
| 6262 | { | 6253 | { |
| @@ -6499,7 +6490,7 @@ mark_object (Lisp_Object arg) | |||
| 6499 | break; | 6490 | break; |
| 6500 | CHECK_ALLOCATED_AND_LIVE (live_string_p); | 6491 | CHECK_ALLOCATED_AND_LIVE (live_string_p); |
| 6501 | MARK_STRING (ptr); | 6492 | MARK_STRING (ptr); |
| 6502 | MARK_INTERVAL_TREE (ptr->intervals); | 6493 | MARK_INTERVAL_TREE (ptr->u.s.intervals); |
| 6503 | #ifdef GC_CHECK_STRING_BYTES | 6494 | #ifdef GC_CHECK_STRING_BYTES |
| 6504 | /* Check that the string size recorded in the string is the | 6495 | /* Check that the string size recorded in the string is the |
| 6505 | same as the one recorded in the sdata structure. */ | 6496 | same as the one recorded in the sdata structure. */ |
| @@ -6640,17 +6631,17 @@ mark_object (Lisp_Object arg) | |||
| 6640 | 6631 | ||
| 6641 | case Lisp_Symbol: | 6632 | case Lisp_Symbol: |
| 6642 | { | 6633 | { |
| 6643 | register struct Lisp_Symbol *ptr = XSYMBOL (obj); | 6634 | struct Lisp_Symbol *ptr = XSYMBOL (obj); |
| 6644 | nextsym: | 6635 | nextsym: |
| 6645 | if (ptr->gcmarkbit) | 6636 | if (ptr->u.s.gcmarkbit) |
| 6646 | break; | 6637 | break; |
| 6647 | CHECK_ALLOCATED_AND_LIVE_SYMBOL (); | 6638 | CHECK_ALLOCATED_AND_LIVE_SYMBOL (); |
| 6648 | ptr->gcmarkbit = 1; | 6639 | ptr->u.s.gcmarkbit = 1; |
| 6649 | /* Attempt to catch bogus objects. */ | 6640 | /* Attempt to catch bogus objects. */ |
| 6650 | eassert (valid_lisp_object_p (ptr->function)); | 6641 | eassert (valid_lisp_object_p (ptr->u.s.function)); |
| 6651 | mark_object (ptr->function); | 6642 | mark_object (ptr->u.s.function); |
| 6652 | mark_object (ptr->plist); | 6643 | mark_object (ptr->u.s.plist); |
| 6653 | switch (ptr->redirect) | 6644 | switch (ptr->u.s.redirect) |
| 6654 | { | 6645 | { |
| 6655 | case SYMBOL_PLAINVAL: mark_object (SYMBOL_VAL (ptr)); break; | 6646 | case SYMBOL_PLAINVAL: mark_object (SYMBOL_VAL (ptr)); break; |
| 6656 | case SYMBOL_VARALIAS: | 6647 | case SYMBOL_VARALIAS: |
| @@ -6671,11 +6662,11 @@ mark_object (Lisp_Object arg) | |||
| 6671 | break; | 6662 | break; |
| 6672 | default: emacs_abort (); | 6663 | default: emacs_abort (); |
| 6673 | } | 6664 | } |
| 6674 | if (!PURE_P (XSTRING (ptr->name))) | 6665 | if (!PURE_P (XSTRING (ptr->u.s.name))) |
| 6675 | MARK_STRING (XSTRING (ptr->name)); | 6666 | MARK_STRING (XSTRING (ptr->u.s.name)); |
| 6676 | MARK_INTERVAL_TREE (string_intervals (ptr->name)); | 6667 | MARK_INTERVAL_TREE (string_intervals (ptr->u.s.name)); |
| 6677 | /* Inner loop to mark next symbol in this bucket, if any. */ | 6668 | /* Inner loop to mark next symbol in this bucket, if any. */ |
| 6678 | po = ptr = ptr->next; | 6669 | po = ptr = ptr->u.s.next; |
| 6679 | if (ptr) | 6670 | if (ptr) |
| 6680 | goto nextsym; | 6671 | goto nextsym; |
| 6681 | } | 6672 | } |
| @@ -6729,14 +6720,14 @@ mark_object (Lisp_Object arg) | |||
| 6729 | CHECK_ALLOCATED_AND_LIVE (live_cons_p); | 6720 | CHECK_ALLOCATED_AND_LIVE (live_cons_p); |
| 6730 | CONS_MARK (ptr); | 6721 | CONS_MARK (ptr); |
| 6731 | /* If the cdr is nil, avoid recursion for the car. */ | 6722 | /* If the cdr is nil, avoid recursion for the car. */ |
| 6732 | if (EQ (ptr->u.cdr, Qnil)) | 6723 | if (EQ (ptr->u.s.u.cdr, Qnil)) |
| 6733 | { | 6724 | { |
| 6734 | obj = ptr->car; | 6725 | obj = ptr->u.s.car; |
| 6735 | cdr_count = 0; | 6726 | cdr_count = 0; |
| 6736 | goto loop; | 6727 | goto loop; |
| 6737 | } | 6728 | } |
| 6738 | mark_object (ptr->car); | 6729 | mark_object (ptr->u.s.car); |
| 6739 | obj = ptr->u.cdr; | 6730 | obj = ptr->u.s.u.cdr; |
| 6740 | cdr_count++; | 6731 | cdr_count++; |
| 6741 | if (cdr_count == mark_object_loop_halt) | 6732 | if (cdr_count == mark_object_loop_halt) |
| 6742 | emacs_abort (); | 6733 | emacs_abort (); |
| @@ -6797,7 +6788,7 @@ survives_gc_p (Lisp_Object obj) | |||
| 6797 | break; | 6788 | break; |
| 6798 | 6789 | ||
| 6799 | case Lisp_Symbol: | 6790 | case Lisp_Symbol: |
| 6800 | survives_p = XSYMBOL (obj)->gcmarkbit; | 6791 | survives_p = XSYMBOL (obj)->u.s.gcmarkbit; |
| 6801 | break; | 6792 | break; |
| 6802 | 6793 | ||
| 6803 | case Lisp_Misc: | 6794 | case Lisp_Misc: |
| @@ -6873,9 +6864,9 @@ sweep_conses (void) | |||
| 6873 | if (!CONS_MARKED_P (&cblk->conses[pos])) | 6864 | if (!CONS_MARKED_P (&cblk->conses[pos])) |
| 6874 | { | 6865 | { |
| 6875 | this_free++; | 6866 | this_free++; |
| 6876 | cblk->conses[pos].u.chain = cons_free_list; | 6867 | cblk->conses[pos].u.s.u.chain = cons_free_list; |
| 6877 | cons_free_list = &cblk->conses[pos]; | 6868 | cons_free_list = &cblk->conses[pos]; |
| 6878 | cons_free_list->car = Vdead; | 6869 | cons_free_list->u.s.car = Vdead; |
| 6879 | } | 6870 | } |
| 6880 | else | 6871 | else |
| 6881 | { | 6872 | { |
| @@ -6894,7 +6885,7 @@ sweep_conses (void) | |||
| 6894 | { | 6885 | { |
| 6895 | *cprev = cblk->next; | 6886 | *cprev = cblk->next; |
| 6896 | /* Unhook from the free list. */ | 6887 | /* Unhook from the free list. */ |
| 6897 | cons_free_list = cblk->conses[0].u.chain; | 6888 | cons_free_list = cblk->conses[0].u.s.u.chain; |
| 6898 | lisp_align_free (cblk); | 6889 | lisp_align_free (cblk); |
| 6899 | } | 6890 | } |
| 6900 | else | 6891 | else |
| @@ -7018,39 +7009,39 @@ sweep_symbols (void) | |||
| 7018 | symbol_free_list = NULL; | 7009 | symbol_free_list = NULL; |
| 7019 | 7010 | ||
| 7020 | for (int i = 0; i < ARRAYELTS (lispsym); i++) | 7011 | for (int i = 0; i < ARRAYELTS (lispsym); i++) |
| 7021 | lispsym[i].s.gcmarkbit = 0; | 7012 | lispsym[i].u.s.gcmarkbit = 0; |
| 7022 | 7013 | ||
| 7023 | for (sblk = symbol_block; sblk; sblk = *sprev) | 7014 | for (sblk = symbol_block; sblk; sblk = *sprev) |
| 7024 | { | 7015 | { |
| 7025 | int this_free = 0; | 7016 | int this_free = 0; |
| 7026 | union aligned_Lisp_Symbol *sym = sblk->symbols; | 7017 | struct Lisp_Symbol *sym = sblk->symbols; |
| 7027 | union aligned_Lisp_Symbol *end = sym + lim; | 7018 | struct Lisp_Symbol *end = sym + lim; |
| 7028 | 7019 | ||
| 7029 | for (; sym < end; ++sym) | 7020 | for (; sym < end; ++sym) |
| 7030 | { | 7021 | { |
| 7031 | if (!sym->s.gcmarkbit) | 7022 | if (!sym->u.s.gcmarkbit) |
| 7032 | { | 7023 | { |
| 7033 | if (sym->s.redirect == SYMBOL_LOCALIZED) | 7024 | if (sym->u.s.redirect == SYMBOL_LOCALIZED) |
| 7034 | { | 7025 | { |
| 7035 | xfree (SYMBOL_BLV (&sym->s)); | 7026 | xfree (SYMBOL_BLV (sym)); |
| 7036 | /* At every GC we sweep all symbol_blocks and rebuild the | 7027 | /* At every GC we sweep all symbol_blocks and rebuild the |
| 7037 | symbol_free_list, so those symbols which stayed unused | 7028 | symbol_free_list, so those symbols which stayed unused |
| 7038 | between the two will be re-swept. | 7029 | between the two will be re-swept. |
| 7039 | So we have to make sure we don't re-free this blv next | 7030 | So we have to make sure we don't re-free this blv next |
| 7040 | time we sweep this symbol_block (bug#29066). */ | 7031 | time we sweep this symbol_block (bug#29066). */ |
| 7041 | sym->s.redirect = SYMBOL_PLAINVAL; | 7032 | sym->u.s.redirect = SYMBOL_PLAINVAL; |
| 7042 | } | 7033 | } |
| 7043 | sym->s.next = symbol_free_list; | 7034 | sym->u.s.next = symbol_free_list; |
| 7044 | symbol_free_list = &sym->s; | 7035 | symbol_free_list = sym; |
| 7045 | symbol_free_list->function = Vdead; | 7036 | symbol_free_list->u.s.function = Vdead; |
| 7046 | ++this_free; | 7037 | ++this_free; |
| 7047 | } | 7038 | } |
| 7048 | else | 7039 | else |
| 7049 | { | 7040 | { |
| 7050 | ++num_used; | 7041 | ++num_used; |
| 7051 | sym->s.gcmarkbit = 0; | 7042 | sym->u.s.gcmarkbit = 0; |
| 7052 | /* Attempt to catch bogus objects. */ | 7043 | /* Attempt to catch bogus objects. */ |
| 7053 | eassert (valid_lisp_object_p (sym->s.function)); | 7044 | eassert (valid_lisp_object_p (sym->u.s.function)); |
| 7054 | } | 7045 | } |
| 7055 | } | 7046 | } |
| 7056 | 7047 | ||
| @@ -7062,7 +7053,7 @@ sweep_symbols (void) | |||
| 7062 | { | 7053 | { |
| 7063 | *sprev = sblk->next; | 7054 | *sprev = sblk->next; |
| 7064 | /* Unhook from the free list. */ | 7055 | /* Unhook from the free list. */ |
| 7065 | symbol_free_list = sblk->symbols[0].s.next; | 7056 | symbol_free_list = sblk->symbols[0].u.s.next; |
| 7066 | lisp_free (sblk); | 7057 | lisp_free (sblk); |
| 7067 | } | 7058 | } |
| 7068 | else | 7059 | else |
| @@ -7289,10 +7280,10 @@ symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj) | |||
| 7289 | struct Lisp_Symbol *sym = XSYMBOL (symbol); | 7280 | struct Lisp_Symbol *sym = XSYMBOL (symbol); |
| 7290 | Lisp_Object val = find_symbol_value (symbol); | 7281 | Lisp_Object val = find_symbol_value (symbol); |
| 7291 | return (EQ (val, obj) | 7282 | return (EQ (val, obj) |
| 7292 | || EQ (sym->function, obj) | 7283 | || EQ (sym->u.s.function, obj) |
| 7293 | || (!NILP (sym->function) | 7284 | || (!NILP (sym->u.s.function) |
| 7294 | && COMPILEDP (sym->function) | 7285 | && COMPILEDP (sym->u.s.function) |
| 7295 | && EQ (AREF (sym->function, COMPILED_BYTECODE), obj)) | 7286 | && EQ (AREF (sym->u.s.function, COMPILED_BYTECODE), obj)) |
| 7296 | || (!NILP (val) | 7287 | || (!NILP (val) |
| 7297 | && COMPILEDP (val) | 7288 | && COMPILEDP (val) |
| 7298 | && EQ (AREF (val, COMPILED_BYTECODE), obj))); | 7289 | && EQ (AREF (val, COMPILED_BYTECODE), obj))); |
| @@ -7323,15 +7314,15 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) | |||
| 7323 | 7314 | ||
| 7324 | for (sblk = symbol_block; sblk; sblk = sblk->next) | 7315 | for (sblk = symbol_block; sblk; sblk = sblk->next) |
| 7325 | { | 7316 | { |
| 7326 | union aligned_Lisp_Symbol *aligned_sym = sblk->symbols; | 7317 | struct Lisp_Symbol *asym = sblk->symbols; |
| 7327 | int bn; | 7318 | int bn; |
| 7328 | 7319 | ||
| 7329 | for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, aligned_sym++) | 7320 | for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, asym++) |
| 7330 | { | 7321 | { |
| 7331 | if (sblk == symbol_block && bn >= symbol_block_index) | 7322 | if (sblk == symbol_block && bn >= symbol_block_index) |
| 7332 | break; | 7323 | break; |
| 7333 | 7324 | ||
| 7334 | Lisp_Object sym = make_lisp_symbol (&aligned_sym->s); | 7325 | Lisp_Object sym = make_lisp_symbol (asym); |
| 7335 | if (symbol_uses_obj (sym, obj)) | 7326 | if (symbol_uses_obj (sym, obj)) |
| 7336 | { | 7327 | { |
| 7337 | found = Fcons (sym, found); | 7328 | found = Fcons (sym, found); |