diff options
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 499 |
1 files changed, 388 insertions, 111 deletions
diff --git a/src/alloc.c b/src/alloc.c index cf7778c05f6..1478ce9ae4e 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -304,7 +304,9 @@ enum mem_type | |||
| 304 | process, hash_table, frame, terminal, and window, but we never made | 304 | process, hash_table, frame, terminal, and window, but we never made |
| 305 | use of the distinction, so it only caused source-code complexity | 305 | use of the distinction, so it only caused source-code complexity |
| 306 | and runtime slowdown. Minor but pointless. */ | 306 | and runtime slowdown. Minor but pointless. */ |
| 307 | MEM_TYPE_VECTORLIKE | 307 | MEM_TYPE_VECTORLIKE, |
| 308 | /* Special type to denote vector blocks. */ | ||
| 309 | MEM_TYPE_VECTOR_BLOCK | ||
| 308 | }; | 310 | }; |
| 309 | 311 | ||
| 310 | static void *lisp_malloc (size_t, enum mem_type); | 312 | static void *lisp_malloc (size_t, enum mem_type); |
| @@ -494,6 +496,11 @@ buffer_memory_full (ptrdiff_t nbytes) | |||
| 494 | xsignal (Qnil, Vmemory_signal_data); | 496 | xsignal (Qnil, Vmemory_signal_data); |
| 495 | } | 497 | } |
| 496 | 498 | ||
| 499 | /* A common multiple of the positive integers A and B. Ideally this | ||
| 500 | would be the least common multiple, but there's no way to do that | ||
| 501 | as a constant expression in C, so do the best that we can easily do. */ | ||
| 502 | #define COMMON_MULTIPLE(a, b) \ | ||
| 503 | ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) | ||
| 497 | 504 | ||
| 498 | #ifndef XMALLOC_OVERRUN_CHECK | 505 | #ifndef XMALLOC_OVERRUN_CHECK |
| 499 | #define XMALLOC_OVERRUN_CHECK_OVERHEAD 0 | 506 | #define XMALLOC_OVERRUN_CHECK_OVERHEAD 0 |
| @@ -525,12 +532,8 @@ buffer_memory_full (ptrdiff_t nbytes) | |||
| 525 | char c; \ | 532 | char c; \ |
| 526 | }, \ | 533 | }, \ |
| 527 | c) | 534 | c) |
| 528 | #ifdef USE_LSB_TAG | 535 | |
| 529 | /* A common multiple of the positive integers A and B. Ideally this | 536 | #if USE_LSB_TAG |
| 530 | would be the least common multiple, but there's no way to do that | ||
| 531 | as a constant expression in C, so do the best that we can easily do. */ | ||
| 532 | # define COMMON_MULTIPLE(a, b) \ | ||
| 533 | ((a) % (b) == 0 ? (a) : (b) % (a) == 0 ? (b) : (a) * (b)) | ||
| 534 | # define XMALLOC_HEADER_ALIGNMENT \ | 537 | # define XMALLOC_HEADER_ALIGNMENT \ |
| 535 | COMMON_MULTIPLE (1 << GCTYPEBITS, XMALLOC_BASE_ALIGNMENT) | 538 | COMMON_MULTIPLE (1 << GCTYPEBITS, XMALLOC_BASE_ALIGNMENT) |
| 536 | #else | 539 | #else |
| @@ -890,8 +893,8 @@ safe_alloca_unwind (Lisp_Object arg) | |||
| 890 | number of bytes to allocate, TYPE describes the intended use of the | 893 | number of bytes to allocate, TYPE describes the intended use of the |
| 891 | allocated memory block (for strings, for conses, ...). */ | 894 | allocated memory block (for strings, for conses, ...). */ |
| 892 | 895 | ||
| 893 | #ifndef USE_LSB_TAG | 896 | #if ! USE_LSB_TAG |
| 894 | static void *lisp_malloc_loser; | 897 | void *lisp_malloc_loser EXTERNALLY_VISIBLE; |
| 895 | #endif | 898 | #endif |
| 896 | 899 | ||
| 897 | static void * | 900 | static void * |
| @@ -907,7 +910,7 @@ lisp_malloc (size_t nbytes, enum mem_type type) | |||
| 907 | 910 | ||
| 908 | val = (void *) malloc (nbytes); | 911 | val = (void *) malloc (nbytes); |
| 909 | 912 | ||
| 910 | #ifndef USE_LSB_TAG | 913 | #if ! USE_LSB_TAG |
| 911 | /* If the memory just allocated cannot be addressed thru a Lisp | 914 | /* If the memory just allocated cannot be addressed thru a Lisp |
| 912 | object's pointer, and it needs to be, | 915 | object's pointer, and it needs to be, |
| 913 | that's equivalent to running out of memory. */ | 916 | that's equivalent to running out of memory. */ |
| @@ -1088,7 +1091,7 @@ lisp_align_malloc (size_t nbytes, enum mem_type type) | |||
| 1088 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | 1091 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); |
| 1089 | #endif | 1092 | #endif |
| 1090 | 1093 | ||
| 1091 | #ifndef USE_LSB_TAG | 1094 | #if ! USE_LSB_TAG |
| 1092 | /* If the memory just allocated cannot be addressed thru a Lisp | 1095 | /* If the memory just allocated cannot be addressed thru a Lisp |
| 1093 | object's pointer, and it needs to be, that's equivalent to | 1096 | object's pointer, and it needs to be, that's equivalent to |
| 1094 | running out of memory. */ | 1097 | running out of memory. */ |
| @@ -1581,35 +1584,6 @@ mark_interval_tree (register INTERVAL tree) | |||
| 1581 | if (! NULL_INTERVAL_P (i)) \ | 1584 | if (! NULL_INTERVAL_P (i)) \ |
| 1582 | (i) = balance_intervals (i); \ | 1585 | (i) = balance_intervals (i); \ |
| 1583 | } while (0) | 1586 | } while (0) |
| 1584 | |||
| 1585 | |||
| 1586 | /* Number support. If USE_LISP_UNION_TYPE is in effect, we | ||
| 1587 | can't create number objects in macros. */ | ||
| 1588 | #ifndef make_number | ||
| 1589 | Lisp_Object | ||
| 1590 | make_number (EMACS_INT n) | ||
| 1591 | { | ||
| 1592 | Lisp_Object obj; | ||
| 1593 | obj.s.val = n; | ||
| 1594 | obj.s.type = Lisp_Int; | ||
| 1595 | return obj; | ||
| 1596 | } | ||
| 1597 | #endif | ||
| 1598 | |||
| 1599 | /* Convert the pointer-sized word P to EMACS_INT while preserving its | ||
| 1600 | type and ptr fields. */ | ||
| 1601 | static Lisp_Object | ||
| 1602 | widen_to_Lisp_Object (void *p) | ||
| 1603 | { | ||
| 1604 | intptr_t i = (intptr_t) p; | ||
| 1605 | #ifdef USE_LISP_UNION_TYPE | ||
| 1606 | Lisp_Object obj; | ||
| 1607 | obj.i = i; | ||
| 1608 | return obj; | ||
| 1609 | #else | ||
| 1610 | return i; | ||
| 1611 | #endif | ||
| 1612 | } | ||
| 1613 | 1587 | ||
| 1614 | /*********************************************************************** | 1588 | /*********************************************************************** |
| 1615 | String Allocation | 1589 | String Allocation |
| @@ -2701,8 +2675,10 @@ make_float (double float_value) | |||
| 2701 | GC are put on a free list to be reallocated before allocating | 2675 | GC are put on a free list to be reallocated before allocating |
| 2702 | any new cons cells from the latest cons_block. */ | 2676 | any new cons cells from the latest cons_block. */ |
| 2703 | 2677 | ||
| 2704 | #define CONS_BLOCK_SIZE \ | 2678 | #define CONS_BLOCK_SIZE \ |
| 2705 | (((BLOCK_BYTES - sizeof (struct cons_block *)) * CHAR_BIT) \ | 2679 | (((BLOCK_BYTES - sizeof (struct cons_block *) \ |
| 2680 | /* The compiler might add padding at the end. */ \ | ||
| 2681 | - (sizeof (struct Lisp_Cons) - sizeof (int))) * CHAR_BIT) \ | ||
| 2706 | / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1)) | 2682 | / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1)) |
| 2707 | 2683 | ||
| 2708 | #define CONS_BLOCK(fptr) \ | 2684 | #define CONS_BLOCK(fptr) \ |
| @@ -2926,17 +2902,302 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | |||
| 2926 | Vector Allocation | 2902 | Vector Allocation |
| 2927 | ***********************************************************************/ | 2903 | ***********************************************************************/ |
| 2928 | 2904 | ||
| 2929 | /* Singly-linked list of all vectors. */ | 2905 | /* This value is balanced well enough to avoid too much internal overhead |
| 2906 | for the most common cases; it's not required to be a power of two, but | ||
| 2907 | it's expected to be a mult-of-ROUNDUP_SIZE (see below). */ | ||
| 2930 | 2908 | ||
| 2931 | static struct Lisp_Vector *all_vectors; | 2909 | #define VECTOR_BLOCK_SIZE 4096 |
| 2932 | 2910 | ||
| 2933 | /* Handy constants for vectorlike objects. */ | 2911 | /* Handy constants for vectorlike objects. */ |
| 2934 | enum | 2912 | enum |
| 2935 | { | 2913 | { |
| 2936 | header_size = offsetof (struct Lisp_Vector, contents), | 2914 | header_size = offsetof (struct Lisp_Vector, contents), |
| 2937 | word_size = sizeof (Lisp_Object) | 2915 | word_size = sizeof (Lisp_Object), |
| 2916 | roundup_size = COMMON_MULTIPLE (sizeof (Lisp_Object), | ||
| 2917 | USE_LSB_TAG ? 1 << GCTYPEBITS : 1) | ||
| 2938 | }; | 2918 | }; |
| 2939 | 2919 | ||
| 2920 | /* ROUNDUP_SIZE must be a power of 2. */ | ||
| 2921 | verify ((roundup_size & (roundup_size - 1)) == 0); | ||
| 2922 | |||
| 2923 | /* Round up X to nearest mult-of-ROUNDUP_SIZE. */ | ||
| 2924 | |||
| 2925 | #define vroundup(x) (((x) + (roundup_size - 1)) & ~(roundup_size - 1)) | ||
| 2926 | |||
| 2927 | /* Rounding helps to maintain alignment constraints if USE_LSB_TAG. */ | ||
| 2928 | |||
| 2929 | #define VECTOR_BLOCK_BYTES (VECTOR_BLOCK_SIZE - vroundup (sizeof (void *))) | ||
| 2930 | |||
| 2931 | /* Size of the minimal vector allocated from block. */ | ||
| 2932 | |||
| 2933 | #define VBLOCK_BYTES_MIN vroundup (sizeof (struct Lisp_Vector)) | ||
| 2934 | |||
| 2935 | /* Size of the largest vector allocated from block. */ | ||
| 2936 | |||
| 2937 | #define VBLOCK_BYTES_MAX \ | ||
| 2938 | vroundup ((VECTOR_BLOCK_BYTES / 2) - sizeof (Lisp_Object)) | ||
| 2939 | |||
| 2940 | /* We maintain one free list for each possible block-allocated | ||
| 2941 | vector size, and this is the number of free lists we have. */ | ||
| 2942 | |||
| 2943 | #define VECTOR_MAX_FREE_LIST_INDEX \ | ||
| 2944 | ((VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) / roundup_size + 1) | ||
| 2945 | |||
| 2946 | /* When the vector is on a free list, vectorlike_header.SIZE is set to | ||
| 2947 | this special value ORed with vector's memory footprint size. */ | ||
| 2948 | |||
| 2949 | #define VECTOR_FREE_LIST_FLAG (~(ARRAY_MARK_FLAG | PSEUDOVECTOR_FLAG \ | ||
| 2950 | | (VECTOR_BLOCK_SIZE - 1))) | ||
| 2951 | |||
| 2952 | /* Common shortcut to advance vector pointer over a block data. */ | ||
| 2953 | |||
| 2954 | #define ADVANCE(v, nbytes) ((struct Lisp_Vector *) ((char *) (v) + (nbytes))) | ||
| 2955 | |||
| 2956 | /* Common shortcut to calculate NBYTES-vector index in VECTOR_FREE_LISTS. */ | ||
| 2957 | |||
| 2958 | #define VINDEX(nbytes) (((nbytes) - VBLOCK_BYTES_MIN) / roundup_size) | ||
| 2959 | |||
| 2960 | /* Common shortcut to setup vector on a free list. */ | ||
| 2961 | |||
| 2962 | #define SETUP_ON_FREE_LIST(v, nbytes, index) \ | ||
| 2963 | do { \ | ||
| 2964 | (v)->header.size = VECTOR_FREE_LIST_FLAG | (nbytes); \ | ||
| 2965 | eassert ((nbytes) % roundup_size == 0); \ | ||
| 2966 | (index) = VINDEX (nbytes); \ | ||
| 2967 | eassert ((index) < VECTOR_MAX_FREE_LIST_INDEX); \ | ||
| 2968 | (v)->header.next.vector = vector_free_lists[index]; \ | ||
| 2969 | vector_free_lists[index] = (v); \ | ||
| 2970 | } while (0) | ||
| 2971 | |||
| 2972 | struct vector_block | ||
| 2973 | { | ||
| 2974 | char data[VECTOR_BLOCK_BYTES]; | ||
| 2975 | struct vector_block *next; | ||
| 2976 | }; | ||
| 2977 | |||
| 2978 | /* Chain of vector blocks. */ | ||
| 2979 | |||
| 2980 | static struct vector_block *vector_blocks; | ||
| 2981 | |||
| 2982 | /* Vector free lists, where NTH item points to a chain of free | ||
| 2983 | vectors of the same NBYTES size, so NTH == VINDEX (NBYTES). */ | ||
| 2984 | |||
| 2985 | static struct Lisp_Vector *vector_free_lists[VECTOR_MAX_FREE_LIST_INDEX]; | ||
| 2986 | |||
| 2987 | /* Singly-linked list of large vectors. */ | ||
| 2988 | |||
| 2989 | static struct Lisp_Vector *large_vectors; | ||
| 2990 | |||
| 2991 | /* The only vector with 0 slots, allocated from pure space. */ | ||
| 2992 | |||
| 2993 | static struct Lisp_Vector *zero_vector; | ||
| 2994 | |||
| 2995 | /* Get a new vector block. */ | ||
| 2996 | |||
| 2997 | static struct vector_block * | ||
| 2998 | allocate_vector_block (void) | ||
| 2999 | { | ||
| 3000 | struct vector_block *block; | ||
| 3001 | |||
| 3002 | #ifdef DOUG_LEA_MALLOC | ||
| 3003 | mallopt (M_MMAP_MAX, 0); | ||
| 3004 | #endif | ||
| 3005 | |||
| 3006 | block = xmalloc (sizeof (struct vector_block)); | ||
| 3007 | |||
| 3008 | #ifdef DOUG_LEA_MALLOC | ||
| 3009 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | ||
| 3010 | #endif | ||
| 3011 | |||
| 3012 | #if GC_MARK_STACK && !defined GC_MALLOC_CHECK | ||
| 3013 | mem_insert (block->data, block->data + VECTOR_BLOCK_BYTES, | ||
| 3014 | MEM_TYPE_VECTOR_BLOCK); | ||
| 3015 | #endif | ||
| 3016 | |||
| 3017 | block->next = vector_blocks; | ||
| 3018 | vector_blocks = block; | ||
| 3019 | return block; | ||
| 3020 | } | ||
| 3021 | |||
| 3022 | /* Called once to initialize vector allocation. */ | ||
| 3023 | |||
| 3024 | static void | ||
| 3025 | init_vectors (void) | ||
| 3026 | { | ||
| 3027 | zero_vector = pure_alloc (header_size, Lisp_Vectorlike); | ||
| 3028 | zero_vector->header.size = 0; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | /* Allocate vector from a vector block. */ | ||
| 3032 | |||
| 3033 | static struct Lisp_Vector * | ||
| 3034 | allocate_vector_from_block (size_t nbytes) | ||
| 3035 | { | ||
| 3036 | struct Lisp_Vector *vector, *rest; | ||
| 3037 | struct vector_block *block; | ||
| 3038 | size_t index, restbytes; | ||
| 3039 | |||
| 3040 | eassert (VBLOCK_BYTES_MIN <= nbytes && nbytes <= VBLOCK_BYTES_MAX); | ||
| 3041 | eassert (nbytes % roundup_size == 0); | ||
| 3042 | |||
| 3043 | /* First, try to allocate from a free list | ||
| 3044 | containing vectors of the requested size. */ | ||
| 3045 | index = VINDEX (nbytes); | ||
| 3046 | if (vector_free_lists[index]) | ||
| 3047 | { | ||
| 3048 | vector = vector_free_lists[index]; | ||
| 3049 | vector_free_lists[index] = vector->header.next.vector; | ||
| 3050 | vector->header.next.nbytes = nbytes; | ||
| 3051 | return vector; | ||
| 3052 | } | ||
| 3053 | |||
| 3054 | /* Next, check free lists containing larger vectors. Since | ||
| 3055 | we will split the result, we should have remaining space | ||
| 3056 | large enough to use for one-slot vector at least. */ | ||
| 3057 | for (index = VINDEX (nbytes + VBLOCK_BYTES_MIN); | ||
| 3058 | index < VECTOR_MAX_FREE_LIST_INDEX; index++) | ||
| 3059 | if (vector_free_lists[index]) | ||
| 3060 | { | ||
| 3061 | /* This vector is larger than requested. */ | ||
| 3062 | vector = vector_free_lists[index]; | ||
| 3063 | vector_free_lists[index] = vector->header.next.vector; | ||
| 3064 | vector->header.next.nbytes = nbytes; | ||
| 3065 | |||
| 3066 | /* Excess bytes are used for the smaller vector, | ||
| 3067 | which should be set on an appropriate free list. */ | ||
| 3068 | restbytes = index * roundup_size + VBLOCK_BYTES_MIN - nbytes; | ||
| 3069 | eassert (restbytes % roundup_size == 0); | ||
| 3070 | rest = ADVANCE (vector, nbytes); | ||
| 3071 | SETUP_ON_FREE_LIST (rest, restbytes, index); | ||
| 3072 | return vector; | ||
| 3073 | } | ||
| 3074 | |||
| 3075 | /* Finally, need a new vector block. */ | ||
| 3076 | block = allocate_vector_block (); | ||
| 3077 | |||
| 3078 | /* New vector will be at the beginning of this block. */ | ||
| 3079 | vector = (struct Lisp_Vector *) block->data; | ||
| 3080 | vector->header.next.nbytes = nbytes; | ||
| 3081 | |||
| 3082 | /* If the rest of space from this block is large enough | ||
| 3083 | for one-slot vector at least, set up it on a free list. */ | ||
| 3084 | restbytes = VECTOR_BLOCK_BYTES - nbytes; | ||
| 3085 | if (restbytes >= VBLOCK_BYTES_MIN) | ||
| 3086 | { | ||
| 3087 | eassert (restbytes % roundup_size == 0); | ||
| 3088 | rest = ADVANCE (vector, nbytes); | ||
| 3089 | SETUP_ON_FREE_LIST (rest, restbytes, index); | ||
| 3090 | } | ||
| 3091 | return vector; | ||
| 3092 | } | ||
| 3093 | |||
| 3094 | /* Return how many Lisp_Objects can be stored in V. */ | ||
| 3095 | |||
| 3096 | #define VECTOR_SIZE(v) ((v)->header.size & PSEUDOVECTOR_FLAG ? \ | ||
| 3097 | (PSEUDOVECTOR_SIZE_MASK & (v)->header.size) : \ | ||
| 3098 | (v)->header.size) | ||
| 3099 | |||
| 3100 | /* Nonzero if VECTOR pointer is valid pointer inside BLOCK. */ | ||
| 3101 | |||
| 3102 | #define VECTOR_IN_BLOCK(vector, block) \ | ||
| 3103 | ((char *) (vector) <= (block)->data \ | ||
| 3104 | + VECTOR_BLOCK_BYTES - VBLOCK_BYTES_MIN) | ||
| 3105 | |||
| 3106 | /* Reclaim space used by unmarked vectors. */ | ||
| 3107 | |||
| 3108 | static void | ||
| 3109 | sweep_vectors (void) | ||
| 3110 | { | ||
| 3111 | struct vector_block *block = vector_blocks, **bprev = &vector_blocks; | ||
| 3112 | struct Lisp_Vector *vector, *next, **vprev = &large_vectors; | ||
| 3113 | |||
| 3114 | total_vector_size = 0; | ||
| 3115 | memset (vector_free_lists, 0, sizeof (vector_free_lists)); | ||
| 3116 | |||
| 3117 | /* Looking through vector blocks. */ | ||
| 3118 | |||
| 3119 | for (block = vector_blocks; block; block = *bprev) | ||
| 3120 | { | ||
| 3121 | int free_this_block = 0; | ||
| 3122 | |||
| 3123 | for (vector = (struct Lisp_Vector *) block->data; | ||
| 3124 | VECTOR_IN_BLOCK (vector, block); vector = next) | ||
| 3125 | { | ||
| 3126 | if (VECTOR_MARKED_P (vector)) | ||
| 3127 | { | ||
| 3128 | VECTOR_UNMARK (vector); | ||
| 3129 | total_vector_size += VECTOR_SIZE (vector); | ||
| 3130 | next = ADVANCE (vector, vector->header.next.nbytes); | ||
| 3131 | } | ||
| 3132 | else | ||
| 3133 | { | ||
| 3134 | ptrdiff_t nbytes; | ||
| 3135 | |||
| 3136 | if ((vector->header.size & VECTOR_FREE_LIST_FLAG) | ||
| 3137 | == VECTOR_FREE_LIST_FLAG) | ||
| 3138 | vector->header.next.nbytes = | ||
| 3139 | vector->header.size & (VECTOR_BLOCK_SIZE - 1); | ||
| 3140 | |||
| 3141 | next = ADVANCE (vector, vector->header.next.nbytes); | ||
| 3142 | |||
| 3143 | /* While NEXT is not marked, try to coalesce with VECTOR, | ||
| 3144 | thus making VECTOR of the largest possible size. */ | ||
| 3145 | |||
| 3146 | while (VECTOR_IN_BLOCK (next, block)) | ||
| 3147 | { | ||
| 3148 | if (VECTOR_MARKED_P (next)) | ||
| 3149 | break; | ||
| 3150 | if ((next->header.size & VECTOR_FREE_LIST_FLAG) | ||
| 3151 | == VECTOR_FREE_LIST_FLAG) | ||
| 3152 | nbytes = next->header.size & (VECTOR_BLOCK_SIZE - 1); | ||
| 3153 | else | ||
| 3154 | nbytes = next->header.next.nbytes; | ||
| 3155 | vector->header.next.nbytes += nbytes; | ||
| 3156 | next = ADVANCE (next, nbytes); | ||
| 3157 | } | ||
| 3158 | |||
| 3159 | eassert (vector->header.next.nbytes % roundup_size == 0); | ||
| 3160 | |||
| 3161 | if (vector == (struct Lisp_Vector *) block->data | ||
| 3162 | && !VECTOR_IN_BLOCK (next, block)) | ||
| 3163 | /* This block should be freed because all of it's | ||
| 3164 | space was coalesced into the only free vector. */ | ||
| 3165 | free_this_block = 1; | ||
| 3166 | else | ||
| 3167 | SETUP_ON_FREE_LIST (vector, vector->header.next.nbytes, nbytes); | ||
| 3168 | } | ||
| 3169 | } | ||
| 3170 | |||
| 3171 | if (free_this_block) | ||
| 3172 | { | ||
| 3173 | *bprev = block->next; | ||
| 3174 | #if GC_MARK_STACK && !defined GC_MALLOC_CHECK | ||
| 3175 | mem_delete (mem_find (block->data)); | ||
| 3176 | #endif | ||
| 3177 | xfree (block); | ||
| 3178 | } | ||
| 3179 | else | ||
| 3180 | bprev = &block->next; | ||
| 3181 | } | ||
| 3182 | |||
| 3183 | /* Sweep large vectors. */ | ||
| 3184 | |||
| 3185 | for (vector = large_vectors; vector; vector = *vprev) | ||
| 3186 | { | ||
| 3187 | if (VECTOR_MARKED_P (vector)) | ||
| 3188 | { | ||
| 3189 | VECTOR_UNMARK (vector); | ||
| 3190 | total_vector_size += VECTOR_SIZE (vector); | ||
| 3191 | vprev = &vector->header.next.vector; | ||
| 3192 | } | ||
| 3193 | else | ||
| 3194 | { | ||
| 3195 | *vprev = vector->header.next.vector; | ||
| 3196 | lisp_free (vector); | ||
| 3197 | } | ||
| 3198 | } | ||
| 3199 | } | ||
| 3200 | |||
| 2940 | /* Value is a pointer to a newly allocated Lisp_Vector structure | 3201 | /* Value is a pointer to a newly allocated Lisp_Vector structure |
| 2941 | with room for LEN Lisp_Objects. */ | 3202 | with room for LEN Lisp_Objects. */ |
| 2942 | 3203 | ||
| @@ -2958,8 +3219,22 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 2958 | /* This gets triggered by code which I haven't bothered to fix. --Stef */ | 3219 | /* This gets triggered by code which I haven't bothered to fix. --Stef */ |
| 2959 | /* eassert (!handling_signal); */ | 3220 | /* eassert (!handling_signal); */ |
| 2960 | 3221 | ||
| 3222 | if (len == 0) | ||
| 3223 | { | ||
| 3224 | MALLOC_UNBLOCK_INPUT; | ||
| 3225 | return zero_vector; | ||
| 3226 | } | ||
| 3227 | |||
| 2961 | nbytes = header_size + len * word_size; | 3228 | nbytes = header_size + len * word_size; |
| 2962 | p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); | 3229 | |
| 3230 | if (nbytes <= VBLOCK_BYTES_MAX) | ||
| 3231 | p = allocate_vector_from_block (vroundup (nbytes)); | ||
| 3232 | else | ||
| 3233 | { | ||
| 3234 | p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTORLIKE); | ||
| 3235 | p->header.next.vector = large_vectors; | ||
| 3236 | large_vectors = p; | ||
| 3237 | } | ||
| 2963 | 3238 | ||
| 2964 | #ifdef DOUG_LEA_MALLOC | 3239 | #ifdef DOUG_LEA_MALLOC |
| 2965 | /* Back to a reasonable maximum of mmap'ed areas. */ | 3240 | /* Back to a reasonable maximum of mmap'ed areas. */ |
| @@ -2969,9 +3244,6 @@ allocate_vectorlike (ptrdiff_t len) | |||
| 2969 | consing_since_gc += nbytes; | 3244 | consing_since_gc += nbytes; |
| 2970 | vector_cells_consed += len; | 3245 | vector_cells_consed += len; |
| 2971 | 3246 | ||
| 2972 | p->header.next.vector = all_vectors; | ||
| 2973 | all_vectors = p; | ||
| 2974 | |||
| 2975 | MALLOC_UNBLOCK_INPUT; | 3247 | MALLOC_UNBLOCK_INPUT; |
| 2976 | 3248 | ||
| 2977 | return p; | 3249 | return p; |
| @@ -3095,6 +3367,19 @@ usage: (vector &rest OBJECTS) */) | |||
| 3095 | return val; | 3367 | return val; |
| 3096 | } | 3368 | } |
| 3097 | 3369 | ||
| 3370 | void | ||
| 3371 | make_byte_code (struct Lisp_Vector *v) | ||
| 3372 | { | ||
| 3373 | if (v->header.size > 1 && STRINGP (v->contents[1]) | ||
| 3374 | && STRING_MULTIBYTE (v->contents[1])) | ||
| 3375 | /* BYTECODE-STRING must have been produced by Emacs 20.2 or the | ||
| 3376 | earlier because they produced a raw 8-bit string for byte-code | ||
| 3377 | and now such a byte-code string is loaded as multibyte while | ||
| 3378 | raw 8-bit characters converted to multibyte form. Thus, now we | ||
| 3379 | must convert them back to the original unibyte form. */ | ||
| 3380 | v->contents[1] = Fstring_as_unibyte (v->contents[1]); | ||
| 3381 | XSETPVECTYPE (v, PVEC_COMPILED); | ||
| 3382 | } | ||
| 3098 | 3383 | ||
| 3099 | DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, | 3384 | DEFUN ("make-byte-code", Fmake_byte_code, Smake_byte_code, 4, MANY, 0, |
| 3100 | doc: /* Create a byte-code object with specified arguments as elements. | 3385 | doc: /* Create a byte-code object with specified arguments as elements. |
| @@ -3118,28 +3403,21 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3118 | ptrdiff_t i; | 3403 | ptrdiff_t i; |
| 3119 | register struct Lisp_Vector *p; | 3404 | register struct Lisp_Vector *p; |
| 3120 | 3405 | ||
| 3121 | XSETFASTINT (len, nargs); | 3406 | /* We used to purecopy everything here, if purify-flga was set. This worked |
| 3122 | if (!NILP (Vpurify_flag)) | 3407 | OK for Emacs-23, but with Emacs-24's lexical binding code, it can be |
| 3123 | val = make_pure_vector (nargs); | 3408 | dangerous, since make-byte-code is used during execution to build |
| 3124 | else | 3409 | closures, so any closure built during the preload phase would end up |
| 3125 | val = Fmake_vector (len, Qnil); | 3410 | copied into pure space, including its free variables, which is sometimes |
| 3411 | just wasteful and other times plainly wrong (e.g. those free vars may want | ||
| 3412 | to be setcar'd). */ | ||
| 3126 | 3413 | ||
| 3127 | if (nargs > 1 && STRINGP (args[1]) && STRING_MULTIBYTE (args[1])) | 3414 | XSETFASTINT (len, nargs); |
| 3128 | /* BYTECODE-STRING must have been produced by Emacs 20.2 or the | 3415 | val = Fmake_vector (len, Qnil); |
| 3129 | earlier because they produced a raw 8-bit string for byte-code | ||
| 3130 | and now such a byte-code string is loaded as multibyte while | ||
| 3131 | raw 8-bit characters converted to multibyte form. Thus, now we | ||
| 3132 | must convert them back to the original unibyte form. */ | ||
| 3133 | args[1] = Fstring_as_unibyte (args[1]); | ||
| 3134 | 3416 | ||
| 3135 | p = XVECTOR (val); | 3417 | p = XVECTOR (val); |
| 3136 | for (i = 0; i < nargs; i++) | 3418 | for (i = 0; i < nargs; i++) |
| 3137 | { | 3419 | p->contents[i] = args[i]; |
| 3138 | if (!NILP (Vpurify_flag)) | 3420 | make_byte_code (p); |
| 3139 | args[i] = Fpurecopy (args[i]); | ||
| 3140 | p->contents[i] = args[i]; | ||
| 3141 | } | ||
| 3142 | XSETPVECTYPE (p, PVEC_COMPILED); | ||
| 3143 | XSETCOMPILED (val, p); | 3421 | XSETCOMPILED (val, p); |
| 3144 | return val; | 3422 | return val; |
| 3145 | } | 3423 | } |
| @@ -3156,7 +3434,7 @@ usage: (make-byte-code ARGLIST BYTE-CODE CONSTANTS DEPTH &optional DOCSTRING INT | |||
| 3156 | union aligned_Lisp_Symbol | 3434 | union aligned_Lisp_Symbol |
| 3157 | { | 3435 | { |
| 3158 | struct Lisp_Symbol s; | 3436 | struct Lisp_Symbol s; |
| 3159 | #ifdef USE_LSB_TAG | 3437 | #if USE_LSB_TAG |
| 3160 | unsigned char c[(sizeof (struct Lisp_Symbol) + (1 << GCTYPEBITS) - 1) | 3438 | unsigned char c[(sizeof (struct Lisp_Symbol) + (1 << GCTYPEBITS) - 1) |
| 3161 | & -(1 << GCTYPEBITS)]; | 3439 | & -(1 << GCTYPEBITS)]; |
| 3162 | #endif | 3440 | #endif |
| @@ -3164,7 +3442,7 @@ union aligned_Lisp_Symbol | |||
| 3164 | 3442 | ||
| 3165 | /* Each symbol_block is just under 1020 bytes long, since malloc | 3443 | /* Each symbol_block is just under 1020 bytes long, since malloc |
| 3166 | really allocates in units of powers of two and uses 4 bytes for its | 3444 | really allocates in units of powers of two and uses 4 bytes for its |
| 3167 | own overhead. */ | 3445 | own overhead. */ |
| 3168 | 3446 | ||
| 3169 | #define SYMBOL_BLOCK_SIZE \ | 3447 | #define SYMBOL_BLOCK_SIZE \ |
| 3170 | ((1020 - sizeof (struct symbol_block *)) / sizeof (union aligned_Lisp_Symbol)) | 3448 | ((1020 - sizeof (struct symbol_block *)) / sizeof (union aligned_Lisp_Symbol)) |
| @@ -3262,7 +3540,7 @@ Its value and function definition are void, and its property list is nil. */) | |||
| 3262 | union aligned_Lisp_Misc | 3540 | union aligned_Lisp_Misc |
| 3263 | { | 3541 | { |
| 3264 | union Lisp_Misc m; | 3542 | union Lisp_Misc m; |
| 3265 | #ifdef USE_LSB_TAG | 3543 | #if USE_LSB_TAG |
| 3266 | unsigned char c[(sizeof (union Lisp_Misc) + (1 << GCTYPEBITS) - 1) | 3544 | unsigned char c[(sizeof (union Lisp_Misc) + (1 << GCTYPEBITS) - 1) |
| 3267 | & -(1 << GCTYPEBITS)]; | 3545 | & -(1 << GCTYPEBITS)]; |
| 3268 | #endif | 3546 | #endif |
| @@ -4070,7 +4348,34 @@ live_misc_p (struct mem_node *m, void *p) | |||
| 4070 | static inline int | 4348 | static inline int |
| 4071 | live_vector_p (struct mem_node *m, void *p) | 4349 | live_vector_p (struct mem_node *m, void *p) |
| 4072 | { | 4350 | { |
| 4073 | return (p == m->start && m->type == MEM_TYPE_VECTORLIKE); | 4351 | if (m->type == MEM_TYPE_VECTOR_BLOCK) |
| 4352 | { | ||
| 4353 | /* This memory node corresponds to a vector block. */ | ||
| 4354 | struct vector_block *block = (struct vector_block *) m->start; | ||
| 4355 | struct Lisp_Vector *vector = (struct Lisp_Vector *) block->data; | ||
| 4356 | |||
| 4357 | /* P is in the block's allocation range. Scan the block | ||
| 4358 | up to P and see whether P points to the start of some | ||
| 4359 | vector which is not on a free list. FIXME: check whether | ||
| 4360 | some allocation patterns (probably a lot of short vectors) | ||
| 4361 | may cause a substantial overhead of this loop. */ | ||
| 4362 | while (VECTOR_IN_BLOCK (vector, block) | ||
| 4363 | && vector <= (struct Lisp_Vector *) p) | ||
| 4364 | { | ||
| 4365 | if ((vector->header.size & VECTOR_FREE_LIST_FLAG) | ||
| 4366 | == VECTOR_FREE_LIST_FLAG) | ||
| 4367 | vector = ADVANCE (vector, (vector->header.size | ||
| 4368 | & (VECTOR_BLOCK_SIZE - 1))); | ||
| 4369 | else if (vector == p) | ||
| 4370 | return 1; | ||
| 4371 | else | ||
| 4372 | vector = ADVANCE (vector, vector->header.next.nbytes); | ||
| 4373 | } | ||
| 4374 | } | ||
| 4375 | else if (m->type == MEM_TYPE_VECTORLIKE && p == m->start) | ||
| 4376 | /* This memory node corresponds to a large vector. */ | ||
| 4377 | return 1; | ||
| 4378 | return 0; | ||
| 4074 | } | 4379 | } |
| 4075 | 4380 | ||
| 4076 | 4381 | ||
| @@ -4217,14 +4522,10 @@ mark_maybe_pointer (void *p) | |||
| 4217 | { | 4522 | { |
| 4218 | struct mem_node *m; | 4523 | struct mem_node *m; |
| 4219 | 4524 | ||
| 4220 | /* Quickly rule out some values which can't point to Lisp data. */ | 4525 | /* Quickly rule out some values which can't point to Lisp data. |
| 4221 | if ((intptr_t) p % | 4526 | USE_LSB_TAG needs Lisp data to be aligned on multiples of 1 << GCTYPEBITS. |
| 4222 | #ifdef USE_LSB_TAG | 4527 | Otherwise, assume that Lisp data is aligned on even addresses. */ |
| 4223 | 8 /* USE_LSB_TAG needs Lisp data to be aligned on multiples of 8. */ | 4528 | if ((intptr_t) p % (USE_LSB_TAG ? 1 << GCTYPEBITS : 2)) |
| 4224 | #else | ||
| 4225 | 2 /* We assume that Lisp data is aligned on even addresses. */ | ||
| 4226 | #endif | ||
| 4227 | ) | ||
| 4228 | return; | 4529 | return; |
| 4229 | 4530 | ||
| 4230 | m = mem_find (p); | 4531 | m = mem_find (p); |
| @@ -4270,6 +4571,7 @@ mark_maybe_pointer (void *p) | |||
| 4270 | break; | 4571 | break; |
| 4271 | 4572 | ||
| 4272 | case MEM_TYPE_VECTORLIKE: | 4573 | case MEM_TYPE_VECTORLIKE: |
| 4574 | case MEM_TYPE_VECTOR_BLOCK: | ||
| 4273 | if (live_vector_p (m, p)) | 4575 | if (live_vector_p (m, p)) |
| 4274 | { | 4576 | { |
| 4275 | Lisp_Object tem; | 4577 | Lisp_Object tem; |
| @@ -4299,8 +4601,8 @@ mark_maybe_pointer (void *p) | |||
| 4299 | wider than a pointer might allocate a Lisp_Object in non-adjacent halves. | 4601 | wider than a pointer might allocate a Lisp_Object in non-adjacent halves. |
| 4300 | If USE_LSB_TAG, the bottom half is not a valid pointer, but it should | 4602 | If USE_LSB_TAG, the bottom half is not a valid pointer, but it should |
| 4301 | suffice to widen it to to a Lisp_Object and check it that way. */ | 4603 | suffice to widen it to to a Lisp_Object and check it that way. */ |
| 4302 | #if defined USE_LSB_TAG || VAL_MAX < UINTPTR_MAX | 4604 | #if USE_LSB_TAG || VAL_MAX < UINTPTR_MAX |
| 4303 | # if !defined USE_LSB_TAG && VAL_MAX < UINTPTR_MAX >> GCTYPEBITS | 4605 | # if !USE_LSB_TAG && VAL_MAX < UINTPTR_MAX >> GCTYPEBITS |
| 4304 | /* If tag bits straddle pointer-word boundaries, neither mark_maybe_pointer | 4606 | /* If tag bits straddle pointer-word boundaries, neither mark_maybe_pointer |
| 4305 | nor mark_maybe_object can follow the pointers. This should not occur on | 4607 | nor mark_maybe_object can follow the pointers. This should not occur on |
| 4306 | any practical porting target. */ | 4608 | any practical porting target. */ |
| @@ -4361,7 +4663,7 @@ mark_memory (void *start, void *end) | |||
| 4361 | void *p = *(void **) ((char *) pp + i); | 4663 | void *p = *(void **) ((char *) pp + i); |
| 4362 | mark_maybe_pointer (p); | 4664 | mark_maybe_pointer (p); |
| 4363 | if (POINTERS_MIGHT_HIDE_IN_OBJECTS) | 4665 | if (POINTERS_MIGHT_HIDE_IN_OBJECTS) |
| 4364 | mark_maybe_object (widen_to_Lisp_Object (p)); | 4666 | mark_maybe_object (XIL ((intptr_t) p)); |
| 4365 | } | 4667 | } |
| 4366 | } | 4668 | } |
| 4367 | 4669 | ||
| @@ -4703,6 +5005,7 @@ valid_lisp_object_p (Lisp_Object obj) | |||
| 4703 | return live_float_p (m, p); | 5005 | return live_float_p (m, p); |
| 4704 | 5006 | ||
| 4705 | case MEM_TYPE_VECTORLIKE: | 5007 | case MEM_TYPE_VECTORLIKE: |
| 5008 | case MEM_TYPE_VECTOR_BLOCK: | ||
| 4706 | return live_vector_p (m, p); | 5009 | return live_vector_p (m, p); |
| 4707 | 5010 | ||
| 4708 | default: | 5011 | default: |
| @@ -4728,7 +5031,7 @@ static void * | |||
| 4728 | pure_alloc (size_t size, int type) | 5031 | pure_alloc (size_t size, int type) |
| 4729 | { | 5032 | { |
| 4730 | void *result; | 5033 | void *result; |
| 4731 | #ifdef USE_LSB_TAG | 5034 | #if USE_LSB_TAG |
| 4732 | size_t alignment = (1 << GCTYPEBITS); | 5035 | size_t alignment = (1 << GCTYPEBITS); |
| 4733 | #else | 5036 | #else |
| 4734 | size_t alignment = sizeof (EMACS_INT); | 5037 | size_t alignment = sizeof (EMACS_INT); |
| @@ -6239,33 +6542,7 @@ gc_sweep (void) | |||
| 6239 | } | 6542 | } |
| 6240 | } | 6543 | } |
| 6241 | 6544 | ||
| 6242 | /* Free all unmarked vectors */ | 6545 | sweep_vectors (); |
| 6243 | { | ||
| 6244 | register struct Lisp_Vector *vector = all_vectors, *prev = 0, *next; | ||
| 6245 | total_vector_size = 0; | ||
| 6246 | |||
| 6247 | while (vector) | ||
| 6248 | if (!VECTOR_MARKED_P (vector)) | ||
| 6249 | { | ||
| 6250 | if (prev) | ||
| 6251 | prev->header.next = vector->header.next; | ||
| 6252 | else | ||
| 6253 | all_vectors = vector->header.next.vector; | ||
| 6254 | next = vector->header.next.vector; | ||
| 6255 | lisp_free (vector); | ||
| 6256 | vector = next; | ||
| 6257 | |||
| 6258 | } | ||
| 6259 | else | ||
| 6260 | { | ||
| 6261 | VECTOR_UNMARK (vector); | ||
| 6262 | if (vector->header.size & PSEUDOVECTOR_FLAG) | ||
| 6263 | total_vector_size += PSEUDOVECTOR_SIZE_MASK & vector->header.size; | ||
| 6264 | else | ||
| 6265 | total_vector_size += vector->header.size; | ||
| 6266 | prev = vector, vector = vector->header.next.vector; | ||
| 6267 | } | ||
| 6268 | } | ||
| 6269 | 6546 | ||
| 6270 | #ifdef GC_CHECK_STRING_BYTES | 6547 | #ifdef GC_CHECK_STRING_BYTES |
| 6271 | if (!noninteractive) | 6548 | if (!noninteractive) |
| @@ -6402,7 +6679,6 @@ init_alloc_once (void) | |||
| 6402 | Vdead = make_pure_string ("DEAD", 4, 4, 0); | 6679 | Vdead = make_pure_string ("DEAD", 4, 4, 0); |
| 6403 | #endif | 6680 | #endif |
| 6404 | 6681 | ||
| 6405 | all_vectors = 0; | ||
| 6406 | ignore_warnings = 1; | 6682 | ignore_warnings = 1; |
| 6407 | #ifdef DOUG_LEA_MALLOC | 6683 | #ifdef DOUG_LEA_MALLOC |
| 6408 | mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ | 6684 | mallopt (M_TRIM_THRESHOLD, 128*1024); /* trim threshold */ |
| @@ -6415,6 +6691,7 @@ init_alloc_once (void) | |||
| 6415 | init_marker (); | 6691 | init_marker (); |
| 6416 | init_float (); | 6692 | init_float (); |
| 6417 | init_intervals (); | 6693 | init_intervals (); |
| 6694 | init_vectors (); | ||
| 6418 | init_weak_hash_tables (); | 6695 | init_weak_hash_tables (); |
| 6419 | 6696 | ||
| 6420 | #ifdef REL_ALLOC | 6697 | #ifdef REL_ALLOC |