emacs-diffs
[Top][All Lists]
Advanced

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

[Emacs-diffs] trunk r114960: Simplify and port recent bool vector change


From: Paul Eggert
Subject: [Emacs-diffs] trunk r114960: Simplify and port recent bool vector changes.
Date: Tue, 05 Nov 2013 07:11:36 +0000
User-agent: Bazaar (2.6b2)

------------------------------------------------------------
revno: 114960
revision-id: address@hidden
parent: address@hidden
committer: Paul Eggert <address@hidden>
branch nick: trunk
timestamp: Mon 2013-11-04 23:11:24 -0800
message:
  Simplify and port recent bool vector changes.
  
  * configure.ac (BITSIZEOF_SIZE_T, SIZEOF_SIZE_T):
  New symbols to configure.
  * src/alloc.c (ROUNDUP): Move here from lisp.h, since it's now used
  only in this file.  Use a more-efficient implementation if the
  second argument is a power of 2.
  (ALIGN): Rewrite in terms of ROUNDUP.  Make it a function.
  Remove no-longer-necessary compile-time checks.
  (bool_vector_exact_payload_bytes): New function.
  (bool_vector_payload_bytes): Remove 2nd arg; callers that need
  exact payload changed to call the new function.  Do not assume
  that the arg or result fits in ptrdiff_t.
  (bool_vector_fill): New function.
  (Fmake_bool_vector): Use it.  Don't assume bit counts fit
  in ptrdiff_t.
  (vroundup_ct): Don't assume arg fits in size_t.
  * src/category.c (SET_CATEGORY_SET): Remove.  All callers now just
  invoke set_category_set.
  (set_category_set): 2nd arg is now EMACS_INT and 3rd is now bool.
  All callers changed.  Use bool_vector_set.
  * src/category.h (XCATEGORY_SET): Remove; no longer needed.
  (CATEGORY_MEMBER): Now a function.  Rewrite in terms of
  bool_vector_bitref.
  * src/data.c (Faref): Use bool_vector_ref.
  (Faset): Use bool_vector_set.
  (bits_word_to_host_endian): Don't assume you can shift by CHAR_BIT.
  (Fbool_vector_not, Fbool_vector_count_matches)
  (Fbool_vector_count_matches_at): Don't assume CHAR_BIT == 8.
  * src/fns.c (concat): Use bool_vector_ref.
  (Ffillarray): Use bool_vector_fill.
  (mapcar1): Use bool_vector_ref.
  (sxhash_bool_vector): Hash words, not bytes.
  * src/lisp.h (BOOL_VECTOR_BITS_PER_CHAR): Now a macro as well as
  a constant, since it's now used in #if.
  (bits_word, BITS_WORD_MAX, BITS_PER_BITS_WORD): Fall back on
  unsigned char on unusual architectures, so that we no longer
  assume that the number of bits per bits_word is a power of two or
  is a multiple of 8 or of CHAR_BIT.
  (Qt): Add forward decl.
  (struct Lisp_Bool_Vector): Don't assume EMACS_INT is aligned
  at least as strictly as bits_word.
  (bool_vector_data, bool_vector_uchar_data): New accessors.
  All data structure accesses changed to use them.
  (bool_vector_words, bool_vector_bitref, bool_vector_ref)
  (bool_vector_set): New functions.
  (bool_vector_fill): New decl.
  (ROUNDUP): Move to alloc.c as described above.
modified:
  ChangeLog                      changelog-20091113204419-o5vbwnq5f7feedwu-1538
  configure.ac                   
configure.in-20091113204419-o5vbwnq5f7feedwu-783
  src/ChangeLog                  changelog-20091113204419-o5vbwnq5f7feedwu-1438
  src/alloc.c                    alloc.c-20091113204419-o5vbwnq5f7feedwu-252
  src/category.c                 category.c-20091113204419-o5vbwnq5f7feedwu-1071
  src/category.h                 category.h-20091113204419-o5vbwnq5f7feedwu-1072
  src/data.c                     data.c-20091113204419-o5vbwnq5f7feedwu-251
  src/fns.c                      fns.c-20091113204419-o5vbwnq5f7feedwu-203
  src/image.c                    image.c-20091113204419-o5vbwnq5f7feedwu-2969
  src/lisp.h                     lisp.h-20091113204419-o5vbwnq5f7feedwu-253
  src/lread.c                    lread.c-20091113204419-o5vbwnq5f7feedwu-266
  src/print.c                    print.c-20091113204419-o5vbwnq5f7feedwu-262
