diff options
| author | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-13 08:51:41 -0800 |
|---|---|---|
| committer | Paul Eggert <eggert@cs.ucla.edu> | 2017-11-13 10:16:51 -0800 |
| commit | b1573a97e17b518723ab3f906eb6d521caed196d (patch) | |
| tree | 2bcfe8f47a99d7ba9b46e75ed5bffd2ba37970e0 /src/alloc.c | |
| parent | 5d68dc9a2fd1b9b883db6bc1c226541b50de8bb1 (diff) | |
| download | emacs-b1573a97e17b518723ab3f906eb6d521caed196d.tar.gz | |
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) /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer to a struct Lisp_String. */ -#define MARK_STRING(S) ((S)->size |= ARRAY_MARK_FLAG) -#define UNMARK_STRING(S) ((S)->size &= ~ARRAY_MARK_FLAG) -#define STRING_MARKED_P(S) (((S)->size & ARRAY_MARK_FLAG) != 0) +#define MARK_STRING(S) ((S)->u.s.size |= ARRAY_MARK_FLAG) +#define UNMARK_STRING(S) ((S)->u.s.size &= ~ARRAY_MARK_FLAG) +#define STRING_MARKED_P(S) (((S)->u.s.size & ARRAY_MARK_FLAG) != 0) #define VECTOR_MARK(V) ((V)->header.size |= ARRAY_MARK_FLAG) #define VECTOR_UNMARK(V) ((V)->header.size &= ~ARRAY_MARK_FLAG) @@ -1730,14 +1730,14 @@ static EMACS_INT total_string_bytes; string_free_list, return a pointer to its successor in the free-list. */ -#define NEXT_FREE_LISP_STRING(S) (*(struct Lisp_String **) (S)) +#define NEXT_FREE_LISP_STRING(S) ((S)->u.next) /* Return a pointer to the sdata structure belonging to Lisp string S. S must be live, i.e. S->data must not be null. S->data is actually a pointer to the `u.data' member of its sdata structure; the structure starts at a constant offset in front of that. */ -#define SDATA_OF_STRING(S) ((sdata *) ((S)->data - SDATA_DATA_OFFSET)) +#define SDATA_OF_STRING(S) ((sdata *) ((S)->u.s.data - SDATA_DATA_OFFSET)) #ifdef GC_CHECK_STRING_OVERRUN @@ -1818,9 +1818,10 @@ ptrdiff_t string_bytes (struct Lisp_String *s) { ptrdiff_t nbytes = - (s->size_byte < 0 ? s->size & ~ARRAY_MARK_FLAG : s->size_byte); + (s->u.s.size_byte < 0 ? s->u.s.size & ~ARRAY_MARK_FLAG : s->u.s.size_byte); - if (!PURE_P (s) && s->data && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) + if (!PURE_P (s) && s->u.s.data + && nbytes != SDATA_NBYTES (SDATA_OF_STRING (s))) emacs_abort (); return nbytes; } @@ -1926,7 +1927,7 @@ allocate_string (void) { s = b->strings + i; /* Every string on a free list should have NULL data pointer. */ - s->data = NULL; + s->u.s.data = NULL; NEXT_FREE_LISP_STRING (s) = string_free_list; string_free_list = s; } @@ -1965,10 +1966,10 @@ allocate_string (void) /* Set up Lisp_String S for holding NCHARS characters, NBYTES bytes, - plus a NUL byte at the end. Allocate an sdata structure for S, and - set S->data to its `u.data' member. Store a NUL byte at the end of - S->data. Set S->size to NCHARS and S->size_byte to NBYTES. Free - S->data if it was initially non-null. */ + plus a NUL byte at the end. Allocate an sdata structure DATA for + S, and set S->u.s.data to SDATA->u.data. Store a NUL byte at the + end of S->u.s.data. Set S->u.s.size to NCHARS and S->u.s.size_byte + to NBYTES. Free S->u.s.data if it was initially non-null. */ void allocate_string_data (struct Lisp_String *s, @@ -1984,7 +1985,7 @@ allocate_string_data (struct Lisp_String *s, /* Determine the number of bytes needed to store NBYTES bytes of string data. */ needed = SDATA_SIZE (nbytes); - if (s->data) + if (s->u.s.data) { old_data = SDATA_OF_STRING (s); old_nbytes = STRING_BYTES (s); @@ -2043,13 +2044,13 @@ allocate_string_data (struct Lisp_String *s, MALLOC_UNBLOCK_INPUT; - s->data = SDATA_DATA (data); + s->u.s.data = SDATA_DATA (data); #ifdef GC_CHECK_STRING_BYTES SDATA_NBYTES (data) = nbytes; #endif - s->size = nchars; - s->size_byte = nbytes; - s->data[nbytes] = '\0'; + s->u.s.size = nchars; + s->u.s.size_byte = nbytes; + s->u.s.data[nbytes] = '\0'; #ifdef GC_CHECK_STRING_OVERRUN memcpy ((char *) data + needed, string_overrun_cookie, GC_STRING_OVERRUN_COOKIE_SIZE); @@ -2093,7 +2094,7 @@ sweep_strings (void) { struct Lisp_String *s = b->strings + i; - if (s->data) + if (s->u.s.data) { /* String was not on free-list before. */ if (STRING_MARKED_P (s)) @@ -2102,7 +2103,7 @@ sweep_strings (void) UNMARK_STRING (s); /* Do not use string_(set|get)_intervals here. */ - s->intervals = balance_intervals (s->intervals); + s->u.s.intervals = balance_intervals (s->u.s.intervals); ++total_strings; total_string_bytes += STRING_BYTES (s); @@ -2125,7 +2126,7 @@ sweep_strings (void) /* Reset the strings's `data' member so that we know it's free. */ - s->data = NULL; + s->u.s.data = NULL; /* Put the string on the free-list. */ NEXT_FREE_LISP_STRING (s) = string_free_list; @@ -2264,7 +2265,7 @@ compact_small_strings (void) { eassert (tb != b || to < from); memmove (to, from, nbytes + GC_STRING_EXTRA); - to->string->data = SDATA_DATA (to); + to->string->u.s.data = SDATA_DATA (to); } /* Advance past the sdata we copied to. */ @@ -2544,7 +2545,7 @@ make_uninit_multibyte_string (EMACS_INT nchars, EMACS_INT nbytes) return empty_multibyte_string; s = allocate_string (); - s->intervals = NULL; + s->u.s.intervals = NULL; allocate_string_data (s, nchars, nbytes); XSETSTRING (string, s); string_chars_consed += nbytes; @@ -2729,8 +2730,8 @@ static struct Lisp_Cons *cons_free_list; void free_cons (struct Lisp_Cons *ptr) { - ptr->u.chain = cons_free_list; - ptr->car = Vdead; + ptr->u.s.u.chain = cons_free_list; + ptr->u.s.car = Vdead; cons_free_list = ptr; consing_since_gc -= sizeof *ptr; total_free_conses++; @@ -2749,7 +2750,7 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, /* We use the cdr for chaining the free list so that we won't use the same field that has the mark bit. */ XSETCONS (val, cons_free_list); - cons_free_list = cons_free_list->u.chain; + cons_free_list = cons_free_list->u.s.u.chain; } else { @@ -2786,7 +2787,7 @@ check_cons_list (void) struct Lisp_Cons *tail = cons_free_list; while (tail) - tail = tail->u.chain; + tail = tail->u.s.u.chain; } #endif @@ -3543,27 +3544,17 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT Symbol Allocation ***********************************************************************/ -/* Like struct Lisp_Symbol, but padded so that the size is a multiple - of the required alignment. */ - -union aligned_Lisp_Symbol -{ - struct Lisp_Symbol s; - unsigned char c[(sizeof (struct Lisp_Symbol) + GCALIGNMENT - 1) - & -GCALIGNMENT]; -}; - /* Each symbol_block is just under 1020 bytes long, since malloc really allocates in units of powers of two and uses 4 bytes for its own overhead. */ #define SYMBOL_BLOCK_SIZE \ - ((1020 - sizeof (struct symbol_block *)) / sizeof (union aligned_Lisp_Symbol)) + ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol)) struct symbol_block { /* Place `symbols' first, to preserve alignment. */ - union aligned_Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; + struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; struct symbol_block *next; }; @@ -3587,7 +3578,7 @@ static struct Lisp_Symbol *symbol_free_list; static void set_symbol_name (Lisp_Object sym, Lisp_Object name) { - XSYMBOL (sym)->name = name; + XSYMBOL (sym)->u.s.name = name; } void @@ -3596,15 +3587,15 @@ init_symbol (Lisp_Object val, Lisp_Object name) struct Lisp_Symbol *p = XSYMBOL (val); set_symbol_name (val, name); set_symbol_plist (val, Qnil); - p->redirect = SYMBOL_PLAINVAL; + p->u.s.redirect = SYMBOL_PLAINVAL; SET_SYMBOL_VAL (p, Qunbound); set_symbol_function (val, Qnil); set_symbol_next (val, NULL); - p->gcmarkbit = false; - p->interned = SYMBOL_UNINTERNED; - p->trapped_write = SYMBOL_UNTRAPPED_WRITE; - p->declared_special = false; - p->pinned = false; + p->u.s.gcmarkbit = false; + p->u.s.interned = SYMBOL_UNINTERNED; + p->u.s.trapped_write = SYMBOL_UNTRAPPED_WRITE; + p->u.s.declared_special = false; + p->u.s.pinned = false; } 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. */) if (symbol_free_list) { XSETSYMBOL (val, symbol_free_list); - symbol_free_list = symbol_free_list->next; + symbol_free_list = symbol_free_list->u.s.next; } else { @@ -3634,7 +3625,7 @@ Its value is void, and its function definition and property list are nil. */) symbol_block_index = 0; total_free_symbols += SYMBOL_BLOCK_SIZE; } - XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index].s); + XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index]); symbol_block_index++; } @@ -4587,7 +4578,7 @@ live_string_holding (struct mem_node *m, void *p) if (0 <= offset && offset < STRING_BLOCK_SIZE * sizeof b->strings[0]) { struct Lisp_String *s = p = cp -= offset % sizeof b->strings[0]; - if (s->data) + if (s->u.s.data) return make_lisp_ptr (s, Lisp_String); } } @@ -4621,7 +4612,7 @@ live_cons_holding (struct mem_node *m, void *p) || offset / sizeof b->conses[0] < cons_block_index)) { struct Lisp_Cons *s = p = cp -= offset % sizeof b->conses[0]; - if (!EQ (s->car, Vdead)) + if (!EQ (s->u.s.car, Vdead)) return make_lisp_ptr (s, Lisp_Cons); } } @@ -4656,7 +4647,7 @@ live_symbol_holding (struct mem_node *m, void *p) || offset / sizeof b->symbols[0] < symbol_block_index)) { struct Lisp_Symbol *s = p = cp -= offset % sizeof b->symbols[0]; - if (!EQ (s->function, Vdead)) + if (!EQ (s->u.s.function, Vdead)) return make_lisp_symbol (s); } } @@ -4984,7 +4975,7 @@ mark_memory (void *start, void *end) Lisp_Object obj = build_string ("test"); struct Lisp_String *s = XSTRING (obj); Fgarbage_collect (); - fprintf (stderr, "test '%s'\n", s->data); + fprintf (stderr, "test '%s'\n", s->u.s.data); return Qnil; } @@ -5484,16 +5475,16 @@ make_pure_string (const char *data, { Lisp_Object string; struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); - s->data = (unsigned char *) find_string_data_in_pure (data, nbytes); - if (s->data == NULL) + s->u.s.data = (unsigned char *) find_string_data_in_pure (data, nbytes); + if (s->u.s.data == NULL) { - s->data = pure_alloc (nbytes + 1, -1); - memcpy (s->data, data, nbytes); - s->data[nbytes] = '\0'; + s->u.s.data = pure_alloc (nbytes + 1, -1); + memcpy (s->u.s.data, data, nbytes); + s->u.s.data[nbytes] = '\0'; } - s->size = nchars; - s->size_byte = multibyte ? nbytes : -1; - s->intervals = NULL; + s->u.s.size = nchars; + s->u.s.size_byte = multibyte ? nbytes : -1; + s->u.s.intervals = NULL; XSETSTRING (string, s); return string; } @@ -5506,10 +5497,10 @@ make_pure_c_string (const char *data, ptrdiff_t nchars) { Lisp_Object string; struct Lisp_String *s = pure_alloc (sizeof *s, Lisp_String); - s->size = nchars; - s->size_byte = -1; - s->data = (unsigned char *) data; - s->intervals = NULL; + s->u.s.size = nchars; + s->u.s.size_byte = -1; + s->u.s.data = (unsigned char *) data; + s->u.s.intervals = NULL; XSETSTRING (string, s); return string; } @@ -5620,7 +5611,7 @@ purecopy (Lisp_Object obj) || SUBRP (obj)) return obj; /* Already pure. */ - if (STRINGP (obj) && XSTRING (obj)->intervals) + if (STRINGP (obj) && XSTRING (obj)->u.s.intervals) message_with_string ("Dropping text-properties while making string `%s' pure", obj, true); @@ -5675,10 +5666,10 @@ purecopy (Lisp_Object obj) } else if (SYMBOLP (obj)) { - if (!XSYMBOL (obj)->pinned && !c_symbol_p (XSYMBOL (obj))) + if (!XSYMBOL (obj)->u.s.pinned && !c_symbol_p (XSYMBOL (obj))) { /* We can't purify them, but they appear in many pure objects. Mark them as `pinned' so we know to mark them at every GC cycle. */ - XSYMBOL (obj)->pinned = true; + XSYMBOL (obj)->u.s.pinned = true; symbol_block_pinned = symbol_block; } /* Don't hash-cons it. */ @@ -5891,10 +5882,10 @@ mark_pinned_symbols (void) for (sblk = symbol_block_pinned; sblk; sblk = sblk->next) { - union aligned_Lisp_Symbol *sym = sblk->symbols, *end = sym + lim; + struct Lisp_Symbol *sym = sblk->symbols, *end = sym + lim; for (; sym < end; ++sym) - if (sym->s.pinned) - mark_object (make_lisp_symbol (&sym->s)); + if (sym->u.s.pinned) + mark_object (make_lisp_symbol (sym)); lim = SYMBOL_BLOCK_SIZE; } @@ -6256,7 +6247,7 @@ mark_char_table (struct Lisp_Vector *ptr, enum pvec_type pvectype) { Lisp_Object val = ptr->contents[i]; - if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->gcmarkbit)) + if (INTEGERP (val) || (SYMBOLP (val) && XSYMBOL (val)->u.s.gcmarkbit)) continue; if (SUB_CHAR_TABLE_P (val)) { @@ -6499,7 +6490,7 @@ mark_object (Lisp_Object arg) break; CHECK_ALLOCATED_AND_LIVE (live_string_p); MARK_STRING (ptr); - MARK_INTERVAL_TREE (ptr->intervals); + MARK_INTERVAL_TREE (ptr->u.s.intervals); #ifdef GC_CHECK_STRING_BYTES /* Check that the string size recorded in the string is the same as the one recorded in the sdata structure. */ @@ -6640,17 +6631,17 @@ mark_object (Lisp_Object arg) case Lisp_Symbol: { - register struct Lisp_Symbol *ptr = XSYMBOL (obj); + struct Lisp_Symbol *ptr = XSYMBOL (obj); nextsym: - if (ptr->gcmarkbit) + if (ptr->u.s.gcmarkbit) break; CHECK_ALLOCATED_AND_LIVE_SYMBOL (); - ptr->gcmarkbit = 1; + ptr->u.s.gcmarkbit = 1; /* Attempt to catch bogus objects. */ - eassert (valid_lisp_object_p (ptr->function)); - mark_object (ptr->function); - mark_object (ptr->plist); - switch (ptr->redirect) + eassert (valid_lisp_object_p (ptr->u.s.function)); + mark_object (ptr->u.s.function); + mark_object (ptr->u.s.plist); + switch (ptr->u.s.redirect) { case SYMBOL_PLAINVAL: mark_object (SYMBOL_VAL (ptr)); break; case SYMBOL_VARALIAS: @@ -6671,11 +6662,11 @@ mark_object (Lisp_Object arg) break; default: emacs_abort (); } - if (!PURE_P (XSTRING (ptr->name))) - MARK_STRING (XSTRING (ptr->name)); - MARK_INTERVAL_TREE (string_intervals (ptr->name)); + if (!PURE_P (XSTRING (ptr->u.s.name))) + MARK_STRING (XSTRING (ptr->u.s.name)); + MARK_INTERVAL_TREE (string_intervals (ptr->u.s.name)); /* Inner loop to mark next symbol in this bucket, if any. */ - po = ptr = ptr->next; + po = ptr = ptr->u.s.next; if (ptr) goto nextsym; } @@ -6729,14 +6720,14 @@ mark_object (Lisp_Object arg) CHECK_ALLOCATED_AND_LIVE (live_cons_p); CONS_MARK (ptr); /* If the cdr is nil, avoid recursion for the car. */ - if (EQ (ptr->u.cdr, Qnil)) + if (EQ (ptr->u.s.u.cdr, Qnil)) { - obj = ptr->car; + obj = ptr->u.s.car; cdr_count = 0; goto loop; } - mark_object (ptr->car); - obj = ptr->u.cdr; + mark_object (ptr->u.s.car); + obj = ptr->u.s.u.cdr; cdr_count++; if (cdr_count == mark_object_loop_halt) emacs_abort (); @@ -6797,7 +6788,7 @@ survives_gc_p (Lisp_Object obj) break; case Lisp_Symbol: - survives_p = XSYMBOL (obj)->gcmarkbit; + survives_p = XSYMBOL (obj)->u.s.gcmarkbit; break; case Lisp_Misc: @@ -6873,9 +6864,9 @@ sweep_conses (void) if (!CONS_MARKED_P (&cblk->conses[pos])) { this_free++; - cblk->conses[pos].u.chain = cons_free_list; + cblk->conses[pos].u.s.u.chain = cons_free_list; cons_free_list = &cblk->conses[pos]; - cons_free_list->car = Vdead; + cons_free_list->u.s.car = Vdead; } else { @@ -6894,7 +6885,7 @@ sweep_conses (void) { *cprev = cblk->next; /* Unhook from the free list. */ - cons_free_list = cblk->conses[0].u.chain; + cons_free_list = cblk->conses[0].u.s.u.chain; lisp_align_free (cblk); } else @@ -7018,39 +7009,39 @@ sweep_symbols (void) symbol_free_list = NULL; for (int i = 0; i < ARRAYELTS (lispsym); i++) - lispsym[i].s.gcmarkbit = 0; + lispsym[i].u.s.gcmarkbit = 0; for (sblk = symbol_block; sblk; sblk = *sprev) { int this_free = 0; - union aligned_Lisp_Symbol *sym = sblk->symbols; - union aligned_Lisp_Symbol *end = sym + lim; + struct Lisp_Symbol *sym = sblk->symbols; + struct Lisp_Symbol *end = sym + lim; for (; sym < end; ++sym) { - if (!sym->s.gcmarkbit) + if (!sym->u.s.gcmarkbit) { - if (sym->s.redirect == SYMBOL_LOCALIZED) + if (sym->u.s.redirect == SYMBOL_LOCALIZED) { - xfree (SYMBOL_BLV (&sym->s)); + xfree (SYMBOL_BLV (sym)); /* At every GC we sweep all symbol_blocks and rebuild the symbol_free_list, so those symbols which stayed unused between the two will be re-swept. So we have to make sure we don't re-free this blv next time we sweep this symbol_block (bug#29066). */ - sym->s.redirect = SYMBOL_PLAINVAL; + sym->u.s.redirect = SYMBOL_PLAINVAL; } - sym->s.next = symbol_free_list; - symbol_free_list = &sym->s; - symbol_free_list->function = Vdead; + sym->u.s.next = symbol_free_list; + symbol_free_list = sym; + symbol_free_list->u.s.function = Vdead; ++this_free; } else { ++num_used; - sym->s.gcmarkbit = 0; + sym->u.s.gcmarkbit = 0; /* Attempt to catch bogus objects. */ - eassert (valid_lisp_object_p (sym->s.function)); + eassert (valid_lisp_object_p (sym->u.s.function)); } } @@ -7062,7 +7053,7 @@ sweep_symbols (void) { *sprev = sblk->next; /* Unhook from the free list. */ - symbol_free_list = sblk->symbols[0].s.next; + symbol_free_list = sblk->symbols[0].u.s.next; lisp_free (sblk); } else @@ -7289,10 +7280,10 @@ symbol_uses_obj (Lisp_Object symbol, Lisp_Object obj) struct Lisp_Symbol *sym = XSYMBOL (symbol); Lisp_Object val = find_symbol_value (symbol); return (EQ (val, obj) - || EQ (sym->function, obj) - || (!NILP (sym->function) - && COMPILEDP (sym->function) - && EQ (AREF (sym->function, COMPILED_BYTECODE), obj)) + || EQ (sym->u.s.function, obj) + || (!NILP (sym->u.s.function) + && COMPILEDP (sym->u.s.function) + && EQ (AREF (sym->u.s.function, COMPILED_BYTECODE), obj)) || (!NILP (val) && COMPILEDP (val) && EQ (AREF (val, COMPILED_BYTECODE), obj))); @@ -7323,15 +7314,15 @@ which_symbols (Lisp_Object obj, EMACS_INT find_max) for (sblk = symbol_block; sblk; sblk = sblk->next) { - union aligned_Lisp_Symbol *aligned_sym = sblk->symbols; + struct Lisp_Symbol *asym = sblk->symbols; int bn; - for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, aligned_sym++) + for (bn = 0; bn < SYMBOL_BLOCK_SIZE; bn++, asym++) { if (sblk == symbol_block && bn >= symbol_block_index) break; - Lisp_Object sym = make_lisp_symbol (&aligned_sym->s); + Lisp_Object sym = make_lisp_symbol (asym); if (symbol_uses_obj (sym, obj)) { found = Fcons (sym, found); |
