aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Colascione2013-09-22 01:31:55 -0800
committerDaniel Colascione2013-09-22 01:31:55 -0800
commit3e0b94e7ff1fc69b077322d672ef5d0b668541c3 (patch)
tree9927abd073960f2460f05a43ae9467cd82c00b9b /src
parent76880d884d87d0bc674249e292ccda70f31cca0e (diff)
downloademacs-3e0b94e7ff1fc69b077322d672ef5d0b668541c3.tar.gz
emacs-3e0b94e7ff1fc69b077322d672ef5d0b668541c3.zip
Add set operations for bool-vector.
http://lists.gnu.org/archive/html/emacs-devel/2013-09/msg00404.html * data.c (Qbool_vector_p): New symbol. (bool_vector_spare_mask,popcount_size_t_generic) (popcount_size_t_msc,popcount_size_t_gcc) (popcount_size_t) (bool_vector_binop_driver) (count_trailing_zero_bits,size_t_to_host_endian) (Fbool_vector_exclusive_or) (Fbool_vector_union) (Fbool_vector_intersection,Fbool_vector_set_difference) (Fbool_vector_subsetp,Fbool_vector_not) (Fbool_vector_count_matches) (Fbool_vector_count_matches_at): New functions. (syms_of_data): Intern new symbol, functions. * alloc.c (bool_vector_payload_bytes): New function. (Fmake_bool_vector): Instead of calling Fmake_vector, which performs redundant initialization and argument checking, just call allocate_vector ourselves. Make sure we clear any terminating padding to zero. (vector_nbytes,sweep_vectors): Use bool_vector_payload_bytes instead of open-coding the size calculation. (vroundup_ct): New macro. (vroundup): Assume argument >= 0; invoke vroundup_ct. * casetab.c (shuffle,set_identity): Change lint_assume to assume. * composite.c (composition_gstring_put_cache): Change lint_assume to assume. * conf_post.h (assume): New macro. (lint_assume): Remove. * dispnew.c (update_frame_1): Change lint_assume to assume. * ftfont.c (ftfont_shape_by_flt): Change lint_assume to assume. * image.c (gif_load): Change lint_assume to assume. * lisp.h (eassert_and_assume): New macro. (Qbool_vector_p): Declare. (CHECK_BOOL_VECTOR,ROUNDUP,BITS_PER_SIZE_T): New macros. (swap16,swap32,swap64): New inline functions. * macfont.c (macfont_shape): Change lint_assume to assume. * ralloc.c: Rename ROUNDUP to PAGE_ROUNDUP throughout. * xsettings.c (parse_settings): Use new swap16 and swap32 from lisp.h instead of file-specific macros.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog42
-rw-r--r--src/alloc.c103
-rw-r--r--src/casetab.c4
-rw-r--r--src/composite.c2
-rw-r--r--src/conf_post.h16
-rw-r--r--src/data.c462
-rw-r--r--src/dispnew.c2
-rw-r--r--src/ftfont.c2
-rw-r--r--src/image.c2
-rw-r--r--src/intervals.c2
-rw-r--r--src/lisp.h50
-rw-r--r--src/macfont.m2
-rw-r--r--src/ralloc.c22
-rw-r--r--src/xsettings.c11
14 files changed, 656 insertions, 66 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 1442650d432..7c3a29c5d86 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,45 @@
12013-09-22 Daniel Colascione <dancol@dancol.org>
2
3 * data.c (Qbool_vector_p): New symbol.
4 (bool_vector_spare_mask,popcount_size_t_generic)
5 (popcount_size_t_msc,popcount_size_t_gcc)
6 (popcount_size_t)
7 (bool_vector_binop_driver)
8 (count_trailing_zero_bits,size_t_to_host_endian)
9 (Fbool_vector_exclusive_or)
10 (Fbool_vector_union)
11 (Fbool_vector_intersection,Fbool_vector_set_difference)
12 (Fbool_vector_subsetp,Fbool_vector_not)
13 (Fbool_vector_count_matches)
14 (Fbool_vector_count_matches_at): New functions.
15 (syms_of_data): Intern new symbol, functions.
16 * alloc.c (bool_vector_payload_bytes): New function.
17 (Fmake_bool_vector): Instead of calling Fmake_vector,
18 which performs redundant initialization and argument checking,
19 just call allocate_vector ourselves. Make sure we clear any
20 terminating padding to zero.
21 (vector_nbytes,sweep_vectors): Use bool_vector_payload_bytes
22 instead of open-coding the size calculation.
23 (vroundup_ct): New macro.
24 (vroundup): Assume argument >= 0; invoke vroundup_ct.
25 * casetab.c (shuffle,set_identity): Change lint_assume to assume.
26 * composite.c (composition_gstring_put_cache): Change
27 lint_assume to assume.
28 * conf_post.h (assume): New macro.
29 (lint_assume): Remove.
30 * dispnew.c (update_frame_1): Change lint_assume to assume.
31 * ftfont.c (ftfont_shape_by_flt): Change lint_assume
32 to assume.
33 * image.c (gif_load): Change lint_assume to assume.
34 * lisp.h (eassert_and_assume): New macro.
35 (Qbool_vector_p): Declare.
36 (CHECK_BOOL_VECTOR,ROUNDUP,BITS_PER_SIZE_T): New macros.
37 (swap16,swap32,swap64): New inline functions.
38 * macfont.c (macfont_shape): Change lint_assume to assume.
39 * ralloc.c: Rename ROUNDUP to PAGE_ROUNDUP throughout.
40 * xsettings.c (parse_settings): Use new swap16 and
41 swap32 from lisp.h instead of file-specific macros.
42
12013-09-22 Eli Zaretskii <eliz@gnu.org> 432013-09-22 Eli Zaretskii <eliz@gnu.org>
2 44
3 * xdisp.c (try_window_id): Don't abort if cursor row could not be 45 * xdisp.c (try_window_id): Don't abort if cursor row could not be
diff --git a/src/alloc.c b/src/alloc.c
index de73ce9bae0..847b3c88bbe 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -2001,6 +2001,35 @@ INIT must be an integer that represents a character. */)
2001 return val; 2001 return val;
2002} 2002}
2003 2003
2004verify (sizeof (size_t) * CHAR_BIT == BITS_PER_SIZE_T);
2005verify ((BITS_PER_SIZE_T & (BITS_PER_SIZE_T - 1)) == 0);
2006
2007static
2008ptrdiff_t
2009bool_vector_payload_bytes (ptrdiff_t nr_bits,
2010 ptrdiff_t* exact_needed_bytes_out)
2011{
2012 ptrdiff_t exact_needed_bytes;
2013 ptrdiff_t needed_bytes;
2014
2015 eassert_and_assume (nr_bits >= 0);
2016
2017 exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT;
2018 needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_SIZE_T) / CHAR_BIT;
2019
2020 if (needed_bytes == 0)
2021 {
2022 /* Always allocate at least one machine word of payload so that
2023 bool-vector operations in data.c don't need a special case
2024 for empty vectors. */
2025 needed_bytes = sizeof (size_t);
2026 }
2027
2028 if (exact_needed_bytes_out != NULL)
2029 *exact_needed_bytes_out = exact_needed_bytes;
2030
2031 return needed_bytes;
2032}
2004 2033
2005DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, 2034DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
2006 doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. 2035 doc: /* Return a new bool-vector of length LENGTH, using INIT for each element.
@@ -2009,37 +2038,43 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */)
2009{ 2038{
2010 register Lisp_Object val; 2039 register Lisp_Object val;
2011 struct Lisp_Bool_Vector *p; 2040 struct Lisp_Bool_Vector *p;
2012 ptrdiff_t length_in_chars; 2041 ptrdiff_t exact_payload_bytes;
2013 EMACS_INT length_in_elts; 2042 ptrdiff_t total_payload_bytes;
2014 int bits_per_value; 2043 ptrdiff_t needed_elements;
2015 int extra_bool_elts = ((bool_header_size - header_size + word_size - 1)
2016 / word_size);
2017 2044
2018 CHECK_NATNUM (length); 2045 CHECK_NATNUM (length);
2046 if (PTRDIFF_MAX < XFASTINT (length))
2047 memory_full (SIZE_MAX);
2019 2048
2020 bits_per_value = sizeof (EMACS_INT) * BOOL_VECTOR_BITS_PER_CHAR; 2049 total_payload_bytes = bool_vector_payload_bytes
2050 (XFASTINT (length), &exact_payload_bytes);
2021 2051
2022 length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value; 2052 eassert_and_assume (exact_payload_bytes <= total_payload_bytes);
2053 eassert_and_assume (0 <= exact_payload_bytes);
2023 2054
2024 val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); 2055 needed_elements = ROUNDUP ((size_t) ((bool_header_size - header_size)
2056 + total_payload_bytes),
2057 word_size) / word_size;
2025 2058
2026 /* No Lisp_Object to trace in there. */ 2059 p = (struct Lisp_Bool_Vector* ) allocate_vector (needed_elements);
2060 XSETVECTOR (val, p);
2027 XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); 2061 XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
2028 2062
2029 p = XBOOL_VECTOR (val);
2030 p->size = XFASTINT (length); 2063 p->size = XFASTINT (length);
2031 2064 if (exact_payload_bytes)
2032 length_in_chars = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1)
2033 / BOOL_VECTOR_BITS_PER_CHAR);
2034 if (length_in_chars)
2035 { 2065 {
2036 memset (p->data, ! NILP (init) ? -1 : 0, length_in_chars); 2066 memset (p->data, ! NILP (init) ? -1 : 0, exact_payload_bytes);
2037 2067
2038 /* Clear any extraneous bits in the last byte. */ 2068 /* Clear any extraneous bits in the last byte. */
2039 p->data[length_in_chars - 1] 2069 p->data[exact_payload_bytes - 1]
2040 &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1; 2070 &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1;
2041 } 2071 }
2042 2072
2073 /* Clear padding at the end. */
2074 memset (p->data + exact_payload_bytes,
2075 0,
2076 total_payload_bytes - exact_payload_bytes);
2077
2043 return val; 2078 return val;
2044} 2079}
2045 2080
@@ -2565,24 +2600,22 @@ enum
2565 roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1) 2600 roundup_size = COMMON_MULTIPLE (word_size, USE_LSB_TAG ? GCALIGNMENT : 1)
2566 }; 2601 };
2567 2602
2568/* ROUNDUP_SIZE must be a power of 2. */
2569verify ((roundup_size & (roundup_size - 1)) == 0);
2570
2571/* Verify assumptions described above. */ 2603/* Verify assumptions described above. */
2572verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); 2604verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0);
2573verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); 2605verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
2574 2606
2575/* Round up X to nearest mult-of-ROUNDUP_SIZE. */ 2607/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */
2576 2608#define vroundup_ct(x) ROUNDUP((size_t)(x), roundup_size)
2577#define vroundup(x) (((x) + (roundup_size - 1)) & ~(roundup_size - 1)) 2609/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */
2610#define vroundup(x) (assume((x) >= 0), vroundup_ct(x))
2578 2611
2579/* Rounding helps to maintain alignment constraints if USE_LSB_TAG. */ 2612/* Rounding helps to maintain alignment constraints if USE_LSB_TAG. */
2580 2613
2581#define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *))) 2614#define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup_ct (sizeof (void *)))
2582 2615
2583/* Size of the minimal vector allocated from block. */ 2616/* Size of the minimal vector allocated from block. */
2584 2617
2585#define VBLOCK_BYTES_MIN vroundup (header_size + sizeof (Lisp_Object)) 2618#define VBLOCK_BYTES_MIN vroundup_ct (header_size + sizeof (Lisp_Object))
2586 2619
2587/* Size of the largest vector allocated from block. */ 2620/* Size of the largest vector allocated from block. */
2588 2621
@@ -2642,7 +2675,7 @@ struct large_vector
2642 struct large_vector *vector; 2675 struct large_vector *vector;
2643#if USE_LSB_TAG 2676#if USE_LSB_TAG
2644 /* We need to maintain ROUNDUP_SIZE alignment for the vector member. */ 2677 /* We need to maintain ROUNDUP_SIZE alignment for the vector member. */
2645 unsigned char c[vroundup (sizeof (struct large_vector *))]; 2678 unsigned char c[vroundup_ct (sizeof (struct large_vector *))];
2646#endif 2679#endif
2647 } next; 2680 } next;
2648 struct Lisp_Vector v; 2681 struct Lisp_Vector v;
@@ -2783,10 +2816,14 @@ vector_nbytes (struct Lisp_Vector *v)
2783 if (size & PSEUDOVECTOR_FLAG) 2816 if (size & PSEUDOVECTOR_FLAG)
2784 { 2817 {
2785 if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) 2818 if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
2786 size = (bool_header_size 2819 {
2787 + (((struct Lisp_Bool_Vector *) v)->size 2820 struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v;
2788 + BOOL_VECTOR_BITS_PER_CHAR - 1) 2821 ptrdiff_t payload_bytes =
2789 / BOOL_VECTOR_BITS_PER_CHAR); 2822 bool_vector_payload_bytes (bv->size, NULL);
2823
2824 eassert_and_assume (payload_bytes >= 0);
2825 size = bool_header_size + ROUNDUP (payload_bytes, word_size);
2826 }
2790 else 2827 else
2791 size = (header_size 2828 size = (header_size
2792 + ((size & PSEUDOVECTOR_SIZE_MASK) 2829 + ((size & PSEUDOVECTOR_SIZE_MASK)
@@ -2886,17 +2923,11 @@ sweep_vectors (void)
2886 total_vectors++; 2923 total_vectors++;
2887 if (vector->header.size & PSEUDOVECTOR_FLAG) 2924 if (vector->header.size & PSEUDOVECTOR_FLAG)
2888 { 2925 {
2889 struct Lisp_Bool_Vector *b = (struct Lisp_Bool_Vector *) vector;
2890
2891 /* All non-bool pseudovectors are small enough to be allocated 2926 /* All non-bool pseudovectors are small enough to be allocated
2892 from vector blocks. This code should be redesigned if some 2927 from vector blocks. This code should be redesigned if some
2893 pseudovector type grows beyond VBLOCK_BYTES_MAX. */ 2928 pseudovector type grows beyond VBLOCK_BYTES_MAX. */
2894 eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR)); 2929 eassert (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_BOOL_VECTOR));
2895 2930 total_vector_slots += vector_nbytes (vector) / word_size;
2896 total_vector_slots
2897 += (bool_header_size
2898 + ((b->size + BOOL_VECTOR_BITS_PER_CHAR - 1)
2899 / BOOL_VECTOR_BITS_PER_CHAR)) / word_size;
2900 } 2931 }
2901 else 2932 else
2902 total_vector_slots 2933 total_vector_slots
diff --git a/src/casetab.c b/src/casetab.c
index b6b1c99c39f..69cd784f4cc 100644
--- a/src/casetab.c
+++ b/src/casetab.c
@@ -205,7 +205,7 @@ set_identity (Lisp_Object table, Lisp_Object c, Lisp_Object elt)
205 from = to = XINT (c); 205 from = to = XINT (c);
206 206
207 to++; 207 to++;
208 lint_assume (to <= MAX_CHAR + 1); 208 assume (to <= MAX_CHAR + 1);
209 for (; from < to; from++) 209 for (; from < to; from++)
210 CHAR_TABLE_SET (table, from, make_number (from)); 210 CHAR_TABLE_SET (table, from, make_number (from));
211 } 211 }
@@ -232,7 +232,7 @@ shuffle (Lisp_Object table, Lisp_Object c, Lisp_Object elt)
232 from = to = XINT (c); 232 from = to = XINT (c);
233 233
234 to++; 234 to++;
235 lint_assume (to <= MAX_CHAR + 1); 235 assume (to <= MAX_CHAR + 1);
236 for (; from < to; from++) 236 for (; from < to; from++)
237 { 237 {
238 Lisp_Object tem = Faref (table, elt); 238 Lisp_Object tem = Faref (table, elt);
diff --git a/src/composite.c b/src/composite.c
index ee4195572a5..47cac715086 100644
--- a/src/composite.c
+++ b/src/composite.c
@@ -674,7 +674,7 @@ composition_gstring_put_cache (Lisp_Object gstring, ptrdiff_t len)
674 len = j; 674 len = j;
675 } 675 }
676 676
677 lint_assume (len <= TYPE_MAXIMUM (ptrdiff_t) - 2); 677 assume (len <= TYPE_MAXIMUM (ptrdiff_t) - 2);
678 copy = Fmake_vector (make_number (len + 2), Qnil); 678 copy = Fmake_vector (make_number (len + 2), Qnil);
679 LGSTRING_SET_HEADER (copy, Fcopy_sequence (header)); 679 LGSTRING_SET_HEADER (copy, Fcopy_sequence (header));
680 for (i = 0; i < len; i++) 680 for (i = 0; i < len; i++)
diff --git a/src/conf_post.h b/src/conf_post.h
index 30a4a5a9422..5f6cf0eca37 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -248,16 +248,24 @@ extern void _DebPrint (const char *fmt, ...);
248# define FLEXIBLE_ARRAY_MEMBER 1 248# define FLEXIBLE_ARRAY_MEMBER 1
249#endif 249#endif
250 250
251/* assume(cond) tells the compiler (and lint) that a certain condition
252 * will always hold, and that it should optimize (or check) accordingly. */
253#if defined lint
254# define assume(cond) ((cond) ? (void) 0 : abort ())
255#elif (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) || __GNUC__ > 4
256# define assume(cond) ((x) || (__builtin_unreachable(), 0))
257#elif defined __MSC_VER
258# define assume(cond) __assume ((cond))
259#else
260# define assume(cond) (0 && (cond))
261#endif
262
251/* Use this to suppress gcc's `...may be used before initialized' warnings. */ 263/* Use this to suppress gcc's `...may be used before initialized' warnings. */
252#ifdef lint 264#ifdef lint
253/* Use CODE only if lint checking is in effect. */ 265/* Use CODE only if lint checking is in effect. */
254# define IF_LINT(Code) Code 266# define IF_LINT(Code) Code
255/* Assume that the expression COND is true. This differs in intent
256 from 'assert', as it is a message from the programmer to the compiler. */
257# define lint_assume(cond) ((cond) ? (void) 0 : abort ())
258#else 267#else
259# define IF_LINT(Code) /* empty */ 268# define IF_LINT(Code) /* empty */
260# define lint_assume(cond) ((void) (0 && (cond)))
261#endif 269#endif
262 270
263/* conf_post.h ends here */ 271/* conf_post.h ends here */
diff --git a/src/data.c b/src/data.c
index 51b0266eca1..5a05e0652ad 100644
--- a/src/data.c
+++ b/src/data.c
@@ -54,6 +54,7 @@ Lisp_Object Qintegerp, Qwholenump, Qsymbolp, Qlistp, Qconsp;
54static Lisp_Object Qnatnump; 54static Lisp_Object Qnatnump;
55Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp; 55Lisp_Object Qstringp, Qarrayp, Qsequencep, Qbufferp;
56Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp; 56Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qvectorp;
57Lisp_Object Qbool_vector_p;
57Lisp_Object Qbuffer_or_string_p; 58Lisp_Object Qbuffer_or_string_p;
58static Lisp_Object Qkeywordp, Qboundp; 59static Lisp_Object Qkeywordp, Qboundp;
59Lisp_Object Qfboundp; 60Lisp_Object Qfboundp;
@@ -2956,6 +2957,457 @@ lowercase l) for small endian machines. */)
2956 return make_number (order); 2957 return make_number (order);
2957} 2958}
2958 2959
2960/* Because we round up the bool vector allocate size to word_size
2961 units, we can safely read past the "end" of the vector in the
2962 operations below. These extra bits are always zero. Also, we
2963 always allocate bool vectors with at least one size_t of storage so
2964 that we don't have to special-case empty bit vectors. */
2965
2966static inline
2967size_t
2968bool_vector_spare_mask (ptrdiff_t nr_bits)
2969{
2970 eassert_and_assume (nr_bits > 0);
2971 return (((size_t) 1) << (nr_bits % BITS_PER_SIZE_T)) - 1;
2972}
2973
2974#if __MSC_VER >= 1500 && (defined _M_IX86 || defined _M_X64)
2975# define USE_MSC_POPCOUNT
2976#elif __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
2977# define USE_GCC_POPCOUNT
2978#else
2979# define NEED_GENERIC_POPCOUNT
2980#endif
2981
2982#ifdef USE_MSC_POPCOUNT
2983#define NEED_GENERIC_POPCOUNT
2984#endif
2985
2986#ifdef NEED_GENERIC_POPCOUNT
2987static inline
2988unsigned int
2989popcount_size_t_generic (size_t val)
2990{
2991 unsigned short j;
2992 unsigned int count = 0;
2993
2994 for (j = 0; j < BITS_PER_SIZE_T; ++j)
2995 count += !!((((size_t) 1) << j) & val);
2996
2997 return count;
2998}
2999#endif
3000
3001#ifdef USE_MSC_POPCOUNT
3002static inline
3003unsigned int
3004popcount_size_t_msc (size_t val)
3005{
3006 unsigned int count;
3007
3008#pragma intrinsic __cpuid
3009 /* While gcc falls back to its own generic code if the machine on
3010 which it's running doesn't support popcount, we need to perform the
3011 detection and fallback ourselves when compiling with Microsoft's
3012 compiler. */
3013
3014 static enum {
3015 popcount_unknown_support,
3016 popcount_use_generic,
3017 popcount_use_intrinsic
3018 } popcount_state;
3019
3020 if (popcount_state == popcount_unknown_support)
3021 {
3022 int cpu_info[4];
3023 __cpuid (cpu_info, 1);
3024 if (cpu_info[2] & (1<<23)) /* See MSDN. */
3025 popcount_state = popcount_use_intrinsic;
3026 else
3027 popcount_state = popcount_use_generic;
3028 }
3029
3030 if (popcount_state == popcount_use_intrinsic)
3031 {
3032# if BITS_PER_SIZE_T == 64
3033# pragma intrinsic __popcnt64
3034 count = __popcnt64 (val);
3035# else
3036# pragma intrinsic __popcnt
3037 count = __popcnt (val);
3038# endif
3039 }
3040 else
3041 count = popcount_size_t_generic (val);
3042
3043 return count;
3044}
3045#endif /* USE_MSC_POPCOUNT */
3046
3047#ifdef USE_GCC_POPCOUNT
3048static inline
3049unsigned int
3050popcount_size_t_gcc (size_t val)
3051{
3052# if BITS_PER_SIZE_T == 64
3053 return __builtin_popcountll (val);
3054# else
3055 return __builtin_popcount (val);
3056# endif
3057}
3058#endif /* USE_GCC_POPCOUNT */
3059
3060static inline
3061unsigned int
3062popcount_size_t(size_t val)
3063{
3064#if defined USE_MSC_POPCOUNT
3065 return popcount_size_t_msc (val);
3066#elif defined USE_GCC_POPCOUNT
3067 return popcount_size_t_gcc (val);
3068#else
3069 return popcount_size_t_generic (val);
3070 #endif
3071}
3072
3073enum bool_vector_op { bool_vector_exclusive_or,
3074 bool_vector_union,
3075 bool_vector_intersection,
3076 bool_vector_set_difference,
3077 bool_vector_subsetp };
3078
3079static inline
3080Lisp_Object
3081bool_vector_binop_driver (Lisp_Object op1,
3082 Lisp_Object op2,
3083 Lisp_Object dest,
3084 enum bool_vector_op op)
3085{
3086 EMACS_INT nr_bits;
3087 size_t *adata, *bdata, *cdata;
3088 ptrdiff_t i;
3089 size_t changed = 0;
3090 size_t mword;
3091 ptrdiff_t nr_words;
3092
3093 CHECK_BOOL_VECTOR (op1);
3094 CHECK_BOOL_VECTOR (op2);
3095
3096 nr_bits = min (XBOOL_VECTOR (op1)->size,
3097 XBOOL_VECTOR (op2)->size);
3098
3099 if (NILP (dest))
3100 {
3101 dest = Fmake_bool_vector (make_number (nr_bits), Qnil);
3102 changed = 1;
3103 }
3104 else
3105 {
3106 CHECK_BOOL_VECTOR (dest);
3107 nr_bits = min (nr_bits, XBOOL_VECTOR (dest)->size);
3108 }
3109
3110 eassert_and_assume (nr_bits >= 0);
3111 nr_words = ROUNDUP(nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T;
3112
3113 adata = (size_t*) XBOOL_VECTOR (dest)->data;
3114 bdata = (size_t*) XBOOL_VECTOR (op1)->data;
3115 cdata = (size_t*) XBOOL_VECTOR (op2)->data;
3116 i = 0;
3117 do
3118 {
3119 if (op == bool_vector_exclusive_or)
3120 mword = bdata[i] ^ cdata[i];
3121 else if (op == bool_vector_union || op == bool_vector_subsetp)
3122 mword = bdata[i] | cdata[i];
3123 else if (op == bool_vector_intersection)
3124 mword = bdata[i] & cdata[i];
3125 else if (op == bool_vector_set_difference)
3126 mword = bdata[i] &~ cdata[i];
3127 else
3128 abort ();
3129
3130 changed |= adata[i] ^ mword;
3131
3132 if (op != bool_vector_subsetp)
3133 adata[i] = mword;
3134
3135 i += 1;
3136 }
3137 while (i < nr_words);
3138 return changed ? dest : Qnil;
3139}
3140
3141/* Compute the number of trailing zero bits in val. If val is zero,
3142 return the number of bits in val. */
3143static inline
3144unsigned int
3145count_trailing_zero_bits (size_t val)
3146{
3147 if (val == 0)
3148 return CHAR_BIT * sizeof (val);
3149
3150#if defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 64
3151 return __builtin_ctzll (val);
3152#elif defined USE_GCC_POPCOUNT && BITS_PER_SIZE_T == 32
3153 return __builtin_ctz (val);
3154#elif __MSC_VER && BITS_PER_SIZE_T == 64
3155# pragma intrinsic _BitScanForward64
3156 {
3157 /* No support test needed: support since 386. */
3158 unsigned long result;
3159 _BitScanForward64 (&result, val);
3160 return (unsigned int) result;
3161 }
3162#elif __MSC_VER && BITS_PER_SIZE_T == 32
3163# pragma intrinsic _BitScanForward
3164 {
3165 /* No support test needed: support since 386. */
3166 unsigned long result;
3167 _BitScanForward (&result, val);
3168 return (unsigned int) result;
3169 }
3170#else
3171 {
3172 unsigned int count;
3173 count = 0;
3174 for(val = ~val; val & 1; val >>= 1)
3175 ++count;
3176
3177 return count;
3178 }
3179#endif
3180}
3181
3182static inline
3183size_t
3184size_t_to_host_endian (size_t val)
3185{
3186#ifdef WORDS_BIGENDIAN
3187# if BITS_PER_SIZE_T == 64
3188 return swap64 (val);
3189# else
3190 return swap32 (val);
3191# endif
3192#else
3193 return val;
3194#endif
3195}
3196
3197DEFUN ("bool-vector-exclusive-or", Fbool_vector_exclusive_or,
3198 Sbool_vector_exclusive_or, 2, 3, 0,
3199 doc: /* Compute C = A ^ B, bitwise exclusive or.
3200A, B, and C must be bool vectors. If C is nil, allocate a new bool
3201vector in which to store the result. Return the destination vector if
3202it changed or nil otherwise. */
3203 )
3204 (Lisp_Object a, Lisp_Object b, Lisp_Object c)
3205{
3206 return bool_vector_binop_driver (a, b, c, bool_vector_exclusive_or);
3207}
3208
3209DEFUN ("bool-vector-union", Fbool_vector_union,
3210 Sbool_vector_union, 2, 3, 0,
3211 doc: /* Compute C = A | B, bitwise or.
3212A, B, and C must be bool vectors. If C is nil, allocate a new bool
3213vector in which to store the result. Return the destination vector if
3214it changed or nil otherwise. */)
3215 (Lisp_Object a, Lisp_Object b, Lisp_Object c)
3216{
3217 return bool_vector_binop_driver (a, b, c, bool_vector_union);
3218}
3219
3220DEFUN ("bool-vector-intersection", Fbool_vector_intersection,
3221 Sbool_vector_intersection, 2, 3, 0,
3222 doc: /* Compute C = A & B, bitwise and.
3223A, B, and C must be bool vectors. If C is nil, allocate a new bool
3224vector in which to store the result. Return the destination vector if
3225it changed or nil otherwise. */)
3226 (Lisp_Object a, Lisp_Object b, Lisp_Object c)
3227{
3228 return bool_vector_binop_driver (a, b, c, bool_vector_intersection);
3229}
3230
3231DEFUN ("bool-vector-set-difference", Fbool_vector_set_difference,
3232 Sbool_vector_set_difference, 2, 3, 0,
3233 doc: /* Compute C = A &~ B, set difference.
3234A, B, and C must be bool vectors. If C is nil, allocate a new bool
3235vector in which to store the result. Return the destination vector if
3236it changed or nil otherwise. */)
3237 (Lisp_Object a, Lisp_Object b, Lisp_Object c)
3238{
3239 return bool_vector_binop_driver (a, b, c, bool_vector_set_difference);
3240}
3241
3242DEFUN ("bool-vector-subsetp", Fbool_vector_subsetp,
3243 Sbool_vector_subsetp, 2, 2, 0,
3244 doc: )
3245 (Lisp_Object a, Lisp_Object b)
3246{
3247 /* Like bool_vector_union, but doesn't modify b. */
3248 return bool_vector_binop_driver (b, a, b, bool_vector_subsetp);
3249}
3250
3251DEFUN ("bool-vector-not", Fbool_vector_not,
3252 Sbool_vector_not, 1, 2, 0,
3253 doc: /* Compute B = ~A.
3254B must be a bool vector. A must be a bool vector or nil.
3255If A is nil, allocate a new bool vector in which to store the result.
3256Return the destination vector. */)
3257 (Lisp_Object a, Lisp_Object b)
3258{
3259 EMACS_INT nr_bits;
3260 size_t *bdata, *adata;
3261 ptrdiff_t i;
3262 size_t mword;
3263
3264 CHECK_BOOL_VECTOR (a);
3265 nr_bits = XBOOL_VECTOR (a)->size;
3266
3267 if (NILP (b))
3268 b = Fmake_bool_vector (make_number (nr_bits), Qnil);
3269 else
3270 {
3271 CHECK_BOOL_VECTOR (b);
3272 nr_bits = min (nr_bits, XBOOL_VECTOR (b)->size);
3273 }
3274
3275 bdata = (size_t*) XBOOL_VECTOR (b)->data;
3276 adata = (size_t*) XBOOL_VECTOR (a)->data;
3277 i = 0;
3278
3279 eassert_and_assume (nr_bits >= 0);
3280
3281 while (i < nr_bits / BITS_PER_SIZE_T)
3282 {
3283 bdata[i] = ~adata[i];
3284 i += 1;
3285 }
3286
3287 if (nr_bits % BITS_PER_SIZE_T)
3288 {
3289 mword = size_t_to_host_endian (adata[i]);
3290 mword = ~mword;
3291 mword &= bool_vector_spare_mask (nr_bits);
3292 bdata[i] = size_t_to_host_endian (mword);
3293 }
3294
3295 return b;
3296}
3297
3298DEFUN ("bool-vector-count-matches", Fbool_vector_count_matches,
3299 Sbool_vector_count_matches, 2, 2, 0,
3300 doc: /* Count how many elements in A equal B.
3301A must be a bool vector. B is a generalized bool. */)
3302 (Lisp_Object a, Lisp_Object b)
3303{
3304 ptrdiff_t count;
3305 EMACS_INT nr_bits;
3306 size_t *adata;
3307 size_t match;
3308 ptrdiff_t i;
3309
3310 CHECK_BOOL_VECTOR (a);
3311
3312 nr_bits = XBOOL_VECTOR (a)->size;
3313 count = 0;
3314 match = NILP (b) ? (size_t) -1 : 0;
3315 adata = (size_t*) XBOOL_VECTOR (a)->data;
3316
3317 eassert_and_assume (nr_bits >= 0);
3318
3319 for(i = 0; i < nr_bits / BITS_PER_SIZE_T; ++i)
3320 count += popcount_size_t (adata[i] ^ match);
3321
3322 /* Mask out trailing parts of final mword. */
3323 if (nr_bits % BITS_PER_SIZE_T)
3324 {
3325 size_t mword = adata[i] ^ match;
3326 mword = size_t_to_host_endian (mword);
3327 count += popcount_size_t (mword & bool_vector_spare_mask (nr_bits));
3328 }
3329
3330 return make_number (count);
3331}
3332
3333DEFUN ("bool-vector-count-matches-at",
3334 Fbool_vector_count_matches_at,
3335 Sbool_vector_count_matches_at, 3, 3, 0,
3336 doc: /* Count how many consecutive elements in A equal B at i.
3337A must be a bool vector. B is a generalized boolean. i is an
3338index into the vector.*/)
3339 (Lisp_Object a, Lisp_Object b, Lisp_Object i)
3340{
3341 ptrdiff_t count;
3342 EMACS_INT nr_bits;
3343 ptrdiff_t offset;
3344 size_t *adata;
3345 size_t twiddle;
3346 size_t mword; /* Machine word. */
3347 ptrdiff_t pos;
3348 ptrdiff_t nr_words;
3349
3350 CHECK_BOOL_VECTOR (a);
3351 CHECK_NATNUM (i);
3352
3353 nr_bits = XBOOL_VECTOR (a)->size;
3354 if (XFASTINT (i) > nr_bits) /* Allow one past the end for convenience */
3355 args_out_of_range (a, i);
3356
3357 adata = (size_t*) XBOOL_VECTOR (a)->data;
3358
3359 assume (nr_bits >= 0);
3360 nr_words = ROUNDUP (nr_bits, BITS_PER_SIZE_T) / BITS_PER_SIZE_T;
3361
3362 pos = XFASTINT (i) / BITS_PER_SIZE_T;
3363 offset = XFASTINT (i) % BITS_PER_SIZE_T;
3364 count = 0;
3365
3366 /* By XORing with twiddle, we transform the problem of "count
3367 consecutive equal values" into "count the zero bits". The latter
3368 operation usually has hardware support. */
3369 twiddle = NILP (b) ? 0 : (size_t) -1;
3370
3371 /* Scan the remainder of the mword at the current offset. */
3372 if (pos < nr_words && offset != 0)
3373 {
3374 mword = size_t_to_host_endian (adata[pos]);
3375 mword ^= twiddle;
3376 mword >>= offset;
3377 count = count_trailing_zero_bits (mword);
3378 count = min (count, BITS_PER_SIZE_T - offset);
3379 pos += 1;
3380 if (count + offset < BITS_PER_SIZE_T)
3381 return make_number (count);
3382 }
3383
3384 /* Scan whole words until we either reach the end of the vector or
3385 find an mword that doesn't completely match. twiddle is
3386 endian-independent. */
3387 while (pos < nr_words && adata[pos] == twiddle)
3388 {
3389 count += BITS_PER_SIZE_T;
3390 ++pos;
3391 }
3392
3393 if (pos < nr_words)
3394 {
3395 /* If we stopped because of a mismatch, see how many bits match
3396 in the current mword. */
3397 mword = size_t_to_host_endian (adata[pos]);
3398 mword ^= twiddle;
3399 count += count_trailing_zero_bits (mword);
3400 }
3401 else if (nr_bits % BITS_PER_SIZE_T != 0)
3402 {
3403 /* If we hit the end, we might have overshot our count. Reduce
3404 the total by the number of spare bits at the end of the
3405 vector. */
3406 count -= BITS_PER_SIZE_T - nr_bits % BITS_PER_SIZE_T;
3407 }
3408
3409 return make_number (count);
3410}
2959 3411
2960 3412
2961void 3413void
@@ -3005,6 +3457,7 @@ syms_of_data (void)
3005 DEFSYM (Qsequencep, "sequencep"); 3457 DEFSYM (Qsequencep, "sequencep");
3006 DEFSYM (Qbufferp, "bufferp"); 3458 DEFSYM (Qbufferp, "bufferp");
3007 DEFSYM (Qvectorp, "vectorp"); 3459 DEFSYM (Qvectorp, "vectorp");
3460 DEFSYM (Qbool_vector_p, "bool-vector-p");
3008 DEFSYM (Qchar_or_string_p, "char-or-string-p"); 3461 DEFSYM (Qchar_or_string_p, "char-or-string-p");
3009 DEFSYM (Qmarkerp, "markerp"); 3462 DEFSYM (Qmarkerp, "markerp");
3010 DEFSYM (Qbuffer_or_string_p, "buffer-or-string-p"); 3463 DEFSYM (Qbuffer_or_string_p, "buffer-or-string-p");
@@ -3222,6 +3675,15 @@ syms_of_data (void)
3222 defsubr (&Ssubr_arity); 3675 defsubr (&Ssubr_arity);
3223 defsubr (&Ssubr_name); 3676 defsubr (&Ssubr_name);
3224 3677
3678 defsubr (&Sbool_vector_exclusive_or);
3679 defsubr (&Sbool_vector_union);
3680 defsubr (&Sbool_vector_intersection);
3681 defsubr (&Sbool_vector_set_difference);
3682 defsubr (&Sbool_vector_not);
3683 defsubr (&Sbool_vector_subsetp);
3684 defsubr (&Sbool_vector_count_matches);
3685 defsubr (&Sbool_vector_count_matches_at);
3686
3225 set_symbol_function (Qwholenump, XSYMBOL (Qnatnump)->function); 3687 set_symbol_function (Qwholenump, XSYMBOL (Qnatnump)->function);
3226 3688
3227 DEFVAR_LISP ("most-positive-fixnum", Vmost_positive_fixnum, 3689 DEFVAR_LISP ("most-positive-fixnum", Vmost_positive_fixnum,
diff --git a/src/dispnew.c b/src/dispnew.c
index 5bdc84f1b1d..ed7349a4507 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -4451,7 +4451,7 @@ update_frame_1 (struct frame *f, bool force_p, bool inhibit_id_p)
4451 } 4451 }
4452 } 4452 }
4453 4453
4454 lint_assume (0 <= FRAME_LINES (f)); 4454 assume (0 <= FRAME_LINES (f));
4455 pause_p = 0 < i && i < FRAME_LINES (f) - 1; 4455 pause_p = 0 < i && i < FRAME_LINES (f) - 1;
4456 4456
4457 /* Now just clean up termcap drivers and set cursor, etc. */ 4457 /* Now just clean up termcap drivers and set cursor, etc. */
diff --git a/src/ftfont.c b/src/ftfont.c
index 3636f86f5c4..4e58d83fd64 100644
--- a/src/ftfont.c
+++ b/src/ftfont.c
@@ -2425,7 +2425,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
2425 } 2425 }
2426 2426
2427 len = i; 2427 len = i;
2428 lint_assume (len <= STRING_BYTES_BOUND); 2428 assume (len <= STRING_BYTES_BOUND);
2429 2429
2430 if (with_variation_selector) 2430 if (with_variation_selector)
2431 { 2431 {
diff --git a/src/image.c b/src/image.c
index e3159533664..e429830cc96 100644
--- a/src/image.c
+++ b/src/image.c
@@ -7523,7 +7523,7 @@ gif_load (struct frame *f, struct image *img)
7523 { 7523 {
7524 while (subimg_height <= row) 7524 while (subimg_height <= row)
7525 { 7525 {
7526 lint_assume (pass < 3); 7526 assume (pass < 3);
7527 row = interlace_start[++pass]; 7527 row = interlace_start[++pass];
7528 } 7528 }
7529 7529
diff --git a/src/intervals.c b/src/intervals.c
index 66b486e1422..69a33867283 100644
--- a/src/intervals.c
+++ b/src/intervals.c
@@ -1405,7 +1405,7 @@ offset_intervals (struct buffer *buffer, ptrdiff_t start, ptrdiff_t length)
1405 start, length); 1405 start, length);
1406 else 1406 else
1407 { 1407 {
1408 lint_assume (- TYPE_MAXIMUM (ptrdiff_t) <= length); 1408 assume (- TYPE_MAXIMUM (ptrdiff_t) <= length);
1409 adjust_intervals_for_deletion (buffer, start, -length); 1409 adjust_intervals_for_deletion (buffer, start, -length);
1410 } 1410 }
1411} 1411}
diff --git a/src/lisp.h b/src/lisp.h
index bd09cab5a75..0fffea57578 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -131,6 +131,13 @@ extern bool suppress_checking EXTERNALLY_VISIBLE;
131 ? (void) 0 \ 131 ? (void) 0 \
132 : die (# cond, __FILE__, __LINE__)) 132 : die (# cond, __FILE__, __LINE__))
133#endif /* ENABLE_CHECKING */ 133#endif /* ENABLE_CHECKING */
134
135/* When checking is enabled, identical to eassert. When checking is
136 * disabled, instruct the compiler (when the compiler has such
137 * capability) to assume that cond is true and optimize
138 * accordingly. */
139#define eassert_and_assume(cond) (eassert (cond), assume (cond))
140
134 141
135/* Use the configure flag --enable-check-lisp-object-type to make 142/* Use the configure flag --enable-check-lisp-object-type to make
136 Lisp_Object use a struct type instead of the default int. The flag 143 Lisp_Object use a struct type instead of the default int. The flag
@@ -730,6 +737,7 @@ extern int char_table_translate (Lisp_Object, int);
730extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p; 737extern Lisp_Object Qarrayp, Qbufferp, Qbuffer_or_string_p, Qchar_table_p;
731extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil; 738extern Lisp_Object Qconsp, Qfloatp, Qintegerp, Qlambda, Qlistp, Qmarkerp, Qnil;
732extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qvectorp; 739extern Lisp_Object Qnumberp, Qstringp, Qsymbolp, Qvectorp;
740extern Lisp_Object Qbool_vector_p;
733extern Lisp_Object Qvector_or_char_table_p, Qwholenump; 741extern Lisp_Object Qvector_or_char_table_p, Qwholenump;
734extern Lisp_Object Qwindow; 742extern Lisp_Object Qwindow;
735extern Lisp_Object Ffboundp (Lisp_Object); 743extern Lisp_Object Ffboundp (Lisp_Object);
@@ -2359,6 +2367,11 @@ CHECK_VECTOR (Lisp_Object x)
2359 CHECK_TYPE (VECTORP (x), Qvectorp, x); 2367 CHECK_TYPE (VECTORP (x), Qvectorp, x);
2360} 2368}
2361INLINE void 2369INLINE void
2370CHECK_BOOL_VECTOR (Lisp_Object x)
2371{
2372 CHECK_TYPE (BOOL_VECTOR_P (x), Qbool_vector_p, x);
2373}
2374INLINE void
2362CHECK_VECTOR_OR_STRING (Lisp_Object x) 2375CHECK_VECTOR_OR_STRING (Lisp_Object x)
2363{ 2376{
2364 CHECK_TYPE (VECTORP (x) || STRINGP (x), Qarrayp, x); 2377 CHECK_TYPE (VECTORP (x) || STRINGP (x), Qarrayp, x);
@@ -4347,6 +4360,43 @@ functionp (Lisp_Object object)
4347 return 0; 4360 return 0;
4348} 4361}
4349 4362
4363INLINE
4364uint16_t
4365swap16 (uint16_t val)
4366{
4367 return (val << 8) | (val & 0xFF);
4368}
4369
4370INLINE
4371uint32_t
4372swap32 (uint32_t val)
4373{
4374 uint32_t low = swap16 (val & 0xFFFF);
4375 uint32_t high = swap16 (val >> 16);
4376 return (low << 16) | high;
4377}
4378
4379#ifdef UINT64_MAX
4380INLINE
4381uint64_t
4382swap64 (uint64_t val)
4383{
4384 uint64_t low = swap32 (val & 0xFFFFFFFF);
4385 uint64_t high = swap32 (val >> 32);
4386 return (low << 32) | high;
4387}
4388#endif
4389
4390#if ((SIZE_MAX >> 31) >> 1) & 1
4391# define BITS_PER_SIZE_T 64
4392#else
4393# define BITS_PER_SIZE_T 32
4394#endif
4395
4396/* Round x to the next multiple of y. Does not overflow. Evaluates
4397 arguments repeatedly. */
4398#define ROUNDUP(x,y) ((y)*((x)/(y) + ((x)%(y)!=0)))
4399
4350INLINE_HEADER_END 4400INLINE_HEADER_END
4351 4401
4352#endif /* EMACS_LISP_H */ 4402#endif /* EMACS_LISP_H */
diff --git a/src/macfont.m b/src/macfont.m
index 2a6d219d059..ab5029743ef 100644
--- a/src/macfont.m
+++ b/src/macfont.m
@@ -2817,7 +2817,7 @@ macfont_shape (Lisp_Object lgstring)
2817 } 2817 }
2818 2818
2819 len = i; 2819 len = i;
2820 lint_assume (len <= TYPE_MAXIMUM (EMACS_INT) - 2); 2820 assume (len <= TYPE_MAXIMUM (EMACS_INT) - 2);
2821 2821
2822 if (INT_MAX / 2 < len) 2822 if (INT_MAX / 2 < len)
2823 memory_full (SIZE_MAX); 2823 memory_full (SIZE_MAX);
diff --git a/src/ralloc.c b/src/ralloc.c
index 5f25ef2c320..5b7d6a512d7 100644
--- a/src/ralloc.c
+++ b/src/ralloc.c
@@ -85,7 +85,7 @@ static int extra_bytes;
85/* Macros for rounding. Note that rounding to any value is possible 85/* Macros for rounding. Note that rounding to any value is possible
86 by changing the definition of PAGE. */ 86 by changing the definition of PAGE. */
87#define PAGE (getpagesize ()) 87#define PAGE (getpagesize ())
88#define ROUNDUP(size) (((size_t) (size) + page_size - 1) \ 88#define PAGE_ROUNDUP(size) (((size_t) (size) + page_size - 1) \
89 & ~((size_t) (page_size - 1))) 89 & ~((size_t) (page_size - 1)))
90 90
91#define MEM_ALIGN sizeof (double) 91#define MEM_ALIGN sizeof (double)
@@ -281,7 +281,7 @@ obtain (void *address, size_t size)
281 Get some extra, so we can come here less often. */ 281 Get some extra, so we can come here less often. */
282 282
283 get = size + extra_bytes - already_available; 283 get = size + extra_bytes - already_available;
284 get = (char *) ROUNDUP ((char *) last_heap->end + get) 284 get = (char *) PAGE_ROUNDUP ((char *) last_heap->end + get)
285 - (char *) last_heap->end; 285 - (char *) last_heap->end;
286 286
287 if (real_morecore (get) != last_heap->end) 287 if (real_morecore (get) != last_heap->end)
@@ -344,7 +344,7 @@ relinquish (void)
344 else 344 else
345 { 345 {
346 excess = ((char *) last_heap->end 346 excess = ((char *) last_heap->end
347 - (char *) ROUNDUP ((char *) last_heap->end - excess)); 347 - (char *) PAGE_ROUNDUP ((char *) last_heap->end - excess));
348 /* If the system doesn't want that much memory back, leave 348 /* If the system doesn't want that much memory back, leave
349 the end of the last heap unchanged to reflect that. This 349 the end of the last heap unchanged to reflect that. This
350 can occur if break_value is still within the original 350 can occur if break_value is still within the original
@@ -768,9 +768,9 @@ r_alloc_sbrk (ptrdiff_t size)
768 not always find a space which is contiguous to the previous. */ 768 not always find a space which is contiguous to the previous. */
769 void *new_bloc_start; 769 void *new_bloc_start;
770 heap_ptr h = first_heap; 770 heap_ptr h = first_heap;
771 size_t get = ROUNDUP (size); 771 size_t get = PAGE_ROUNDUP (size);
772 772
773 address = (void *) ROUNDUP (virtual_break_value); 773 address = (void *) PAGE_ROUNDUP (virtual_break_value);
774 774
775 /* Search the list upward for a heap which is large enough. */ 775 /* Search the list upward for a heap which is large enough. */
776 while ((char *) h->end < (char *) MEM_ROUNDUP ((char *) address + get)) 776 while ((char *) h->end < (char *) MEM_ROUNDUP ((char *) address + get))
@@ -778,7 +778,7 @@ r_alloc_sbrk (ptrdiff_t size)
778 h = h->next; 778 h = h->next;
779 if (h == NIL_HEAP) 779 if (h == NIL_HEAP)
780 break; 780 break;
781 address = (void *) ROUNDUP (h->start); 781 address = (void *) PAGE_ROUNDUP (h->start);
782 } 782 }
783 783
784 /* If not found, obtain more space. */ 784 /* If not found, obtain more space. */
@@ -790,9 +790,9 @@ r_alloc_sbrk (ptrdiff_t size)
790 return 0; 790 return 0;
791 791
792 if (first_heap == last_heap) 792 if (first_heap == last_heap)
793 address = (void *) ROUNDUP (virtual_break_value); 793 address = (void *) PAGE_ROUNDUP (virtual_break_value);
794 else 794 else
795 address = (void *) ROUNDUP (last_heap->start); 795 address = (void *) PAGE_ROUNDUP (last_heap->start);
796 h = last_heap; 796 h = last_heap;
797 } 797 }
798 798
@@ -1054,7 +1054,7 @@ r_alloc_check (void)
1054 for (h = first_heap; h; h = h->next) 1054 for (h = first_heap; h; h = h->next)
1055 { 1055 {
1056 assert (h->prev == ph); 1056 assert (h->prev == ph);
1057 assert ((void *) ROUNDUP (h->end) == h->end); 1057 assert ((void *) PAGE_ROUNDUP (h->end) == h->end);
1058#if 0 /* ??? The code in ralloc.c does not really try to ensure 1058#if 0 /* ??? The code in ralloc.c does not really try to ensure
1059 the heap start has any sort of alignment. 1059 the heap start has any sort of alignment.
1060 Perhaps it should. */ 1060 Perhaps it should. */
@@ -1190,7 +1190,7 @@ r_alloc_init (void)
1190 if (break_value == NULL) 1190 if (break_value == NULL)
1191 emacs_abort (); 1191 emacs_abort ();
1192 1192
1193 extra_bytes = ROUNDUP (50000); 1193 extra_bytes = PAGE_ROUNDUP (50000);
1194#endif 1194#endif
1195 1195
1196#ifdef DOUG_LEA_MALLOC 1196#ifdef DOUG_LEA_MALLOC
@@ -1212,7 +1212,7 @@ r_alloc_init (void)
1212#endif 1212#endif
1213 1213
1214#ifndef SYSTEM_MALLOC 1214#ifndef SYSTEM_MALLOC
1215 first_heap->end = (void *) ROUNDUP (first_heap->start); 1215 first_heap->end = (void *) PAGE_ROUNDUP (first_heap->start);
1216 1216
1217 /* The extra call to real_morecore guarantees that the end of the 1217 /* The extra call to real_morecore guarantees that the end of the
1218 address space is a multiple of page_size, even if page_size is 1218 address space is a multiple of page_size, even if page_size is
diff --git a/src/xsettings.c b/src/xsettings.c
index bdf9f2876be..8fe82fec74b 100644
--- a/src/xsettings.c
+++ b/src/xsettings.c
@@ -336,9 +336,6 @@ get_prop_window (struct x_display_info *dpyinfo)
336 XUngrabServer (dpy); 336 XUngrabServer (dpy);
337} 337}
338 338
339#define SWAP32(nr) (((nr) << 24) | (((nr) << 8) & 0xff0000) \
340 | (((nr) >> 8) & 0xff00) | ((nr) >> 24))
341#define SWAP16(nr) (((nr) << 8) | ((nr) >> 8))
342#define PAD(nr) (((nr) + 3) & ~3) 339#define PAD(nr) (((nr) + 3) & ~3)
343 340
344/* Parse xsettings and extract those that deal with Xft. 341/* Parse xsettings and extract those that deal with Xft.
@@ -408,7 +405,7 @@ parse_settings (unsigned char *prop,
408 405
409 if (bytes < 12) return BadLength; 406 if (bytes < 12) return BadLength;
410 memcpy (&n_settings, prop+8, 4); 407 memcpy (&n_settings, prop+8, 4);
411 if (my_bo != that_bo) n_settings = SWAP32 (n_settings); 408 if (my_bo != that_bo) n_settings = swap32 (n_settings);
412 bytes_parsed = 12; 409 bytes_parsed = 12;
413 410
414 memset (settings, 0, sizeof (*settings)); 411 memset (settings, 0, sizeof (*settings));
@@ -430,7 +427,7 @@ parse_settings (unsigned char *prop,
430 427
431 memcpy (&nlen, prop+bytes_parsed, 2); 428 memcpy (&nlen, prop+bytes_parsed, 2);
432 bytes_parsed += 2; 429 bytes_parsed += 2;
433 if (my_bo != that_bo) nlen = SWAP16 (nlen); 430 if (my_bo != that_bo) nlen = swap16 (nlen);
434 if (bytes_parsed+nlen > bytes) return BadLength; 431 if (bytes_parsed+nlen > bytes) return BadLength;
435 to_cpy = nlen > 127 ? 127 : nlen; 432 to_cpy = nlen > 127 ? 127 : nlen;
436 memcpy (name, prop+bytes_parsed, to_cpy); 433 memcpy (name, prop+bytes_parsed, to_cpy);
@@ -457,7 +454,7 @@ parse_settings (unsigned char *prop,
457 if (want_this) 454 if (want_this)
458 { 455 {
459 memcpy (&ival, prop+bytes_parsed, 4); 456 memcpy (&ival, prop+bytes_parsed, 4);
460 if (my_bo != that_bo) ival = SWAP32 (ival); 457 if (my_bo != that_bo) ival = swap32 (ival);
461 } 458 }
462 bytes_parsed += 4; 459 bytes_parsed += 4;
463 break; 460 break;
@@ -466,7 +463,7 @@ parse_settings (unsigned char *prop,
466 if (bytes_parsed+4 > bytes) return BadLength; 463 if (bytes_parsed+4 > bytes) return BadLength;
467 memcpy (&vlen, prop+bytes_parsed, 4); 464 memcpy (&vlen, prop+bytes_parsed, 4);
468 bytes_parsed += 4; 465 bytes_parsed += 4;
469 if (my_bo != that_bo) vlen = SWAP32 (vlen); 466 if (my_bo != that_bo) vlen = swap32 (vlen);
470 if (want_this) 467 if (want_this)
471 { 468 {
472 to_cpy = vlen > 127 ? 127 : vlen; 469 to_cpy = vlen > 127 ? 127 : vlen;