=== modified file 'ChangeLog'
--- a/ChangeLog 2013-11-04 17:30:33 +0000
+++ b/ChangeLog 2013-11-05 07:11:24 +0000
@@ -1,3 +1,9 @@
+2013-11-05  Paul Eggert  <address@hidden>
+
+       Simplify and port recent bool vector changes.
+       * configure.ac (BITSIZEOF_SIZE_T, SIZEOF_SIZE_T):
+       New symbols to configure.
+
 2013-11-04  Eli Zaretskii  <address@hidden>
 
        * configure.ac: Don't disallow builds in non-ASCII directories.

=== modified file 'configure.ac'
--- a/configure.ac      2013-11-04 17:30:33 +0000
+++ b/configure.ac      2013-11-05 07:11:24 +0000
@@ -4719,6 +4719,8 @@
 gl_ASSERT_NO_GNULIB_POSIXCHECK
 gl_ASSERT_NO_GNULIB_TESTS
 gl_INIT
+gl_STDINT_BITSIZEOF([size_t], [[#include <stddef.h>]])
+AC_CHECK_SIZEOF([size_t])
 CFLAGS=$SAVE_CFLAGS
 LIBS=$SAVE_LIBS
 

=== modified file 'src/ChangeLog'
--- a/src/ChangeLog     2013-11-05 05:32:19 +0000
+++ b/src/ChangeLog     2013-11-05 07:11:24 +0000
@@ -1,5 +1,51 @@
 2013-11-05  Paul Eggert  <address@hidden>
 
+       Simplify and port recent bool vector changes.
+       * alloc.c (ROUNDUP): Move here from lisp.h, since it's now used
+       only in this file.  Use a more-efficient implementation if the
+       second argument is a power of 2.
+       (ALIGN): Rewrite in terms of ROUNDUP.  Make it a function.
+       Remove no-longer-necessary compile-time checks.
+       (bool_vector_exact_payload_bytes): New function.
+       (bool_vector_payload_bytes): Remove 2nd arg; callers that need
+       exact payload changed to call the new function.  Do not assume
+       that the arg or result fits in ptrdiff_t.
+       (bool_vector_fill): New function.
+       (Fmake_bool_vector): Use it.  Don't assume bit counts fit
+       in ptrdiff_t.
+       (vroundup_ct): Don't assume arg fits in size_t.
+       * category.c (SET_CATEGORY_SET): Remove.  All callers now just
+       invoke set_category_set.
+       (set_category_set): 2nd arg is now EMACS_INT and 3rd is now bool.
+       All callers changed.  Use bool_vector_set.
+       * category.h (XCATEGORY_SET): Remove; no longer needed.
+       (CATEGORY_MEMBER): Now a function.  Rewrite in terms of
+       bool_vector_bitref.
+       * data.c (Faref): Use bool_vector_ref.
+       (Faset): Use bool_vector_set.
+       (bits_word_to_host_endian): Don't assume you can shift by CHAR_BIT.
+       (Fbool_vector_not, Fbool_vector_count_matches)
+       (Fbool_vector_count_matches_at): Don't assume CHAR_BIT == 8.
+       * fns.c (concat): Use bool_vector_ref.
+       (Ffillarray): Use bool_vector_fill.
+       (mapcar1): Use bool_vector_ref.
+       (sxhash_bool_vector): Hash words, not bytes.
+       * lisp.h (BOOL_VECTOR_BITS_PER_CHAR): Now a macro as well as
+       a constant, since it's now used in #if.
+       (bits_word, BITS_WORD_MAX, BITS_PER_BITS_WORD): Fall back on
+       unsigned char on unusual architectures, so that we no longer
+       assume that the number of bits per bits_word is a power of two or
+       is a multiple of 8 or of CHAR_BIT.
+       (Qt): Add forward decl.
+       (struct Lisp_Bool_Vector): Don't assume EMACS_INT is aligned
+       at least as strictly as bits_word.
+       (bool_vector_data, bool_vector_uchar_data): New accessors.
+       All data structure accesses changed to use them.
+       (bool_vector_words, bool_vector_bitref, bool_vector_ref)
+       (bool_vector_set): New functions.
+       (bool_vector_fill): New decl.
+       (ROUNDUP): Move to alloc.c as described above.
+
        Fix recent gnutls changes.
        * gnutls.c (Fgnutls_boot): Don't assume C99.
        * process.c (wait_reading_process_output): Fix typo in recent change.

=== modified file 'src/alloc.c'
--- a/src/alloc.c       2013-11-04 06:09:03 +0000
+++ b/src/alloc.c       2013-11-05 07:11:24 +0000
@@ -361,13 +361,21 @@
 
 static void *pure_alloc (size_t, int);
 
-
-/* Value is SZ rounded up to the next multiple of ALIGNMENT.
-   ALIGNMENT must be a power of 2.  */
-
-#define ALIGN(ptr, ALIGNMENT) \
-  ((void *) (((uintptr_t) (ptr) + (ALIGNMENT) - 1) \
-            & ~ ((ALIGNMENT) - 1)))
+/* Return X rounded to the next multiple of Y.  Arguments should not
+   have side effects, as they are evaluated more than once.  Assume X
+   + Y - 1 does not overflow.  Tune for Y being a power of 2.  */
+
+#define ROUNDUP(x, y) ((y) & ((y) - 1)                                 \
+                      ? ((x) + (y) - 1) - ((x) + (y) - 1) % (y)        \
+                      : ((x) + (y) - 1) & ~ ((y) - 1))
+
+/* Return PTR rounded up to the next multiple of ALIGNMENT.  */
+
+static void *
+ALIGN (void *ptr, int alignment)
+{
+  return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
+}
 
 static void
 XFLOAT_INIT (Lisp_Object f, double n)
@@ -2026,33 +2034,39 @@
   return val;
 }
 
-verify (sizeof (size_t) * CHAR_BIT == BITS_PER_BITS_WORD);
-verify ((BITS_PER_BITS_WORD & (BITS_PER_BITS_WORD - 1)) == 0);
-
-static ptrdiff_t
-bool_vector_payload_bytes (ptrdiff_t nr_bits,
-                           ptrdiff_t *exact_needed_bytes_out)
-{
-  ptrdiff_t exact_needed_bytes;
-  ptrdiff_t needed_bytes;
-
-  eassume (nr_bits >= 0);
-
-  exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT;
-  needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_BITS_WORD) / CHAR_BIT;
-
-  if (needed_bytes == 0)
+static EMACS_INT
+bool_vector_exact_payload_bytes (EMACS_INT nbits)
+{
+  eassume (0 <= nbits);
+  return (nbits + BOOL_VECTOR_BITS_PER_CHAR - 1) / BOOL_VECTOR_BITS_PER_CHAR;
+}
+
+static EMACS_INT
+bool_vector_payload_bytes (EMACS_INT nbits)
+{
+  EMACS_INT exact_needed_bytes = bool_vector_exact_payload_bytes (nbits);
+
+  /* Always allocate at least one machine word of payload so that
+     bool-vector operations in data.c don't need a special case
+     for empty vectors.  */
+  return ROUNDUP (exact_needed_bytes + !exact_needed_bytes,
+                 sizeof (bits_word));
+}
+
+void
+bool_vector_fill (Lisp_Object a, Lisp_Object init)
+{
+  EMACS_INT nbits = bool_vector_size (a);
+  if (0 < nbits)
     {
-      /* Always allocate at least one machine word of payload so that
-         bool-vector operations in data.c don't need a special case
-         for empty vectors.  */
-      needed_bytes = sizeof (bits_word);
+      unsigned char *data = bool_vector_uchar_data (a);
+      int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1;
+      ptrdiff_t nbytes = ((nbits + BOOL_VECTOR_BITS_PER_CHAR - 1)
+                         / BOOL_VECTOR_BITS_PER_CHAR);
+      int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1));
+      memset (data, pattern, nbytes - 1);
+      data[nbytes - 1] = pattern & last_mask;
     }
