diff options
| author | Paul Eggert | 2013-11-18 10:37:25 -0800 |
|---|---|---|
| committer | Paul Eggert | 2013-11-18 10:37:25 -0800 |
| commit | 87d86601022feb7a330fc6344cc85ec65563c1b6 (patch) | |
| tree | bd7b266fcaca082eb4f3854ef32344d98106a58d /src | |
| parent | 37c790b38599cc80a16c6a76152abbf8160fe2a1 (diff) | |
| download | emacs-87d86601022feb7a330fc6344cc85ec65563c1b6.tar.gz emacs-87d86601022feb7a330fc6344cc85ec65563c1b6.zip | |
Always allocate at least one bits_word per bool vector.
See Daniel Colascione in:
http://lists.gnu.org/archive/html/emacs-devel/2013-11/msg00518.html
* alloc.c (make_uninit_bool_vector): Always allocate at least one word.
* data.c (bool_vector_binop_driver): Rely on this. Tune.
* lisp.h (struct Lisp_Bool_vector): Document this.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 9 | ||||
| -rw-r--r-- | src/alloc.c | 21 | ||||
| -rw-r--r-- | src/data.c | 88 | ||||
| -rw-r--r-- | src/lisp.h | 1 |
4 files changed, 84 insertions, 35 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index a2dfa5bf613..21025c677fc 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,12 @@ | |||
| 1 | 2013-11-18 Paul Eggert <eggert@cs.ucla.edu> | ||
| 2 | |||
| 3 | Always allocate at least one bits_word per bool vector. | ||
| 4 | See Daniel Colascione in: | ||
| 5 | http://lists.gnu.org/archive/html/emacs-devel/2013-11/msg00518.html | ||
| 6 | * alloc.c (make_uninit_bool_vector): Always allocate at least one word. | ||
| 7 | * data.c (bool_vector_binop_driver): Rely on this. Tune. | ||
| 8 | * lisp.h (struct Lisp_Bool_vector): Document this. | ||
| 9 | |||
| 1 | 2013-11-18 Eli Zaretskii <eliz@gnu.org> | 10 | 2013-11-18 Eli Zaretskii <eliz@gnu.org> |
| 2 | 11 | ||
| 3 | * insdel.c (invalidate_buffer_caches): New function, consolidated | 12 | * insdel.c (invalidate_buffer_caches): New function, consolidated |
diff --git a/src/alloc.c b/src/alloc.c index f12fdc5c861..7c560fd0f0d 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -2066,20 +2066,21 @@ Lisp_Object | |||
| 2066 | make_uninit_bool_vector (EMACS_INT nbits) | 2066 | make_uninit_bool_vector (EMACS_INT nbits) |
| 2067 | { | 2067 | { |
| 2068 | Lisp_Object val; | 2068 | Lisp_Object val; |
| 2069 | struct Lisp_Bool_Vector *p; | 2069 | EMACS_INT words0 = bool_vector_words (nbits); |
| 2070 | EMACS_INT word_bytes, needed_elements; | 2070 | EMACS_INT words = words0 + !words0; /* Allocate at least one word. */ |
| 2071 | word_bytes = bool_vector_words (nbits) * sizeof (bits_word); | 2071 | EMACS_INT word_bytes = words * sizeof (bits_word); |
| 2072 | needed_elements = ((bool_header_size - header_size + word_bytes | 2072 | EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes |
| 2073 | + word_size - 1) | 2073 | + word_size - 1) |
| 2074 | / word_size); | 2074 | / word_size); |
| 2075 | p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); | 2075 | struct Lisp_Bool_Vector *p |
| 2076 | = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); | ||
| 2076 | XSETVECTOR (val, p); | 2077 | XSETVECTOR (val, p); |
| 2077 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); | 2078 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2078 | p->size = nbits; | 2079 | p->size = nbits; |
| 2079 | 2080 | ||
| 2080 | /* Clear padding at the end. */ | 2081 | /* Clear padding at the end. If NBITS != 0 this initializes more |
| 2081 | if (nbits) | 2082 | than it needs to, but that's OK. */ |
| 2082 | p->data[bool_vector_words (nbits) - 1] = 0; | 2083 | p->data[words - 1] = 0; |
| 2083 | 2084 | ||
| 2084 | return val; | 2085 | return val; |
| 2085 | } | 2086 | } |
diff --git a/src/data.c b/src/data.c index d0171b5d758..b8b0f248dfa 100644 --- a/src/data.c +++ b/src/data.c | |||
| @@ -3025,9 +3025,7 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3025 | { | 3025 | { |
| 3026 | EMACS_INT nr_bits; | 3026 | EMACS_INT nr_bits; |
| 3027 | bits_word *adata, *bdata, *cdata; | 3027 | bits_word *adata, *bdata, *cdata; |
| 3028 | ptrdiff_t i; | 3028 | ptrdiff_t i = 0; |
| 3029 | bool changed = 0; | ||
| 3030 | bits_word mword; | ||
| 3031 | ptrdiff_t nr_words; | 3029 | ptrdiff_t nr_words; |
| 3032 | 3030 | ||
| 3033 | CHECK_BOOL_VECTOR (op1); | 3031 | CHECK_BOOL_VECTOR (op1); |
| @@ -3037,45 +3035,82 @@ bool_vector_binop_driver (Lisp_Object op1, | |||
| 3037 | if (bool_vector_size (op2) != nr_bits) | 3035 | if (bool_vector_size (op2) != nr_bits) |
| 3038 | wrong_length_argument (op1, op2, dest); | 3036 | wrong_length_argument (op1, op2, dest); |
| 3039 | 3037 | ||
| 3038 | nr_words = bool_vector_words (nr_bits); | ||
| 3039 | bdata = bool_vector_data (op1); | ||
| 3040 | cdata = bool_vector_data (op2); | ||
| 3041 | |||
| 3040 | if (NILP (dest)) | 3042 | if (NILP (dest)) |
| 3041 | { | 3043 | { |
| 3042 | dest = make_uninit_bool_vector (nr_bits); | 3044 | dest = make_uninit_bool_vector (nr_bits); |
| 3043 | changed = 1; | 3045 | adata = bool_vector_data (dest); |
| 3044 | } | 3046 | } |
| 3045 | else | 3047 | else |
| 3046 | { | 3048 | { |
| 3047 | CHECK_BOOL_VECTOR (dest); | 3049 | CHECK_BOOL_VECTOR (dest); |
| 3050 | adata = bool_vector_data (dest); | ||
| 3048 | if (bool_vector_size (dest) != nr_bits) | 3051 | if (bool_vector_size (dest) != nr_bits) |
| 3049 | wrong_length_argument (op1, op2, dest); | 3052 | wrong_length_argument (op1, op2, dest); |
| 3050 | } | ||
| 3051 | 3053 | ||
| 3052 | nr_words = bool_vector_words (nr_bits); | 3054 | switch (op) |
| 3055 | { | ||
| 3056 | case bool_vector_exclusive_or: | ||
| 3057 | while (adata[i] == (bdata[i] ^ cdata[i])) | ||
| 3058 | if (! (++i < nr_words)) | ||
| 3059 | return Qnil; | ||
| 3060 | break; | ||
| 3053 | 3061 | ||
| 3054 | adata = bool_vector_data (dest); | 3062 | case bool_vector_subsetp: |
| 3055 | bdata = bool_vector_data (op1); | 3063 | case bool_vector_union: |
| 3056 | cdata = bool_vector_data (op2); | 3064 | while (adata[i] == (bdata[i] | cdata[i])) |
| 3065 | if (! (++i < nr_words)) | ||
| 3066 | return Qnil; | ||
| 3067 | break; | ||
| 3068 | |||
| 3069 | case bool_vector_intersection: | ||
| 3070 | while (adata[i] == (bdata[i] & cdata[i])) | ||
| 3071 | if (! (++i < nr_words)) | ||
| 3072 | return Qnil; | ||
| 3073 | break; | ||
| 3057 | 3074 | ||
| 3058 | for (i = 0; i < nr_words; i++) | 3075 | case bool_vector_set_difference: |
| 3076 | while (adata[i] == (bdata[i] &~ cdata[i])) | ||
| 3077 | if (! (++i < nr_words)) | ||
| 3078 | return Qnil; | ||
| 3079 | break; | ||
| 3080 | } | ||
| 3081 | } | ||
| 3082 | |||
| 3083 | switch (op) | ||
| 3059 | { | 3084 | { |
| 3060 | if (op == bool_vector_exclusive_or) | 3085 | case bool_vector_exclusive_or: |
| 3061 | mword = bdata[i] ^ cdata[i]; | 3086 | do |
| 3062 | else if (op == bool_vector_union || op == bool_vector_subsetp) | 3087 | adata[i] = bdata[i] ^ cdata[i]; |
| 3063 | mword = bdata[i] | cdata[i]; | 3088 | while (++i < nr_words); |
| 3064 | else if (op == bool_vector_intersection) | 3089 | break; |
| 3065 | mword = bdata[i] & cdata[i]; | 3090 | |
| 3066 | else if (op == bool_vector_set_difference) | 3091 | case bool_vector_subsetp: |
| 3067 | mword = bdata[i] &~ cdata[i]; | 3092 | break; |
| 3068 | else | 3093 | |
| 3069 | abort (); | 3094 | case bool_vector_union: |
| 3095 | do | ||
| 3096 | adata[i] = bdata[i] | cdata[i]; | ||
| 3097 | while (++i < nr_words); | ||
| 3098 | break; | ||
| 3070 | 3099 | ||
| 3071 | if (! changed) | 3100 | case bool_vector_intersection: |
| 3072 | changed = adata[i] != mword; | 3101 | do |
| 3102 | adata[i] = bdata[i] & cdata[i]; | ||
| 3103 | while (++i < nr_words); | ||
| 3104 | break; | ||
| 3073 | 3105 | ||
| 3074 | if (op != bool_vector_subsetp) | 3106 | case bool_vector_set_difference: |
| 3075 | adata[i] = mword; | 3107 | do |
| 3108 | adata[i] = bdata[i] &~ cdata[i]; | ||
| 3109 | while (++i < nr_words); | ||
| 3110 | break; | ||
| 3076 | } | 3111 | } |
| 3077 | 3112 | ||
| 3078 | return changed ? dest : Qnil; | 3113 | return dest; |
| 3079 | } | 3114 | } |
| 3080 | 3115 | ||
| 3081 | /* PRECONDITION must be true. Return VALUE. This odd construction | 3116 | /* PRECONDITION must be true. Return VALUE. This odd construction |
| @@ -3314,7 +3349,10 @@ index into the vector. */) | |||
| 3314 | mword = bits_word_to_host_endian (adata[pos]); | 3349 | mword = bits_word_to_host_endian (adata[pos]); |
| 3315 | mword ^= twiddle; | 3350 | mword ^= twiddle; |
| 3316 | mword >>= offset; | 3351 | mword >>= offset; |
| 3352 | |||
| 3353 | /* Do not count the pad bits. */ | ||
| 3317 | mword |= (bits_word) 1 << (BITS_PER_BITS_WORD - offset); | 3354 | mword |= (bits_word) 1 << (BITS_PER_BITS_WORD - offset); |
| 3355 | |||
| 3318 | count = count_trailing_zero_bits (mword); | 3356 | count = count_trailing_zero_bits (mword); |
| 3319 | pos++; | 3357 | pos++; |
| 3320 | if (count + offset < BITS_PER_BITS_WORD) | 3358 | if (count + offset < BITS_PER_BITS_WORD) |
diff --git a/src/lisp.h b/src/lisp.h index a5aec41be38..8521c87e5d7 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -1213,6 +1213,7 @@ struct Lisp_Bool_Vector | |||
| 1213 | /* This is the size in bits. */ | 1213 | /* This is the size in bits. */ |
| 1214 | EMACS_INT size; | 1214 | EMACS_INT size; |
| 1215 | /* The actual bits, packed into bytes. | 1215 | /* The actual bits, packed into bytes. |
| 1216 | Zeros fill out the last word as needed; there's always at least one word. | ||
| 1216 | The bits are in little-endian order in the bytes, and | 1217 | The bits are in little-endian order in the bytes, and |
| 1217 | the bytes are in little-endian order in the words. */ | 1218 | the bytes are in little-endian order in the words. */ |
| 1218 | bits_word data[FLEXIBLE_ARRAY_MEMBER]; | 1219 | bits_word data[FLEXIBLE_ARRAY_MEMBER]; |