aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
authorPaul Eggert2017-11-13 08:51:41 -0800
committerPaul Eggert2017-11-13 10:16:51 -0800
commitb1573a97e17b518723ab3f906eb6d521caed196d (patch)
tree2bcfe8f47a99d7ba9b46e75ed5bffd2ba37970e0 /src/alloc.c
parent5d68dc9a2fd1b9b883db6bc1c226541b50de8bb1 (diff)
downloademacs-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.c211
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
1818string_bytes (struct Lisp_String *s) 1818string_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
1973void 1974void
1974allocate_string_data (struct Lisp_String *s, 1975allocate_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;
2729void 2730void
2730free_cons (struct Lisp_Cons *ptr) 2731free_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
3549union 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
3563struct symbol_block 3554struct 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;
3587static void 3578static void
3588set_symbol_name (Lisp_Object sym, Lisp_Object name) 3579set_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
3593void 3584void
@@ -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
3610DEFUN ("make-symbol", Fmake_symbol, Smake_symbol, 1, 1, 0, 3601DEFUN ("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);