-
-  if (exact_needed_bytes_out != NULL)
-    *exact_needed_bytes_out = exact_needed_bytes;
-
-  return needed_bytes;
 }
 
 DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
@@ -2060,42 +2074,29 @@
 LENGTH must be a number.  INIT matters only in whether it is t or nil.  */)
   (Lisp_Object length, Lisp_Object init)
 {
-  register Lisp_Object val;
+  Lisp_Object val;
   struct Lisp_Bool_Vector *p;
-  ptrdiff_t exact_payload_bytes;
-  ptrdiff_t total_payload_bytes;
-  ptrdiff_t needed_elements;
+  EMACS_INT exact_payload_bytes, total_payload_bytes, needed_elements;
 
   CHECK_NATNUM (length);
-  if (PTRDIFF_MAX < XFASTINT (length))
-    memory_full (SIZE_MAX);
-
-  total_payload_bytes = bool_vector_payload_bytes
-    (XFASTINT (length), &exact_payload_bytes);
-
-  eassume (exact_payload_bytes <= total_payload_bytes);
-  eassume (0 <= exact_payload_bytes);
-
-  needed_elements = ROUNDUP ((size_t) ((bool_header_size - header_size)
-                                       + total_payload_bytes),
-                             word_size) / word_size;
+
+  exact_payload_bytes = bool_vector_exact_payload_bytes (XFASTINT (length));
+  total_payload_bytes = bool_vector_payload_bytes (XFASTINT (length));
+
+  needed_elements = ((bool_header_size - header_size + total_payload_bytes
+                     + word_size - 1)
+                    / word_size);
 
   p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
   XSETVECTOR (val, p);
   XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
 
   p->size = XFASTINT (length);
-  if (exact_payload_bytes)
-    {
-      memset (p->data, ! NILP (init) ? -1 : 0, exact_payload_bytes);
-
-      /* Clear any extraneous bits in the last byte.  */
-      p->data[exact_payload_bytes - 1]
-       &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1;
-    }
+  bool_vector_fill (val, init);
 
   /* Clear padding at the end.  */
-  memset (p->data + exact_payload_bytes,
+  eassume (exact_payload_bytes <= total_payload_bytes);
+  memset (bool_vector_uchar_data (val) + exact_payload_bytes,
           0,
           total_payload_bytes - exact_payload_bytes);
 
@@ -2648,7 +2649,7 @@
 verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
 
 /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time.  */
-#define vroundup_ct(x) ROUNDUP ((size_t) (x), roundup_size)
+#define vroundup_ct(x) ROUNDUP (x, roundup_size)
 /* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime.  */
 #define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x))
 
@@ -2856,11 +2857,8 @@
       if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
         {
           struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v;
-          ptrdiff_t payload_bytes =
-              bool_vector_payload_bytes (bv->size, NULL);
-
-          eassume (payload_bytes >= 0);
-          size = bool_header_size + ROUNDUP (payload_bytes, word_size);
+          ptrdiff_t payload_bytes = bool_vector_payload_bytes (bv->size);
+          size = bool_header_size + payload_bytes;
         }
       else
        size = (header_size

=== modified file 'src/category.c'
--- a/src/category.c    2013-09-20 15:34:36 +0000
+++ b/src/category.c    2013-11-05 07:11:24 +0000
@@ -55,17 +55,9 @@
 static int category_table_version;
 
 static Lisp_Object Qcategory_table, Qcategoryp, Qcategorysetp, 
Qcategory_table_p;
-
-/* Make CATEGORY_SET includes (if VAL is t) or excludes (if VAL is
-   nil) CATEGORY.  */
-#define SET_CATEGORY_SET(category_set, category, val) \
-  set_category_set (category_set, category, val)
-static void set_category_set (Lisp_Object, Lisp_Object, Lisp_Object);
 
 /* Category set staff.  */
 
-static Lisp_Object hash_get_category_set (Lisp_Object, Lisp_Object);
-
 static Lisp_Object
 hash_get_category_set (Lisp_Object table, Lisp_Object category_set)
 {
@@ -88,6 +80,13 @@
   return category_set;
 }
 
+/* Make CATEGORY_SET include (if VAL) or exclude (if !VAL) CATEGORY.  */
+
+static void
+set_category_set (Lisp_Object category_set, EMACS_INT category, bool val)
+{
+  bool_vector_set (category_set, category, val);
+}
 
 DEFUN ("make-category-set", Fmake_category_set, Smake_category_set, 1, 1, 0,
        doc: /* Return a newly created category-set which contains CATEGORIES.
@@ -108,11 +107,11 @@
   len = SCHARS (categories);
   while (--len >= 0)
     {
-      Lisp_Object category;
+      unsigned char cat = SREF (categories, len);
+      Lisp_Object category = make_number (cat);
 
-      XSETFASTINT (category, SREF (categories, len));
       CHECK_CATEGORY (category);
-      SET_CATEGORY_SET (val, category, Qt);
+      set_category_set (val, cat, 1);
     }
   return val;
 }
@@ -334,20 +333,6 @@
   return build_string (str);
 }
 
-static void
-set_category_set (Lisp_Object category_set, Lisp_Object category, Lisp_Object 
val)
-{
-  do {
-    int idx = XINT (category) / 8;
-    unsigned char bits = 1 << (XINT (category) % 8);
-
-    if (NILP (val))
-      XCATEGORY_SET (category_set)->data[idx] &= ~bits;
-    else
-      XCATEGORY_SET (category_set)->data[idx] |= bits;
-  } while (0);
-}
-
 DEFUN ("modify-category-entry", Fmodify_category_entry,
        Smodify_category_entry, 2, 4, 0,
        doc: /* Modify the category set of CHARACTER by adding CATEGORY to it.
@@ -359,7 +344,7 @@
 then delete CATEGORY from the category set instead of adding it.  */)
   (Lisp_Object character, Lisp_Object category, Lisp_Object table, Lisp_Object 
reset)
 {
-  Lisp_Object set_value;       /* Actual value to be set in category sets.  */
+  bool set_value;      /* Actual value to be set in category sets.  */
   Lisp_Object category_set;
   int start, end;
   int from, to;
@@ -384,7 +369,7 @@
   if (NILP (CATEGORY_DOCSTRING (table, XFASTINT (category))))
     error ("Undefined category: %c", (int) XFASTINT (category));
 
-  set_value = NILP (reset) ? Qt : Qnil;
+  set_value = NILP (reset);
 
   while (start <= end)
     {
@@ -393,7 +378,7 @@
       if (CATEGORY_MEMBER (XFASTINT (category), category_set) != NILP (reset))
        {
          category_set = Fcopy_sequence (category_set);
-         SET_CATEGORY_SET (category_set, category, set_value);
+         set_category_set (category_set, XFASTINT (category), set_value);
          category_set = hash_get_category_set (table, category_set);
          char_table_set_range (table, start, to, category_set);
        }

=== modified file 'src/category.h'
--- a/src/category.h    2013-10-14 07:12:49 +0000
+++ b/src/category.h    2013-11-05 07:11:24 +0000
@@ -60,8 +60,6 @@
 #define CHECK_CATEGORY(x) \
   CHECK_TYPE (CATEGORYP (x), Qcategoryp, x)
 
-#define XCATEGORY_SET XBOOL_VECTOR
-
 #define CATEGORY_SET_P(x) \
   (BOOL_VECTOR_P (x) && bool_vector_size (x) == 128)
 
@@ -75,10 +73,12 @@
 #define CATEGORY_SET(c) char_category_set (c)
 
 /* Return true if CATEGORY_SET contains CATEGORY.
-   The faster version of `!NILP (Faref (category_set, category))'.  */
-#define CATEGORY_MEMBER(category, category_set)                                
\
-  ((XCATEGORY_SET (category_set)->data[(category) / 8]                 \
-    >> ((category) % 8)) & 1)
+   Faster than '!NILP (Faref (category_set, make_number (category)))'.  */
+INLINE bool
+CATEGORY_MEMBER (EMACS_INT category, Lisp_Object category_set)
+{
+  return bool_vector_bitref (category_set, category);
+}
 
 /* Return true if category set of CH contains CATEGORY.  */
 INLINE bool

=== modified file 'src/data.c'
--- a/src/data.c        2013-10-17 01:02:32 +0000
+++ b/src/data.c        2013-11-05 07:11:24 +0000
@@ -2141,13 +2141,9 @@
     }
   else if (BOOL_VECTOR_P (array))
     {
-      int val;
-
       if (idxval < 0 || idxval >= bool_vector_size (array))
        args_out_of_range (array, idx);
-
-      val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / 
BOOL_VECTOR_BITS_PER_CHAR];
-      return (val & (1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR)) ? Qt : Qnil);
+      return bool_vector_ref (array, idxval);
     }
   else if (CHAR_TABLE_P (array))
     {
@@ -2191,18 +2187,9 @@
     }
   else if (BOOL_VECTOR_P (array))
     {
-      int val;
-
       if (idxval < 0 || idxval >= bool_vector_size (array))
        args_out_of_range (array, idx);
-
-      val = (unsigned char) XBOOL_VECTOR (array)->data[idxval / 
BOOL_VECTOR_BITS_PER_CHAR];
-
-      if (! NILP (newelt))
-       val |= 1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR);
-      else
-       val &= ~(1 << (idxval % BOOL_VECTOR_BITS_PER_CHAR));
-      XBOOL_VECTOR (array)->data[idxval / BOOL_VECTOR_BITS_PER_CHAR] = val;
+      bool_vector_set (array, idxval, !NILP (newelt));
     }
   else if (CHAR_TABLE_P (array))
     {
@@ -3033,11 +3020,11 @@
        wrong_length_argument (op1, op2, dest);
     }
 
-  nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD;
+  nr_words = bool_vector_words (nr_bits);
 
-  adata = (bits_word *) XBOOL_VECTOR (dest)->data;
-  bdata = (bits_word *) XBOOL_VECTOR (op1)->data;
-  cdata = (bits_word *) XBOOL_VECTOR (op2)->data;
+  adata = bool_vector_data (dest);
+  bdata = bool_vector_data (op1);
+  cdata = bool_vector_data (op2);
   i = 0;
   do
     {
@@ -3110,8 +3097,9 @@
   bits_word r = 0;
   for (i = 0; i < sizeof val; i++)
     {
-      r = (r << CHAR_BIT) | (val & ((1u << CHAR_BIT) - 1));
-      val >>= CHAR_BIT;
+      r = ((r << 1 << (CHAR_BIT - 1))
+          | (val & ((1u << 1 << (CHAR_BIT - 1)) - 1)));
+      val = val >> 1 >> (CHAR_BIT - 1);
     }
   return r;
 #endif
@@ -3181,7 +3169,6 @@
   EMACS_INT nr_bits;
   bits_word *bdata, *adata;
   ptrdiff_t i;
-  bits_word mword;
 
   CHECK_BOOL_VECTOR (a);
   nr_bits = bool_vector_size (a);
@@ -3195,15 +3182,15 @@
        wrong_length_argument (a, b, Qnil);
     }
 
-  bdata = (bits_word *) XBOOL_VECTOR (b)->data;
-  adata = (bits_word *) XBOOL_VECTOR (a)->data;
+  bdata = bool_vector_data (b);
+  adata = bool_vector_data (a);
 
   for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; i++)
