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.
This commit is contained in:
Paul Eggert 2013-11-18 10:37:25 -08:00
parent 37c790b385
commit 87d8660102
4 changed files with 85 additions and 36 deletions

View file

@ -1,3 +1,12 @@
2013-11-18 Paul Eggert <eggert@cs.ucla.edu>
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.
2013-11-18 Eli Zaretskii <eliz@gnu.org>
* insdel.c (invalidate_buffer_caches): New function, consolidated

View file

@ -2066,20 +2066,21 @@ Lisp_Object
make_uninit_bool_vector (EMACS_INT nbits)
{
Lisp_Object val;
struct Lisp_Bool_Vector *p;
EMACS_INT word_bytes, needed_elements;
word_bytes = bool_vector_words (nbits) * sizeof (bits_word);
needed_elements = ((bool_header_size - header_size + word_bytes
+ word_size - 1)
/ word_size);
p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
EMACS_INT words0 = bool_vector_words (nbits);
EMACS_INT words = words0 + !words0; /* Allocate at least one word. */
EMACS_INT word_bytes = words * sizeof (bits_word);
EMACS_INT needed_elements = ((bool_header_size - header_size + word_bytes
+ word_size - 1)
/ word_size);
struct Lisp_Bool_Vector *p
= (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
XSETVECTOR (val, p);
XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
p->size = nbits;
/* Clear padding at the end. */
if (nbits)
p->data[bool_vector_words (nbits) - 1] = 0;
/* Clear padding at the end. If NBITS != 0 this initializes more
than it needs to, but that's OK. */
p->data[words - 1] = 0;
return val;
}

View file

@ -3025,9 +3025,7 @@ bool_vector_binop_driver (Lisp_Object op1,
{
EMACS_INT nr_bits;
bits_word *adata, *bdata, *cdata;
ptrdiff_t i;
bool changed = 0;
bits_word mword;
ptrdiff_t i = 0;
ptrdiff_t nr_words;
CHECK_BOOL_VECTOR (op1);
@ -3037,45 +3035,82 @@ bool_vector_binop_driver (Lisp_Object op1,
if (bool_vector_size (op2) != nr_bits)
wrong_length_argument (op1, op2, dest);
nr_words = bool_vector_words (nr_bits);
bdata = bool_vector_data (op1);
cdata = bool_vector_data (op2);
if (NILP (dest))
{
dest = make_uninit_bool_vector (nr_bits);
changed = 1;
adata = bool_vector_data (dest);
}
else
{
CHECK_BOOL_VECTOR (dest);
adata = bool_vector_data (dest);
if (bool_vector_size (dest) != nr_bits)
wrong_length_argument (op1, op2, dest);
switch (op)
{
case bool_vector_exclusive_or:
while (adata[i] == (bdata[i] ^ cdata[i]))
if (! (++i < nr_words))
return Qnil;
break;
case bool_vector_subsetp:
case bool_vector_union:
while (adata[i] == (bdata[i] | cdata[i]))
if (! (++i < nr_words))
return Qnil;
break;
case bool_vector_intersection:
while (adata[i] == (bdata[i] & cdata[i]))
if (! (++i < nr_words))
return Qnil;
break;
case bool_vector_set_difference:
while (adata[i] == (bdata[i] &~ cdata[i]))
if (! (++i < nr_words))
return Qnil;
break;
}
}
nr_words = bool_vector_words (nr_bits);
adata = bool_vector_data (dest);
bdata = bool_vector_data (op1);
cdata = bool_vector_data (op2);
for (i = 0; i < nr_words; i++)
switch (op)
{
if (op == bool_vector_exclusive_or)
mword = bdata[i] ^ cdata[i];
else if (op == bool_vector_union || op == bool_vector_subsetp)
mword = bdata[i] | cdata[i];
else if (op == bool_vector_intersection)
mword = bdata[i] & cdata[i];
else if (op == bool_vector_set_difference)
mword = bdata[i] &~ cdata[i];
else
abort ();
case bool_vector_exclusive_or:
do
adata[i] = bdata[i] ^ cdata[i];
while (++i < nr_words);
break;
if (! changed)
changed = adata[i] != mword;
case bool_vector_subsetp:
break;
if (op != bool_vector_subsetp)
adata[i] = mword;
case bool_vector_union:
do
adata[i] = bdata[i] | cdata[i];
while (++i < nr_words);
break;
case bool_vector_intersection:
do
adata[i] = bdata[i] & cdata[i];
while (++i < nr_words);
break;
case bool_vector_set_difference:
do
adata[i] = bdata[i] &~ cdata[i];
while (++i < nr_words);
break;
}
return changed ? dest : Qnil;
return dest;
}
/* PRECONDITION must be true. Return VALUE. This odd construction
@ -3314,7 +3349,10 @@ index into the vector. */)
mword = bits_word_to_host_endian (adata[pos]);
mword ^= twiddle;
mword >>= offset;
/* Do not count the pad bits. */
mword |= (bits_word) 1 << (BITS_PER_BITS_WORD - offset);
count = count_trailing_zero_bits (mword);
pos++;
if (count + offset < BITS_PER_BITS_WORD)

View file

@ -1213,6 +1213,7 @@ struct Lisp_Bool_Vector
/* This is the size in bits. */
EMACS_INT size;
/* The actual bits, packed into bytes.
Zeros fill out the last word as needed; there's always at least one word.
The bits are in little-endian order in the bytes, and
the bytes are in little-endian order in the words. */
bits_word data[FLEXIBLE_ARRAY_MEMBER];