diff options
| author | Stefan Monnier | 2012-07-04 10:38:02 -0400 |
|---|---|---|
| committer | Stefan Monnier | 2012-07-04 10:38:02 -0400 |
| commit | ee28be33a535e41c74f3a4d5c0f3878e44366942 (patch) | |
| tree | aea01076d95159b7559ec34cd47acd9245f46a7b /src | |
| parent | 1a9746debdc8965edd84d27537ef9c55511ea04e (diff) | |
| download | emacs-ee28be33a535e41c74f3a4d5c0f3878e44366942.tar.gz emacs-ee28be33a535e41c74f3a4d5c0f3878e44366942.zip | |
Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE.
* src/lisp.h (enum pvec_type): Use fewer bits.
(PSEUDOVECTOR_SIZE_BITS): New constant.
(PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK): Use it.
(XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR, DEFUN): Adapt code to
change in pvec_type.
(PSEUDOVECTOR_TYPEP): New macro.
(TYPED_PSEUDOVECTORP): Use it.
* src/fns.c (internal_equal): Adapt code to extract pvectype.
* src/emacs.c (gdb_pvec_type): Update type.
* src/alloc.c (PSEUDOVECTOR_NBYTES): New macro.
(VECTOR_FREE_LIST_SIZE_MASK): Remove (=> PSEUDOVECTOR_SIZE_MASK).
(VECTOR_FREE_LIST_FLAG): Remove (=> PVEC_FREE).
(SETUP_ON_FREE_LIST): Use XSETPVECTYPESIZE.
(sweep_vectors): Use it. Use local var `total_bytes' instead of
abusing vector->header.next.nbytes.
(live_vector_p): Use PVEC_TYPE.
(mark_object): Adapt code to extract pvectype. Use switch.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 21 | ||||
| -rw-r--r-- | src/alloc.c | 184 | ||||
| -rw-r--r-- | src/emacs.c | 2 | ||||
| -rw-r--r-- | src/fns.c | 5 | ||||
| -rw-r--r-- | src/lisp.h | 98 |
5 files changed, 184 insertions, 126 deletions
diff --git a/src/ChangeLog b/src/ChangeLog index a600a0b2b6f..70f7fedf5ad 100644 --- a/src/ChangeLog +++ b/src/ChangeLog | |||
| @@ -1,3 +1,24 @@ | |||
| 1 | 2012-07-04 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | Turn VECTOR_FREE_LIST_FLAG into PVEC_FREE. | ||
| 4 | * lisp.h (enum pvec_type): Use fewer bits. | ||
| 5 | (PSEUDOVECTOR_SIZE_BITS): New constant. | ||
| 6 | (PSEUDOVECTOR_SIZE_MASK, PVEC_TYPE_MASK): Use it. | ||
| 7 | (XSETPVECTYPESIZE, XSETTYPED_PSEUDOVECTOR, DEFUN): Adapt code to | ||
| 8 | change in pvec_type. | ||
| 9 | (PSEUDOVECTOR_TYPEP): New macro. | ||
| 10 | (TYPED_PSEUDOVECTORP): Use it. | ||
| 11 | * fns.c (internal_equal): Adapt code to extract pvectype. | ||
| 12 | * emacs.c (gdb_pvec_type): Update type. | ||
| 13 | * alloc.c (PSEUDOVECTOR_NBYTES): New macro. | ||
| 14 | (VECTOR_FREE_LIST_SIZE_MASK): Remove (=> PSEUDOVECTOR_SIZE_MASK). | ||
| 15 | (VECTOR_FREE_LIST_FLAG): Remove (=> PVEC_FREE). | ||
| 16 | (SETUP_ON_FREE_LIST): Use XSETPVECTYPESIZE. | ||
| 17 | (sweep_vectors): Use it. Use local var `total_bytes' instead of | ||
| 18 | abusing vector->header.next.nbytes. | ||
| 19 | (live_vector_p): Use PVEC_TYPE. | ||
| 20 | (mark_object): Adapt code to extract pvectype. Use switch. | ||
| 21 | |||
| 1 | 2012-07-04 Paul Eggert <eggert@cs.ucla.edu> | 22 | 2012-07-04 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 23 | ||
| 3 | * doprnt.c (doprnt): Don't assume string length fits in 'int'. | 24 | * doprnt.c (doprnt): Don't assume string length fits in 'int'. |
diff --git a/src/alloc.c b/src/alloc.c index b1e2ed0a2ed..bd68f2b31f2 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1529,7 +1529,7 @@ make_interval (void) | |||
| 1529 | } | 1529 | } |
| 1530 | 1530 | ||
| 1531 | 1531 | ||
| 1532 | /* Mark Lisp objects in interval I. */ | 1532 | /* Mark Lisp objects in interval I. */ |
| 1533 | 1533 | ||
| 1534 | static void | 1534 | static void |
| 1535 | mark_interval (register INTERVAL i, Lisp_Object dummy) | 1535 | mark_interval (register INTERVAL i, Lisp_Object dummy) |
| @@ -1836,7 +1836,7 @@ check_sblock (struct sblock *b) | |||
| 1836 | ptrdiff_t nbytes; | 1836 | ptrdiff_t nbytes; |
| 1837 | 1837 | ||
| 1838 | /* Check that the string size recorded in the string is the | 1838 | /* Check that the string size recorded in the string is the |
| 1839 | same as the one recorded in the sdata structure. */ | 1839 | same as the one recorded in the sdata structure. */ |
| 1840 | if (from->string) | 1840 | if (from->string) |
| 1841 | CHECK_STRING_BYTES (from->string); | 1841 | CHECK_STRING_BYTES (from->string); |
| 1842 | 1842 | ||
| @@ -2869,12 +2869,6 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | |||
| 2869 | 2869 | ||
| 2870 | #define VECTOR_BLOCK_SIZE 4096 | 2870 | #define VECTOR_BLOCK_SIZE 4096 |
| 2871 | 2871 | ||
| 2872 | /* This special value is used to calculate vector size when the vector is | ||
| 2873 | on a free list. It should be VECTOR_BLOCK_SIZE rounded up to nearest | ||
| 2874 | power of two, minus one. */ | ||
| 2875 | |||
| 2876 | #define VECTOR_FREE_LIST_SIZE_MASK 4095 | ||
| 2877 | |||
| 2878 | /* Handy constants for vectorlike objects. */ | 2872 | /* Handy constants for vectorlike objects. */ |
| 2879 | enum | 2873 | enum |
| 2880 | { | 2874 | { |
| @@ -2889,8 +2883,7 @@ verify ((roundup_size & (roundup_size - 1)) == 0); | |||
| 2889 | 2883 | ||
| 2890 | /* Verify assumptions described above. */ | 2884 | /* Verify assumptions described above. */ |
| 2891 | verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); | 2885 | verify ((VECTOR_BLOCK_SIZE % roundup_size) == 0); |
| 2892 | verify ((VECTOR_FREE_LIST_SIZE_MASK + 1) >= VECTOR_BLOCK_SIZE); | 2886 | verify (VECTOR_BLOCK_SIZE <= (1 << PSEUDOVECTOR_SIZE_BITS)); |
| 2893 | verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); | ||
| 2894 | 2887 | ||
| 2895 | /* Round up X to nearest mult-of-ROUNDUP_SIZE. */ | 2888 | /* Round up X to nearest mult-of-ROUNDUP_SIZE. */ |
| 2896 | 2889 | ||
| @@ -2915,12 +2908,6 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); | |||
| 2915 | #define VECTOR_MAX_FREE_LIST_INDEX \ | 2908 | #define VECTOR_MAX_FREE_LIST_INDEX \ |
| 2916 | ((VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1) | 2909 | ((VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1) |
| 2917 | 2910 | ||
| 2918 | /* When the vector is on a free list, vectorlike_header.SIZE is set to | ||
| 2919 | this special value ORed with vector's memory footprint size. */ | ||
| 2920 | |||
| 2921 | #define VECTOR_FREE_LIST_FLAG (~(ARRAY_MARK_FLAG | PSEUDOVECTOR_FLAG \ | ||
| 2922 | | VECTOR_FREE_LIST_SIZE_MASK)) | ||
| 2923 | |||
| 2924 | /* Common shortcut to advance vector pointer over a block data. */ | 2911 | /* Common shortcut to advance vector pointer over a block data. */ |
| 2925 | 2912 | ||
| 2926 | #define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes))) | 2913 | #define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes))) |
| @@ -2933,7 +2920,7 @@ verify ((VECTOR_FREE_LIST_SIZE_MASK & (VECTOR_FREE_LIST_SIZE_MASK + 1)) == 0); | |||
| 2933 | 2920 | ||
| 2934 | #define SETUP_ON_FREE_LIST(v, nbytes, index) \ | 2921 | #define SETUP_ON_FREE_LIST(v, nbytes, index) \ |
| 2935 | do { \ | 2922 | do { \ |
| 2936 | (v)->header.size = VECTOR_FREE_LIST_FLAG | (nbytes); \ | 2923 | XSETPVECTYPESIZE (v, PVEC_FREE, nbytes); \ |
| 2937 | eassert ((nbytes) % roundup_size == 0); \ | 2924 | eassert ((nbytes) % roundup_size == 0); \ |
| 2938 | (index) = VINDEX (nbytes); \ | 2925 | (index) = VINDEX (nbytes); \ |
| 2939 | eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ | 2926 | eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ |
| @@ -3065,6 +3052,16 @@ allocate_vector_from_block (size_t nbytes) | |||
| 3065 | ((char *) (vector) <= (block)->data \ | 3052 | ((char *) (vector) <= (block)->data \ |
| 3066 | + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) | 3053 | + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) |
| 3067 | 3054 | ||
| 3055 | /* Number of bytes used by vector-block-allocated object. This is the only | ||
| 3056 | place where we actually use the `nbytes' field of the vector-header. | ||
| 3057 | I.e. we could get rid of the `nbytes' field by computing it based on the | ||
| 3058 | vector-type. */ | ||
| 3059 | |||
| 3060 | #define PSEUDOVECTOR_NBYTES(vector) \ | ||
| 3061 | (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE) \ | ||
| 3062 | ? vector->header.size & PSEUDOVECTOR_SIZE_MASK \ | ||
| 3063 | : vector->header.next.nbytes); | ||
| 3064 | |||
| 3068 | /* Reclaim space used by unmarked vectors. */ | 3065 | /* Reclaim space used by unmarked vectors. */ |
| 3069 | 3066 | ||
| 3070 | static void | 3067 | static void |
| @@ -3093,14 +3090,10 @@ sweep_vectors (void) | |||
| 3093 | } | 3090 | } |
| 3094 | else | 3091 | else |
| 3095 | { | 3092 | { |
| 3096 | ptrdiff_t nbytes; | 3093 | ptrdiff_t nbytes = PSEUDOVECTOR_NBYTES (vector); |
| 3094 | ptrdiff_t total_bytes = nbytes; | ||
| 3097 | 3095 | ||
| 3098 | if ((vector->header.size & VECTOR_FREE_LIST_FLAG) | 3096 | next = ADVANCE (vector, nbytes); |
| 3099 | == VECTOR_FREE_LIST_FLAG) | ||
| 3100 | vector->header.next.nbytes = | ||
| 3101 | vector->header.size & VECTOR_FREE_LIST_SIZE_MASK; | ||
| 3102 | |||
| 3103 | next = ADVANCE (vector, vector->header.next.nbytes); | ||
| 3104 | 3097 | ||
| 3105 | /* While NEXT is not marked, try to coalesce with VECTOR, | 3098 | /* While NEXT is not marked, try to coalesce with VECTOR, |
| 3106 | thus making VECTOR of the largest possible size. */ | 3099 | thus making VECTOR of the largest possible size. */ |
| @@ -3109,16 +3102,12 @@ sweep_vectors (void) | |||
| 3109 | { | 3102 | { |
| 3110 | if (VECTOR_MARKED_P (next)) | 3103 | if (VECTOR_MARKED_P (next)) |
| 3111 | break; | 3104 | break; |
| 3112 | if ((next->header.size & VECTOR_FREE_LIST_FLAG) | 3105 | nbytes = PSEUDOVECTOR_NBYTES (next); |
| 3113 | == VECTOR_FREE_LIST_FLAG) | 3106 | total_bytes += nbytes; |
| 3114 | nbytes = next->header.size & VECTOR_FREE_LIST_SIZE_MASK; | ||
| 3115 | else | ||
| 3116 | nbytes = next->header.next.nbytes; | ||
| 3117 | vector->header.next.nbytes += nbytes; | ||
| 3118 | next = ADVANCE (next, nbytes); | 3107 | next = ADVANCE (next, nbytes); |
| 3119 | } | 3108 | } |
| 3120 | 3109 | ||
| 3121 | eassert (vector->header.next.nbytes % roundup_size == 0); | 3110 | eassert (total_bytes % roundup_size == 0); |
| 3122 | 3111 | ||
| 3123 | if (vector == (struct Lisp_Vector *) block->data | 3112 | if (vector == (struct Lisp_Vector *) block->data |
| 3124 | && !VECTOR_IN_BLOCK (next, block)) | 3113 | && !VECTOR_IN_BLOCK (next, block)) |
| @@ -3126,7 +3115,10 @@ sweep_vectors (void) | |||
| 3126 | space was coalesced into the only free vector. */ | 3115 | space was coalesced into the only free vector. */ |
| 3127 | free_this_block = 1; | 3116 | free_this_block = 1; |
| 3128 | else | 3117 | else |
| 3129 | SETUP_ON_FREE_LIST (vector, vector->header.next.nbytes, nbytes); | 3118 | { |
| 3119 | int tmp; | ||
| 3120 | SETUP_ON_FREE_LIST (vector, total_bytes, tmp); | ||
| 3121 | } | ||
| 3130 | } | 3122 | } |
| 3131 | } | 3123 | } |
| 3132 | 3124 | ||
| @@ -4342,10 +4334,9 @@ live_vector_p (struct mem_node *m, void *p) | |||
| 4342 | while (VECTOR_IN_BLOCK (vector, block) | 4334 | while (VECTOR_IN_BLOCK (vector, block) |
| 4343 | && vector <= (struct Lisp_Vector *) p) | 4335 | && vector <= (struct Lisp_Vector *) p) |
| 4344 | { | 4336 | { |
| 4345 | if ((vector->header.size & VECTOR_FREE_LIST_FLAG) | 4337 | if (PSEUDOVECTOR_TYPEP (&vector->header, PVEC_FREE)) |
| 4346 | == VECTOR_FREE_LIST_FLAG) | ||
| 4347 | vector = ADVANCE (vector, (vector->header.size | 4338 | vector = ADVANCE (vector, (vector->header.size |
| 4348 | & VECTOR_FREE_LIST_SIZE_MASK)); | 4339 | & PSEUDOVECTOR_SIZE_MASK)); |
| 4349 | else if (vector == p) | 4340 | else if (vector == p) |
| 4350 | return 1; | 4341 | return 1; |
| 4351 | else | 4342 | else |
| @@ -5913,15 +5904,17 @@ mark_object (Lisp_Object arg) | |||
| 5913 | #endif /* GC_CHECK_MARKED_OBJECTS */ | 5904 | #endif /* GC_CHECK_MARKED_OBJECTS */ |
| 5914 | 5905 | ||
| 5915 | if (ptr->header.size & PSEUDOVECTOR_FLAG) | 5906 | if (ptr->header.size & PSEUDOVECTOR_FLAG) |
| 5916 | pvectype = ptr->header.size & PVEC_TYPE_MASK; | 5907 | pvectype = ((ptr->header.size & PVEC_TYPE_MASK) |
| 5908 | >> PSEUDOVECTOR_SIZE_BITS); | ||
| 5917 | else | 5909 | else |
| 5918 | pvectype = 0; | 5910 | pvectype = 0; |
| 5919 | 5911 | ||
| 5920 | if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) | 5912 | if (pvectype != PVEC_SUBR && pvectype != PVEC_BUFFER) |
| 5921 | CHECK_LIVE (live_vector_p); | 5913 | CHECK_LIVE (live_vector_p); |
| 5922 | 5914 | ||
| 5923 | if (pvectype == PVEC_BUFFER) | 5915 | switch (pvectype) |
| 5924 | { | 5916 | { |
| 5917 | case PVEC_BUFFER: | ||
| 5925 | #ifdef GC_CHECK_MARKED_OBJECTS | 5918 | #ifdef GC_CHECK_MARKED_OBJECTS |
| 5926 | if (po != &buffer_defaults && po != &buffer_local_symbols) | 5919 | if (po != &buffer_defaults && po != &buffer_local_symbols) |
| 5927 | { | 5920 | { |
| @@ -5933,67 +5926,82 @@ mark_object (Lisp_Object arg) | |||
| 5933 | } | 5926 | } |
| 5934 | #endif /* GC_CHECK_MARKED_OBJECTS */ | 5927 | #endif /* GC_CHECK_MARKED_OBJECTS */ |
| 5935 | mark_buffer ((struct buffer *) ptr); | 5928 | mark_buffer ((struct buffer *) ptr); |
| 5936 | } | 5929 | break; |
| 5937 | 5930 | ||
| 5938 | else if (pvectype == PVEC_COMPILED) | 5931 | case PVEC_COMPILED: |
| 5939 | /* We could treat this just like a vector, but it is better | 5932 | { /* We could treat this just like a vector, but it is better |
| 5940 | to save the COMPILED_CONSTANTS element for last and avoid | 5933 | to save the COMPILED_CONSTANTS element for last and avoid |
| 5941 | recursion there. */ | 5934 | recursion there. */ |
| 5942 | { | 5935 | int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; |
| 5943 | int size = ptr->header.size & PSEUDOVECTOR_SIZE_MASK; | 5936 | int i; |
| 5944 | int i; | 5937 | |
| 5938 | VECTOR_MARK (ptr); | ||
| 5939 | for (i = 0; i < size; i++) | ||
| 5940 | if (i != COMPILED_CONSTANTS) | ||
| 5941 | mark_object (ptr->contents[i]); | ||
| 5942 | if (size > COMPILED_CONSTANTS) | ||
| 5943 | { | ||
| 5944 | obj = ptr->contents[COMPILED_CONSTANTS]; | ||
| 5945 | goto loop; | ||
| 5946 | } | ||
| 5947 | } | ||
| 5948 | break; | ||
| 5945 | 5949 | ||
| 5946 | VECTOR_MARK (ptr); | 5950 | case PVEC_FRAME: |
| 5947 | for (i = 0; i < size; i++) | 5951 | { |
| 5948 | if (i != COMPILED_CONSTANTS) | 5952 | mark_vectorlike (ptr); |
| 5949 | mark_object (ptr->contents[i]); | 5953 | mark_face_cache (((struct frame *) ptr)->face_cache); |
| 5950 | obj = ptr->contents[COMPILED_CONSTANTS]; | 5954 | } |
| 5951 | goto loop; | 5955 | break; |
| 5952 | } | ||
| 5953 | 5956 | ||
| 5954 | else if (pvectype == PVEC_FRAME) | 5957 | case PVEC_WINDOW: |
| 5955 | { | 5958 | { |
| 5956 | mark_vectorlike (ptr); | 5959 | struct window *w = (struct window *) ptr; |
| 5957 | mark_face_cache (((struct frame *) ptr)->face_cache); | ||
| 5958 | } | ||
| 5959 | 5960 | ||
| 5960 | else if (pvectype == PVEC_WINDOW) | 5961 | mark_vectorlike (ptr); |
| 5961 | { | 5962 | /* Mark glyphs for leaf windows. Marking window |
| 5962 | struct window *w = (struct window *) ptr; | 5963 | matrices is sufficient because frame matrices |
| 5964 | use the same glyph memory. */ | ||
| 5965 | if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) | ||
| 5966 | { | ||
| 5967 | mark_glyph_matrix (w->current_matrix); | ||
| 5968 | mark_glyph_matrix (w->desired_matrix); | ||
| 5969 | } | ||
| 5970 | } | ||
| 5971 | break; | ||
| 5963 | 5972 | ||
| 5964 | mark_vectorlike (ptr); | 5973 | case PVEC_HASH_TABLE: |
| 5965 | /* Mark glyphs for leaf windows. Marking window | 5974 | { |
| 5966 | matrices is sufficient because frame matrices | 5975 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; |
| 5967 | use the same glyph memory. */ | ||
| 5968 | if (NILP (w->hchild) && NILP (w->vchild) && w->current_matrix) | ||
| 5969 | { | ||
| 5970 | mark_glyph_matrix (w->current_matrix); | ||
| 5971 | mark_glyph_matrix (w->desired_matrix); | ||
| 5972 | } | ||
| 5973 | } | ||
| 5974 | 5976 | ||
| 5975 | else if (pvectype == PVEC_HASH_TABLE) | 5977 | mark_vectorlike (ptr); |
| 5976 | { | 5978 | /* If hash table is not weak, mark all keys and values. |
| 5977 | struct Lisp_Hash_Table *h = (struct Lisp_Hash_Table *) ptr; | 5979 | For weak tables, mark only the vector. */ |
| 5980 | if (NILP (h->weak)) | ||
| 5981 | mark_object (h->key_and_value); | ||
| 5982 | else | ||
| 5983 | VECTOR_MARK (XVECTOR (h->key_and_value)); | ||
| 5984 | } | ||
| 5985 | break; | ||
| 5978 | 5986 | ||
| 5979 | mark_vectorlike (ptr); | 5987 | case PVEC_CHAR_TABLE: |
| 5980 | /* If hash table is not weak, mark all keys and values. | 5988 | mark_char_table (ptr); |
| 5981 | For weak tables, mark only the vector. */ | 5989 | break; |
| 5982 | if (NILP (h->weak)) | 5990 | |
| 5983 | mark_object (h->key_and_value); | 5991 | case PVEC_BOOL_VECTOR: |
| 5984 | else | 5992 | /* No Lisp_Objects to mark in a bool vector. */ |
| 5985 | VECTOR_MARK (XVECTOR (h->key_and_value)); | 5993 | VECTOR_MARK (ptr); |
| 5986 | } | 5994 | break; |
| 5987 | 5995 | ||
| 5988 | else if (pvectype == PVEC_CHAR_TABLE) | 5996 | case PVEC_SUBR: |
| 5989 | mark_char_table (ptr); | 5997 | break; |
| 5990 | 5998 | ||
| 5991 | else if (pvectype == PVEC_BOOL_VECTOR) | 5999 | case PVEC_FREE: |
| 5992 | /* No Lisp_Objects to mark in a bool vector. */ | 6000 | abort (); |
| 5993 | VECTOR_MARK (ptr); | ||
| 5994 | 6001 | ||
| 5995 | else if (pvectype != PVEC_SUBR) | 6002 | default: |
| 5996 | mark_vectorlike (ptr); | 6003 | mark_vectorlike (ptr); |
| 6004 | } | ||
| 5997 | } | 6005 | } |
| 5998 | break; | 6006 | break; |
| 5999 | 6007 | ||
diff --git a/src/emacs.c b/src/emacs.c index 72e280c7409..143a44e0847 100644 --- a/src/emacs.c +++ b/src/emacs.c | |||
| @@ -119,7 +119,7 @@ ptrdiff_t PVEC_FLAG EXTERNALLY_VISIBLE = PSEUDOVECTOR_FLAG; | |||
| 119 | ptrdiff_t gdb_array_mark_flag EXTERNALLY_VISIBLE = ARRAY_MARK_FLAG; | 119 | ptrdiff_t gdb_array_mark_flag EXTERNALLY_VISIBLE = ARRAY_MARK_FLAG; |
| 120 | /* GDB might say "No enum type named pvec_type" if we don't have at | 120 | /* GDB might say "No enum type named pvec_type" if we don't have at |
| 121 | least one symbol with that type, and then xbacktrace could fail. */ | 121 | least one symbol with that type, and then xbacktrace could fail. */ |
| 122 | enum pvec_type gdb_pvec_type EXTERNALLY_VISIBLE = PVEC_TYPE_MASK; | 122 | ptrdiff_t gdb_pvec_type EXTERNALLY_VISIBLE = PVEC_TYPE_MASK; |
| 123 | 123 | ||
| 124 | /* Empty lisp strings. To avoid having to build any others. */ | 124 | /* Empty lisp strings. To avoid having to build any others. */ |
| 125 | Lisp_Object empty_unibyte_string, empty_multibyte_string; | 125 | Lisp_Object empty_unibyte_string, empty_multibyte_string; |
| @@ -2095,8 +2095,9 @@ internal_equal (register Lisp_Object o1, register Lisp_Object o2, int depth, int | |||
| 2095 | are sensible to compare, so eliminate the others now. */ | 2095 | are sensible to compare, so eliminate the others now. */ |
| 2096 | if (size & PSEUDOVECTOR_FLAG) | 2096 | if (size & PSEUDOVECTOR_FLAG) |
| 2097 | { | 2097 | { |
| 2098 | if (!(size & (PVEC_COMPILED | 2098 | if (!(size & ((PVEC_COMPILED | PVEC_CHAR_TABLE |
| 2099 | | PVEC_CHAR_TABLE | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) | 2099 | | PVEC_SUB_CHAR_TABLE | PVEC_FONT) |
| 2100 | << PSEUDOVECTOR_SIZE_BITS))) | ||
| 2100 | return 0; | 2101 | return 0; |
| 2101 | size &= PSEUDOVECTOR_SIZE_MASK; | 2102 | size &= PSEUDOVECTOR_SIZE_MASK; |
| 2102 | } | 2103 | } |
diff --git a/src/lisp.h b/src/lisp.h index a0d6c6b3c0b..9b2dda244e9 100644 --- a/src/lisp.h +++ b/src/lisp.h | |||
| @@ -341,28 +341,26 @@ typedef EMACS_INT Lisp_Object; | |||
| 341 | It is not crucial, but there are plenty of bits here, so why not do it? */ | 341 | It is not crucial, but there are plenty of bits here, so why not do it? */ |
| 342 | enum pvec_type | 342 | enum pvec_type |
| 343 | { | 343 | { |
| 344 | PVEC_NORMAL_VECTOR = 0, | 344 | PVEC_NORMAL_VECTOR = 0, /* Unused! */ |
| 345 | PVEC_PROCESS = 0x200, | 345 | PVEC_FREE, |
| 346 | PVEC_FRAME = 0x400, | 346 | PVEC_PROCESS, |
| 347 | PVEC_COMPILED = 0x800, | 347 | PVEC_FRAME, |
| 348 | PVEC_WINDOW = 0x1000, | 348 | PVEC_WINDOW, |
| 349 | PVEC_WINDOW_CONFIGURATION = 0x2000, | 349 | PVEC_BOOL_VECTOR, |
| 350 | PVEC_SUBR = 0x4000, | 350 | PVEC_BUFFER, |
| 351 | PVEC_CHAR_TABLE = 0x8000, | 351 | PVEC_HASH_TABLE, |
| 352 | PVEC_BOOL_VECTOR = 0x10000, | 352 | PVEC_TERMINAL, |
| 353 | PVEC_BUFFER = 0x20000, | 353 | PVEC_WINDOW_CONFIGURATION, |
| 354 | PVEC_HASH_TABLE = 0x40000, | 354 | PVEC_SUBR, |
| 355 | PVEC_TERMINAL = 0x80000, | 355 | PVEC_OTHER, |
| 356 | PVEC_SUB_CHAR_TABLE = 0x100000, | 356 | /* These last 4 are special because we OR them in fns.c:internal_equal, |
| 357 | PVEC_FONT = 0x200000, | 357 | so they have to use a disjoint bit pattern: |
| 358 | PVEC_OTHER = 0x400000, | 358 | if (!(size & (PVEC_COMPILED | PVEC_CHAR_TABLE |
| 359 | PVEC_TYPE_MASK = 0x7ffe00 | 359 | | PVEC_SUB_CHAR_TABLE | PVEC_FONT))) */ |
| 360 | 360 | PVEC_COMPILED = 0x10, | |
| 361 | #if 0 /* This is used to make the value of PSEUDOVECTOR_FLAG available to | 361 | PVEC_CHAR_TABLE = 0x20, |
| 362 | GDB. It doesn't work on OS Alpha. Moved to a variable in | 362 | PVEC_SUB_CHAR_TABLE = 0x30, |
| 363 | emacs.c. */ | 363 | PVEC_FONT = 0x40 |
| 364 | PVEC_FLAG = PSEUDOVECTOR_FLAG | ||
| 365 | #endif | ||
| 366 | }; | 364 | }; |
| 367 | 365 | ||
| 368 | /* For convenience, we also store the number of elements in these bits. | 366 | /* For convenience, we also store the number of elements in these bits. |
| @@ -370,7 +368,9 @@ enum pvec_type | |||
| 370 | only the number of Lisp_Object fields (that need to be traced by the GC). | 368 | only the number of Lisp_Object fields (that need to be traced by the GC). |
| 371 | The distinction is used e.g. by Lisp_Process which places extra | 369 | The distinction is used e.g. by Lisp_Process which places extra |
| 372 | non-Lisp_Object fields at the end of the structure. */ | 370 | non-Lisp_Object fields at the end of the structure. */ |
| 373 | #define PSEUDOVECTOR_SIZE_MASK 0x1ff | 371 | #define PSEUDOVECTOR_SIZE_BITS 16 |
| 372 | #define PSEUDOVECTOR_SIZE_MASK ((1 << PSEUDOVECTOR_SIZE_BITS) - 1) | ||
| 373 | #define PVEC_TYPE_MASK (0x0fff << PSEUDOVECTOR_SIZE_BITS) | ||
| 374 | 374 | ||
| 375 | /* Number of bits to put in each character in the internal representation | 375 | /* Number of bits to put in each character in the internal representation |
| 376 | of bool vectors. This should not vary across implementations. */ | 376 | of bool vectors. This should not vary across implementations. */ |
| @@ -536,9 +536,11 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) | |||
| 536 | 536 | ||
| 537 | #define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code) | 537 | #define XSETPVECTYPE(v, code) XSETTYPED_PVECTYPE (v, header.size, code) |
| 538 | #define XSETTYPED_PVECTYPE(v, size_member, code) \ | 538 | #define XSETTYPED_PVECTYPE(v, size_member, code) \ |
| 539 | ((v)->size_member |= PSEUDOVECTOR_FLAG | (code)) | 539 | ((v)->size_member |= PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS)) |
| 540 | #define XSETPVECTYPESIZE(v, code, sizeval) \ | 540 | #define XSETPVECTYPESIZE(v, code, sizeval) \ |
| 541 | ((v)->header.size = PSEUDOVECTOR_FLAG | (code) | (sizeval)) | 541 | ((v)->header.size = (PSEUDOVECTOR_FLAG \ |
| 542 | | ((code) << PSEUDOVECTOR_SIZE_BITS) \ | ||
| 543 | | (sizeval))) | ||
| 542 | 544 | ||
| 543 | /* The cast to struct vectorlike_header * avoids aliasing issues. */ | 545 | /* The cast to struct vectorlike_header * avoids aliasing issues. */ |
| 544 | #define XSETPSEUDOVECTOR(a, b, code) \ | 546 | #define XSETPSEUDOVECTOR(a, b, code) \ |
| @@ -550,7 +552,7 @@ clip_to_bounds (ptrdiff_t lower, EMACS_INT num, ptrdiff_t upper) | |||
| 550 | #define XSETTYPED_PSEUDOVECTOR(a, b, size, code) \ | 552 | #define XSETTYPED_PSEUDOVECTOR(a, b, size, code) \ |
| 551 | (XSETVECTOR (a, b), \ | 553 | (XSETVECTOR (a, b), \ |
| 552 | eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ | 554 | eassert ((size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ |
| 553 | == (PSEUDOVECTOR_FLAG | (code)))) | 555 | == (PSEUDOVECTOR_FLAG | (code << PSEUDOVECTOR_SIZE_BITS)))) |
| 554 | 556 | ||
| 555 | #define XSETWINDOW_CONFIGURATION(a, b) \ | 557 | #define XSETWINDOW_CONFIGURATION(a, b) \ |
| 556 | (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION)) | 558 | (XSETPSEUDOVECTOR (a, b, PVEC_WINDOW_CONFIGURATION)) |
| @@ -730,13 +732,13 @@ extern ptrdiff_t string_bytes (struct Lisp_String *); | |||
| 730 | /* Set text properties. */ | 732 | /* Set text properties. */ |
| 731 | #define STRING_SET_INTERVALS(STR, INT) (XSTRING (STR)->intervals = (INT)) | 733 | #define STRING_SET_INTERVALS(STR, INT) (XSTRING (STR)->intervals = (INT)) |
| 732 | 734 | ||
| 733 | /* In a string or vector, the sign bit of the `size' is the gc mark bit */ | 735 | /* In a string or vector, the sign bit of the `size' is the gc mark bit. */ |
| 734 | 736 | ||
| 735 | struct Lisp_String | 737 | struct Lisp_String |
| 736 | { | 738 | { |
| 737 | ptrdiff_t size; | 739 | ptrdiff_t size; |
| 738 | ptrdiff_t size_byte; | 740 | ptrdiff_t size_byte; |
| 739 | INTERVAL intervals; /* text properties in this string */ | 741 | INTERVAL intervals; /* Text properties in this string. */ |
| 740 | unsigned char *data; | 742 | unsigned char *data; |
| 741 | }; | 743 | }; |
| 742 | 744 | ||
| @@ -749,6 +751,20 @@ struct Lisp_String | |||
| 749 | <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */ | 751 | <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=8546>. */ |
| 750 | struct vectorlike_header | 752 | struct vectorlike_header |
| 751 | { | 753 | { |
| 754 | /* This field contains various pieces of information: | ||
| 755 | - The MSB (ARRAY_MARK_FLAG) holds the gcmarkbit. | ||
| 756 | - The next bit (PSEUDOVECTOR_FLAG) indicates whether this is a plain | ||
| 757 | vector (0) or a pseudovector (1). | ||
| 758 | - If PSEUDOVECTOR_FLAG is 0, the rest holds the size (number | ||
| 759 | of slots) of the vector. | ||
| 760 | - If PSEUDOVECTOR_FLAG is 1, the rest is subdivided into | ||
| 761 | a "pvec type" tag held in PVEC_TYPE_MASK and a size held in the lowest | ||
| 762 | PSEUDOVECTOR_SIZE_BITS. That size normally indicates the number of | ||
| 763 | Lisp_Object slots at the beginning of the object that need to be | ||
| 764 | traced by the GC, tho some types use it slightly differently. | ||
| 765 | - E.g. if the pvec type is PVEC_FREE it means this is an unallocated | ||
| 766 | vector on a free-list and PSEUDOVECTOR_SIZE_BITS indicates its size | ||
| 767 | in bytes. */ | ||
| 752 | ptrdiff_t size; | 768 | ptrdiff_t size; |
| 753 | 769 | ||
| 754 | /* When the vector is allocated from a vector block, NBYTES is used | 770 | /* When the vector is allocated from a vector block, NBYTES is used |
| @@ -759,8 +775,17 @@ struct vectorlike_header | |||
| 759 | pointer: this way, one can write P->next.vector instead of ((struct | 775 | pointer: this way, one can write P->next.vector instead of ((struct |
| 760 | Lisp_Vector *) P->next). */ | 776 | Lisp_Vector *) P->next). */ |
| 761 | union { | 777 | union { |
| 778 | /* This is only needed for small vectors that are not free because the | ||
| 779 | `size' field only gives us the number of Lisp_Object slots, whereas we | ||
| 780 | need to know the total size, including non-Lisp_Object data. | ||
| 781 | FIXME: figure out a way to store this info elsewhere so we can | ||
| 782 | finally get rid of this extra word of overhead. */ | ||
| 762 | ptrdiff_t nbytes; | 783 | ptrdiff_t nbytes; |
| 763 | struct buffer *buffer; | 784 | struct buffer *buffer; |
| 785 | /* FIXME: This can be removed: For large vectors, this field could be | ||
| 786 | placed *before* the vector itself. And for small vectors on a free | ||
| 787 | list, this field could be stored in the vector's bytes, since the | ||
| 788 | empty vector is handled specially anyway. */ | ||
| 764 | struct Lisp_Vector *vector; | 789 | struct Lisp_Vector *vector; |
| 765 | } next; | 790 | } next; |
| 766 | }; | 791 | }; |
| @@ -775,7 +800,7 @@ struct Lisp_Vector | |||
| 775 | of the shortest vector that would hold that struct. */ | 800 | of the shortest vector that would hold that struct. */ |
| 776 | #define VECSIZE(type) ((sizeof (type) \ | 801 | #define VECSIZE(type) ((sizeof (type) \ |
| 777 | - offsetof (struct Lisp_Vector, contents[0]) \ | 802 | - offsetof (struct Lisp_Vector, contents[0]) \ |
| 778 | + sizeof (Lisp_Object) - 1) /* round up */ \ | 803 | + sizeof (Lisp_Object) - 1) /* Round up. */ \ |
| 779 | / sizeof (Lisp_Object)) | 804 | / sizeof (Lisp_Object)) |
| 780 | 805 | ||
| 781 | /* Like VECSIZE, but used when the pseudo-vector has non-Lisp_Object fields | 806 | /* Like VECSIZE, but used when the pseudo-vector has non-Lisp_Object fields |
| @@ -1617,15 +1642,17 @@ typedef struct { | |||
| 1617 | /* True if object X is a pseudovector whose code is CODE. The cast to struct | 1642 | /* True if object X is a pseudovector whose code is CODE. The cast to struct |
| 1618 | vectorlike_header * avoids aliasing issues. */ | 1643 | vectorlike_header * avoids aliasing issues. */ |
| 1619 | #define PSEUDOVECTORP(x, code) \ | 1644 | #define PSEUDOVECTORP(x, code) \ |
| 1620 | TYPED_PSEUDOVECTORP(x, vectorlike_header, code) | 1645 | TYPED_PSEUDOVECTORP (x, vectorlike_header, code) |
| 1646 | |||
| 1647 | #define PSEUDOVECTOR_TYPEP(v, code) \ | ||
| 1648 | (((v)->size & (PSEUDOVECTOR_FLAG | PVEC_TYPE_MASK)) \ | ||
| 1649 | == (PSEUDOVECTOR_FLAG | ((code) << PSEUDOVECTOR_SIZE_BITS))) | ||
| 1621 | 1650 | ||
| 1622 | /* True if object X, with internal type struct T *, is a pseudovector whose | 1651 | /* True if object X, with internal type struct T *, is a pseudovector whose |
| 1623 | code is CODE. */ | 1652 | code is CODE. */ |
| 1624 | #define TYPED_PSEUDOVECTORP(x, t, code) \ | 1653 | #define TYPED_PSEUDOVECTORP(x, t, code) \ |
| 1625 | (VECTORLIKEP (x) \ | 1654 | (VECTORLIKEP (x) \ |
| 1626 | && (((((struct t *) XUNTAG (x, Lisp_Vectorlike))->size \ | 1655 | && PSEUDOVECTOR_TYPEP ((struct t *) XUNTAG (x, Lisp_Vectorlike), code)) |
| 1627 | & (PSEUDOVECTOR_FLAG | (code)))) \ | ||
| 1628 | == (PSEUDOVECTOR_FLAG | (code)))) | ||
| 1629 | 1656 | ||
| 1630 | /* Test for specific pseudovector types. */ | 1657 | /* Test for specific pseudovector types. */ |
| 1631 | #define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION) | 1658 | #define WINDOW_CONFIGURATIONP(x) PSEUDOVECTORP (x, PVEC_WINDOW_CONFIGURATION) |
| @@ -1818,7 +1845,8 @@ typedef struct { | |||
| 1818 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ | 1845 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ |
| 1819 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ | 1846 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ |
| 1820 | static DECL_ALIGN (struct Lisp_Subr, sname) = \ | 1847 | static DECL_ALIGN (struct Lisp_Subr, sname) = \ |
| 1821 | { PVEC_SUBR | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \ | 1848 | { (PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS) \ |
| 1849 | | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)), \ | ||
| 1822 | { (Lisp_Object (__cdecl *)(void))fnname }, \ | 1850 | { (Lisp_Object (__cdecl *)(void))fnname }, \ |
| 1823 | minargs, maxargs, lname, intspec, 0}; \ | 1851 | minargs, maxargs, lname, intspec, 0}; \ |
| 1824 | Lisp_Object fnname | 1852 | Lisp_Object fnname |
| @@ -1826,7 +1854,7 @@ typedef struct { | |||
| 1826 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ | 1854 | #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc) \ |
| 1827 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ | 1855 | Lisp_Object fnname DEFUN_ARGS_ ## maxargs ; \ |
| 1828 | static DECL_ALIGN (struct Lisp_Subr, sname) = \ | 1856 | static DECL_ALIGN (struct Lisp_Subr, sname) = \ |
| 1829 | { PVEC_SUBR, \ | 1857 | { PVEC_SUBR << PSEUDOVECTOR_SIZE_BITS, \ |
| 1830 | { .a ## maxargs = fnname }, \ | 1858 | { .a ## maxargs = fnname }, \ |
| 1831 | minargs, maxargs, lname, intspec, 0}; \ | 1859 | minargs, maxargs, lname, intspec, 0}; \ |
| 1832 | Lisp_Object fnname | 1860 | Lisp_Object fnname |