emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] /srv/bzr/emacs/trunk r108861: Turn VECTOR_FREE_LIST_FLAG i


From: Stefan Monnier
Subject: [Emacs-diffs] /srv/bzr/emacs/trunk r108861: Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE.
Date: Wed, 04 Jul 2012 10:38:02 -0400
User-agent: Bazaar (2.5.0)

------------------------------------------------------------
revno: 108861
committer: Stefan Monnier <address@hidden>
branch nick: trunk
timestamp: Wed 2012-07-04 10:38:02 -0400
message:
  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.
modified:
  src/ChangeLog
  src/alloc.c
  src/emacs.c
  src/fns.c
  src/lisp.h
=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2012-07-04 08:26:20 +0000
+++ b/src/ChangeLog     2012-07-04 14:38:02 +0000
@@ -1,3 +1,24 @@
+2012-07-04  Stefan Monnier  <address@hidden>
+
+       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  <address@hidden>
 
        * doprnt.c (doprnt): Don't assume string length fits in 'int'.

=== modified file 'src/alloc.c'
--- a/src/alloc.c       2012-07-03 16:35:53 +0000
+++ b/src/alloc.c       2012-07-04 14:38:02 +0000
@@ -1529,7 +1529,7 @@
 }
 
 
-/* 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 @@
       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 @@
 
 #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 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 @@
 #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 @@
 
 #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 @@
   ((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 @@
            }
          else
            {
-             ptrdiff_t 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);
+             ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector);
+             ptrdiff_t total_bytes = 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 @@
                {
                  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 @@
                   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 @@
       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 @@
 #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 @@
              }
 #endif /* GC_CHECK_MARKED_OBJECTS */
            mark_buffer ((struct buffer *) ptr);
-         }
-
-       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;
-
+           break;
+
+         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;
+
+         case PVEC_FRAME:
+           {
+             mark_vectorlike (ptr);
+             mark_face_cache (((struct frame *) ptr)->face_cache);
+           }
+           break;
+
+         case 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;
+
+         case 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;
+
+         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);
-           for (i = 0; i < size; i++)
-             if (i != COMPILED_CONSTANTS)
-               mark_object (ptr->contents[i]);
-           obj = ptr->contents[COMPILED_CONSTANTS];
-           goto loop;
-         }
-
-       else if (pvectype == PVEC_FRAME)
-         {
-           mark_vectorlike (ptr);
-           mark_face_cache (((struct frame *) ptr)->face_cache);
-         }
-
-       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);
-             }
-         }
-
-       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));
-       }
-
-       else if (pvectype == PVEC_CHAR_TABLE)
-         mark_char_table (ptr);
-
-       else if (pvectype == PVEC_BOOL_VECTOR)
-         /* No Lisp_Objects to mark in a bool vector.  */
-         VECTOR_MARK (ptr);
-
-       else if (pvectype != PVEC_SUBR)
-         mark_vectorlike (ptr);
+           break;
+
+         case PVEC_SUBR:
+           break;
+
+         case PVEC_FREE:
+           abort ();
+
+         default:
+           mark_vectorlike (ptr);
+         }
       }
       break;
 

=== modified file 'src/emacs.c'
--- a/src/emacs.c       2012-06-24 20:22:22 +0000
+++ b/src/emacs.c       2012-07-04 14:38:02 +0000
@@ -119,7 +119,7 @@
 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;

=== modified file 'src/fns.c'
--- a/src/fns.c 2012-06-28 07:50:27 +0000
+++ b/src/fns.c 2012-07-04 14:38:02 +0000
@@ -2095,8 +2095,9 @@
           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;
          }

=== modified file 'src/lisp.h'
--- a/src/lisp.h        2012-07-03 20:34:47 +0000
+++ b/src/lisp.h        2012-07-04 14:38:02 +0000
@@ -341,28 +341,26 @@
    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 @@
    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 @@
 
 #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 @@
 #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 @@
 /* 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 @@
    <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>.  */
 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 @@
        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 @@
    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 @@
 /* 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 @@
 #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 @@
 #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


reply via email to

[Prev in Thread] Current Thread [Next in Thread]