-    bdata[i] = ~adata[i];
+    bdata[i] = BITS_WORD_MAX & ~adata[i];
 
   if (nr_bits % BITS_PER_BITS_WORD)
     {
-      mword = bits_word_to_host_endian (adata[i]);
+      bits_word mword = bits_word_to_host_endian (adata[i]);
       mword = ~mword;
       mword &= bool_vector_spare_mask (nr_bits);
       bdata[i] = bits_word_to_host_endian (mword);
@@ -3228,8 +3215,8 @@
 
   nr_bits = bool_vector_size (a);
   count = 0;
-  match = NILP (b) ? -1 : 0;
-  adata = (bits_word *) XBOOL_VECTOR (a)->data;
+  match = NILP (b) ? BITS_WORD_MAX : 0;
+  adata = bool_vector_data (a);
 
   for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; ++i)
     count += popcount_bits_word (adata[i] ^ match);
@@ -3269,10 +3256,8 @@
   if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */
     args_out_of_range (a, i);
 
-  adata = (bits_word *) XBOOL_VECTOR (a)->data;
-
-  nr_words = ROUNDUP (nr_bits, BITS_PER_BITS_WORD) / BITS_PER_BITS_WORD;
-
+  adata = bool_vector_data (a);
+  nr_words = bool_vector_words (nr_bits);
   pos = XFASTINT (i) / BITS_PER_BITS_WORD;
   offset = XFASTINT (i) % BITS_PER_BITS_WORD;
   count = 0;
