diff options
| author | Daniel Colascione | 2013-09-22 01:31:55 -0800 |
|---|---|---|
| committer | Daniel Colascione | 2013-09-22 01:31:55 -0800 |
| commit | 3e0b94e7ff1fc69b077322d672ef5d0b668541c3 (patch) | |
| tree | 9927abd073960f2460f05a43ae9467cd82c00b9b /src/alloc.c | |
| parent | 76880d884d87d0bc674249e292ccda70f31cca0e (diff) | |
| download | emacs-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.c | 103 |
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 | ||
| 2004 | verify (sizeof (size_t) * CHAR_BIT == BITS_PER_SIZE_T); | ||
| 2005 | verify ((BITS_PER_SIZE_T & (BITS_PER_SIZE_T - 1)) == 0); | ||
| 2006 | |||
| 2007 | static | ||
| 2008 | ptrdiff_t | ||
| 2009 | bool_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 | ||
| 2005 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | 2034 | DEFUN ("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. */ | ||
| 2569 | verify ((roundup_size & (roundup_size - 1)) == 0); | ||
| 2570 | |||
| 2571 | /* Verify assumptions described above. */ | 2603 | /* Verify assumptions described above. */ |
| 2572 | verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); | 2604 | verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); |
| 2573 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | 2605 | verify (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 |