diff options
| author | Dmitry Antipov | 2012-11-08 18:10:28 +0400 |
|---|---|---|
| committer | Dmitry Antipov | 2012-11-08 18:10:28 +0400 |
| commit | 914adc427f7d1159356e465ec616c65a2ea902af (patch) | |
| tree | a4af121088abea87624dd93640d1deb1dd54ea95 /src | |
| parent | d14bb752ea51331ce2fb459c6ffacd8b11f80bb0 (diff) | |
| download | emacs-914adc427f7d1159356e465ec616c65a2ea902af.tar.gz emacs-914adc427f7d1159356e465ec616c65a2ea902af.zip | |
Shrink struct vectorlike_header to the only size field.
* lisp.h (enum pvec_type): Avoid explicit enum member values.
Adjust comment.
(enum More_Lisp_Bits): Change PSEUDOVECTOR_SIZE_BITS and
PVEC_TYPE_MASK to arrange new bitfield in the vector header.
(PSEUDOVECTOR_REST_BITS, PSEUDOVECTOR_REST_MASK): New members.
(PSEUDOVECTOR_AREA_BITS): New member used to extract subtype
information from the vector header. Adjust comment.
(XSETPVECTYPE, XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR)
(PSEUDOVECTOR_TYPEP, DEFUN): Adjust to match new vector header
layout.
(XSETSUBR, SUBRP): Adjust to match new Lisp_Subr layout.
(struct vectorlike_header): Remove next member. Adjust comment.
(struct Lisp_Subr): Add convenient header. Adjust comment.
(allocate_pseudovector): Adjust prototype.
* alloc.c (mark_glyph_matrix, mark_face_cache, allocate_string)
(sweep_string, lisp_malloc): Remove useless prototypes.
(enum mem_type): Adjust comment.
(NEXT_IN_FREE_LIST): New macro.
(SETUP_ON_FREE_LIST): Adjust XSETPVECTYPESIZE usage.
(Fmake_bool_vector): Likewise.
(struct large_vector): New type to represent allocation unit for
the vectors with the memory footprint more than VBLOOCK_BYTES_MAX.
(large_vectors): Change type to struct large_vector.
(allocate_vector_from_block): Simplify.
(PSEUDOVECTOR_NBYTES): Replace with...
(vector_nbytes): ...new function. Adjust users.
(sweep_vectors): Adjust processing of large vectors.
(allocate_vectorlike): Likewise.
(allocate_pseudovector): Change type of 3rd arg to enum pvec_type.
Add easserts. Adjust XSETPVECTYPESIZE usage.
(allocate_buffer): Use BUFFER_PVEC_INIT.
(live_vector_p): Adjust to match large vector.
* buffer.c (init_buffer_once): Use BUFFER_PVEC_INIT.
* buffer.h (struct buffer): Add next member.
(BUFFER_LISP_SIZE, BUFFER_REST_SIZE, BUFFER_PVEC_INIT):
New macros.
(FOR_EACH_BUFFER): Adjust to match struct buffer change.
* fns.c (internal_equal): Adjust to match enum pvec_type change.
(copy_hash_table): Adjust to match vector header change.
* lread.c (defsubr): Use XSETPVECTYPE.
* .gdbinit (xpr, xbacktrace): Adjust to match vector header change.
(xvectype): Likewise. Print PVEC_NORMAL_VECTOR for regular vectors.
(xvecsize): New command.
Diffstat (limited to 'src')
| -rw-r--r-- | src/.gdbinit | 25 | ||||
| -rw-r--r-- | src/ChangeLog | 47 | ||||
| -rw-r--r-- | src/alloc.c | 185 | ||||
| -rw-r--r-- | src/buffer.c | 9 | ||||
| -rw-r--r-- | src/buffer.h | 31 | ||||
| -rw-r--r-- | src/fns.c | 8 | ||||
| -rw-r--r-- | src/lisp.h | 114 | ||||
| -rw-r--r-- | src/lread.c | 2 |
8 files changed, 260 insertions, 161 deletions
diff --git a/src/.gdbinit b/src/.gdbinit index 952d7392a4c..f187bafcba7 100644 --- a/src/.gdbinit +++ b/src/.gdbinit | |||
| @@ -654,13 +654,30 @@ define xvectype | |||
| 654 | xgetptr $ | 654 | xgetptr $ |
| 655 | set $size = ((struct Lisp_Vector *) $ptr)->header.size | 655 | set $size = ((struct Lisp_Vector *) $ptr)->header.size |
| 656 | if ($size & PSEUDOVECTOR_FLAG) | 656 | if ($size & PSEUDOVECTOR_FLAG) |
| 657 | output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_SIZE_BITS) | 657 | output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS) |
| 658 | else | 658 | else |
| 659 | output $size & ~ARRAY_MARK_FLAG | 659 | output PVEC_NORMAL_VECTOR |
| 660 | end | 660 | end |
| 661 | echo \n | 661 | echo \n |
| 662 | end | 662 | end |
| 663 | document xvectype | 663 | document xvectype |
| 664 | Print the type or vector subtype of $. | ||
| 665 | This command assumes that $ is a vector or pseudovector. | ||
| 666 | end | ||
| 667 | |||
| 668 | define xvecsize | ||
| 669 | xgetptr $ | ||
| 670 | set $size = ((struct Lisp_Vector *) $ptr)->header.size | ||
| 671 | if ($size & PSEUDOVECTOR_FLAG) | ||
| 672 | output ($size & PSEUDOVECTOR_SIZE_MASK) | ||
| 673 | echo \n | ||
| 674 | output (($size & PSEUDOVECTOR_REST_MASK) >> PSEUDOVECTOR_SIZE_BITS) | ||
| 675 | else | ||
| 676 | output ($size & ~ARRAY_MARK_FLAG) | ||
| 677 | end | ||
| 678 | echo \n | ||
| 679 | end | ||
| 680 | document xvecsize | ||
| 664 | Print the size or vector subtype of $. | 681 | Print the size or vector subtype of $. |
| 665 | This command assumes that $ is a vector or pseudovector. | 682 | This command assumes that $ is a vector or pseudovector. |
| 666 | end | 683 | end |
| @@ -996,7 +1013,7 @@ define xpr | |||
| 996 | if $type == Lisp_Vectorlike | 1013 | if $type == Lisp_Vectorlike |
| 997 | set $size = ((struct Lisp_Vector *) $ptr)->header.size | 1014 | set $size = ((struct Lisp_Vector *) $ptr)->header.size |
| 998 | if ($size & PSEUDOVECTOR_FLAG) | 1015 | if ($size & PSEUDOVECTOR_FLAG) |
| 999 | set $vec = (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_SIZE_BITS) | 1016 | set $vec = (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS) |
| 1000 | if $vec == PVEC_NORMAL_VECTOR | 1017 | if $vec == PVEC_NORMAL_VECTOR |
| 1001 | xvector | 1018 | xvector |
| 1002 | end | 1019 | end |
| @@ -1132,7 +1149,7 @@ define xbacktrace | |||
| 1132 | xgetptr ($bt->function) | 1149 | xgetptr ($bt->function) |
| 1133 | set $size = ((struct Lisp_Vector *) $ptr)->header.size | 1150 | set $size = ((struct Lisp_Vector *) $ptr)->header.size |
| 1134 | if ($size & PSEUDOVECTOR_FLAG) | 1151 | if ($size & PSEUDOVECTOR_FLAG) |
| 1135 | output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_SIZE_BITS) | 1152 | output (enum pvec_type) (($size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS) |
| 1136 | else | 1153 | else |
| 1137 | output $size & ~ARRAY_MARK_FLAG | 1154 | output $size & ~ARRAY_MARK_FLAG |
| 1138 | end | 1155 | end |
diff --git a/src/ChangeLog b/src/ChangeLog index 291eec18fe9..7ddff43d94d 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,5 +1,52 @@ | |||
| 1 | 2012-11-08 Dmitry Antipov <dmantipov@yandex.ru> | 1 | 2012-11-08 Dmitry Antipov <dmantipov@yandex.ru> |
| 2 | 2 | ||
| 3 | Shrink struct vectorlike_header to the only size field. | ||
| 4 | * lisp.h (enum pvec_type): Avoid explicit enum member values. | ||
| 5 | Adjust comment. | ||
| 6 | (enum More_Lisp_Bits): Change PSEUDOVECTOR_SIZE_BITS and | ||
| 7 | PVEC_TYPE_MASK to arrange new bitfield in the vector header. | ||
| 8 | (PSEUDOVECTOR_REST_BITS, PSEUDOVECTOR_REST_MASK): New members. | ||
| 9 | (PSEUDOVECTOR_AREA_BITS): New member used to extract subtype | ||
| 10 | information from the vector header. Adjust comment. | ||
| 11 | (XSETPVECTYPE, XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR) | ||
| 12 | (PSEUDOVECTOR_TYPEP, DEFUN): Adjust to match new vector header | ||
| 13 | layout. | ||
| 14 | (XSETSUBR, SUBRP): Adjust to match new Lisp_Subr layout. | ||
| 15 | (struct vectorlike_header): Remove next member. Adjust comment. | ||
| 16 | (struct Lisp_Subr): Add convenient header. Adjust comment. | ||
| 17 | (allocate_pseudovector): Adjust prototype. | ||
| 18 | * alloc.c (mark_glyph_matrix, mark_face_cache, allocate_string) | ||
| 19 | (sweep_string, lisp_malloc): Remove useless prototypes. | ||
| 20 | (enum mem_type): Adjust comment. | ||
| 21 | (NEXT_IN_FREE_LIST): New macro. | ||
| 22 | (SETUP_ON_FREE_LIST): Adjust XSETPVECTYPESIZE usage. | ||
| 23 | (Fmake_bool_vector): Likewise. | ||
| 24 | (struct large_vector): New type to represent allocation unit for | ||
| 25 | the vectors with the memory footprint more than VBLOOCK_BYTES_MAX. | ||
| 26 | (large_vectors): Change type to struct large_vector. | ||
| 27 | (allocate_vector_from_block): Simplify. | ||
| 28 | (PSEUDOVECTOR_NBYTES): Replace with... | ||
| 29 | (vector_nbytes): ...new function. Adjust users. | ||
| 30 | (sweep_vectors): Adjust processing of large vectors. | ||
| 31 | (allocate_vectorlike): Likewise. | ||
| 32 | (allocate_pseudovector): Change type of 3rd arg to enum pvec_type. | ||
| 33 | Add easserts. Adjust XSETPVECTYPESIZE usage. | ||
| 34 | (allocate_buffer): Use BUFFER_PVEC_INIT. | ||
| 35 | (live_vector_p): Adjust to match large vector. | ||
| 36 | * buffer.c (init_buffer_once): Use BUFFER_PVEC_INIT. | ||
| 37 | * buffer.h (struct buffer): Add next member. | ||
| 38 | (BUFFER_LISP_SIZE, BUFFER_REST_SIZE, BUFFER_PVEC_INIT): | ||
| 39 | New macros. | ||
| 40 | (FOR_EACH_BUFFER): Adjust to match struct buffer change. | ||
| 41 | * fns.c (internal_equal): Adjust to match enum pvec_type change. | ||
| 42 | (copy_hash_table): Adjust to match vector header change. | ||
| 43 | * lread.c (defsubr): Use XSETPVECTYPE. | ||
| 44 | * .gdbinit (xpr, xbacktrace): Adjust to match vector header change. | ||
| 45 | (xvectype): Likewise. Print PVEC_NORMAL_VECTOR for regular vectors. | ||
| 46 | (xvecsize): New command. | ||
| 47 | |||
| 48 | 2012-11-08 Dmitry Antipov <dmantipov@yandex.ru> | ||
| 49 | |||
| 3 | * keyboard.c (event_to_kboard): Do not dereference | 50 | * keyboard.c (event_to_kboard): Do not dereference |
| 4 | frame_or_window field of SELECTION_REQUEST_EVENT | 51 | frame_or_window field of SELECTION_REQUEST_EVENT |
| 5 | and SELECTION_CLEAR_EVENT events (Bug#12814). | 52 | and SELECTION_CLEAR_EVENT events (Bug#12814). |
diff --git a/src/alloc.c b/src/alloc.c index 5bb528c64ab..557c68ca5af 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -216,23 +216,19 @@ static Lisp_Object Qpost_gc_hook; | |||
| 216 | static void mark_terminals (void); | 216 | static void mark_terminals (void); |
| 217 | static void gc_sweep (void); | 217 | static void gc_sweep (void); |
| 218 | static Lisp_Object make_pure_vector (ptrdiff_t); | 218 | static Lisp_Object make_pure_vector (ptrdiff_t); |
| 219 | static void mark_glyph_matrix (struct glyph_matrix *); | ||
| 220 | static void mark_face_cache (struct face_cache *); | ||
| 221 | static void mark_buffer (struct buffer *); | 219 | static void mark_buffer (struct buffer *); |
| 222 | 220 | ||
| 223 | #if !defined REL_ALLOC || defined SYSTEM_MALLOC | 221 | #if !defined REL_ALLOC || defined SYSTEM_MALLOC |
| 224 | static void refill_memory_reserve (void); | 222 | static void refill_memory_reserve (void); |
| 225 | #endif | 223 | #endif |
| 226 | static struct Lisp_String *allocate_string (void); | ||
| 227 | static void compact_small_strings (void); | 224 | static void compact_small_strings (void); |
| 228 | static void free_large_strings (void); | 225 | static void free_large_strings (void); |
| 229 | static void sweep_strings (void); | ||
| 230 | static void free_misc (Lisp_Object); | 226 | static void free_misc (Lisp_Object); |
| 231 | extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE; | 227 | extern Lisp_Object which_symbols (Lisp_Object, EMACS_INT) EXTERNALLY_VISIBLE; |
| 232 | 228 | ||
| 233 | /* When scanning the C stack for live Lisp objects, Emacs keeps track | 229 | /* When scanning the C stack for live Lisp objects, Emacs keeps track of |
| 234 | of what memory allocated via lisp_malloc is intended for what | 230 | what memory allocated via lisp_malloc and lisp_align_malloc is intended |
| 235 | purpose. This enumeration specifies the type of memory. */ | 231 | for what purpose. This enumeration specifies the type of memory. */ |
| 236 | 232 | ||
| 237 | enum mem_type | 233 | enum mem_type |
| 238 | { | 234 | { |
| @@ -243,10 +239,9 @@ enum mem_type | |||
| 243 | MEM_TYPE_MISC, | 239 | MEM_TYPE_MISC, |
| 244 | MEM_TYPE_SYMBOL, | 240 | MEM_TYPE_SYMBOL, |
| 245 | MEM_TYPE_FLOAT, | 241 | MEM_TYPE_FLOAT, |
| 246 | /* We used to keep separate mem_types for subtypes of vectors such as | 242 | /* Since all non-bool pseudovectors are small enough to be |
| 247 | process, hash_table, frame, terminal, and window, but we never made | 243 | allocated from vector blocks, this memory type denotes |
| 248 | use of the distinction, so it only caused source-code complexity | 244 | large regular vectors and large bool pseudovectors. */ |
| 249 | and runtime slowdown. Minor but pointless. */ | ||
| 250 | MEM_TYPE_VECTORLIKE, | 245 | MEM_TYPE_VECTORLIKE, |
| 251 | /* Special type to denote vector blocks. */ | 246 | /* Special type to denote vector blocks. */ |
| 252 | MEM_TYPE_VECTOR_BLOCK, | 247 | MEM_TYPE_VECTOR_BLOCK, |
| @@ -254,9 +249,6 @@ enum mem_type | |||
| 254 | MEM_TYPE_SPARE | 249 | MEM_TYPE_SPARE |
| 255 | }; | 250 | }; |
| 256 | 251 | ||
| 257 | static void *lisp_malloc (size_t, enum mem_type); | ||
| 258 | |||
| 259 | |||
| 260 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK | 252 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK |
| 261 | 253 | ||
| 262 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 254 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| @@ -2040,7 +2032,7 @@ LENGTH must be a number. INIT matters only in whether it is t or nil. */) | |||
| 2040 | val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); | 2032 | val = Fmake_vector (make_number (length_in_elts + extra_bool_elts), Qnil); |
| 2041 | 2033 | ||
| 2042 | /* No Lisp_Object to trace in there. */ | 2034 | /* No Lisp_Object to trace in there. */ |
| 2043 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0); | 2035 | XSETPVECTYPESIZE (XVECTOR (val), PVEC_BOOL_VECTOR, 0, 0); |
| 2044 | 2036 | ||
| 2045 | p = XBOOL_VECTOR (val); | 2037 | p = XBOOL_VECTOR (val); |
| 2046 | p->size = XFASTINT (length); | 2038 | p->size = XFASTINT (length); |
| @@ -2619,19 +2611,49 @@ verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); | |||
| 2619 | 2611 | ||
| 2620 | #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size) | 2612 | #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size) |
| 2621 | 2613 | ||
| 2614 | /* When V is on the free list, first word after header is used as a pointer | ||
| 2615 | to next vector on the free list. It might be done in a better way with: | ||
| 2616 | |||
| 2617 | (*(struct Lisp_Vector **)&(v->contents[0])) | ||
| 2618 | |||
| 2619 | but this breaks GCC's strict-aliasing rules (which looks more relaxed | ||
| 2620 | for char and void pointers). */ | ||
| 2621 | |||
| 2622 | #define NEXT_IN_FREE_LIST(v) \ | ||
| 2623 | (*(struct Lisp_Vector **)((char *) v + header_size)) | ||
| 2624 | |||
| 2622 | /* Common shortcut to setup vector on a free list. */ | 2625 | /* Common shortcut to setup vector on a free list. */ |
| 2623 | 2626 | ||
| 2624 | #define SETUP_ON_FREE_LIST(v, nbytes, index) \ | 2627 | #define SETUP_ON_FREE_LIST(v, nbytes, tmp) \ |
| 2625 | do { \ | 2628 | do { \ |
| 2626 | XSETPVECTYPESIZE (v, PVEC_FREE, nbytes); \ | 2629 | (tmp) = ((nbytes - header_size) / word_size); \ |
| 2627 | eassert ((nbytes) % roundup_size == 0); \ | 2630 | XSETPVECTYPESIZE (v, PVEC_FREE, 0, (tmp)); \ |
| 2628 | (index) = VINDEX (nbytes); \ | 2631 | eassert ((nbytes) % roundup_size == 0); \ |
| 2629 | eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ | 2632 | (tmp) = VINDEX (nbytes); \ |
| 2630 | (v)->header.next.vector = vector_free_lists[index]; \ | 2633 | eassert ((tmp) < VECTOR_MAX_FREE_LIST_INDEX); \ |
| 2631 | vector_free_lists[index] = (v); \ | 2634 | NEXT_IN_FREE_LIST (v) = vector_free_lists[tmp]; \ |
| 2632 | total_free_vector_slots += (nbytes) / word_size; \ | 2635 | vector_free_lists[tmp] = (v); \ |
| 2636 | total_free_vector_slots += (nbytes) / word_size; \ | ||
| 2633 | } while (0) | 2637 | } while (0) |
| 2634 | 2638 | ||
| 2639 | /* This internal type is used to maintain the list of large vectors | ||
| 2640 | which are allocated at their own, e.g. outside of vector blocks. */ | ||
| 2641 | |||
| 2642 | struct large_vector | ||
| 2643 | { | ||
| 2644 | union { | ||
| 2645 | struct large_vector *vector; | ||
| 2646 | #if USE_LSB_TAG | ||
| 2647 | /* We need to maintain ROUNDUP_SIZE alignment for the vector member. */ | ||
| 2648 | unsigned char c[vroundup (sizeof (struct large_vector *))]; | ||
| 2649 | #endif | ||
| 2650 | } next; | ||
| 2651 | struct Lisp_Vector v; | ||
| 2652 | }; | ||
| 2653 | |||
| 2654 | /* This internal type is used to maintain an underlying storage | ||
| 2655 | for small vectors. */ | ||
| 2656 | |||
| 2635 | struct vector_block | 2657 | struct vector_block |
| 2636 | { | 2658 | { |
| 2637 | char data[VECTOR_BLOCK_BYTES]; | 2659 | char data[VECTOR_BLOCK_BYTES]; |
| @@ -2649,7 +2671,7 @@ static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX]; | |||
| 2649 | 2671 | ||
| 2650 | /* Singly-linked list of large vectors. */ | 2672 | /* Singly-linked list of large vectors. */ |
| 2651 | 2673 | ||
| 2652 | static struct Lisp_Vector *large_vectors; | 2674 | static struct large_vector *large_vectors; |
| 2653 | 2675 | ||
| 2654 | /* The only vector with 0 slots, allocated from pure space. */ | 2676 | /* The only vector with 0 slots, allocated from pure space. */ |
| 2655 | 2677 | ||
| @@ -2693,7 +2715,7 @@ init_vectors (void) | |||
| 2693 | static struct Lisp_Vector * | 2715 | static struct Lisp_Vector * |
| 2694 | allocate_vector_from_block (size_t nbytes) | 2716 | allocate_vector_from_block (size_t nbytes) |
| 2695 | { | 2717 | { |
| 2696 | struct Lisp_Vector *vector, *rest; | 2718 | struct Lisp_Vector *vector; |
| 2697 | struct vector_block *block; | 2719 | struct vector_block *block; |
| 2698 | size_t index, restbytes; | 2720 | size_t index, restbytes; |
| 2699 | 2721 | ||
| @@ -2706,8 +2728,7 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2706 | if (vector_free_lists[index]) | 2728 | if (vector_free_lists[index]) |
| 2707 | { | 2729 | { |
| 2708 | vector = vector_free_lists[index]; | 2730 | vector = vector_free_lists[index]; |
| 2709 | vector_free_lists[index] = vector->header.next.vector; | 2731 | vector_free_lists[index] = NEXT_IN_FREE_LIST (vector); |
| 2710 | vector->header.next.nbytes = nbytes; | ||
| 2711 | total_free_vector_slots -= nbytes / word_size; | 2732 | total_free_vector_slots -= nbytes / word_size; |
| 2712 | return vector; | 2733 | return vector; |
| 2713 | } | 2734 | } |
| @@ -2721,16 +2742,14 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2721 | { | 2742 | { |
| 2722 | /* This vector is larger than requested. */ | 2743 | /* This vector is larger than requested. */ |
| 2723 | vector = vector_free_lists[index]; | 2744 | vector = vector_free_lists[index]; |
| 2724 | vector_free_lists[index] = vector->header.next.vector; | 2745 | vector_free_lists[index] = NEXT_IN_FREE_LIST (vector); |
| 2725 | vector->header.next.nbytes = nbytes; | ||
| 2726 | total_free_vector_slots -= nbytes / word_size; | 2746 | total_free_vector_slots -= nbytes / word_size; |
| 2727 | 2747 | ||
| 2728 | /* Excess bytes are used for the smaller vector, | 2748 | /* Excess bytes are used for the smaller vector, |
| 2729 | which should be set on an appropriate free list. */ | 2749 | which should be set on an appropriate free list. */ |
| 2730 | restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; | 2750 | restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; |
| 2731 | eassert (restbytes % roundup_size == 0); | 2751 | eassert (restbytes % roundup_size == 0); |
| 2732 | rest = ADVANCE (vector, nbytes); | 2752 | SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index); |
| 2733 | SETUP_ON_FREE_LIST (rest, restbytes, index); | ||
| 2734 | return vector; | 2753 | return vector; |
| 2735 | } | 2754 | } |
| 2736 | 2755 | ||
| @@ -2739,7 +2758,6 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2739 | 2758 | ||
| 2740 | /* New vector will be at the beginning of this block. */ | 2759 | /* New vector will be at the beginning of this block. */ |
| 2741 | vector = (struct Lisp_Vector *) block->data; | 2760 | vector = (struct Lisp_Vector *) block->data; |
| 2742 | vector->header.next.nbytes = nbytes; | ||
| 2743 | 2761 | ||
| 2744 | /* If the rest of space from this block is large enough | 2762 | /* If the rest of space from this block is large enough |
| 2745 | for one-slot vector at least, set up it on a free list. */ | 2763 | for one-slot vector at least, set up it on a free list. */ |
| @@ -2747,11 +2765,10 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2747 | if (restbytes >= VBLOCK_BYTES_MIN) | 2765 | if (restbytes >= VBLOCK_BYTES_MIN) |
| 2748 | { | 2766 | { |
| 2749 | eassert (restbytes % roundup_size == 0); | 2767 | eassert (restbytes % roundup_size == 0); |
| 2750 | rest = ADVANCE (vector, nbytes); | 2768 | SETUP_ON_FREE_LIST (ADVANCE (vector, nbytes), restbytes, index); |
| 2751 | SETUP_ON_FREE_LIST (rest, restbytes, index); | ||
| 2752 | } | 2769 | } |
| 2753 | return vector; | 2770 | return vector; |
| 2754 | } | 2771 | } |
| 2755 | 2772 | ||
| 2756 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ | 2773 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ |
| 2757 | 2774 | ||
| @@ -2759,15 +2776,30 @@ allocate_vector_from_block (size_t nbytes) | |||
| 2759 | ((char *) (vector) <= (block)->data \ | 2776 | ((char *) (vector) <= (block)->data \ |
| 2760 | + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) | 2777 | + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) |
| 2761 | 2778 | ||
| 2762 | /* Number of bytes used by vector-block-allocated object. This is the only | 2779 | /* Return the memory footprint of V in bytes. */ |
| 2763 | place where we actually use the `nbytes' field of the vector-header. | ||
| 2764 | I.e. we could get rid of the `nbytes' field by computing it based on the | ||
| 2765 | vector-type. */ | ||
| 2766 | 2780 | ||
| 2767 | #define PSEUDOVECTOR_NBYTES(vector) \ | 2781 | static ptrdiff_t |
| 2768 | (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \ | 2782 | vector_nbytes (struct Lisp_Vector *v) |
| 2769 | ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \ | 2783 | { |
| 2770 | : vector->header.next.nbytes) | 2784 | ptrdiff_t size = v->header.size & ~ARRAY_MARK_FLAG; |
| 2785 | |||
| 2786 | if (size & PSEUDOVECTOR_FLAG) | ||
| 2787 | { | ||
| 2788 | if (PSEUDOVECTOR_TYPEP (&v->header, PVEC_BOOL_VECTOR)) | ||
| 2789 | size = (bool_header_size | ||
| 2790 | + (((struct Lisp_Bool_Vector *) v)->size | ||
| 2791 | + BOOL_VECTOR_BITS_PER_CHAR - 1) | ||
| 2792 | / BOOL_VECTOR_BITS_PER_CHAR); | ||
| 2793 | else | ||
| 2794 | size = (header_size | ||
| 2795 | + ((size & PSEUDOVECTOR_SIZE_MASK) | ||
| 2796 | + ((size & PSEUDOVECTOR_REST_MASK) | ||
| 2797 | >> PSEUDOVECTOR_SIZE_BITS)) * word_size); | ||
| 2798 | } | ||
| 2799 | else | ||
| 2800 | size = header_size + size * word_size; | ||
| 2801 | return vroundup (size); | ||
| 2802 | } | ||
| 2771 | 2803 | ||
| 2772 | /* Reclaim space used by unmarked vectors. */ | 2804 | /* Reclaim space used by unmarked vectors. */ |
| 2773 | 2805 | ||
| @@ -2775,7 +2807,8 @@ static void | |||
| 2775 | sweep_vectors (void) | 2807 | sweep_vectors (void) |
| 2776 | { | 2808 | { |
| 2777 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; | 2809 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; |
| 2778 | struct Lisp_Vector *vector, *next, **vprev = &large_vectors; | 2810 | struct large_vector *lv, **lvprev = &large_vectors; |
| 2811 | struct Lisp_Vector *vector, *next; | ||
| 2779 | 2812 | ||
| 2780 | total_vectors = total_vector_slots = total_free_vector_slots = 0; | 2813 | total_vectors = total_vector_slots = total_free_vector_slots = 0; |
| 2781 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); | 2814 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); |
| @@ -2785,6 +2818,7 @@ sweep_vectors (void) | |||
| 2785 | for (block = vector_blocks; block; block = *bprev) | 2818 | for (block = vector_blocks; block; block = *bprev) |
| 2786 | { | 2819 | { |
| 2787 | bool free_this_block = 0; | 2820 | bool free_this_block = 0; |
| 2821 | ptrdiff_t nbytes; | ||
| 2788 | 2822 | ||
| 2789 | for (vector = (struct Lisp_Vector *) block->data; | 2823 | for (vector = (struct Lisp_Vector *) block->data; |
| 2790 | VECTOR_IN_BLOCK (vector, block); vector = next) | 2824 | VECTOR_IN_BLOCK (vector, block); vector = next) |
| @@ -2793,14 +2827,16 @@ sweep_vectors (void) | |||
| 2793 | { | 2827 | { |
| 2794 | VECTOR_UNMARK (vector); | 2828 | VECTOR_UNMARK (vector); |
| 2795 | total_vectors++; | 2829 | total_vectors++; |
| 2796 | total_vector_slots += vector->header.next.nbytes / word_size; | 2830 | nbytes = vector_nbytes (vector); |
| 2797 | next = ADVANCE (vector, vector->header.next.nbytes); | 2831 | total_vector_slots += nbytes / word_size; |
| 2832 | next = ADVANCE (vector, nbytes); | ||
| 2798 | } | 2833 | } |
| 2799 | else | 2834 | else |
| 2800 | { | 2835 | { |
| 2801 | ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector); | 2836 | ptrdiff_t total_bytes; |
| 2802 | ptrdiff_t total_bytes = nbytes; | ||
| 2803 | 2837 | ||
| 2838 | nbytes = vector_nbytes (vector); | ||
| 2839 | total_bytes = nbytes; | ||
| 2804 | next = ADVANCE (vector, nbytes); | 2840 | next = ADVANCE (vector, nbytes); |
| 2805 | 2841 | ||
| 2806 | /* While NEXT is not marked, try to coalesce with VECTOR, | 2842 | /* While NEXT is not marked, try to coalesce with VECTOR, |
| @@ -2810,7 +2846,7 @@ sweep_vectors (void) | |||
| 2810 | { | 2846 | { |
| 2811 | if (VECTOR_MARKED_P (next)) | 2847 | if (VECTOR_MARKED_P (next)) |
| 2812 | break; | 2848 | break; |
| 2813 | nbytes = PSEUDOVECTOR_NBYTES (next); | 2849 | nbytes = vector_nbytes (next); |
| 2814 | total_bytes += nbytes; | 2850 | total_bytes += nbytes; |
| 2815 | next = ADVANCE (next, nbytes); | 2851 | next = ADVANCE (next, nbytes); |
| 2816 | } | 2852 | } |
| @@ -2844,8 +2880,9 @@ sweep_vectors (void) | |||
| 2844 | 2880 | ||
| 2845 | /* Sweep large vectors. */ | 2881 | /* Sweep large vectors. */ |
| 2846 | 2882 | ||
| 2847 | for (vector = large_vectors; vector; vector = *vprev) | 2883 | for (lv = large_vectors; lv; lv = *lvprev) |
| 2848 | { | 2884 | { |
| 2885 | vector = &lv->v; | ||
| 2849 | if (VECTOR_MARKED_P (vector)) | 2886 | if (VECTOR_MARKED_P (vector)) |
| 2850 | { | 2887 | { |
| 2851 | VECTOR_UNMARK (vector); | 2888 | VECTOR_UNMARK (vector); |
| @@ -2867,12 +2904,12 @@ sweep_vectors (void) | |||
| 2867 | else | 2904 | else |
| 2868 | total_vector_slots | 2905 | total_vector_slots |
| 2869 | += header_size / word_size + vector->header.size; | 2906 | += header_size / word_size + vector->header.size; |
| 2870 | vprev = &vector->header.next.vector; | 2907 | lvprev = &lv->next.vector; |
| 2871 | } | 2908 | } |
| 2872 | else | 2909 | else |
| 2873 | { | 2910 | { |
| 2874 | *vprev = vector->header.next.vector; | 2911 | *lvprev = lv->next.vector; |
| 2875 | lisp_free (vector); | 2912 | lisp_free (lv); |
| 2876 | } | 2913 | } |
| 2877 | } | 2914 | } |
| 2878 | } | 2915 | } |
| @@ -2904,9 +2941,12 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 2904 | p = allocate_vector_from_block (vroundup (nbytes)); | 2941 | p = allocate_vector_from_block (vroundup (nbytes)); |
| 2905 | else | 2942 | else |
| 2906 | { | 2943 | { |
| 2907 | p = lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); | 2944 | struct large_vector *lv |
| 2908 | p->header.next.vector = large_vectors; | 2945 | = lisp_malloc (sizeof (*lv) + (len - 1) * word_size, |
| 2909 | large_vectors = p; | 2946 | MEM_TYPE_VECTORLIKE); |
| 2947 | lv->next.vector = large_vectors; | ||
| 2948 | large_vectors = lv; | ||
| 2949 | p = &lv->v; | ||
| 2910 | } | 2950 | } |
| 2911 | 2951 | ||
| 2912 | #ifdef DOUG_LEA_MALLOC | 2952 | #ifdef DOUG_LEA_MALLOC |
| @@ -2943,16 +2983,21 @@ allocate_vector (EMACS_INT len) | |||
| 2943 | /* Allocate other vector-like structures. */ | 2983 | /* Allocate other vector-like structures. */ |
| 2944 | 2984 | ||
| 2945 | struct Lisp_Vector * | 2985 | struct Lisp_Vector * |
| 2946 | allocate_pseudovector (int memlen, int lisplen, int tag) | 2986 | allocate_pseudovector (int memlen, int lisplen, enum pvec_type tag) |
| 2947 | { | 2987 | { |
| 2948 | struct Lisp_Vector *v = allocate_vectorlike (memlen); | 2988 | struct Lisp_Vector *v = allocate_vectorlike (memlen); |
| 2949 | int i; | 2989 | int i; |
| 2950 | 2990 | ||
| 2991 | /* Catch bogus values. */ | ||
| 2992 | eassert (tag <= PVEC_FONT); | ||
| 2993 | eassert (memlen - lisplen <= (1 << PSEUDOVECTOR_REST_BITS) - 1); | ||
| 2994 | eassert (lisplen <= (1 << PSEUDOVECTOR_SIZE_BITS) - 1); | ||
| 2995 | |||
| 2951 | /* Only the first lisplen slots will be traced normally by the GC. */ | 2996 | /* Only the first lisplen slots will be traced normally by the GC. */ |
| 2952 | for (i = 0; i < lisplen; ++i) | 2997 | for (i = 0; i < lisplen; ++i) |
| 2953 | v->contents[i] = Qnil; | 2998 | v->contents[i] = Qnil; |
| 2954 | 2999 | ||
| 2955 | XSETPVECTYPESIZE (v, tag, lisplen); | 3000 | XSETPVECTYPESIZE (v, tag, lisplen, memlen - lisplen); |
| 2956 | return v; | 3001 | return v; |
| 2957 | } | 3002 | } |
| 2958 | 3003 | ||
| @@ -2961,10 +3006,9 @@ allocate_buffer (void) | |||
| 2961 | { | 3006 | { |
| 2962 | struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER); | 3007 | struct buffer *b = lisp_malloc (sizeof *b, MEM_TYPE_BUFFER); |
| 2963 | 3008 | ||
| 2964 | XSETPVECTYPESIZE (b, PVEC_BUFFER, (offsetof (struct buffer, own_text) | 3009 | BUFFER_PVEC_INIT (b); |
| 2965 | - header_size) / word_size); | ||
| 2966 | /* Put B on the chain of all buffers including killed ones. */ | 3010 | /* Put B on the chain of all buffers including killed ones. */ |
| 2967 | b->header.next.buffer = all_buffers; | 3011 | b->next = all_buffers; |
| 2968 | all_buffers = b; | 3012 | all_buffers = b; |
| 2969 | /* Note that the rest fields of B are not initialized. */ | 3013 | /* Note that the rest fields of B are not initialized. */ |
| 2970 | return b; | 3014 | return b; |
| @@ -4068,16 +4112,15 @@ live_vector_p (struct mem_node *m, void *p) | |||
| 4068 | while (VECTOR_IN_BLOCK (vector, block) | 4112 | while (VECTOR_IN_BLOCK (vector, block) |
| 4069 | && vector <= (struct Lisp_Vector *) p) | 4113 | && vector <= (struct Lisp_Vector *) p) |
| 4070 | { | 4114 | { |
| 4071 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) | 4115 | if (!PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) && vector == p) |
| 4072 | vector = ADVANCE (vector, (vector->header.size | ||
| 4073 | & PSEUDOVECTOR_SIZE_MASK)); | ||
| 4074 | else if (vector == p) | ||
| 4075 | return 1; | 4116 | return 1; |
| 4076 | else | 4117 | else |
| 4077 | vector = ADVANCE (vector, vector->header.next.nbytes); | 4118 | vector = ADVANCE (vector, vector_nbytes (vector)); |
| 4078 | } | 4119 | } |
| 4079 | } | 4120 | } |
| 4080 | else if (m->type == MEM_TYPE_VECTORLIKE && p == m->start) | 4121 | else if (m->type == MEM_TYPE_VECTORLIKE |
| 4122 | && (char *) p == ((char *) m->start | ||
| 4123 | + offsetof (struct large_vector, v))) | ||
| 4081 | /* This memory node corresponds to a large vector. */ | 4124 | /* This memory node corresponds to a large vector. */ |
| 4082 | return 1; | 4125 | return 1; |
| 4083 | return 0; | 4126 | return 0; |
| @@ -5687,7 +5730,7 @@ mark_object (Lisp_Object arg) | |||
| 5687 | 5730 | ||
| 5688 | if (ptr->header.size & PSEUDOVECTOR_FLAG) | 5731 | if (ptr->header.size & PSEUDOVECTOR_FLAG) |
| 5689 | pvectype = ((ptr->header.size & PVEC_TYPE_MASK) | 5732 | pvectype = ((ptr->header.size & PVEC_TYPE_MASK) |
| 5690 | >> PSEUDOVECTOR_SIZE_BITS); | 5733 | >> PSEUDOVECTOR_AREA_BITS); |
| 5691 | else | 5734 | else |
| 5692 | pvectype = PVEC_NORMAL_VECTOR; | 5735 | pvectype = PVEC_NORMAL_VECTOR; |
| 5693 | 5736 | ||
| @@ -6317,7 +6360,7 @@ gc_sweep (void) | |||
| 6317 | for (buffer = all_buffers; buffer; buffer = *bprev) | 6360 | for (buffer = all_buffers; buffer; buffer = *bprev) |
| 6318 | if (!VECTOR_MARKED_P (buffer)) | 6361 | if (!VECTOR_MARKED_P (buffer)) |
| 6319 | { | 6362 | { |
| 6320 | *bprev = buffer->header.next.buffer; | 6363 | *bprev = buffer->next; |
| 6321 | lisp_free (buffer); | 6364 | lisp_free (buffer); |
| 6322 | } | 6365 | } |
| 6323 | else | 6366 | else |
| @@ -6326,7 +6369,7 @@ gc_sweep (void) | |||
| 6326 | /* Do not use buffer_(set|get)_intervals here. */ | 6369 | /* Do not use buffer_(set|get)_intervals here. */ |
| 6327 | buffer->text->intervals = balance_intervals (buffer->text->intervals); | 6370 | buffer->text->intervals = balance_intervals (buffer->text->intervals); |
| 6328 | total_buffers++; | 6371 | total_buffers++; |
| 6329 | bprev = &buffer->header.next.buffer; | 6372 | bprev = &buffer->next; |
| 6330 | } | 6373 | } |
| 6331 | } | 6374 | } |
| 6332 | 6375 | ||
diff --git a/src/buffer.c b/src/buffer.c index bb69675346a..1d58df54f6f 100644 --- a/src/buffer.c +++ b/src/buffer.c | |||
| @@ -5105,11 +5105,6 @@ void | |||
| 5105 | init_buffer_once (void) | 5105 | init_buffer_once (void) |
| 5106 | { | 5106 | { |
| 5107 | int idx; | 5107 | int idx; |
| 5108 | /* If you add, remove, or reorder Lisp_Objects in a struct buffer, make | ||
| 5109 | sure that this is still correct. Otherwise, mark_vectorlike may not | ||
| 5110 | trace all Lisp_Objects in buffer_defaults and buffer_local_symbols. */ | ||
| 5111 | const int pvecsize | ||
| 5112 | = (offsetof (struct buffer, own_text) - header_size) / word_size; | ||
| 5113 | 5108 | ||
| 5114 | memset (buffer_permanent_local_flags, 0, sizeof buffer_permanent_local_flags); | 5109 | memset (buffer_permanent_local_flags, 0, sizeof buffer_permanent_local_flags); |
| 5115 | 5110 | ||
| @@ -5132,8 +5127,8 @@ init_buffer_once (void) | |||
| 5132 | /* This is not strictly necessary, but let's make them initialized. */ | 5127 | /* This is not strictly necessary, but let's make them initialized. */ |
| 5133 | bset_name (&buffer_defaults, build_pure_c_string (" *buffer-defaults*")); | 5128 | bset_name (&buffer_defaults, build_pure_c_string (" *buffer-defaults*")); |
| 5134 | bset_name (&buffer_local_symbols, build_pure_c_string (" *buffer-local-symbols*")); | 5129 | bset_name (&buffer_local_symbols, build_pure_c_string (" *buffer-local-symbols*")); |
| 5135 | XSETPVECTYPESIZE (&buffer_defaults, PVEC_BUFFER, pvecsize); | 5130 | BUFFER_PVEC_INIT (&buffer_defaults); |
| 5136 | XSETPVECTYPESIZE (&buffer_local_symbols, PVEC_BUFFER, pvecsize); | 5131 | BUFFER_PVEC_INIT (&buffer_local_symbols); |
| 5137 | 5132 | ||
| 5138 | /* Set up the default values of various buffer slots. */ | 5133 | /* Set up the default values of various buffer slots. */ |
| 5139 | /* Must do these before making the first buffer! */ | 5134 | /* Must do these before making the first buffer! */ |
diff --git a/src/buffer.h b/src/buffer.h index 9e0e9eef0b1..fbbbf1b8434 100644 --- a/src/buffer.h +++ b/src/buffer.h | |||
| @@ -482,11 +482,6 @@ struct buffer_text | |||
| 482 | 482 | ||
| 483 | struct buffer | 483 | struct buffer |
| 484 | { | 484 | { |
| 485 | /* HEADER.NEXT is the next buffer, in chain of all buffers, including killed | ||
| 486 | buffers. This chain, starting from all_buffers, is used only for garbage | ||
| 487 | collection, in order to collect killed buffers properly. Note that large | ||
| 488 | vectors and large pseudo-vector objects are all on another chain starting | ||
| 489 | from large_vectors. */ | ||
| 490 | struct vectorlike_header header; | 485 | struct vectorlike_header header; |
| 491 | 486 | ||
| 492 | /* The name of this buffer. */ | 487 | /* The name of this buffer. */ |
| @@ -750,6 +745,9 @@ struct buffer | |||
| 750 | In an indirect buffer, this is the own_text field of another buffer. */ | 745 | In an indirect buffer, this is the own_text field of another buffer. */ |
| 751 | struct buffer_text *text; | 746 | struct buffer_text *text; |
| 752 | 747 | ||
| 748 | /* Next buffer, in chain of all buffers, including killed ones. */ | ||
| 749 | struct buffer *next; | ||
| 750 | |||
| 753 | /* Char position of point in buffer. */ | 751 | /* Char position of point in buffer. */ |
| 754 | ptrdiff_t pt; | 752 | ptrdiff_t pt; |
| 755 | 753 | ||
| @@ -959,6 +957,27 @@ bset_width_table (struct buffer *b, Lisp_Object val) | |||
| 959 | b->INTERNAL_FIELD (width_table) = val; | 957 | b->INTERNAL_FIELD (width_table) = val; |
| 960 | } | 958 | } |
| 961 | 959 | ||
| 960 | /* Number of Lisp_Objects at the beginning of struct buffer. | ||
| 961 | If you add, remove, or reorder Lisp_Objects within buffer | ||
| 962 | structure, make sure that this is still correct. */ | ||
| 963 | |||
| 964 | #define BUFFER_LISP_SIZE \ | ||
| 965 | ((offsetof (struct buffer, own_text) - header_size) / word_size) | ||
| 966 | |||
| 967 | /* Size of the struct buffer part beyond leading Lisp_Objects, in word_size | ||
| 968 | units. Rounding is needed for --with-wide-int configuration. */ | ||
| 969 | |||
| 970 | #define BUFFER_REST_SIZE \ | ||
| 971 | ((((sizeof (struct buffer) - offsetof (struct buffer, own_text)) \ | ||
| 972 | + (word_size - 1)) & ~(word_size - 1)) / word_size) | ||
| 973 | |||
| 974 | /* Initialize the pseudovector header of buffer object. BUFFER_LISP_SIZE | ||
| 975 | is required for GC, but BUFFER_REST_SIZE is set up just to be consistent | ||
| 976 | with other pseudovectors. */ | ||
| 977 | |||
| 978 | #define BUFFER_PVEC_INIT(b) \ | ||
| 979 | XSETPVECTYPESIZE (b, PVEC_BUFFER, BUFFER_LISP_SIZE, BUFFER_REST_SIZE) | ||
| 980 | |||
| 962 | /* Convenient check whether buffer B is live. */ | 981 | /* Convenient check whether buffer B is live. */ |
| 963 | 982 | ||
| 964 | #define BUFFER_LIVE_P(b) (!NILP (BVAR (b, name))) | 983 | #define BUFFER_LIVE_P(b) (!NILP (BVAR (b, name))) |
| @@ -986,7 +1005,7 @@ extern struct buffer *all_buffers; | |||
| 986 | /* Used to iterate over the chain above. */ | 1005 | /* Used to iterate over the chain above. */ |
| 987 | 1006 | ||
| 988 | #define FOR_EACH_BUFFER(b) \ | 1007 | #define FOR_EACH_BUFFER(b) \ |
| 989 | for ((b) = all_buffers; (b); (b) = (b)->header.next.buffer) | 1008 | for ((b) = all_buffers; (b); (b) = (b)->next) |
| 990 | 1009 | ||
| 991 | /* This points to the current buffer. */ | 1010 | /* This points to the current buffer. */ |
| 992 | 1011 | ||
| @@ -2076,9 +2076,8 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, int depth, bool props) | |||
| 2076 | are sensible to compare, so eliminate the others now. */ | 2076 | are sensible to compare, so eliminate the others now. */ |
| 2077 | if (size & PSEUDOVECTOR_FLAG) | 2077 | if (size & PSEUDOVECTOR_FLAG) |
| 2078 | { | 2078 | { |
| 2079 | if (!(size & ((PVEC_COMPILED | PVEC_CHAR_TABLE | 2079 | if (((size & PVEC_TYPE_MASK) >> PSEUDOVECTOR_AREA_BITS) |
| 2080 | | PVEC_SUB_CHAR_TABLE | PVEC_FONT) | 2080 | < PVEC_COMPILED) |
| 2081 | << PSEUDOVECTOR_SIZE_BITS))) | ||
| 2082 | return 0; | 2081 | return 0; |
| 2083 | size &= PSEUDOVECTOR_SIZE_MASK; | 2082 | size &= PSEUDOVECTOR_SIZE_MASK; |
| 2084 | } | 2083 | } |
| @@ -3661,12 +3660,9 @@ copy_hash_table (struct Lisp_Hash_Table *h1) | |||
| 3661 | { | 3660 | { |
| 3662 | Lisp_Object table; | 3661 | Lisp_Object table; |
| 3663 | struct Lisp_Hash_Table *h2; | 3662 | struct Lisp_Hash_Table *h2; |
| 3664 | struct Lisp_Vector *next; | ||
| 3665 | 3663 | ||
| 3666 | h2 = allocate_hash_table (); | 3664 | h2 = allocate_hash_table (); |
| 3667 | next = h2->header.next.vector; | ||
| 3668 | *h2 = *h1; | 3665 | *h2 = *h1; |
| 3669 | h2->header.next.vector = next; | ||
| 3670 | h2->key_and_value = Fcopy_sequence (h1->key_and_value); | 3666 | h2->key_and_value = Fcopy_sequence (h1->key_and_value); |
| 3671 | h2->hash = Fcopy_sequence (h1->hash); | 3667 | h2->hash = Fcopy_sequence (h1->hash); |
| 3672 | h2->next = Fcopy_sequence (h1->next); | 3668 | h2->next = Fcopy_sequence (h1->next); |
diff --git a/src/lisp.h b/src/lisp.h index 88d9b766f38..66612e2987e 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -408,14 +408,11 @@ enum pvec_type | |||
| 408 | PVEC_WINDOW_CONFIGURATION, | 408 | PVEC_WINDOW_CONFIGURATION, |
| 409 | PVEC_SUBR, | 409 | PVEC_SUBR, |
| 410 | PVEC_OTHER, | 410 | PVEC_OTHER, |
| 411 | /* These last 4 are special because we OR them in fns.c:internal_equal, | 411 | /* These should be last, check internal_equal to see why. */ |
| 412 | so they have to use a disjoint bit pattern: | 412 | PVEC_COMPILED, |
| 413 | if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE | 413 | PVEC_CHAR_TABLE, |
| 414 | | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) */ | 414 | PVEC_SUB_CHAR_TABLE, |
| 415 | PVEC_COMPILED = 0x10, | 415 | PVEC_FONT /* Should be last because it's used for range checking. */ |
| 416 | PVEC_CHAR_TABLE = 0x20, | ||
| 417 | PVEC_SUB_CHAR_TABLE = 0x30, | ||
| 418 | PVEC_FONT = 0x40 | ||
| 419 | }; | 416 | }; |
| 420 | 417 | ||
| 421 | /* DATA_SEG_BITS forces extra bits to be or'd in with any pointers | 418 | /* DATA_SEG_BITS forces extra bits to be or'd in with any pointers |
| @@ -435,9 +432,18 @@ enum More_Lisp_Bits | |||
| 435 | only the number of Lisp_Object fields (that need to be traced by GC). | 432 | only the number of Lisp_Object fields (that need to be traced by GC). |
| 436 | The distinction is used, e.g., by Lisp_Process, which places extra | 433 | The distinction is used, e.g., by Lisp_Process, which places extra |
| 437 | non-Lisp_Object fields at the end of the structure. */ | 434 | non-Lisp_Object fields at the end of the structure. */ |
| 438 | PSEUDOVECTOR_SIZE_BITS = 16, | 435 | PSEUDOVECTOR_SIZE_BITS = 12, |
| 439 | PSEUDOVECTOR_SIZE_MASK = (1 << PSEUDOVECTOR_SIZE_BITS) - 1, | 436 | PSEUDOVECTOR_SIZE_MASK = (1 << PSEUDOVECTOR_SIZE_BITS) - 1, |
| 440 | PVEC_TYPE_MASK = 0x0fff << PSEUDOVECTOR_SIZE_BITS, | 437 | |
| 438 | /* To calculate the memory footprint of the pseudovector, it's useful | ||
| 439 | to store the size of non-Lisp area in word_size units here. */ | ||
| 440 | PSEUDOVECTOR_REST_BITS = 12, | ||
| 441 | PSEUDOVECTOR_REST_MASK = (((1 << PSEUDOVECTOR_REST_BITS) - 1) | ||
| 442 | << PSEUDOVECTOR_SIZE_BITS), | ||
| 443 | |||
| 444 | /* Used to extract pseudovector subtype information. */ | ||
| 445 | PSEUDOVECTOR_AREA_BITS = PSEUDOVECTOR_SIZE_BITS + PSEUDOVECTOR_REST_BITS, | ||
| 446 | PVEC_TYPE_MASK = 0x3f << PSEUDOVECTOR_AREA_BITS, | ||
| 441 | 447 | ||
| 442 | /* Number of bits to put in each character in the internal representation | 448 | /* Number of bits to put in each character in the internal representation |
| 443 | of bool vectors. This should not vary across implementations. */ | 449 | of bool vectors. This should not vary across implementations. */ |
| @@ -608,13 +614,13 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) | |||
| 608 | 614 | ||
| 609 | /* Pseudovector types. */ | 615 | /* Pseudovector types. */ |
| 610 | 616 | ||
| 611 | #define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code) | 617 | #define XSETPVECTYPE(v, code) \ |
| 612 | #define XSETTYPED_PVECTYPE(v, size_member, code) \ | 618 | ((v)->header.size |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS)) |
| 613 | ((v)->size_member |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)) | 619 | #define XSETPVECTYPESIZE(v, code, lispsize, restsize) \ |
| 614 | #define XSETPVECTYPESIZE(v, code, sizeval) \ | ||
| 615 | ((v)->header.size = (PSEUDOVECTOR_FLAG \ | 620 | ((v)->header.size = (PSEUDOVECTOR_FLAG \ |
| 616 | | ((code) << PSEUDOVECTOR_SIZE_BITS) \ | 621 | | ((code) << PSEUDOVECTOR_AREA_BITS) \ |
| 617 | | (sizeval))) | 622 | | ((restsize) << PSEUDOVECTOR_SIZE_BITS) \ |
| 623 | | (lispsize))) | ||
| 618 | 624 | ||
| 619 | /* The cast to struct vectorlike_header * avoids aliasing issues. */ | 625 | /* The cast to struct vectorlike_header * avoids aliasing issues. */ |
| 620 | #define XSETPSEUDOVECTOR(a, b, code) \ | 626 | #define XSETPSEUDOVECTOR(a, b, code) \ |
| @@ -626,16 +632,14 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) | |||
| 626 | #define XSETTYPED_PSEUDOVECTOR(a, b, size, code) \ | 632 | #define XSETTYPED_PSEUDOVECTOR(a, b, size, code) \ |
| 627 | (XSETVECTOR (a, b), \ | 633 | (XSETVECTOR (a, b), \ |
| 628 | eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ | 634 | eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ |
| 629 | == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS)))) | 635 | == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_AREA_BITS)))) |
| 630 | 636 | ||
| 631 | #define XSETWINDOW_CONFIGURATION(a, b) \ | 637 | #define XSETWINDOW_CONFIGURATION(a, b) \ |
| 632 | (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION)) | 638 | (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION)) |
| 633 | #define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS)) | 639 | #define XSETPROCESS(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_PROCESS)) |
| 634 | #define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW)) | 640 | #define XSETWINDOW(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW)) |
| 635 | #define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL)) | 641 | #define XSETTERMINAL(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_TERMINAL)) |
| 636 | /* XSETSUBR is special since Lisp_Subr lacks struct vectorlike_header. */ | 642 | #define XSETSUBR(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_SUBR)) |
| 637 | #define XSETSUBR(a, b) \ | ||
| 638 | XSETTYPED_PSEUDOVECTOR (a, b, XSUBR (a)->size, PVEC_SUBR) | ||
| 639 | #define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED)) | 643 | #define XSETCOMPILED(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_COMPILED)) |
| 640 | #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER)) | 644 | #define XSETBUFFER(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_BUFFER)) |
| 641 | #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE)) | 645 | #define XSETCHAR_TABLE(a, b) (XSETPSEUDOVECTOR (a, b, PVEC_CHAR_TABLE)) |
| @@ -802,7 +806,7 @@ struct Lisp_String | |||
| 802 | }; | 806 | }; |
| 803 | 807 | ||
| 804 | /* Header of vector-like objects. This documents the layout constraints on | 808 | /* Header of vector-like objects. This documents the layout constraints on |
| 805 | vectors and pseudovectors other than struct Lisp_Subr. It also prevents | 809 | vectors and pseudovectors (objects of PVEC_xxx subtype). It also prevents |
| 806 | compilers from being fooled by Emacs's type punning: the XSETPSEUDOVECTOR | 810 | compilers from being fooled by Emacs's type punning: the XSETPSEUDOVECTOR |
| 807 | and PSEUDOVECTORP macros cast their pointers to struct vectorlike_header *, | 811 | and PSEUDOVECTORP macros cast their pointers to struct vectorlike_header *, |
| 808 | because when two such pointers potentially alias, a compiler won't | 812 | because when two such pointers potentially alias, a compiler won't |
| @@ -810,43 +814,26 @@ struct Lisp_String | |||
| 810 | <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */ | 814 | <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */ |
| 811 | struct vectorlike_header | 815 | struct vectorlike_header |
| 812 | { | 816 | { |
| 813 | /* This field contains various pieces of information: | 817 | /* The only field contains various pieces of information: |
| 814 | - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit. | 818 | - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit. |
| 815 | - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain | 819 | - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain |
| 816 | vector (0) or a pseudovector (1). | 820 | vector (0) or a pseudovector (1). |
| 817 | - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number | 821 | - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number |
| 818 | of slots) of the vector. | 822 | of slots) of the vector. |
| 819 | - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into | 823 | - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into three fields: |
| 820 | a "pvec type" tag held in PVEC_TYPE_MASK and a size held in the lowest | 824 | - a) pseudovector subtype held in PVEC_TYPE_MASK field; |
| 821 | PSEUDOVECTOR_SIZE_BITS. That size normally indicates the number of | 825 | - b) number of Lisp_Objects slots at the beginning of the object |
| 822 | Lisp_Object slots at the beginning of the object that need to be | 826 | held in PSEUDOVECTOR_SIZE_MASK field. These objects are always |
| 823 | traced by the GC, tho some types use it slightly differently. | 827 | traced by the GC; |
| 824 | - E.g. if the pvec type is PVEC_FREE it means this is an unallocated | 828 | - c) size of the rest fields held in PSEUDOVECTOR_REST_MASK and |
| 825 | vector on a free-list and PSEUDOVECTOR_SIZE_BITS indicates its size | 829 | measured in word_size units. Rest fields may also include |
| 826 | in bytes. */ | 830 | Lisp_Objects, but these objects usually needs some special treatment |
| 831 | during GC. | ||
| 832 | There are some exceptions. For PVEC_FREE, b) is always zero. For | ||
| 833 | PVEC_BOOL_VECTOR and PVEC_SUBR, both b) and c) are always zero. | ||
| 834 | Current layout limits the pseudovectors to 63 PVEC_xxx subtypes, | ||
| 835 | 4095 Lisp_Objects in GC-ed area and 4095 word-sized other slots. */ | ||
| 827 | ptrdiff_t size; | 836 | ptrdiff_t size; |
| 828 | |||
| 829 | /* When the vector is allocated from a vector block, NBYTES is used | ||
| 830 | if the vector is not on a free list, and VECTOR is used otherwise. | ||
| 831 | For large vector-like objects, BUFFER or VECTOR is used as a pointer | ||
| 832 | to the next vector-like object. It is generally a buffer or a | ||
| 833 | Lisp_Vector alias, so for convenience it is a union instead of a | ||
| 834 | pointer: this way, one can write P->next.vector instead of ((struct | ||
| 835 | Lisp_Vector *) P->next). */ | ||
| 836 | union { | ||
| 837 | /* This is only needed for small vectors that are not free because the | ||
| 838 | `size' field only gives us the number of Lisp_Object slots, whereas we | ||
| 839 | need to know the total size, including non-Lisp_Object data. | ||
| 840 | FIXME: figure out a way to store this info elsewhere so we can | ||
| 841 | finally get rid of this extra word of overhead. */ | ||
| 842 | ptrdiff_t nbytes; | ||
| 843 | struct buffer *buffer; | ||
| 844 | /* FIXME: This can be removed: For large vectors, this field could be | ||
| 845 | placed *before* the vector itself. And for small vectors on a free | ||
| 846 | list, this field could be stored in the vector's bytes, since the | ||
| 847 | empty vector is handled specially anyway. */ | ||
| 848 | struct Lisp_Vector *vector; | ||
| 849 | } next; | ||
| 850 | }; | 837 | }; |
| 851 | 838 | ||
| 852 | /* Regular vector is just a header plus array of Lisp_Objects. */ | 839 | /* Regular vector is just a header plus array of Lisp_Objects. */ |
| @@ -1020,15 +1007,11 @@ struct Lisp_Sub_Char_Table | |||
| 1020 | 1007 | ||
| 1021 | /* This structure describes a built-in function. | 1008 | /* This structure describes a built-in function. |
| 1022 | It is generated by the DEFUN macro only. | 1009 | It is generated by the DEFUN macro only. |
| 1023 | defsubr makes it into a Lisp object. | 1010 | defsubr makes it into a Lisp object. */ |
| 1024 | |||
| 1025 | This type is treated in most respects as a pseudovector, | ||
| 1026 | but since we never dynamically allocate or free them, | ||
| 1027 | we don't need a struct vectorlike_header and its 'next' field. */ | ||
| 1028 | 1011 | ||
| 1029 | struct Lisp_Subr | 1012 | struct Lisp_Subr |
| 1030 | { | 1013 | { |
| 1031 | ptrdiff_t size; | 1014 | struct vectorlike_header header; |
| 1032 | union { | 1015 | union { |
| 1033 | Lisp_Object (*a0) (void); | 1016 | Lisp_Object (*a0) (void); |
| 1034 | Lisp_Object (*a1) (Lisp_Object); | 1017 | Lisp_Object (*a1) (Lisp_Object); |
| @@ -1709,7 +1692,7 @@ typedef struct { | |||
| 1709 | 1692 | ||
| 1710 | #define PSEUDOVECTOR_TYPEP(v, code) \ | 1693 | #define PSEUDOVECTOR_TYPEP(v, code) \ |
| 1711 | (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ | 1694 | (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ |
| 1712 | == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS))) | 1695 | == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_AREA_BITS))) |
| 1713 | 1696 | ||
| 1714 | /* True if object X, with internal type struct T *, is a pseudovector whose | 1697 | /* True if object X, with internal type struct T *, is a pseudovector whose |
| 1715 | code is CODE. */ | 1698 | code is CODE. */ |
| @@ -1722,8 +1705,7 @@ typedef struct { | |||
| 1722 | #define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS) | 1705 | #define PROCESSP(x) PSEUDOVECTORP (x, PVEC_PROCESS) |
| 1723 | #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW) | 1706 | #define WINDOWP(x) PSEUDOVECTORP (x, PVEC_WINDOW) |
| 1724 | #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL) | 1707 | #define TERMINALP(x) PSEUDOVECTORP (x, PVEC_TERMINAL) |
| 1725 | /* SUBRP is special since Lisp_Subr lacks struct vectorlike_header. */ | 1708 | #define SUBRP(x) PSEUDOVECTORP (x, PVEC_SUBR) |
| 1726 | #define SUBRP(x) TYPED_PSEUDOVECTORP (x, Lisp_Subr, PVEC_SUBR) | ||
| 1727 | #define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED) | 1709 | #define COMPILEDP(x) PSEUDOVECTORP (x, PVEC_COMPILED) |
| 1728 | #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER) | 1710 | #define BUFFERP(x) PSEUDOVECTORP (x, PVEC_BUFFER) |
| 1729 | #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE) | 1711 | #define CHAR_TABLE_P(x) PSEUDOVECTORP (x, PVEC_CHAR_TABLE) |
| @@ -1898,8 +1880,8 @@ typedef struct { | |||
| 1898 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ | 1880 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ |
| 1899 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ | 1881 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ |
| 1900 | static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ | 1882 | static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ |
| 1901 | { (PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS) \ | 1883 | { { (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS) \ |
| 1902 | | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \ | 1884 | | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)) }, \ |
| 1903 | { (Lisp_Object (__cdecl *)(void))fnname }, \ | 1885 | { (Lisp_Object (__cdecl *)(void))fnname }, \ |
| 1904 | minargs, maxargs, lname, intspec, 0}; \ | 1886 | minargs, maxargs, lname, intspec, 0}; \ |
| 1905 | Lisp_Object fnname | 1887 | Lisp_Object fnname |
| @@ -1907,8 +1889,8 @@ typedef struct { | |||
| 1907 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ | 1889 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ |
| 1908 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ | 1890 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ |
| 1909 | static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ | 1891 | static struct Lisp_Subr alignas (GCALIGNMENT) sname = \ |
| 1910 | { PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS, \ | 1892 | { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS }, \ |
| 1911 | { .a ## maxargs = fnname }, \ | 1893 | { .a ## maxargs = fnname }, \ |
| 1912 | minargs, maxargs, lname, intspec, 0}; \ | 1894 | minargs, maxargs, lname, intspec, 0}; \ |
| 1913 | Lisp_Object fnname | 1895 | Lisp_Object fnname |
| 1914 | #endif | 1896 | #endif |
| @@ -2952,7 +2934,7 @@ extern void make_byte_code (struct Lisp_Vector *); | |||
| 2952 | extern Lisp_Object Qautomatic_gc; | 2934 | extern Lisp_Object Qautomatic_gc; |
| 2953 | extern Lisp_Object Qchar_table_extra_slots; | 2935 | extern Lisp_Object Qchar_table_extra_slots; |
| 2954 | extern struct Lisp_Vector *allocate_vector (EMACS_INT); | 2936 | extern struct Lisp_Vector *allocate_vector (EMACS_INT); |
| 2955 | extern struct Lisp_Vector *allocate_pseudovector (int memlen, int lisplen, int tag); | 2937 | extern struct Lisp_Vector *allocate_pseudovector (int, int, enum pvec_type); |
| 2956 | #define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ | 2938 | #define ALLOCATE_PSEUDOVECTOR(typ,field,tag) \ |
| 2957 | ((typ*) \ | 2939 | ((typ*) \ |
| 2958 | allocate_pseudovector \ | 2940 | allocate_pseudovector \ |
diff --git a/src/lread.c b/src/lread.c index 94744620279..3a82e0057e2 100644 --- a/src/lread.c +++ b/src/lread.c | |||
| @@ -3981,7 +3981,7 @@ defsubr (struct Lisp_Subr *sname) | |||
| 3981 | { | 3981 | { |
| 3982 | Lisp_Object sym, tem; | 3982 | Lisp_Object sym, tem; |
| 3983 | sym = intern_c_string (sname->symbol_name); | 3983 | sym = intern_c_string (sname->symbol_name); |
| 3984 | XSETTYPED_PVECTYPE (sname, size, PVEC_SUBR); | 3984 | XSETPVECTYPE (sname, PVEC_SUBR); |
| 3985 | XSETSUBR (tem, sname); | 3985 | XSETSUBR (tem, sname); |
| 3986 | set_symbol_function (sym, tem); | 3986 | set_symbol_function (sym, tem); |
| 3987 | } | 3987 | } |