diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 184 |
1 files changed, 96 insertions, 88 deletions
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 | ||