@@ -3280,7 +3265,7 @@
   /* By XORing with twiddle, we transform the problem of "count
      consecutive equal values" into "count the zero bits".  The latter
      operation usually has hardware support.  */
-  twiddle = NILP (b) ? 0 : -1;
+  twiddle = NILP (b) ? 0 : BITS_WORD_MAX;
 
   /* Scan the remainder of the mword at the current offset.  */
   if (pos < nr_words && offset != 0)

=== modified file 'src/fns.c'
--- a/src/fns.c 2013-11-04 06:09:03 +0000
+++ b/src/fns.c 2013-11-05 07:11:24 +0000
@@ -441,8 +441,7 @@
           / BOOL_VECTOR_BITS_PER_CHAR);
 
       val = Fmake_bool_vector (Flength (arg), Qnil);
-      memcpy (XBOOL_VECTOR (val)->data, XBOOL_VECTOR (arg)->data,
-             size_in_chars);
+      memcpy (bool_vector_data (val), bool_vector_data (arg), size_in_chars);
       return val;
     }
 
@@ -674,12 +673,7 @@
              }
            else if (BOOL_VECTOR_P (this))
              {
-               int byte;
-               byte = XBOOL_VECTOR (this)->data[thisindex / 
BOOL_VECTOR_BITS_PER_CHAR];
-               if (byte & (1 << (thisindex % BOOL_VECTOR_BITS_PER_CHAR)))
-                 elt = Qt;
-               else
-                 elt = Qnil;
+               elt = bool_vector_ref (this, thisindex);
                thisindex++;
              }
            else
