aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
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/alloc.c
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/alloc.c')
-rw-r--r--src/alloc.c103
1 files changed, 67 insertions, 36 deletions
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