From: Stefan Monnier Date: Wed, 4 Jul 2012 14:38:02 +0000 (-0400) Subject: Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE. X-Git-Tag: emacs-24.2.90~1199^2~226 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=ee28be33a535e41c74f3a4d5c0f3878e44366942;p=emacs.git Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE. * src/lisp.h (enum pvec_type): Use fewer bits. (PSEUDOVECTOR_SIZE_BITS): New constant. (PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK): Use it. (XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR, DEFUN): Adapt code to change in pvec_type. (PSEUDOVECTOR_TYPEP): New macro. (TYPED_PSEUDOVECTORP): Use it. * src/fns.c (internal_equal): Adapt code to extract pvectype. * src/emacs.c (gdb_pvec_type): Update type. * src/alloc.c (PSEUDOVECTOR_NBYTES): New macro. (VECTOR_FREE_LIST_SIZE_MASK): Remove (=> PSEUDOVECTOR_SIZE_MASK). (VECTOR_FREE_LIST_FLAG): Remove (=> PVEC_FREE). (SETUP_ON_FREE_LIST): Use XSETPVECTYPESIZE. (sweep_vectors): Use it. Use local var `total_bytes' instead of abusing vector->header.next.nbytes. (live_vector_p): Use PVEC_TYPE. (mark_object): Adapt code to extract pvectype. Use switch. --- diff --git a/src/ChangeLog b/src/ChangeLog index a600a0b2b6f..70f7fedf5ad 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,24 @@ +2012-07-04 Stefan Monnier + + Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE. + * lisp.h (enum pvec_type): Use fewer bits. + (PSEUDOVECTOR_SIZE_BITS): New constant. + (PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK): Use it. + (XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR, DEFUN): Adapt code to + change in pvec_type. + (PSEUDOVECTOR_TYPEP): New macro. + (TYPED_PSEUDOVECTORP): Use it. + * fns.c (internal_equal): Adapt code to extract pvectype. + * emacs.c (gdb_pvec_type): Update type. + * alloc.c (PSEUDOVECTOR_NBYTES): New macro. + (VECTOR_FREE_LIST_SIZE_MASK): Remove (=> PSEUDOVECTOR_SIZE_MASK). + (VECTOR_FREE_LIST_FLAG): Remove (=> PVEC_FREE). + (SETUP_ON_FREE_LIST): Use XSETPVECTYPESIZE. + (sweep_vectors): Use it. Use local var `total_bytes' instead of + abusing vector->header.next.nbytes. + (live_vector_p): Use PVEC_TYPE. + (mark_object): Adapt code to extract pvectype. Use switch. + 2012-07-04 Paul Eggert * doprnt.c (doprnt): Don't assume string length fits in 'int'. diff --git a/src/alloc.c b/src/alloc.c index b1e2ed0a2ed..bd68f2b31f2 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -1529,7 +1529,7 @@ make_interval (void) } -/* Mark Lisp objects in interval I. */ +/* Mark Lisp objects in interval I. */ static void mark_interval (register INTERVAL i, Lisp_Object dummy) @@ -1836,7 +1836,7 @@ check_sblock (struct sblock *b) ptrdiff_t nbytes; /* Check that the string size recorded in the string is the - same as the one recorded in the sdata structure. */ + same as the one recorded in the sdata structure. */ if (from->string) CHECK_STRING_BYTES (from->string); @@ -2869,12 +2869,6 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, #define VECTOR_BLOCK_SIZE 4096 -/* This special value is used to calculate vector size when the vector is - on a free list. It should be VECTOR_BLOCK_SIZE rounded up to nearest - power of two, minus one. */ - -#define VECTOR_FREE_LIST_SIZE_MASK 4095 - /* Handy constants for vectorlike objects. */ enum { @@ -2889,8 +2883,7 @@ verify ((roundup_size & (roundup_size - 1)) == 0); /* Verify assumptions described above. */ verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); -verify ((VECTOR_FREE_LIST_SIZE_MASK + 1) >= VECTOR_BLOCK_SIZE); -verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); +verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); /* Round up X to nearest mult-of-ROUNDUP_SIZE. */ @@ -2915,12 +2908,6 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); #define VECTOR_MAX_FREE_LIST_INDEX \ ((VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1) -/* When the vector is on a free list, vectorlike_header.SIZE is set to - this special value ORed with vector's memory footprint size. */ - -#define VECTOR_FREE_LIST_FLAG (~(ARRAY_MARK_FLAG | PSEUDOVECTOR_FLAG \ - | VECTOR_FREE_LIST_SIZE_MASK)) - /* Common shortcut to advance vector pointer over a block data. */ #define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes))) @@ -2933,7 +2920,7 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); #define SETUP_ON_FREE_LIST(v, nbytes, index) \ do { \ - (v)->header.size = VECTOR_FREE_LIST_FLAG | (nbytes); \ + XSETPVECTYPESIZE (v, PVEC_FREE, nbytes); \ eassert ((nbytes) % roundup_size == 0); \ (index) = VINDEX (nbytes); \ eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ @@ -3065,6 +3052,16 @@ allocate_vector_from_block (size_t nbytes) ((char *) (vector) <= (block)->data \ + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) +/* Number of bytes used by vector-block-allocated object. This is the only + place where we actually use the `nbytes' field of the vector-header. + I.e. we could get rid of the `nbytes' field by computing it based on the + vector-type. */ + +#define PSEUDOVECTOR_NBYTES(vector) \ + (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \ + ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \ + : vector->header.next.nbytes); + /* Reclaim space used by unmarked vectors. */ static void @@ -3093,14 +3090,10 @@ sweep_vectors (void) } else { - ptrdiff_t nbytes; + ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector); + ptrdiff_t total_bytes = nbytes; - if ((vector->header.size & VECTOR_FREE_LIST_FLAG) - == VECTOR_FREE_LIST_FLAG) - vector->header.next.nbytes = - vector->header.size & VECTOR_FREE_LIST_SIZE_MASK; - - next = ADVANCE (vector, vector->header.next.nbytes); + next = ADVANCE (vector, nbytes); /* While NEXT is not marked, try to coalesce with VECTOR, thus making VECTOR of the largest possible size. */ @@ -3109,16 +3102,12 @@ sweep_vectors (void) { if (VECTOR_MARKED_P (next)) break; - if ((next->header.size & VECTOR_FREE_LIST_FLAG) - == VECTOR_FREE_LIST_FLAG) - nbytes = next->header.size & VECTOR_FREE_LIST_SIZE_MASK; - else - nbytes = next->header.next.nbytes; - vector->header.next.nbytes += nbytes; + nbytes = PSEUDOVECTOR_NBYTES (next); + total_bytes += nbytes; next = ADVANCE (next, nbytes); } - eassert (vector->header.next.nbytes % roundup_size == 0); + eassert (total_bytes % roundup_size == 0); if (vector == (struct Lisp_Vector *) block->data && !VECTOR_IN_BLOCK (next, block)) @@ -3126,7 +3115,10 @@ sweep_vectors (void) space was coalesced into the only free vector. */ free_this_block = 1; else - SETUP_ON_FREE_LIST (vector, vector->header.next.nbytes, nbytes); + { + int tmp; + SETUP_ON_FREE_LIST (vector, total_bytes, tmp); + } } } @@ -4342,10 +4334,9 @@ live_vector_p (struct mem_node *m, void *p) while (VECTOR_IN_BLOCK (vector, block) && vector <= (struct Lisp_Vector *) p) { - if ((vector->header.size & VECTOR_FREE_LIST_FLAG) - == VECTOR_FREE_LIST_FLAG) + if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) vector = ADVANCE (vector, (vector->header.size - & VECTOR_FREE_LIST_SIZE_MASK)); + & PSEUDOVECTOR_SIZE_MASK)); else if (vector == p) return 1; else @@ -5913,15 +5904,17 @@ mark_object (Lisp_Object arg) #endif /* GC_CHECK_MARKED_OBJECTS */ if (ptr->header.size & PSEUDOVECTOR_FLAG) - pvectype = ptr->header.size & PVEC_TYPE_MASK; + pvectype = ((ptr->header.size & PVEC_TYPE_MASK) + >> PSEUDOVECTOR_SIZE_BITS); else pvectype = 0; if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) CHECK_LIVE (live_vector_p); - if (pvectype == PVEC_BUFFER) + switch (pvectype) { + case PVEC_BUFFER: #ifdef GC_CHECK_MARKED_OBJECTS if (po != &buffer_defaults && po != &buffer_local_symbols) { @@ -5933,67 +5926,82 @@ mark_object (Lisp_Object arg) } #endif /* GC_CHECK_MARKED_OBJECTS */ mark_buffer ((struct buffer *) ptr); - } + break; - else if (pvectype == PVEC_COMPILED) - /* We could treat this just like a vector, but it is better - to save the COMPILED_CONSTANTS element for last and avoid - recursion there. */ - { - int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; - int i; + case PVEC_COMPILED: + { /* We could treat this just like a vector, but it is better + to save the COMPILED_CONSTANTS element for last and avoid + recursion there. */ + int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; + int i; + + VECTOR_MARK (ptr); + for (i = 0; i < size; i++) + if (i != COMPILED_CONSTANTS) + mark_object (ptr->contents[i]); + if (size > COMPILED_CONSTANTS) + { + obj = ptr->contents[COMPILED_CONSTANTS]; + goto loop; + } + } + break; - VECTOR_MARK (ptr); - for (i = 0; i < size; i++) - if (i != COMPILED_CONSTANTS) - mark_object (ptr->contents[i]); - obj = ptr->contents[COMPILED_CONSTANTS]; - goto loop; - } + case PVEC_FRAME: + { + mark_vectorlike (ptr); + mark_face_cache (((struct frame *) ptr)->face_cache); + } + break; - else if (pvectype == PVEC_FRAME) - { - mark_vectorlike (ptr); - mark_face_cache (((struct frame *) ptr)->face_cache); - } + case PVEC_WINDOW: + { + struct window *w = (struct window *) ptr; - else if (pvectype == PVEC_WINDOW) - { - struct window *w = (struct window *) ptr; + mark_vectorlike (ptr); + /* Mark glyphs for leaf windows. Marking window + matrices is sufficient because frame matrices + use the same glyph memory. */ + if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) + { + mark_glyph_matrix (w->current_matrix); + mark_glyph_matrix (w->desired_matrix); + } + } + break; - mark_vectorlike (ptr); - /* Mark glyphs for leaf windows. Marking window - matrices is sufficient because frame matrices - use the same glyph memory. */ - if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) - { - mark_glyph_matrix (w->current_matrix); - mark_glyph_matrix (w->desired_matrix); - } - } + case PVEC_HASH_TABLE: + { + struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; - else if (pvectype == PVEC_HASH_TABLE) - { - struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; + mark_vectorlike (ptr); + /* If hash table is not weak, mark all keys and values. + For weak tables, mark only the vector. */ + if (NILP (h->weak)) + mark_object (h->key_and_value); + else + VECTOR_MARK (XVECTOR (h->key_and_value)); + } + break; - mark_vectorlike (ptr); - /* If hash table is not weak, mark all keys and values. - For weak tables, mark only the vector. */ - if (NILP (h->weak)) - mark_object (h->key_and_value); - else - VECTOR_MARK (XVECTOR (h->key_and_value)); - } + case PVEC_CHAR_TABLE: + mark_char_table (ptr); + break; + + case PVEC_BOOL_VECTOR: + /* No Lisp_Objects to mark in a bool vector. */ + VECTOR_MARK (ptr); + break; - else if (pvectype == PVEC_CHAR_TABLE) - mark_char_table (ptr); + case PVEC_SUBR: + break; - else if (pvectype == PVEC_BOOL_VECTOR) - /* No Lisp_Objects to mark in a bool vector. */ - VECTOR_MARK (ptr); + case PVEC_FREE: + abort (); - else if (pvectype != PVEC_SUBR) - mark_vectorlike (ptr); + default: + mark_vectorlike (ptr); + } } break; diff --git a/src/emacs.c b/src/emacs.c index 72e280c7409..143a44e0847 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -119,7 +119,7 @@ ptrdiff_t PVEC_FLAG EXTERNALLY_VISIBLE = PSEUDOVECTOR_FLAG; ptrdiff_t gdb_array_mark_flag EXTERNALLY_VISIBLE = ARRAY_MARK_FLAG; /* GDB might say "No enum type named pvec_type" if we don't have at least one symbol with that type, and then xbacktrace could fail. */ -enum pvec_type gdb_pvec_type EXTERNALLY_VISIBLE = PVEC_TYPE_MASK; +ptrdiff_t gdb_pvec_type EXTERNALLY_VISIBLE = PVEC_TYPE_MASK; /* Empty lisp strings. To avoid having to build any others. */ Lisp_Object empty_unibyte_string, empty_multibyte_string; diff --git a/src/fns.c b/src/fns.c index 2c6e75e60c5..5ed283a8719 100644 --- a/src/fns.c +++ b/src/fns.c @@ -2095,8 +2095,9 @@ internal_equal (register Lisp_Object o1, register Lisp_Object o2, int depth, int are sensible to compare, so eliminate the others now. */ if (size & PSEUDOVECTOR_FLAG) { - if (!(size & (PVEC_COMPILED - | PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) + if (!(size & ((PVEC_COMPILED | PVEC_CHAR_TABLE + | PVEC_SUB_CHAR_TABLE | PVEC_FONT) + << PSEUDOVECTOR_SIZE_BITS))) return 0; size &= PSEUDOVECTOR_SIZE_MASK; } diff --git a/src/lisp.h b/src/lisp.h index a0d6c6b3c0b..9b2dda244e9 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -341,28 +341,26 @@ typedef EMACS_INT Lisp_Object; It is not crucial, but there are plenty of bits here, so why not do it? */ enum pvec_type { - PVEC_NORMAL_VECTOR = 0, - PVEC_PROCESS = 0x200, - PVEC_FRAME = 0x400, - PVEC_COMPILED = 0x800, - PVEC_WINDOW = 0x1000, - PVEC_WINDOW_CONFIGURATION = 0x2000, - PVEC_SUBR = 0x4000, - PVEC_CHAR_TABLE = 0x8000, - PVEC_BOOL_VECTOR = 0x10000, - PVEC_BUFFER = 0x20000, - PVEC_HASH_TABLE = 0x40000, - PVEC_TERMINAL = 0x80000, - PVEC_SUB_CHAR_TABLE = 0x100000, - PVEC_FONT = 0x200000, - PVEC_OTHER = 0x400000, - PVEC_TYPE_MASK = 0x7ffe00 - -#if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to - GDB. It doesn't work on OS Alpha. Moved to a variable in - emacs.c. */ - PVEC_FLAG = PSEUDOVECTOR_FLAG -#endif + PVEC_NORMAL_VECTOR = 0, /* Unused! */ + PVEC_FREE, + PVEC_PROCESS, + PVEC_FRAME, + PVEC_WINDOW, + PVEC_BOOL_VECTOR, + PVEC_BUFFER, + PVEC_HASH_TABLE, + PVEC_TERMINAL, + PVEC_WINDOW_CONFIGURATION, + PVEC_SUBR, + PVEC_OTHER, + /* These last 4 are special because we OR them in fns.c:internal_equal, + so they have to use a disjoint bit pattern: + if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE + | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) */ + PVEC_COMPILED = 0x10, + PVEC_CHAR_TABLE = 0x20, + PVEC_SUB_CHAR_TABLE = 0x30, + PVEC_FONT = 0x40 }; /* For convenience, we also store the number of elements in these bits. @@ -370,7 +368,9 @@ enum pvec_type only the number of Lisp_Object fields (that need to be traced by the GC). The distinction is used e.g. by Lisp_Process which places extra non-Lisp_Object fields at the end of the structure. */ -#define PSEUDOVECTOR_SIZE_MASK 0x1ff +#define PSEUDOVECTOR_SIZE_BITS 16 +#define PSEUDOVECTOR_SIZE_MASK ((1 << PSEUDOVECTOR_SIZE_BITS) - 1) +#define PVEC_TYPE_MASK (0x0fff << PSEUDOVECTOR_SIZE_BITS) /* Number of bits to put in each character in the internal representation of bool vectors. This should not vary across implementations. */ @@ -536,9 +536,11 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) #define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code) #define XSETTYPED_PVECTYPE(v, size_member, code) \ - ((v)->size_member |= PSEUDOVECTOR_FLAG | (code)) + ((v)->size_member |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)) #define XSETPVECTYPESIZE(v, code, sizeval) \ - ((v)->header.size = PSEUDOVECTOR_FLAG | (code) | (sizeval)) + ((v)->header.size = (PSEUDOVECTOR_FLAG \ + | ((code) << PSEUDOVECTOR_SIZE_BITS) \ + | (sizeval))) /* The cast to struct vectorlike_header * avoids aliasing issues. */ #define XSETPSEUDOVECTOR(a, b, code) \ @@ -550,7 +552,7 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) #define XSETTYPED_PSEUDOVECTOR(a, b, size, code) \ (XSETVECTOR (a, b), \ eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ - == (PSEUDOVECTOR_FLAG | (code)))) + == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS)))) #define XSETWINDOW_CONFIGURATION(a, b) \ (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION)) @@ -730,13 +732,13 @@ extern ptrdiff_t string_bytes (struct Lisp_String *); /* Set text properties. */ #define STRING_SET_INTERVALS(STR, INT) (XSTRING (STR)->intervals = (INT)) -/* In a string or vector, the sign bit of the `size' is the gc mark bit */ +/* In a string or vector, the sign bit of the `size' is the gc mark bit. */ struct Lisp_String { ptrdiff_t size; ptrdiff_t size_byte; - INTERVAL intervals; /* text properties in this string */ + INTERVAL intervals; /* Text properties in this string. */ unsigned char *data; }; @@ -749,6 +751,20 @@ struct Lisp_String . */ struct vectorlike_header { + /* This field contains various pieces of information: + - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit. + - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain + vector (0) or a pseudovector (1). + - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number + of slots) of the vector. + - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into + a "pvec type" tag held in PVEC_TYPE_MASK and a size held in the lowest + PSEUDOVECTOR_SIZE_BITS. That size normally indicates the number of + Lisp_Object slots at the beginning of the object that need to be + traced by the GC, tho some types use it slightly differently. + - E.g. if the pvec type is PVEC_FREE it means this is an unallocated + vector on a free-list and PSEUDOVECTOR_SIZE_BITS indicates its size + in bytes. */ ptrdiff_t size; /* When the vector is allocated from a vector block, NBYTES is used @@ -759,8 +775,17 @@ struct vectorlike_header pointer: this way, one can write P->next.vector instead of ((struct Lisp_Vector *) P->next). */ union { + /* This is only needed for small vectors that are not free because the + `size' field only gives us the number of Lisp_Object slots, whereas we + need to know the total size, including non-Lisp_Object data. + FIXME: figure out a way to store this info elsewhere so we can + finally get rid of this extra word of overhead. */ ptrdiff_t nbytes; struct buffer *buffer; + /* FIXME: This can be removed: For large vectors, this field could be + placed *before* the vector itself. And for small vectors on a free + list, this field could be stored in the vector's bytes, since the + empty vector is handled specially anyway. */ struct Lisp_Vector *vector; } next; }; @@ -775,7 +800,7 @@ struct Lisp_Vector of the shortest vector that would hold that struct. */ #define VECSIZE(type) ((sizeof (type) \ - offsetof (struct Lisp_Vector, contents[0]) \ - + sizeof (Lisp_Object) - 1) /* round up */ \ + + sizeof (Lisp_Object) - 1) /* Round up. */ \ / sizeof (Lisp_Object)) /* Like VECSIZE, but used when the pseudo-vector has non-Lisp_Object fields @@ -1617,15 +1642,17 @@ typedef struct { /* True if object X is a pseudovector whose code is CODE. The cast to struct vectorlike_header * avoids aliasing issues. */ #define PSEUDOVECTORP(x, code) \ - TYPED_PSEUDOVECTORP(x, vectorlike_header, code) + TYPED_PSEUDOVECTORP (x, vectorlike_header, code) + +#define PSEUDOVECTOR_TYPEP(v, code) \ + (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ + == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS))) /* True if object X, with internal type struct T *, is a pseudovector whose code is CODE. */ #define TYPED_PSEUDOVECTORP(x, t, code) \ (VECTORLIKEP (x) \ - && (((((struct t *) XUNTAG (x, Lisp_Vectorlike))->size \ - & (PSEUDOVECTOR_FLAG | (code)))) \ - == (PSEUDOVECTOR_FLAG | (code)))) + && PSEUDOVECTOR_TYPEP ((struct t *) XUNTAG (x, Lisp_Vectorlike), code)) /* Test for specific pseudovector types. */ #define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION) @@ -1818,7 +1845,8 @@ typedef struct { #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ static DECL_ALIGN (struct Lisp_Subr, sname) = \ - { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \ + { (PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS) \ + | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \ { (Lisp_Object (__cdecl *)(void))fnname }, \ minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname @@ -1826,7 +1854,7 @@ typedef struct { #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ static DECL_ALIGN (struct Lisp_Subr, sname) = \ - { PVEC_SUBR, \ + { PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS, \ { .a ## maxargs = fnname }, \ minargs, maxargs, lname, intspec, 0}; \ Lisp_Object fnname