@@ -2071,7 +2065,7 @@
            EMACS_INT size = bool_vector_size (o1);
            if (size != bool_vector_size (o2))
              return 0;
-           if (memcmp (XBOOL_VECTOR (o1)->data, XBOOL_VECTOR (o2)->data,
+           if (memcmp (bool_vector_data (o1), bool_vector_data (o2),
                        ((size + BOOL_VECTOR_BITS_PER_CHAR - 1)
                         / BOOL_VECTOR_BITS_PER_CHAR)))
              return 0;
@@ -2163,19 +2157,7 @@
          p[idx] = charval;
     }
   else if (BOOL_VECTOR_P (array))
-    {
-      unsigned char *p = XBOOL_VECTOR (array)->data;
-      size = ((bool_vector_size (array) + BOOL_VECTOR_BITS_PER_CHAR - 1)
-             / BOOL_VECTOR_BITS_PER_CHAR);
-
-      if (size)
-       {
-         memset (p, ! NILP (item) ? -1 : 0, size);
-
-         /* Clear any extraneous bits in the last byte.  */
-         p[size - 1] &= (1 << (size % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
-       }
-    }
+    bool_vector_fill (array, item);
   else
     wrong_type_argument (Qarrayp, array);
   return array;
@@ -2287,10 +2269,7 @@
     {
       for (i = 0; i < leni; i++)
        {
-         unsigned char byte;
-         byte = XBOOL_VECTOR (seq)->data[i / BOOL_VECTOR_BITS_PER_CHAR];
-         dummy = (byte & (1 << (i % BOOL_VECTOR_BITS_PER_CHAR))) ? Qt : Qnil;
-         dummy = call1 (fn, dummy);
+         dummy = call1 (fn, bool_vector_ref (seq, i));
          if (vals)
            vals[i] = dummy;
        }
@@ -4189,11 +4168,9 @@
   EMACS_UINT hash = size;
   int i, n;
 
-  n = min (SXHASH_MAX_LEN,
-          ((size + BOOL_VECTOR_BITS_PER_CHAR - 1)
-           / BOOL_VECTOR_BITS_PER_CHAR));
+  n = min (SXHASH_MAX_LEN, bool_vector_words (size));
   for (i = 0; i < n; ++i)
-    hash = sxhash_combine (hash, XBOOL_VECTOR (vec)->data[i]);
+    hash = sxhash_combine (hash, bool_vector_data (vec)[i]);
 
   return SXHASH_REDUCE (hash);
 }

=== modified file 'src/image.c'
--- a/src/image.c       2013-11-01 09:10:13 +0000
+++ b/src/image.c       2013-11-05 07:11:24 +0000
@@ -3026,13 +3026,13 @@
                  if (STRINGP (line))
                    memcpy (p, SDATA (line), nbytes);
                  else
-                   memcpy (p, XBOOL_VECTOR (line)->data, nbytes);
+                   memcpy (p, bool_vector_data (line), nbytes);
                }
            }
          else if (STRINGP (data))
            bits = SSDATA (data);
          else
-           bits = (char *) XBOOL_VECTOR (data)->data;
+           bits = (char *) bool_vector_data (data);
 
 #ifdef HAVE_NTGUI
           {

=== modified file 'src/lisp.h'
--- a/src/lisp.h        2013-11-04 06:09:03 +0000
+++ b/src/lisp.h        2013-11-05 07:11:24 +0000
@@ -82,10 +82,26 @@
 # endif
 #endif
 
+/* Number of bits to put in each character in the internal representation
+   of bool vectors.  This should not vary across implementations.  */
+enum {  BOOL_VECTOR_BITS_PER_CHAR =
+#define BOOL_VECTOR_BITS_PER_CHAR 8
+        BOOL_VECTOR_BITS_PER_CHAR
+};
+
 /* An unsigned integer type representing a fixed-length bit sequence,
-   suitable for words in a Lisp bool vector.  */
+   suitable for words in a Lisp bool vector.  Normally it is size_t
+   for speed, but it is unsigned char on weird platforms.  */
+#if (BITSIZEOF_SIZE_T == CHAR_BIT * SIZEOF_SIZE_T \
+     && BOOL_VECTOR_BITS_PER_CHAR == CHAR_BIT)
 typedef size_t bits_word;
 #define BITS_WORD_MAX SIZE_MAX
+enum { BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word) };
+#else
+typedef unsigned char bits_word;
+#define BITS_WORD_MAX ((1u << BOOL_VECTOR_BITS_PER_CHAR) - 1)
+enum { BITS_PER_BITS_WORD = BOOL_VECTOR_BITS_PER_CHAR };
+#endif
 
 /* Number of bits in some machine integer types.  */
 enum
