diff options
| author | Paul Eggert | 2013-11-13 18:39:28 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-11-13 18:39:28 -0800 |
| commit | 2cf00efc1b0db0ddc26fa14239026dd2d12c7d59 (patch) | |
| tree | 1bd3fcc233230eb7e2ffdee78da9433b3915623e /src | |
| parent | d672ac3c611453c624948ed8cc2ced65cadc3400 (diff) | |
| download | emacs-2cf00efc1b0db0ddc26fa14239026dd2d12c7d59.tar.gz emacs-2cf00efc1b0db0ddc26fa14239026dd2d12c7d59.zip | |
Simplify, port and tune bool vector implementation.
* configure.ac (BITSIZEOF_SIZE_T, SIZEOF_SIZE_T): Remove.
* src/alloc.c (bool_vector_exact_payload_bytes)
(bool_vector_payload_bytes): Remove.
(bool_vector_fill): Return its argument.
* src/alloc.c (bool_vector_fill):
* src/lread.c (read1):
* src/print.c (print_object):
Simplify by using bool_vector_bytes.
* src/alloc.c (make_uninit_bool_vector):
New function, broken out from Fmake_bool_vector.
(Fmake_bool_vector): Use it. Use tail call.
(make_uninit_bool_vector, vector_nbytes): Simplify size calculations.
* src/data.c (BITS_PER_ULL): New constant.
(ULLONG_MAX, count_one_bits_ll): Fall back on long counterparts
if long long versions don't exist.
(shift_right_ull): New function.
(count_one_bits_word): New function, replacing popcount_bits_word
macro. Don't assume that bits_word is no wider than long long.
(count_one_bits_word, count_trailing_zero_bits):
Don't assume that bits_word is no wider than long long.
* src/data.c (bool_vector_binop_driver, bool_vector_not):
* src/fns.c (Fcopy_sequence):
* src/lread.c (read1):
Create an uninitialized destination, to avoid needless work.
(internal_equal): Simplify.
(Ffillarray): Prefer tail call.
* src/data.c (bool_vector_binop_driver): Don't assume bit vectors always
contain at least one word.
(bits_word_to_host_endian): Prefer if to #if. Don't assume
chars are narrower than ints.
* src/data.c (Fbool_vector_count_matches, Fbool_vector_count_matches_at):
* src/fns.c (Fcopy_sequence):
Simplify and tune.
* src/lisp.h (bits_word, BITS_WORD_MAX, BITS_PER_BITS_WORD):
Don't try to port to hosts where bits_word values have holes; the
code wouldn't work there anyway. Verify this assumption, though.
(bool_vector_bytes): New function.
(make_uninit_bool_vector): New decl.
(bool_vector_fill): Now returns Lisp_Object.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 40 | ||||
| -rw-r--r-- | src/alloc.c | 87 | ||||
| -rw-r--r-- | src/data.c | 155 | ||||
| -rw-r--r-- | src/fns.c | 16 | ||||
| -rw-r--r-- | src/lisp.h | 24 | ||||
| -rw-r--r-- | src/lread.c | 6 | ||||
| -rw-r--r-- | src/print.c | 3 |
7 files changed, 196 insertions, 135 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index 3861449cf5a..290b83a7ecf 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,45 @@ | |||
| 1 | 2013-11-14 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2013-11-14 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Simplify, port and tune bool vector implementation. | ||
| 4 | * alloc.c (bool_vector_exact_payload_bytes) | ||
| 5 | (bool_vector_payload_bytes): Remove. | ||
| 6 | (bool_vector_fill): Return its argument. | ||
| 7 | * alloc.c (bool_vector_fill): | ||
| 8 | * lread.c (read1): | ||
| 9 | * print.c (print_object): | ||
| 10 | Simplify by using bool_vector_bytes. | ||
| 11 | * alloc.c (make_uninit_bool_vector): | ||
| 12 | New function, broken out from Fmake_bool_vector. | ||
| 13 | (Fmake_bool_vector): Use it. Use tail call. | ||
| 14 | (make_uninit_bool_vector, vector_nbytes): Simplify size calculations. | ||
| 15 | * data.c (BITS_PER_ULL): New constant. | ||
| 16 | (ULLONG_MAX, count_one_bits_ll): Fall back on long counterparts | ||
| 17 | if long long versions don't exist. | ||
| 18 | (shift_right_ull): New function. | ||
| 19 | (count_one_bits_word): New function, replacing popcount_bits_word | ||
| 20 | macro. Don't assume that bits_word is no wider than long long. | ||
| 21 | (count_one_bits_word, count_trailing_zero_bits): | ||
| 22 | Don't assume that bits_word is no wider than long long. | ||
| 23 | * data.c (bool_vector_binop_driver, bool_vector_not): | ||
| 24 | * fns.c (Fcopy_sequence): | ||
| 25 | * lread.c (read1): | ||
| 26 | Create an uninitialized destination, to avoid needless work. | ||
| 27 | (internal_equal): Simplify. | ||
| 28 | (Ffillarray): Prefer tail call. | ||
| 29 | * data.c (bool_vector_binop_driver): Don't assume bit vectors always | ||
| 30 | contain at least one word. | ||
| 31 | (bits_word_to_host_endian): Prefer if to #if. Don't assume | ||
| 32 | chars are narrower than ints. | ||
| 33 | * data.c (Fbool_vector_count_matches, Fbool_vector_count_matches_at): | ||
| 34 | * fns.c (Fcopy_sequence): | ||
| 35 | Simplify and tune. | ||
| 36 | * lisp.h (bits_word, BITS_WORD_MAX, BITS_PER_BITS_WORD): | ||
| 37 | Don't try to port to hosts where bits_word values have holes; the | ||
| 38 | code wouldn't work there anyway. Verify this assumption, though. | ||
| 39 | (bool_vector_bytes): New function. | ||
| 40 | (make_uninit_bool_vector): New decl. | ||
| 41 | (bool_vector_fill): Now returns Lisp_Object. | ||
| 42 | |||
| 3 | * xfns.c (xic_create_fontsetname): | 43 | * xfns.c (xic_create_fontsetname): |
| 4 | * xrdb.c (gethomedir): Prefer tail calls. | 44 | * xrdb.c (gethomedir): Prefer tail calls. |
| 5 | 45 | ||
diff --git a/src/alloc.c b/src/alloc.c index bc5ed6d94bb..f12fdc5c861 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2041,26 +2041,10 @@ INIT must be an integer that represents a character. */) | |||
| 2041 | return val; | 2041 | return val; |
| 2042 | } | 2042 | } |
| 2043 | 2043 | ||
| 2044 | static EMACS_INT | 2044 | /* Fill A with 1 bits if INIT is non-nil, and with 0 bits otherwise. |
| 2045 | bool_vector_exact_payload_bytes (EMACS_INT nbits) | 2045 | Return A. */ |
| 2046 | { | ||
| 2047 | eassume (0 <= nbits); | ||
| 2048 | return (nbits + BOOL_VECTOR_BITS_PER_CHAR - 1) / BOOL_VECTOR_BITS_PER_CHAR; | ||
| 2049 | } | ||
| 2050 | |||
| 2051 | static EMACS_INT | ||
| 2052 | bool_vector_payload_bytes (EMACS_INT nbits) | ||
| 2053 | { | ||
| 2054 | EMACS_INT exact_needed_bytes = bool_vector_exact_payload_bytes (nbits); | ||
| 2055 | 2046 | ||
| 2056 | /* Always allocate at least one machine word of payload so that | 2047 | Lisp_Object |
| 2057 | bool-vector operations in data.c don't need a special case | ||
| 2058 | for empty vectors. */ | ||
| 2059 | return ROUNDUP (exact_needed_bytes + !exact_needed_bytes, | ||
| 2060 | sizeof (bits_word)); | ||
| 2061 | } | ||
| 2062 | |||
| 2063 | void | ||
| 2064 | bool_vector_fill (Lisp_Object a, Lisp_Object init) | 2048 | bool_vector_fill (Lisp_Object a, Lisp_Object init) |
| 2065 | { | 2049 | { |
| 2066 | EMACS_INT nbits = bool_vector_size (a); | 2050 | EMACS_INT nbits = bool_vector_size (a); |
| @@ -2068,48 +2052,50 @@ bool_vector_fill (Lisp_Object a, Lisp_Object init) | |||
| 2068 | { | 2052 | { |
| 2069 | unsigned char *data = bool_vector_uchar_data (a); | 2053 | unsigned char *data = bool_vector_uchar_data (a); |
| 2070 | int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; | 2054 | int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1; |
| 2071 | ptrdiff_t nbytes = ((nbits + BOOL_VECTOR_BITS_PER_CHAR - 1) | 2055 | ptrdiff_t nbytes = bool_vector_bytes (nbits); |
| 2072 | / BOOL_VECTOR_BITS_PER_CHAR); | ||
| 2073 | int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); | 2056 | int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)); |
| 2074 | memset (data, pattern, nbytes - 1); | 2057 | memset (data, pattern, nbytes - 1); |
| 2075 | data[nbytes - 1] = pattern & last_mask; | 2058 | data[nbytes - 1] = pattern & last_mask; |
| 2076 | } | 2059 | } |
| 2060 | return a; | ||
| 2077 | } | 2061 | } |
| 2078 | 2062 | ||
| 2079 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | 2063 | /* Return a newly allocated, uninitialized bool vector of size NBITS. */ |
| 2080 | doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. | 2064 | |
| 2081 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) | 2065 | Lisp_Object |
| 2082 | (Lisp_Object length, Lisp_Object init) | 2066 | make_uninit_bool_vector (EMACS_INT nbits) |
| 2083 | { | 2067 | { |
| 2084 | Lisp_Object val; | 2068 | Lisp_Object val; |
| 2085 | struct Lisp_Bool_Vector *p; | 2069 | struct Lisp_Bool_Vector *p; |
| 2086 | EMACS_INT exact_payload_bytes, total_payload_bytes, needed_elements; | 2070 | EMACS_INT word_bytes, needed_elements; |
| 2087 | 2071 | word_bytes = bool_vector_words (nbits) * sizeof (bits_word); | |
| 2088 | CHECK_NATNUM (length); | 2072 | needed_elements = ((bool_header_size - header_size + word_bytes |
| 2089 | |||
| 2090 | exact_payload_bytes = bool_vector_exact_payload_bytes (XFASTINT (length)); | ||
| 2091 | total_payload_bytes = bool_vector_payload_bytes (XFASTINT (length)); | ||
| 2092 | |||
| 2093 | needed_elements = ((bool_header_size - header_size + total_payload_bytes | ||
| 2094 | + word_size - 1) | 2073 | + word_size - 1) |
| 2095 | / word_size); | 2074 | / word_size); |
| 2096 | |||
| 2097 | p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); | 2075 | p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); |
| 2098 | XSETVECTOR (val, p); | 2076 | XSETVECTOR (val, p); |
| 2099 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); | 2077 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2100 | 2078 | p->size = nbits; | |
| 2101 | p->size = XFASTINT (length); | ||
| 2102 | bool_vector_fill (val, init); | ||
| 2103 | 2079 | ||
| 2104 | /* Clear padding at the end. */ | 2080 | /* Clear padding at the end. */ |
| 2105 | eassume (exact_payload_bytes <= total_payload_bytes); | 2081 | if (nbits) |
| 2106 | memset (bool_vector_uchar_data (val) + exact_payload_bytes, | 2082 | p->data[bool_vector_words (nbits) - 1] = 0; |
| 2107 | 0, | ||
| 2108 | total_payload_bytes - exact_payload_bytes); | ||
| 2109 | 2083 | ||
| 2110 | return val; | 2084 | return val; |
| 2111 | } | 2085 | } |
| 2112 | 2086 | ||
| 2087 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | ||
| 2088 | doc: /* Return a new bool-vector of length LENGTH, using INIT for each element. | ||
| 2089 | LENGTH must be a number. INIT matters only in whether it is t or nil. */) | ||
| 2090 | (Lisp_Object length, Lisp_Object init) | ||
| 2091 | { | ||
| 2092 | Lisp_Object val; | ||
| 2093 | |||
| 2094 | CHECK_NATNUM (length); | ||
| 2095 | val = make_uninit_bool_vector (XFASTINT (length)); | ||
| 2096 | return bool_vector_fill (val, init); | ||
| 2097 | } | ||
| 2098 | |||
| 2113 | 2099 | ||
| 2114 | /* Make a string from NBYTES bytes at CONTENTS, and compute the number | 2100 | /* Make a string from NBYTES bytes at CONTENTS, and compute the number |
| 2115 | of characters from the contents. This string may be unibyte or | 2101 | of characters from the contents. This string may be unibyte or |
| @@ -2858,24 +2844,27 @@ static ptrdiff_t | |||
| 2858 | vector_nbytes (struct Lisp_Vector *v) | 2844 | vector_nbytes (struct Lisp_Vector *v) |
| 2859 | { | 2845 | { |
| 2860 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; | 2846 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; |
| 2847 | ptrdiff_t nwords; | ||
| 2861 | 2848 | ||
| 2862 | if (size & PSEUDOVECTOR_FLAG) | 2849 | if (size & PSEUDOVECTOR_FLAG) |
| 2863 | { | 2850 | { |
| 2864 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) | 2851 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) |
| 2865 | { | 2852 | { |
| 2866 | struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; | 2853 | struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; |
| 2867 | ptrdiff_t payload_bytes = bool_vector_payload_bytes (bv->size); | 2854 | ptrdiff_t word_bytes = (bool_vector_words (bv->size) |
| 2868 | size = bool_header_size + payload_bytes; | 2855 | * sizeof (bits_word)); |
| 2856 | ptrdiff_t boolvec_bytes = bool_header_size + word_bytes; | ||
| 2857 | verify (header_size <= bool_header_size); | ||
| 2858 | nwords = (boolvec_bytes - header_size + word_size - 1) / word_size; | ||
| 2869 | } | 2859 | } |
| 2870 | else | 2860 | else |
| 2871 | size = (header_size | 2861 | nwords = ((size & PSEUDOVECTOR_SIZE_MASK) |
| 2872 | + ((size & PSEUDOVECTOR_SIZE_MASK) | 2862 | + ((size & PSEUDOVECTOR_REST_MASK) |
| 2873 | + ((size & PSEUDOVECTOR_REST_MASK) | 2863 | >> PSEUDOVECTOR_SIZE_BITS)); |
| 2874 | >> PSEUDOVECTOR_SIZE_BITS)) * word_size); | ||
| 2875 | } | 2864 | } |
| 2876 | else | 2865 | else |
| 2877 | size = header_size + size * word_size; | 2866 | nwords = size; |
| 2878 | return vroundup (size); | 2867 | return vroundup (header_size + word_size * nwords); |
| 2879 | } | 2868 | } |
| 2880 | 2869 | ||
| 2881 | /* Release extra resources still in use by VECTOR, which may be any | 2870 | /* Release extra resources still in use by VECTOR, which may be any |
diff --git a/src/data.c b/src/data.c index 4043fbe279b..7ff7ac6b130 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -2962,9 +2962,7 @@ lowercase l) for small endian machines. */) | |||
| 2962 | 2962 | ||
| 2963 | /* Because we round up the bool vector allocate size to word_size | 2963 | /* Because we round up the bool vector allocate size to word_size |
| 2964 | units, we can safely read past the "end" of the vector in the | 2964 | units, we can safely read past the "end" of the vector in the |
| 2965 | operations below. These extra bits are always zero. Also, we | 2965 | operations below. These extra bits are always zero. */ |
| 2966 | always allocate bool vectors with at least one bits_word of storage so | ||
| 2967 | that we don't have to special-case empty bit vectors. */ | ||
| 2968 | 2966 | ||
| 2969 | static bits_word | 2967 | static bits_word |
| 2970 | bool_vector_spare_mask (EMACS_INT nr_bits) | 2968 | bool_vector_spare_mask (EMACS_INT nr_bits) |
| @@ -2972,16 +2970,47 @@ bool_vector_spare_mask (EMACS_INT nr_bits) | |||
| 2972 | return (((bits_word) 1) << (nr_bits % BITS_PER_BITS_WORD)) - 1; | 2970 | return (((bits_word) 1) << (nr_bits % BITS_PER_BITS_WORD)) - 1; |
| 2973 | } | 2971 | } |
| 2974 | 2972 | ||
| 2975 | #if BITS_WORD_MAX <= UINT_MAX | 2973 | /* Info about unsigned long long, falling back on unsigned long |
| 2976 | # define popcount_bits_word count_one_bits | 2974 | if unsigned long long is not available. */ |
| 2977 | #elif BITS_WORD_MAX <= ULONG_MAX | 2975 | |
| 2978 | # define popcount_bits_word count_one_bits_l | 2976 | #if HAVE_UNSIGNED_LONG_LONG_INT |
| 2979 | #elif BITS_WORD_MAX <= ULLONG_MAX | 2977 | enum { BITS_PER_ULL = CHAR_BIT * sizeof (unsigned long long) }; |
| 2980 | # define popcount_bits_word count_one_bits_ll | ||
| 2981 | #else | 2978 | #else |
| 2982 | # error "bits_word wider than long long? Please file a bug report." | 2979 | enum { BITS_PER_ULL = CHAR_BIT * sizeof (unsigned long) }; |
| 2980 | # define ULLONG_MAX ULONG_MAX | ||
| 2981 | # define count_one_bits_ll count_one_bits_l | ||
| 2983 | #endif | 2982 | #endif |
| 2984 | 2983 | ||
| 2984 | /* Shift VAL right by the width of an unsigned long long. | ||
| 2985 | BITS_PER_ULL must be less than BITS_PER_BITS_WORD. */ | ||
| 2986 | |||
| 2987 | static bits_word | ||
| 2988 | shift_right_ull (bits_word w) | ||
| 2989 | { | ||
| 2990 | /* Pacify bogus GCC warning about shift count exceeding type width. */ | ||
| 2991 | int shift = BITS_PER_ULL - BITS_PER_BITS_WORD < 0 ? BITS_PER_ULL : 0; | ||
| 2992 | return w >> shift; | ||
| 2993 | } | ||
| 2994 | |||
| 2995 | /* Return the number of 1 bits in W. */ | ||
| 2996 | |||
| 2997 | static int | ||
| 2998 | count_one_bits_word (bits_word w) | ||
| 2999 | { | ||
| 3000 | if (BITS_WORD_MAX <= UINT_MAX) | ||
| 3001 | return count_one_bits (w); | ||
| 3002 | else if (BITS_WORD_MAX <= ULONG_MAX) | ||
| 3003 | return count_one_bits_l (w); | ||
| 3004 | else | ||
| 3005 | { | ||
| 3006 | int i = 0, count = 0; | ||
| 3007 | while (count += count_one_bits_ll (w), | ||
| 3008 | BITS_PER_BITS_WORD <= (i += BITS_PER_ULL)) | ||
| 3009 | w = shift_right_ull (w); | ||
| 3010 | return count; | ||
| 3011 | } | ||
| 3012 | } | ||
| 3013 | |||
| 2985 | enum bool_vector_op { bool_vector_exclusive_or, | 3014 | enum bool_vector_op { bool_vector_exclusive_or, |
| 2986 | bool_vector_union, | 3015 | bool_vector_union, |
| 2987 | bool_vector_intersection, | 3016 | bool_vector_intersection, |
| @@ -2997,7 +3026,7 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 2997 | EMACS_INT nr_bits; | 3026 | EMACS_INT nr_bits; |
| 2998 | bits_word *adata, *bdata, *cdata; | 3027 | bits_word *adata, *bdata, *cdata; |
| 2999 | ptrdiff_t i; | 3028 | ptrdiff_t i; |
| 3000 | bits_word changed = 0; | 3029 | bool changed = 0; |
| 3001 | bits_word mword; | 3030 | bits_word mword; |
| 3002 | ptrdiff_t nr_words; | 3031 | ptrdiff_t nr_words; |
| 3003 | 3032 | ||
| @@ -3010,7 +3039,7 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3010 | 3039 | ||
| 3011 | if (NILP (dest)) | 3040 | if (NILP (dest)) |
| 3012 | { | 3041 | { |
| 3013 | dest = Fmake_bool_vector (make_number (nr_bits), Qnil); | 3042 | dest = make_uninit_bool_vector (nr_bits); |
| 3014 | changed = 1; | 3043 | changed = 1; |
| 3015 | } | 3044 | } |
| 3016 | else | 3045 | else |
| @@ -3025,8 +3054,8 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3025 | adata = bool_vector_data (dest); | 3054 | adata = bool_vector_data (dest); |
| 3026 | bdata = bool_vector_data (op1); | 3055 | bdata = bool_vector_data (op1); |
| 3027 | cdata = bool_vector_data (op2); | 3056 | cdata = bool_vector_data (op2); |
| 3028 | i = 0; | 3057 | |
| 3029 | do | 3058 | for (i = 0; i < nr_words; i++) |
| 3030 | { | 3059 | { |
| 3031 | if (op == bool_vector_exclusive_or) | 3060 | if (op == bool_vector_exclusive_or) |
| 3032 | mword = bdata[i] ^ cdata[i]; | 3061 | mword = bdata[i] ^ cdata[i]; |
| @@ -3039,14 +3068,12 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3039 | else | 3068 | else |
| 3040 | abort (); | 3069 | abort (); |
| 3041 | 3070 | ||
| 3042 | changed |= adata[i] ^ mword; | 3071 | if (! changed) |
| 3072 | changed = adata[i] != mword; | ||
| 3043 | 3073 | ||
| 3044 | if (op != bool_vector_subsetp) | 3074 | if (op != bool_vector_subsetp) |
| 3045 | adata[i] = mword; | 3075 | adata[i] = mword; |
| 3046 | |||
| 3047 | i++; | ||
| 3048 | } | 3076 | } |
| 3049 | while (i < nr_words); | ||
| 3050 | 3077 | ||
| 3051 | return changed ? dest : Qnil; | 3078 | return changed ? dest : Qnil; |
| 3052 | } | 3079 | } |
| @@ -3060,27 +3087,33 @@ count_trailing_zero_bits (bits_word val) | |||
| 3060 | return count_trailing_zeros (val); | 3087 | return count_trailing_zeros (val); |
| 3061 | if (BITS_WORD_MAX == ULONG_MAX) | 3088 | if (BITS_WORD_MAX == ULONG_MAX) |
| 3062 | return count_trailing_zeros_l (val); | 3089 | return count_trailing_zeros_l (val); |
| 3063 | # if HAVE_UNSIGNED_LONG_LONG_INT | ||
| 3064 | if (BITS_WORD_MAX == ULLONG_MAX) | 3090 | if (BITS_WORD_MAX == ULLONG_MAX) |
| 3065 | return count_trailing_zeros_ll (val); | 3091 | return count_trailing_zeros_ll (val); |
| 3066 | # endif | ||
| 3067 | 3092 | ||
| 3068 | /* The rest of this code is for the unlikely platform where bits_word differs | 3093 | /* The rest of this code is for the unlikely platform where bits_word differs |
| 3069 | in width from unsigned int, unsigned long, and unsigned long long. */ | 3094 | in width from unsigned int, unsigned long, and unsigned long long. */ |
| 3070 | if (val == 0) | 3095 | val |= ~ BITS_WORD_MAX; |
| 3071 | return CHAR_BIT * sizeof (val); | ||
| 3072 | if (BITS_WORD_MAX <= UINT_MAX) | 3096 | if (BITS_WORD_MAX <= UINT_MAX) |
| 3073 | return count_trailing_zeros (val); | 3097 | return count_trailing_zeros (val); |
| 3074 | if (BITS_WORD_MAX <= ULONG_MAX) | 3098 | if (BITS_WORD_MAX <= ULONG_MAX) |
| 3075 | return count_trailing_zeros_l (val); | 3099 | return count_trailing_zeros_l (val); |
| 3076 | { | 3100 | else |
| 3077 | # if HAVE_UNSIGNED_LONG_LONG_INT | 3101 | { |
| 3078 | verify (BITS_WORD_MAX <= ULLONG_MAX); | 3102 | int count; |
| 3079 | return count_trailing_zeros_ll (val); | 3103 | for (count = 0; |
| 3080 | # else | 3104 | count < BITS_PER_BITS_WORD - BITS_PER_ULL; |
| 3081 | verify (BITS_WORD_MAX <= ULONG_MAX); | 3105 | count += BITS_PER_ULL) |
| 3082 | # endif | 3106 | { |
| 3083 | } | 3107 | if (val & ULLONG_MAX) |
| 3108 | return count + count_trailing_zeros_ll (val); | ||
| 3109 | val = shift_right_ull (val); | ||
| 3110 | } | ||
| 3111 | |||
| 3112 | if (BITS_PER_BITS_WORD % BITS_PER_ULL != 0 | ||
| 3113 | && BITS_WORD_MAX == (bits_word) -1) | ||
| 3114 | val |= (bits_word) 1 << (BITS_PER_BITS_WORD % BITS_PER_ULL); | ||
| 3115 | return count + count_trailing_zeros_ll (val); | ||
| 3116 | } | ||
| 3084 | } | 3117 | } |
| 3085 | 3118 | ||
| 3086 | static bits_word | 3119 | static bits_word |
| @@ -3088,20 +3121,24 @@ bits_word_to_host_endian (bits_word val) | |||
| 3088 | { | 3121 | { |
| 3089 | #ifndef WORDS_BIGENDIAN | 3122 | #ifndef WORDS_BIGENDIAN |
| 3090 | return val; | 3123 | return val; |
| 3091 | #elif BITS_WORD_MAX >> 31 == 1 | ||
| 3092 | return bswap_32 (val); | ||
| 3093 | #elif BITS_WORD_MAX >> 31 >> 31 >> 1 == 1 | ||
| 3094 | return bswap_64 (val); | ||
| 3095 | #else | 3124 | #else |
| 3096 | int i; | 3125 | if (BITS_WORD_MAX >> 31 == 1) |
| 3097 | bits_word r = 0; | 3126 | return bswap_32 (val); |
| 3098 | for (i = 0; i < sizeof val; i++) | 3127 | # if HAVE_UNSIGNED_LONG_LONG |
| 3099 | { | 3128 | if (BITS_WORD_MAX >> 31 >> 31 >> 1 == 1) |
| 3100 | r = ((r << 1 << (CHAR_BIT - 1)) | 3129 | return bswap_64 (val); |
| 3101 | | (val & ((1u << 1 << (CHAR_BIT - 1)) - 1))); | 3130 | # endif |
| 3102 | val = val >> 1 >> (CHAR_BIT - 1); | 3131 | { |
| 3103 | } | 3132 | int i; |
| 3104 | return r; | 3133 | bits_word r = 0; |
| 3134 | for (i = 0; i < sizeof val; i++) | ||
| 3135 | { | ||
| 3136 | r = ((r << 1 << (CHAR_BIT - 1)) | ||
| 3137 | | (val & ((1u << 1 << (CHAR_BIT - 1)) - 1))); | ||
| 3138 | val = val >> 1 >> (CHAR_BIT - 1); | ||
| 3139 | } | ||
| 3140 | return r; | ||
| 3141 | } | ||
| 3105 | #endif | 3142 | #endif |
| 3106 | } | 3143 | } |
| 3107 | 3144 | ||
| @@ -3174,7 +3211,7 @@ Return the destination vector. */) | |||
| 3174 | nr_bits = bool_vector_size (a); | 3211 | nr_bits = bool_vector_size (a); |
| 3175 | 3212 | ||
| 3176 | if (NILP (b)) | 3213 | if (NILP (b)) |
| 3177 | b = Fmake_bool_vector (make_number (nr_bits), Qnil); | 3214 | b = make_uninit_bool_vector (nr_bits); |
| 3178 | else | 3215 | else |
| 3179 | { | 3216 | { |
| 3180 | CHECK_BOOL_VECTOR (b); | 3217 | CHECK_BOOL_VECTOR (b); |
| @@ -3208,27 +3245,20 @@ A must be a bool vector. B is a generalized bool. */) | |||
| 3208 | EMACS_INT count; | 3245 | EMACS_INT count; |
| 3209 | EMACS_INT nr_bits; | 3246 | EMACS_INT nr_bits; |
| 3210 | bits_word *adata; | 3247 | bits_word *adata; |
| 3211 | bits_word match; | 3248 | ptrdiff_t i, nwords; |
| 3212 | ptrdiff_t i; | ||
| 3213 | 3249 | ||
| 3214 | CHECK_BOOL_VECTOR (a); | 3250 | CHECK_BOOL_VECTOR (a); |
| 3215 | 3251 | ||
| 3216 | nr_bits = bool_vector_size (a); | 3252 | nr_bits = bool_vector_size (a); |
| 3253 | nwords = bool_vector_words (nr_bits); | ||
| 3217 | count = 0; | 3254 | count = 0; |
| 3218 | match = NILP (b) ? BITS_WORD_MAX : 0; | ||
| 3219 | adata = bool_vector_data (a); | 3255 | adata = bool_vector_data (a); |
| 3220 | 3256 | ||
| 3221 | for (i = 0; i < nr_bits / BITS_PER_BITS_WORD; ++i) | 3257 | for (i = 0; i < nwords; i++) |
| 3222 | count += popcount_bits_word (adata[i] ^ match); | 3258 | count += count_one_bits_word (adata[i]); |
| 3223 | |||
| 3224 | /* Mask out trailing parts of final mword. */ | ||
| 3225 | if (nr_bits % BITS_PER_BITS_WORD) | ||
| 3226 | { | ||
| 3227 | bits_word mword = adata[i] ^ match; | ||
| 3228 | mword = bits_word_to_host_endian (mword); | ||
| 3229 | count += popcount_bits_word (mword & bool_vector_spare_mask (nr_bits)); | ||
| 3230 | } | ||
| 3231 | 3259 | ||
| 3260 | if (NILP (b)) | ||
| 3261 | count = nr_bits - count; | ||
| 3232 | return make_number (count); | 3262 | return make_number (count); |
| 3233 | } | 3263 | } |
| 3234 | 3264 | ||
| @@ -3246,7 +3276,7 @@ index into the vector. */) | |||
| 3246 | bits_word *adata; | 3276 | bits_word *adata; |
| 3247 | bits_word twiddle; | 3277 | bits_word twiddle; |
| 3248 | bits_word mword; /* Machine word. */ | 3278 | bits_word mword; /* Machine word. */ |
| 3249 | ptrdiff_t pos; | 3279 | ptrdiff_t pos, pos0; |
| 3250 | ptrdiff_t nr_words; | 3280 | ptrdiff_t nr_words; |
| 3251 | 3281 | ||
| 3252 | CHECK_BOOL_VECTOR (a); | 3282 | CHECK_BOOL_VECTOR (a); |
| @@ -3273,8 +3303,8 @@ index into the vector. */) | |||
| 3273 | mword = bits_word_to_host_endian (adata[pos]); | 3303 | mword = bits_word_to_host_endian (adata[pos]); |
| 3274 | mword ^= twiddle; | 3304 | mword ^= twiddle; |
| 3275 | mword >>= offset; | 3305 | mword >>= offset; |
| 3306 | mword |= (bits_word) 1 << (BITS_PER_BITS_WORD - offset); | ||
| 3276 | count = count_trailing_zero_bits (mword); | 3307 | count = count_trailing_zero_bits (mword); |
| 3277 | count = min (count, BITS_PER_BITS_WORD - offset); | ||
| 3278 | pos++; | 3308 | pos++; |
| 3279 | if (count + offset < BITS_PER_BITS_WORD) | 3309 | if (count + offset < BITS_PER_BITS_WORD) |
| 3280 | return make_number (count); | 3310 | return make_number (count); |
| @@ -3283,11 +3313,10 @@ index into the vector. */) | |||
| 3283 | /* Scan whole words until we either reach the end of the vector or | 3313 | /* Scan whole words until we either reach the end of the vector or |
| 3284 | find an mword that doesn't completely match. twiddle is | 3314 | find an mword that doesn't completely match. twiddle is |
| 3285 | endian-independent. */ | 3315 | endian-independent. */ |
| 3316 | pos0 = pos; | ||
| 3286 | while (pos < nr_words && adata[pos] == twiddle) | 3317 | while (pos < nr_words && adata[pos] == twiddle) |
| 3287 | { | 3318 | pos++; |
| 3288 | count += BITS_PER_BITS_WORD; | 3319 | count += (pos - pos0) * BITS_PER_BITS_WORD; |
| 3289 | ++pos; | ||
| 3290 | } | ||
| 3291 | 3320 | ||
| 3292 | if (pos < nr_words) | 3321 | if (pos < nr_words) |
| 3293 | { | 3322 | { |
| @@ -435,13 +435,10 @@ with the original. */) | |||
| 435 | 435 | ||
| 436 | if (BOOL_VECTOR_P (arg)) | 436 | if (BOOL_VECTOR_P (arg)) |
| 437 | { | 437 | { |
| 438 | Lisp_Object val; | 438 | EMACS_INT nbits = bool_vector_size (arg); |
| 439 | ptrdiff_t size_in_chars | 439 | ptrdiff_t nbytes = bool_vector_bytes (nbits); |
| 440 | = ((bool_vector_size (arg) + BOOL_VECTOR_BITS_PER_CHAR - 1) | 440 | Lisp_Object val = make_uninit_bool_vector (nbits); |
| 441 | / BOOL_VECTOR_BITS_PER_CHAR); | 441 | memcpy (bool_vector_data (val), bool_vector_data (arg), nbytes); |
| 442 | |||
| 443 | val = Fmake_bool_vector (Flength (arg), Qnil); | ||
| 444 | memcpy (bool_vector_data (val), bool_vector_data (arg), size_in_chars); | ||
| 445 | return val; | 442 | return val; |
| 446 | } | 443 | } |
| 447 | 444 | ||
| @@ -2066,8 +2063,7 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props) | |||
| 2066 | if (size != bool_vector_size (o2)) | 2063 | if (size != bool_vector_size (o2)) |
| 2067 | return 0; | 2064 | return 0; |
| 2068 | if (memcmp (bool_vector_data (o1), bool_vector_data (o2), | 2065 | if (memcmp (bool_vector_data (o1), bool_vector_data (o2), |
| 2069 | ((size + BOOL_VECTOR_BITS_PER_CHAR - 1) | 2066 | bool_vector_bytes (size))) |
| 2070 | / BOOL_VECTOR_BITS_PER_CHAR))) | ||
| 2071 | return 0; | 2067 | return 0; |
| 2072 | return 1; | 2068 | return 1; |
| 2073 | } | 2069 | } |
| @@ -2157,7 +2153,7 @@ ARRAY is a vector, string, char-table, or bool-vector. */) | |||
| 2157 | p[idx] = charval; | 2153 | p[idx] = charval; |
| 2158 | } | 2154 | } |
| 2159 | else if (BOOL_VECTOR_P (array)) | 2155 | else if (BOOL_VECTOR_P (array)) |
| 2160 | bool_vector_fill (array, item); | 2156 | return bool_vector_fill (array, item); |
| 2161 | else | 2157 | else |
| 2162 | wrong_type_argument (Qarrayp, array); | 2158 | wrong_type_argument (Qarrayp, array); |
| 2163 | return array; | 2159 | return array; |
diff --git a/src/lisp.h b/src/lisp.h index 2b197cd32b1..72e5dad8ca3 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -92,16 +92,16 @@ enum { BOOL_VECTOR_BITS_PER_CHAR = | |||
| 92 | /* An unsigned integer type representing a fixed-length bit sequence, | 92 | /* An unsigned integer type representing a fixed-length bit sequence, |
| 93 | suitable for words in a Lisp bool vector. Normally it is size_t | 93 | suitable for words in a Lisp bool vector. Normally it is size_t |
| 94 | for speed, but it is unsigned char on weird platforms. */ | 94 | for speed, but it is unsigned char on weird platforms. */ |
| 95 | #if (BITSIZEOF_SIZE_T == CHAR_BIT * SIZEOF_SIZE_T \ | 95 | #if BOOL_VECTOR_BITS_PER_CHAR == CHAR_BIT |
| 96 | && BOOL_VECTOR_BITS_PER_CHAR == CHAR_BIT) | ||
| 97 | typedef size_t bits_word; | 96 | typedef size_t bits_word; |
| 98 | #define BITS_WORD_MAX SIZE_MAX | 97 | # define BITS_WORD_MAX SIZE_MAX |
| 99 | enum { BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word) }; | 98 | enum { BITS_PER_BITS_WORD = CHAR_BIT * sizeof (bits_word) }; |
| 100 | #else | 99 | #else |
| 101 | typedef unsigned char bits_word; | 100 | typedef unsigned char bits_word; |
| 102 | #define BITS_WORD_MAX ((1u << BOOL_VECTOR_BITS_PER_CHAR) - 1) | 101 | # define BITS_WORD_MAX ((1u << BOOL_VECTOR_BITS_PER_CHAR) - 1) |
| 103 | enum { BITS_PER_BITS_WORD = BOOL_VECTOR_BITS_PER_CHAR }; | 102 | enum { BITS_PER_BITS_WORD = BOOL_VECTOR_BITS_PER_CHAR }; |
| 104 | #endif | 103 | #endif |
| 104 | verify (BITS_WORD_MAX >> (BITS_PER_BITS_WORD - 1) == 1); | ||
| 105 | 105 | ||
| 106 | /* Number of bits in some machine integer types. */ | 106 | /* Number of bits in some machine integer types. */ |
| 107 | enum | 107 | enum |
| @@ -1212,7 +1212,9 @@ struct Lisp_Bool_Vector | |||
| 1212 | struct vectorlike_header header; | 1212 | struct vectorlike_header header; |
| 1213 | /* This is the size in bits. */ | 1213 | /* This is the size in bits. */ |
| 1214 | EMACS_INT size; | 1214 | EMACS_INT size; |
| 1215 | /* This contains the actual bits, packed into bytes. */ | 1215 | /* The actual bits, packed into bytes. |
| 1216 | The bits are in little-endian order in the bytes, and | ||
| 1217 | the bytes are in little-endian order in the words. */ | ||
| 1216 | bits_word data[FLEXIBLE_ARRAY_MEMBER]; | 1218 | bits_word data[FLEXIBLE_ARRAY_MEMBER]; |
| 1217 | }; | 1219 | }; |
| 1218 | 1220 | ||
| @@ -1236,7 +1238,7 @@ bool_vector_uchar_data (Lisp_Object a) | |||
| 1236 | return (unsigned char *) bool_vector_data (a); | 1238 | return (unsigned char *) bool_vector_data (a); |
| 1237 | } | 1239 | } |
| 1238 | 1240 | ||
| 1239 | /* The number of data words in a bool vector with SIZE bits. */ | 1241 | /* The number of data words and bytes in a bool vector with SIZE bits. */ |
| 1240 | 1242 | ||
| 1241 | INLINE EMACS_INT | 1243 | INLINE EMACS_INT |
| 1242 | bool_vector_words (EMACS_INT size) | 1244 | bool_vector_words (EMACS_INT size) |
| @@ -1245,6 +1247,13 @@ bool_vector_words (EMACS_INT size) | |||
| 1245 | return (size + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD; | 1247 | return (size + BITS_PER_BITS_WORD - 1) / BITS_PER_BITS_WORD; |
| 1246 | } | 1248 | } |
| 1247 | 1249 | ||
| 1250 | INLINE EMACS_INT | ||
| 1251 | bool_vector_bytes (EMACS_INT size) | ||
| 1252 | { | ||
| 1253 | eassume (0 <= size && size <= EMACS_INT_MAX - (BITS_PER_BITS_WORD - 1)); | ||
| 1254 | return (size + BOOL_VECTOR_BITS_PER_CHAR - 1) / BOOL_VECTOR_BITS_PER_CHAR; | ||
| 1255 | } | ||
| 1256 | |||
| 1248 | /* True if A's Ith bit is set. */ | 1257 | /* True if A's Ith bit is set. */ |
| 1249 | 1258 | ||
| 1250 | INLINE bool | 1259 | INLINE bool |
| @@ -3588,7 +3597,8 @@ list4i (EMACS_INT x, EMACS_INT y, EMACS_INT w, EMACS_INT h) | |||
| 3588 | make_number (w), make_number (h)); | 3597 | make_number (w), make_number (h)); |
| 3589 | } | 3598 | } |
| 3590 | 3599 | ||
| 3591 | extern void bool_vector_fill (Lisp_Object, Lisp_Object); | 3600 | extern Lisp_Object make_uninit_bool_vector (EMACS_INT); |
| 3601 | extern Lisp_Object bool_vector_fill (Lisp_Object, Lisp_Object); | ||
| 3592 | extern _Noreturn void string_overflow (void); | 3602 | extern _Noreturn void string_overflow (void); |
| 3593 | extern Lisp_Object make_string (const char *, ptrdiff_t); | 3603 | extern Lisp_Object make_string (const char *, ptrdiff_t); |
| 3594 | extern Lisp_Object make_formatted_string (char *, const char *, ...) | 3604 | extern Lisp_Object make_formatted_string (char *, const char *, ...) |
diff --git a/src/lread.c b/src/lread.c index 7e4f5d38d09..6c1b17f62b7 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -2577,9 +2577,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) | |||
| 2577 | if (c == '"') | 2577 | if (c == '"') |
| 2578 | { | 2578 | { |
| 2579 | Lisp_Object tmp, val; | 2579 | Lisp_Object tmp, val; |
| 2580 | EMACS_INT size_in_chars | 2580 | EMACS_INT size_in_chars = bool_vector_bytes (XFASTINT (length)); |
| 2581 | = ((XFASTINT (length) + BOOL_VECTOR_BITS_PER_CHAR - 1) | ||
| 2582 | / BOOL_VECTOR_BITS_PER_CHAR); | ||
| 2583 | unsigned char *data; | 2581 | unsigned char *data; |
| 2584 | 2582 | ||
| 2585 | UNREAD (c); | 2583 | UNREAD (c); |
| @@ -2594,7 +2592,7 @@ read1 (Lisp_Object readcharfun, int *pch, bool first_in_list) | |||
| 2594 | == (SCHARS (tmp) - 1) * BOOL_VECTOR_BITS_PER_CHAR))) | 2592 | == (SCHARS (tmp) - 1) * BOOL_VECTOR_BITS_PER_CHAR))) |
| 2595 | invalid_syntax ("#&..."); | 2593 | invalid_syntax ("#&..."); |
| 2596 | 2594 | ||
| 2597 | val = Fmake_bool_vector (length, Qnil); | 2595 | val = make_uninit_bool_vector (XFASTINT (length)); |
| 2598 | data = bool_vector_uchar_data (val); | 2596 | data = bool_vector_uchar_data (val); |
| 2599 | memcpy (data, SDATA (tmp), size_in_chars); | 2597 | memcpy (data, SDATA (tmp), size_in_chars); |
| 2600 | /* Clear the extraneous bits in the last byte. */ | 2598 | /* Clear the extraneous bits in the last byte. */ |
diff --git a/src/print.c b/src/print.c index 6eda6a86fc4..e3c56a6de62 100644 --- a/src/print.c +++ b/src/print.c | |||
| @@ -1705,8 +1705,7 @@ print_object (Lisp_Object obj, Lisp_Object printcharfun, bool escapeflag) | |||
| 1705 | unsigned char c; | 1705 | unsigned char c; |
| 1706 | struct gcpro gcpro1; | 1706 | struct gcpro gcpro1; |
| 1707 | EMACS_INT size = bool_vector_size (obj); | 1707 | EMACS_INT size = bool_vector_size (obj); |
| 1708 | ptrdiff_t size_in_chars = ((size + BOOL_VECTOR_BITS_PER_CHAR - 1) | 1708 | ptrdiff_t size_in_chars = bool_vector_bytes (size); |
| 1709 | / BOOL_VECTOR_BITS_PER_CHAR); | ||
| 1710 | ptrdiff_t real_size_in_chars = size_in_chars; | 1709 | ptrdiff_t real_size_in_chars = size_in_chars; |
| 1711 | GCPRO1 (obj); | 1710 | GCPRO1 (obj); |
| 1712 | 1711 | ||