aboutsummaryrefslogtreecommitdiffstats
path: root/src/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/alloc.c')
-rw-r--r--src/alloc.c108
1 files changed, 53 insertions, 55 deletions
diff --git a/src/alloc.c b/src/alloc.c
index b35f7c4333f..7054083acba 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -361,13 +361,21 @@ static int staticidx;
361 361
362static void *pure_alloc (size_t, int); 362static void *pure_alloc (size_t, int);
363 363
364/* Return X rounded to the next multiple of Y. Arguments should not
365 have side effects, as they are evaluated more than once. Assume X
366 + Y - 1 does not overflow. Tune for Y being a power of 2. */
364 367
365/* Value is SZ rounded up to the next multiple of ALIGNMENT. 368#define ROUNDUP(x, y) ((y) & ((y) - 1) \
366 ALIGNMENT must be a power of 2. */ 369 ? ((x) + (y) - 1) - ((x) + (y) - 1) % (y) \
370 : ((x) + (y) - 1) & ~ ((y) - 1))
367 371
368#define ALIGN(ptr, ALIGNMENT) \ 372/* Return PTR rounded up to the next multiple of ALIGNMENT. */
369 ((void *) (((uintptr_t) (ptr) + (ALIGNMENT) - 1) \ 373
370 & ~ ((ALIGNMENT) - 1))) 374static void *
375ALIGN (void *ptr, int alignment)
376{
377 return (void *) ROUNDUP ((uintptr_t) ptr, alignment);
378}
371 379
372static void 380static void
373XFLOAT_INIT (Lisp_Object f, double n) 381XFLOAT_INIT (Lisp_Object f, double n)
@@ -2026,33 +2034,39 @@ INIT must be an integer that represents a character. */)
2026 return val; 2034 return val;
2027} 2035}
2028 2036
2029verify (sizeof (size_t) * CHAR_BIT == BITS_PER_BITS_WORD); 2037static EMACS_INT
2030verify ((BITS_PER_BITS_WORD & (BITS_PER_BITS_WORD - 1)) == 0); 2038bool_vector_exact_payload_bytes (EMACS_INT nbits)
2031
2032static ptrdiff_t
2033bool_vector_payload_bytes (ptrdiff_t nr_bits,
2034 ptrdiff_t *exact_needed_bytes_out)
2035{ 2039{
2036 ptrdiff_t exact_needed_bytes; 2040 eassume (0 <= nbits);
2037 ptrdiff_t needed_bytes; 2041 return (nbits + BOOL_VECTOR_BITS_PER_CHAR - 1) / BOOL_VECTOR_BITS_PER_CHAR;
2042}
2038 2043
2039 eassume (nr_bits >= 0); 2044static EMACS_INT
2045bool_vector_payload_bytes (EMACS_INT nbits)
2046{
2047 EMACS_INT exact_needed_bytes = bool_vector_exact_payload_bytes (nbits);
2040 2048
2041 exact_needed_bytes = ROUNDUP ((size_t) nr_bits, CHAR_BIT) / CHAR_BIT; 2049 /* Always allocate at least one machine word of payload so that
2042 needed_bytes = ROUNDUP ((size_t) nr_bits, BITS_PER_BITS_WORD) / CHAR_BIT; 2050 bool-vector operations in data.c don't need a special case
2051 for empty vectors. */
2052 return ROUNDUP (exact_needed_bytes + !exact_needed_bytes,
2053 sizeof (bits_word));
2054}
2043 2055
2044 if (needed_bytes == 0) 2056void
2057bool_vector_fill (Lisp_Object a, Lisp_Object init)
2058{
2059 EMACS_INT nbits = bool_vector_size (a);
2060 if (0 < nbits)
2045 { 2061 {
2046 /* Always allocate at least one machine word of payload so that 2062 unsigned char *data = bool_vector_uchar_data (a);
2047 bool-vector operations in data.c don't need a special case 2063 int pattern = NILP (init) ? 0 : (1 << BOOL_VECTOR_BITS_PER_CHAR) - 1;
2048 for empty vectors. */ 2064 ptrdiff_t nbytes = ((nbits + BOOL_VECTOR_BITS_PER_CHAR - 1)
2049 needed_bytes = sizeof (bits_word); 2065 / BOOL_VECTOR_BITS_PER_CHAR);
2066 int last_mask = ~ (~0 << ((nbits - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1));
2067 memset (data, pattern, nbytes - 1);
2068 data[nbytes - 1] = pattern & last_mask;
2050 } 2069 }
2051
2052 if (exact_needed_bytes_out != NULL)
2053 *exact_needed_bytes_out = exact_needed_bytes;
2054
2055 return needed_bytes;
2056} 2070}
2057 2071
2058DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, 2072DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
@@ -2060,42 +2074,29 @@ DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0,
2060LENGTH must be a number. INIT matters only in whether it is t or nil. */) 2074LENGTH must be a number. INIT matters only in whether it is t or nil. */)
2061 (Lisp_Object length, Lisp_Object init) 2075 (Lisp_Object length, Lisp_Object init)
2062{ 2076{
2063 register Lisp_Object val; 2077 Lisp_Object val;
2064 struct Lisp_Bool_Vector *p; 2078 struct Lisp_Bool_Vector *p;
2065 ptrdiff_t exact_payload_bytes; 2079 EMACS_INT exact_payload_bytes, total_payload_bytes, needed_elements;
2066 ptrdiff_t total_payload_bytes;
2067 ptrdiff_t needed_elements;
2068 2080
2069 CHECK_NATNUM (length); 2081 CHECK_NATNUM (length);
2070 if (PTRDIFF_MAX < XFASTINT (length))
2071 memory_full (SIZE_MAX);
2072
2073 total_payload_bytes = bool_vector_payload_bytes
2074 (XFASTINT (length), &exact_payload_bytes);
2075 2082
2076 eassume (exact_payload_bytes <= total_payload_bytes); 2083 exact_payload_bytes = bool_vector_exact_payload_bytes (XFASTINT (length));
2077 eassume (0 <= exact_payload_bytes); 2084 total_payload_bytes = bool_vector_payload_bytes (XFASTINT (length));
2078 2085
2079 needed_elements = ROUNDUP ((size_t) ((bool_header_size - header_size) 2086 needed_elements = ((bool_header_size - header_size + total_payload_bytes
2080 + total_payload_bytes), 2087 + word_size - 1)
2081 word_size) / word_size; 2088 / word_size);
2082 2089
2083 p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements); 2090 p = (struct Lisp_Bool_Vector *) allocate_vector (needed_elements);
2084 XSETVECTOR (val, p); 2091 XSETVECTOR (val, p);
2085 XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); 2092 XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0);
2086 2093
2087 p->size = XFASTINT (length); 2094 p->size = XFASTINT (length);
2088 if (exact_payload_bytes) 2095 bool_vector_fill (val, init);
2089 {
2090 memset (p->data, ! NILP (init) ? -1 : 0, exact_payload_bytes);
2091
2092 /* Clear any extraneous bits in the last byte. */
2093 p->data[exact_payload_bytes - 1]
2094 &= (1 << ((XFASTINT (length) - 1) % BOOL_VECTOR_BITS_PER_CHAR + 1)) - 1;
2095 }
2096 2096
2097 /* Clear padding at the end. */ 2097 /* Clear padding at the end. */
2098 memset (p->data + exact_payload_bytes, 2098 eassume (exact_payload_bytes <= total_payload_bytes);
2099 memset (bool_vector_uchar_data (val) + exact_payload_bytes,
2099 0, 2100 0,
2100 total_payload_bytes - exact_payload_bytes); 2101 total_payload_bytes - exact_payload_bytes);
2101 2102
@@ -2648,7 +2649,7 @@ verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0);
2648verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); 2649verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS));
2649 2650
2650/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */ 2651/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at compile time. */
2651#define vroundup_ct(x) ROUNDUP ((size_t) (x), roundup_size) 2652#define vroundup_ct(x) ROUNDUP (x, roundup_size)
2652/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */ 2653/* Round up X to nearest mult-of-ROUNDUP_SIZE --- use at runtime. */
2653#define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x)) 2654#define vroundup(x) (eassume ((x) >= 0), vroundup_ct (x))
2654 2655
@@ -2856,11 +2857,8 @@ vector_nbytes (struct Lisp_Vector *v)
2856 if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) 2857 if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR))
2857 { 2858 {
2858 struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v; 2859 struct Lisp_Bool_Vector *bv = (struct Lisp_Bool_Vector *) v;
2859 ptrdiff_t payload_bytes = 2860 ptrdiff_t payload_bytes = bool_vector_payload_bytes (bv->size);
2860 bool_vector_payload_bytes (bv->size, NULL); 2861 size = bool_header_size + payload_bytes;
2861
2862 eassume (payload_bytes >= 0);
2863 size = bool_header_size + ROUNDUP (payload_bytes, word_size);
2864 } 2862 }
2865 else 2863 else
2866 size = (header_size 2864 size = (header_size