@@ -94,7 +110,6 @@
     BITS_PER_SHORT     = CHAR_BIT * sizeof (short),
     BITS_PER_INT       = CHAR_BIT * sizeof (int),
     BITS_PER_LONG      = CHAR_BIT * sizeof (long int),
-    BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word),
     BITS_PER_EMACS_INT = CHAR_BIT * sizeof (EMACS_INT)
   };
 
@@ -616,10 +631,6 @@
     /* Used to extract pseudovector subtype information.  */
     PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS,
     PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS,
-
-    /* Number of bits to put in each character in the internal representation
-       of bool vectors.  This should not vary across implementations.  */
-    BOOL_VECTOR_BITS_PER_CHAR = 8
   };
 
 /* These functions extract various sorts of values from a Lisp_Object.
@@ -777,7 +788,7 @@
 /* Defined in data.c.  */
 extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p;
 extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil;
-extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qvectorp;
+extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qt, Qvectorp;
 extern Lisp_Object Qbool_vector_p;
 extern Lisp_Object Qvector_or_char_table_p, Qwholenump;
 extern Lisp_Object Qwindow;
@@ -1152,7 +1163,7 @@
    and PSEUDOVECTORP cast their pointers to struct vectorlike_header *,
    because when two such pointers potentially alias, a compiler won't
    incorrectly reorder loads and stores to their size fields.  See
-   <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>.  */
+   Bug#8546.  */
 struct vectorlike_header
   {
     /* The only field contains various pieces of information:
@@ -1202,7 +1213,7 @@
     /* This is the size in bits.  */
     EMACS_INT size;
     /* This contains the actual bits, packed into bytes.  */
-    unsigned char data[FLEXIBLE_ARRAY_MEMBER];
+    bits_word data[FLEXIBLE_ARRAY_MEMBER];
   };
 
 INLINE EMACS_INT
@@ -1213,6 +1224,59 @@
   return size;
 }
 
+INLINE bits_word *
+bool_vector_data (Lisp_Object a)
+{
+  return XBOOL_VECTOR (a)->data;
+}
+
+INLINE unsigned char *
+bool_vector_uchar_data (Lisp_Object a)
+{
+  return (unsigned char *) bool_vector_data (a);
+}
+
+/* The number of data words in a bool vector with SIZE bits.  */
+
+INLINE EMACS_INT
+bool_vector_words (EMACS_INT size)
+{
+  eassume (0 <= size && size <= EMACS_INT_MAX - (BITS_PER_BITS_WORD - 1));
+  return (size + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD;
+}
+
+/* True if A's Ith bit is set.  */
+
+INLINE bool
+bool_vector_bitref (Lisp_Object a, EMACS_INT i)
+{
+  eassume (0 <= i && i < bool_vector_size (a));
+  return !! (bool_vector_uchar_data (a)[i / BOOL_VECTOR_BITS_PER_CHAR]
+            & (1 << (i % BOOL_VECTOR_BITS_PER_CHAR)));
+}
+
+INLINE Lisp_Object
+bool_vector_ref (Lisp_Object a, EMACS_INT i)
+{
+  return bool_vector_bitref (a, i) ? Qt : Qnil;
+}
+
+/* Set A's Ith bit to B.  */
+
+INLINE void
+bool_vector_set (Lisp_Object a, EMACS_INT i, bool b)
+{
+  unsigned char *addr;
+
+  eassume (0 <= i && i < bool_vector_size (a));
+  addr = &bool_vector_uchar_data (a)[i / BOOL_VECTOR_BITS_PER_CHAR];
+
+  if (b)
+    *addr |= 1 << (i % BOOL_VECTOR_BITS_PER_CHAR);
+  else
+    *addr &= ~ (1 << (i % BOOL_VECTOR_BITS_PER_CHAR));
+}
+
 /* Some handy constants for calculating sizes
    and offsets, mostly of vectorlike objects.   */
 
@@ -3526,6 +3590,7 @@
                make_number (w), make_number (h));
 }
 
+extern void bool_vector_fill (Lisp_Object, Lisp_Object);
 extern _Noreturn void string_overflow (void);
 extern Lisp_Object make_string (const char *, ptrdiff_t);
 extern Lisp_Object make_formatted_string (char *, const char *, ...)
@@ -4419,10 +4484,6 @@
     return 0;
 }
 
-/* Round x to the next multiple of y.  Does not overflow.  Evaluates
-   arguments repeatedly.  */
-#define ROUNDUP(x,y) ((y)*((x)/(y) + ((x)%(y)!=0)))
-
 INLINE_HEADER_END
 
 #endif /* EMACS_LISP_H */

=== modified file 'src/lread.c'
--- a/src/lread.c       2013-11-04 17:30:33 +0000
+++ b/src/lread.c       2013-11-05 07:11:24 +0000
@@ -2580,6 +2580,7 @@
              EMACS_INT size_in_chars
                = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1)
                   / BOOL_VECTOR_BITS_PER_CHAR);
+             unsigned char *data;
 
              UNREAD (c);
              tmp = read1 (readcharfun, pch, first_in_list);
@@ -2594,10 +2595,11 @@
                invalid_syntax ("#&...");
 
              val = Fmake_bool_vector (length, Qnil);
-             memcpy (XBOOL_VECTOR (val)->data, SDATA (tmp), size_in_chars);
+             data = bool_vector_uchar_data (val);
+             memcpy (data, SDATA (tmp), size_in_chars);
              /* Clear the extraneous bits in the last byte.  */
              if (XINT (length) != size_in_chars * BOOL_VECTOR_BITS_PER_CHAR)
-               XBOOL_VECTOR (val)->data[size_in_chars - 1]
+               data[size_in_chars - 1]
                  &= (1 << (XINT (length) % BOOL_VECTOR_BITS_PER_CHAR)) - 1;
              return val;
            }

=== modified file 'src/print.c'
--- a/src/print.c       2013-10-15 21:03:00 +0000
+++ b/src/print.c       2013-11-05 07:11:24 +0000
@@ -1726,7 +1726,7 @@
          for (i = 0; i < size_in_chars; i++)
            {
              QUIT;
-             c = XBOOL_VECTOR (obj)->data[i];
+             c = bool_vector_uchar_data (obj)[i];
              if (c == '\n' && print_escape_newlines)
                {
                  PRINTCHAR ('\\');


reply via email to

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