diff options
| author | Gerd Moellmann | 2000-01-04 12:25:51 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2000-01-04 12:25:51 +0000 |
| commit | 2e471eb5f3defe261f403bc076f0abf77c0341a5 (patch) | |
| tree | 41813cb680cca0c76227f5371050ed2e16f9047f /src/alloc.c | |
| parent | f05d7ea2293fabf30b066ec5c0a0c209bf54eea9 (diff) | |
| download | emacs-2e471eb5f3defe261f403bc076f0abf77c0341a5.tar.gz emacs-2e471eb5f3defe261f403bc076f0abf77c0341a5.zip | |
(Fgarbage_collect): Return number of live and free
strings.
(mark_buffer): Remove code in #if 0.
(gc_sweep): Ditto.
(UNMARK_BALANCE_INTERVALS): Give the macro statement form.
(strings_consed): New variable.
(allocate_string): Set it.
(syms_of_alloc): Add DEFVAR_INT for strings_consed.
(Fmemory_use_counts): Return strings_consed. Use Flist.
General cleanup in comments etc. Remove conditional
compilation for `standalone'.
(MARK_STRING, UNMARK_STRING, STRING_MARKED_P):
(GC_STRING_BYTES, GC_STRING_CHARS): New macros.
(DONT_COPY_FLAG): Removed.
(SBLOCK_SIZE, LARGE_STRING_BYTES): New macros.
(struct sdata, struct sblock): New
(struct string_block): Rewritten.
(STRINGS_IN_STRING_BLOCK): New macro.
(oldest_sblock, current_sblock, total_strings, total_free_strings)
(large_sblocks, string_blocks, string_free_list): New variables.
(NEXT_FREE_LISP_STRING, SDATA_OF_STRING, SDATA_SIZE): New macros.
(init_strings): Rewritten.
(allocate_string, allocate_string_data, compact_small_strings)
(free_large_strings, sweep_strings): New functions.
(STRING_BLOCK_SIZE, STRING_BLOCK_OUTSIZE)
(struct string_block_head, current_string_block)
(first_string_block, large_string_blocks, STRING_FULLSIZE)
(STRING_PAD): Removed.
(make_uninit_multibyte_string, make_pure_string): Rewritten.
(Fgarbage_collect): Don't set mark bit in large strings.
(mark_object): Mark strings differently. Mark symbol names
differently.
(survives_gc_p): Test marked strings differently.
(gc_sweep): Sweep strings differently, unmark strings in
symbol names.
(compact_strings): Removed.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 1788 |
1 files changed, 998 insertions, 790 deletions
diff --git a/src/alloc.c b/src/alloc.c index 556149695e4..552d791616d 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Storage allocation and gc for GNU Emacs Lisp interpreter. | 1 | /* Storage allocation and gc for GNU Emacs Lisp interpreter. |
| 2 | Copyright (C) 1985, 86, 88, 93, 94, 95, 97, 98, 1999 | 2 | Copyright (C) 1985, 86, 88, 93, 94, 95, 97, 98, 1999, 2000 |
| 3 | Free Software Foundation, Inc. | 3 | Free Software Foundation, Inc. |
| 4 | 4 | ||
| 5 | This file is part of GNU Emacs. | 5 | This file is part of GNU Emacs. |
| @@ -22,38 +22,39 @@ Boston, MA 02111-1307, USA. */ | |||
| 22 | #include <config.h> | 22 | #include <config.h> |
| 23 | 23 | ||
| 24 | /* Note that this declares bzero on OSF/1. How dumb. */ | 24 | /* Note that this declares bzero on OSF/1. How dumb. */ |
| 25 | |||
| 25 | #include <signal.h> | 26 | #include <signal.h> |
| 26 | 27 | ||
| 27 | /* This file is part of the core Lisp implementation, and thus must | 28 | /* This file is part of the core Lisp implementation, and thus must |
| 28 | deal with the real data structures. If the Lisp implementation is | 29 | deal with the real data structures. If the Lisp implementation is |
| 29 | replaced, this file likely will not be used. */ | 30 | replaced, this file likely will not be used. */ |
| 31 | |||
| 30 | #undef HIDE_LISP_IMPLEMENTATION | 32 | #undef HIDE_LISP_IMPLEMENTATION |
| 31 | #include "lisp.h" | 33 | #include "lisp.h" |
| 32 | #include "intervals.h" | 34 | #include "intervals.h" |
| 33 | #include "puresize.h" | 35 | #include "puresize.h" |
| 34 | #ifndef standalone | ||
| 35 | #include "buffer.h" | 36 | #include "buffer.h" |
| 36 | #include "window.h" | 37 | #include "window.h" |
| 37 | #include "frame.h" | 38 | #include "frame.h" |
| 38 | #include "blockinput.h" | 39 | #include "blockinput.h" |
| 39 | #include "keyboard.h" | 40 | #include "keyboard.h" |
| 40 | #include "charset.h" | 41 | #include "charset.h" |
| 41 | #endif | ||
| 42 | |||
| 43 | #include "syssignal.h" | 42 | #include "syssignal.h" |
| 44 | 43 | ||
| 45 | extern char *sbrk (); | 44 | extern char *sbrk (); |
| 46 | 45 | ||
| 47 | #ifdef DOUG_LEA_MALLOC | 46 | #ifdef DOUG_LEA_MALLOC |
| 47 | |||
| 48 | #include <malloc.h> | 48 | #include <malloc.h> |
| 49 | #define __malloc_size_t int | 49 | #define __malloc_size_t int |
| 50 | 50 | ||
| 51 | /* Specify maximum number of areas to mmap. | 51 | /* Specify maximum number of areas to mmap. It would be nice to use a |
| 52 | It would be nice to use a value that explicitly | 52 | value that explicitly means "no limit". */ |
| 53 | means "no limit". */ | 53 | |
| 54 | #define MMAP_MAX_AREAS 100000000 | 54 | #define MMAP_MAX_AREAS 100000000 |
| 55 | 55 | ||
| 56 | #else | 56 | #else /* not DOUG_LEA_MALLOC */ |
| 57 | |||
| 57 | /* The following come from gmalloc.c. */ | 58 | /* The following come from gmalloc.c. */ |
| 58 | 59 | ||
| 59 | #if defined (__STDC__) && __STDC__ | 60 | #if defined (__STDC__) && __STDC__ |
| @@ -64,7 +65,8 @@ extern char *sbrk (); | |||
| 64 | #endif | 65 | #endif |
| 65 | extern __malloc_size_t _bytes_used; | 66 | extern __malloc_size_t _bytes_used; |
| 66 | extern int __malloc_extra_blocks; | 67 | extern int __malloc_extra_blocks; |
| 67 | #endif /* !defined(DOUG_LEA_MALLOC) */ | 68 | |
| 69 | #endif /* not DOUG_LEA_MALLOC */ | ||
| 68 | 70 | ||
| 69 | #define max(A,B) ((A) > (B) ? (A) : (B)) | 71 | #define max(A,B) ((A) > (B) ? (A) : (B)) |
| 70 | #define min(A,B) ((A) < (B) ? (A) : (B)) | 72 | #define min(A,B) ((A) < (B) ? (A) : (B)) |
| @@ -73,6 +75,7 @@ extern int __malloc_extra_blocks; | |||
| 73 | out of range to fit in the space for a pointer. | 75 | out of range to fit in the space for a pointer. |
| 74 | ADDRESS is the start of the block, and SIZE | 76 | ADDRESS is the start of the block, and SIZE |
| 75 | is the amount of space within which objects can start. */ | 77 | is the amount of space within which objects can start. */ |
| 78 | |||
| 76 | #define VALIDATE_LISP_STORAGE(address, size) \ | 79 | #define VALIDATE_LISP_STORAGE(address, size) \ |
| 77 | do \ | 80 | do \ |
| 78 | { \ | 81 | { \ |
| @@ -86,12 +89,30 @@ do \ | |||
| 86 | } while (0) | 89 | } while (0) |
| 87 | 90 | ||
| 88 | /* Value of _bytes_used, when spare_memory was freed. */ | 91 | /* Value of _bytes_used, when spare_memory was freed. */ |
| 92 | |||
| 89 | static __malloc_size_t bytes_used_when_full; | 93 | static __malloc_size_t bytes_used_when_full; |
| 90 | 94 | ||
| 91 | /* Number of bytes of consing done since the last gc */ | 95 | /* Mark, unmark, query mark bit of a Lisp string. S must be a pointer |
| 96 | to a struct Lisp_String. */ | ||
| 97 | |||
| 98 | #define MARK_STRING(S) XMARK ((S)->size) | ||
| 99 | #define UNMARK_STRING(S) XUNMARK ((S)->size) | ||
| 100 | #define STRING_MARKED_P(S) XMARKBIT ((S)->size) | ||
| 101 | |||
| 102 | /* Value is the number of bytes/chars of S, a pointer to a struct | ||
| 103 | Lisp_String. This must be used instead of STRING_BYTES (S) or | ||
| 104 | S->size during GC, because S->size contains the mark bit for | ||
| 105 | strings. */ | ||
| 106 | |||
| 107 | #define GC_STRING_BYTES(S) (STRING_BYTES (S) & ~MARKBIT) | ||
| 108 | #define GC_STRING_CHARS(S) ((S)->size & ~MARKBIT) | ||
| 109 | |||
| 110 | /* Number of bytes of consing done since the last gc. */ | ||
| 111 | |||
| 92 | int consing_since_gc; | 112 | int consing_since_gc; |
| 93 | 113 | ||
| 94 | /* Count the amount of consing of various sorts of space. */ | 114 | /* Count the amount of consing of various sorts of space. */ |
| 115 | |||
| 95 | int cons_cells_consed; | 116 | int cons_cells_consed; |
| 96 | int floats_consed; | 117 | int floats_consed; |
| 97 | int vector_cells_consed; | 118 | int vector_cells_consed; |
| @@ -99,75 +120,97 @@ int symbols_consed; | |||
| 99 | int string_chars_consed; | 120 | int string_chars_consed; |
| 100 | int misc_objects_consed; | 121 | int misc_objects_consed; |
| 101 | int intervals_consed; | 122 | int intervals_consed; |
| 123 | int strings_consed; | ||
| 124 | |||
| 125 | /* Number of bytes of consing since GC before another GC should be done. */ | ||
| 102 | 126 | ||
| 103 | /* Number of bytes of consing since gc before another gc should be done. */ | ||
| 104 | int gc_cons_threshold; | 127 | int gc_cons_threshold; |
| 105 | 128 | ||
| 106 | /* Nonzero during gc */ | 129 | /* Nonzero during GC. */ |
| 130 | |||
| 107 | int gc_in_progress; | 131 | int gc_in_progress; |
| 108 | 132 | ||
| 109 | /* Nonzero means display messages at beginning and end of GC. */ | 133 | /* Nonzero means display messages at beginning and end of GC. */ |
| 134 | |||
| 110 | int garbage_collection_messages; | 135 | int garbage_collection_messages; |
| 111 | 136 | ||
| 112 | #ifndef VIRT_ADDR_VARIES | 137 | #ifndef VIRT_ADDR_VARIES |
| 113 | extern | 138 | extern |
| 114 | #endif /* VIRT_ADDR_VARIES */ | 139 | #endif /* VIRT_ADDR_VARIES */ |
| 115 | int malloc_sbrk_used; | 140 | int malloc_sbrk_used; |
| 116 | 141 | ||
| 117 | #ifndef VIRT_ADDR_VARIES | 142 | #ifndef VIRT_ADDR_VARIES |
| 118 | extern | 143 | extern |
| 119 | #endif /* VIRT_ADDR_VARIES */ | 144 | #endif /* VIRT_ADDR_VARIES */ |
| 120 | int malloc_sbrk_unused; | 145 | int malloc_sbrk_unused; |
| 121 | 146 | ||
| 122 | /* Two limits controlling how much undo information to keep. */ | 147 | /* Two limits controlling how much undo information to keep. */ |
| 148 | |||
| 123 | int undo_limit; | 149 | int undo_limit; |
| 124 | int undo_strong_limit; | 150 | int undo_strong_limit; |
| 125 | 151 | ||
| 126 | int total_conses, total_markers, total_symbols, total_string_size, total_vector_size; | 152 | int total_conses, total_markers, total_symbols, total_vector_size; |
| 127 | int total_free_conses, total_free_markers, total_free_symbols; | 153 | int total_free_conses, total_free_markers, total_free_symbols; |
| 128 | #ifdef LISP_FLOAT_TYPE | 154 | #ifdef LISP_FLOAT_TYPE |
| 129 | int total_free_floats, total_floats; | 155 | int total_free_floats, total_floats; |
| 130 | #endif /* LISP_FLOAT_TYPE */ | 156 | #endif /* LISP_FLOAT_TYPE */ |
| 131 | 157 | ||
| 132 | /* Points to memory space allocated as "spare", | 158 | /* Points to memory space allocated as "spare", to be freed if we run |
| 133 | to be freed if we run out of memory. */ | 159 | out of memory. */ |
| 160 | |||
| 134 | static char *spare_memory; | 161 | static char *spare_memory; |
| 135 | 162 | ||
| 136 | /* Amount of spare memory to keep in reserve. */ | 163 | /* Amount of spare memory to keep in reserve. */ |
| 164 | |||
| 137 | #define SPARE_MEMORY (1 << 14) | 165 | #define SPARE_MEMORY (1 << 14) |
| 138 | 166 | ||
| 139 | /* Number of extra blocks malloc should get when it needs more core. */ | 167 | /* Number of extra blocks malloc should get when it needs more core. */ |
| 168 | |||
| 140 | static int malloc_hysteresis; | 169 | static int malloc_hysteresis; |
| 141 | 170 | ||
| 142 | /* Nonzero when malloc is called for allocating Lisp object space. */ | 171 | /* Nonzero when malloc is called for allocating Lisp object space. |
| 172 | Currently set but not used. */ | ||
| 173 | |||
| 143 | int allocating_for_lisp; | 174 | int allocating_for_lisp; |
| 144 | 175 | ||
| 145 | /* Non-nil means defun should do purecopy on the function definition */ | 176 | /* Non-nil means defun should do purecopy on the function definition. */ |
| 177 | |||
| 146 | Lisp_Object Vpurify_flag; | 178 | Lisp_Object Vpurify_flag; |
| 147 | 179 | ||
| 148 | #ifndef HAVE_SHM | 180 | #ifndef HAVE_SHM |
| 149 | EMACS_INT pure[PURESIZE / sizeof (EMACS_INT)] = {0,}; /* Force it into data space! */ | 181 | |
| 182 | /* Force it into data space! */ | ||
| 183 | |||
| 184 | EMACS_INT pure[PURESIZE / sizeof (EMACS_INT)] = {0,}; | ||
| 150 | #define PUREBEG (char *) pure | 185 | #define PUREBEG (char *) pure |
| 151 | #else | 186 | |
| 187 | #else /* not HAVE_SHM */ | ||
| 188 | |||
| 152 | #define pure PURE_SEG_BITS /* Use shared memory segment */ | 189 | #define pure PURE_SEG_BITS /* Use shared memory segment */ |
| 153 | #define PUREBEG (char *)PURE_SEG_BITS | 190 | #define PUREBEG (char *)PURE_SEG_BITS |
| 154 | 191 | ||
| 155 | /* This variable is used only by the XPNTR macro when HAVE_SHM is | 192 | /* This variable is used only by the XPNTR macro when HAVE_SHM is |
| 156 | defined. If we used the PURESIZE macro directly there, that would | 193 | defined. If we used the PURESIZE macro directly there, that would |
| 157 | make most of emacs dependent on puresize.h, which we don't want - | 194 | make most of Emacs dependent on puresize.h, which we don't want - |
| 158 | you should be able to change that without too much recompilation. | 195 | you should be able to change that without too much recompilation. |
| 159 | So map_in_data initializes pure_size, and the dependencies work | 196 | So map_in_data initializes pure_size, and the dependencies work |
| 160 | out. */ | 197 | out. */ |
| 198 | |||
| 161 | EMACS_INT pure_size; | 199 | EMACS_INT pure_size; |
| 200 | |||
| 162 | #endif /* not HAVE_SHM */ | 201 | #endif /* not HAVE_SHM */ |
| 163 | 202 | ||
| 164 | /* Index in pure at which next pure object will be allocated. */ | 203 | /* Index in pure at which next pure object will be allocated.. */ |
| 204 | |||
| 165 | int pureptr; | 205 | int pureptr; |
| 166 | 206 | ||
| 167 | /* If nonzero, this is a warning delivered by malloc and not yet displayed. */ | 207 | /* If nonzero, this is a warning delivered by malloc and not yet |
| 208 | displayed. */ | ||
| 209 | |||
| 168 | char *pending_malloc_warning; | 210 | char *pending_malloc_warning; |
| 169 | 211 | ||
| 170 | /* Pre-computed signal argument for use when memory is exhausted. */ | 212 | /* Pre-computed signal argument for use when memory is exhausted. */ |
| 213 | |||
| 171 | Lisp_Object memory_signal_data; | 214 | Lisp_Object memory_signal_data; |
| 172 | 215 | ||
| 173 | /* Maximum amount of C stack to save when a GC happens. */ | 216 | /* Maximum amount of C stack to save when a GC happens. */ |
| @@ -176,30 +219,21 @@ Lisp_Object memory_signal_data; | |||
| 176 | #define MAX_SAVE_STACK 16000 | 219 | #define MAX_SAVE_STACK 16000 |
| 177 | #endif | 220 | #endif |
| 178 | 221 | ||
| 179 | /* Define DONT_COPY_FLAG to be some bit which will always be zero in a | ||
| 180 | pointer to a Lisp_Object, when that pointer is viewed as an integer. | ||
| 181 | (On most machines, pointers are even, so we can use the low bit. | ||
| 182 | Word-addressable architectures may need to override this in the m-file.) | ||
| 183 | When linking references to small strings through the size field, we | ||
| 184 | use this slot to hold the bit that would otherwise be interpreted as | ||
| 185 | the GC mark bit. */ | ||
| 186 | #ifndef DONT_COPY_FLAG | ||
| 187 | #define DONT_COPY_FLAG 1 | ||
| 188 | #endif /* no DONT_COPY_FLAG */ | ||
| 189 | |||
| 190 | /* Buffer in which we save a copy of the C stack at each GC. */ | 222 | /* Buffer in which we save a copy of the C stack at each GC. */ |
| 191 | 223 | ||
| 192 | char *stack_copy; | 224 | char *stack_copy; |
| 193 | int stack_copy_size; | 225 | int stack_copy_size; |
| 194 | 226 | ||
| 195 | /* Non-zero means ignore malloc warnings. Set during initialization. */ | 227 | /* Non-zero means ignore malloc warnings. Set during initialization. |
| 228 | Currently not used. */ | ||
| 229 | |||
| 196 | int ignore_warnings; | 230 | int ignore_warnings; |
| 197 | 231 | ||
| 198 | Lisp_Object Qgc_cons_threshold, Qchar_table_extra_slots; | 232 | Lisp_Object Qgc_cons_threshold, Qchar_table_extra_slots; |
| 199 | 233 | ||
| 200 | static void mark_buffer (), mark_kboards (); | 234 | static void mark_buffer P_ ((Lisp_Object)); |
| 201 | static void gc_sweep (); | 235 | static void mark_kboards P_ ((void)); |
| 202 | static void compact_strings (); | 236 | static void gc_sweep P_ ((void)); |
| 203 | static void mark_glyph_matrix P_ ((struct glyph_matrix *)); | 237 | static void mark_glyph_matrix P_ ((struct glyph_matrix *)); |
| 204 | static void mark_face_cache P_ ((struct face_cache *)); | 238 | static void mark_face_cache P_ ((struct face_cache *)); |
| 205 | #if 0 | 239 | #if 0 |
| @@ -211,10 +245,15 @@ static void mark_image P_ ((struct image *)); | |||
| 211 | static void mark_image_cache P_ ((struct frame *)); | 245 | static void mark_image_cache P_ ((struct frame *)); |
| 212 | #endif /* HAVE_WINDOW_SYSTEM */ | 246 | #endif /* HAVE_WINDOW_SYSTEM */ |
| 213 | 247 | ||
| 248 | static struct Lisp_String *allocate_string P_ ((void)); | ||
| 249 | static void compact_small_strings P_ ((void)); | ||
| 250 | static void free_large_strings P_ ((void)); | ||
| 251 | static void sweep_strings P_ ((void)); | ||
| 214 | 252 | ||
| 215 | extern int message_enable_multibyte; | 253 | extern int message_enable_multibyte; |
| 216 | 254 | ||
| 217 | /* Versions of malloc and realloc that print warnings as memory gets full. */ | 255 | /* Versions of malloc and realloc that print warnings as memory gets |
| 256 | full. */ | ||
| 218 | 257 | ||
| 219 | Lisp_Object | 258 | Lisp_Object |
| 220 | malloc_warning_1 (str) | 259 | malloc_warning_1 (str) |
| @@ -227,7 +266,7 @@ malloc_warning_1 (str) | |||
| 227 | return Qnil; | 266 | return Qnil; |
| 228 | } | 267 | } |
| 229 | 268 | ||
| 230 | /* malloc calls this if it finds we are near exhausting storage */ | 269 | /* malloc calls this if it finds we are near exhausting storage. */ |
| 231 | 270 | ||
| 232 | void | 271 | void |
| 233 | malloc_warning (str) | 272 | malloc_warning (str) |
| @@ -252,7 +291,7 @@ display_malloc_warning () | |||
| 252 | # define BYTES_USED _bytes_used | 291 | # define BYTES_USED _bytes_used |
| 253 | #endif | 292 | #endif |
| 254 | 293 | ||
| 255 | /* Called if malloc returns zero */ | 294 | /* Called if malloc returns zero. */ |
| 256 | 295 | ||
| 257 | void | 296 | void |
| 258 | memory_full () | 297 | memory_full () |
| @@ -268,8 +307,8 @@ memory_full () | |||
| 268 | spare_memory = 0; | 307 | spare_memory = 0; |
| 269 | } | 308 | } |
| 270 | 309 | ||
| 271 | /* This used to call error, but if we've run out of memory, we could get | 310 | /* This used to call error, but if we've run out of memory, we could |
| 272 | infinite recursion trying to build the string. */ | 311 | get infinite recursion trying to build the string. */ |
| 273 | while (1) | 312 | while (1) |
| 274 | Fsignal (Qnil, memory_signal_data); | 313 | Fsignal (Qnil, memory_signal_data); |
| 275 | } | 314 | } |
| @@ -279,24 +318,25 @@ memory_full () | |||
| 279 | void | 318 | void |
| 280 | buffer_memory_full () | 319 | buffer_memory_full () |
| 281 | { | 320 | { |
| 282 | /* If buffers use the relocating allocator, | 321 | /* If buffers use the relocating allocator, no need to free |
| 283 | no need to free spare_memory, because we may have plenty of malloc | 322 | spare_memory, because we may have plenty of malloc space left |
| 284 | space left that we could get, and if we don't, the malloc that fails | 323 | that we could get, and if we don't, the malloc that fails will |
| 285 | will itself cause spare_memory to be freed. | 324 | itself cause spare_memory to be freed. If buffers don't use the |
| 286 | If buffers don't use the relocating allocator, | 325 | relocating allocator, treat this like any other failing |
| 287 | treat this like any other failing malloc. */ | 326 | malloc. */ |
| 288 | 327 | ||
| 289 | #ifndef REL_ALLOC | 328 | #ifndef REL_ALLOC |
| 290 | memory_full (); | 329 | memory_full (); |
| 291 | #endif | 330 | #endif |
| 292 | 331 | ||
| 293 | /* This used to call error, but if we've run out of memory, we could get | 332 | /* This used to call error, but if we've run out of memory, we could |
| 294 | infinite recursion trying to build the string. */ | 333 | get infinite recursion trying to build the string. */ |
| 295 | while (1) | 334 | while (1) |
| 296 | Fsignal (Qerror, memory_signal_data); | 335 | Fsignal (Qerror, memory_signal_data); |
| 297 | } | 336 | } |
| 298 | 337 | ||
| 299 | /* Like malloc routines but check for no memory and block interrupt input. */ | 338 | /* Like malloc routines but check for no memory and block interrupt |
| 339 | input.. */ | ||
| 300 | 340 | ||
| 301 | long * | 341 | long * |
| 302 | xmalloc (size) | 342 | xmalloc (size) |
| @@ -308,7 +348,8 @@ xmalloc (size) | |||
| 308 | val = (long *) malloc (size); | 348 | val = (long *) malloc (size); |
| 309 | UNBLOCK_INPUT; | 349 | UNBLOCK_INPUT; |
| 310 | 350 | ||
| 311 | if (!val && size) memory_full (); | 351 | if (!val && size) |
| 352 | memory_full (); | ||
| 312 | return val; | 353 | return val; |
| 313 | } | 354 | } |
| 314 | 355 | ||
| @@ -381,6 +422,7 @@ lisp_free (block) | |||
| 381 | GNU malloc. */ | 422 | GNU malloc. */ |
| 382 | 423 | ||
| 383 | #ifndef SYSTEM_MALLOC | 424 | #ifndef SYSTEM_MALLOC |
| 425 | |||
| 384 | extern void * (*__malloc_hook) (); | 426 | extern void * (*__malloc_hook) (); |
| 385 | static void * (*old_malloc_hook) (); | 427 | static void * (*old_malloc_hook) (); |
| 386 | extern void * (*__realloc_hook) (); | 428 | extern void * (*__realloc_hook) (); |
| @@ -479,25 +521,32 @@ uninterrupt_malloc () | |||
| 479 | old_realloc_hook = __realloc_hook; | 521 | old_realloc_hook = __realloc_hook; |
| 480 | __realloc_hook = emacs_blocked_realloc; | 522 | __realloc_hook = emacs_blocked_realloc; |
| 481 | } | 523 | } |
| 482 | #endif | 524 | |
| 525 | #endif /* not SYSTEM_MALLOC */ | ||
| 526 | |||
| 527 | |||
| 483 | 528 | ||
| 484 | /* Interval allocation. */ | 529 | /*********************************************************************** |
| 530 | Interval Allocation | ||
| 531 | ***********************************************************************/ | ||
| 485 | 532 | ||
| 486 | #define INTERVAL_BLOCK_SIZE \ | 533 | #define INTERVAL_BLOCK_SIZE \ |
| 487 | ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval)) | 534 | ((1020 - sizeof (struct interval_block *)) / sizeof (struct interval)) |
| 488 | 535 | ||
| 489 | struct interval_block | 536 | struct interval_block |
| 490 | { | 537 | { |
| 491 | struct interval_block *next; | 538 | struct interval_block *next; |
| 492 | struct interval intervals[INTERVAL_BLOCK_SIZE]; | 539 | struct interval intervals[INTERVAL_BLOCK_SIZE]; |
| 493 | }; | 540 | }; |
| 494 | 541 | ||
| 495 | struct interval_block *interval_block; | 542 | struct interval_block *interval_block; |
| 496 | static int interval_block_index; | 543 | static int interval_block_index; |
| 544 | static int total_free_intervals, total_intervals; | ||
| 497 | 545 | ||
| 498 | INTERVAL interval_free_list; | 546 | INTERVAL interval_free_list; |
| 499 | 547 | ||
| 500 | /* Total number of interval blocks now in use. */ | 548 | /* Total number of interval blocks now in use. */ |
| 549 | |||
| 501 | int n_interval_blocks; | 550 | int n_interval_blocks; |
| 502 | 551 | ||
| 503 | static void | 552 | static void |
| @@ -546,8 +595,6 @@ make_interval () | |||
| 546 | return val; | 595 | return val; |
| 547 | } | 596 | } |
| 548 | 597 | ||
| 549 | static int total_free_intervals, total_intervals; | ||
| 550 | |||
| 551 | /* Mark the pointers of one interval. */ | 598 | /* Mark the pointers of one interval. */ |
| 552 | 599 | ||
| 553 | static void | 600 | static void |
| @@ -584,44 +631,745 @@ mark_interval_tree (tree) | |||
| 584 | } while (0) | 631 | } while (0) |
| 585 | 632 | ||
| 586 | /* The oddity in the call to XUNMARK is necessary because XUNMARK | 633 | /* The oddity in the call to XUNMARK is necessary because XUNMARK |
| 587 | expands to an assignment to its argument, and most C compilers don't | 634 | expands to an assignment to its argument, and most C compilers |
| 588 | support casts on the left operand of `='. */ | 635 | don't support casts on the left operand of `='. */ |
| 589 | #define UNMARK_BALANCE_INTERVALS(i) \ | 636 | |
| 590 | { \ | 637 | #define UNMARK_BALANCE_INTERVALS(i) \ |
| 591 | if (! NULL_INTERVAL_P (i)) \ | 638 | do { \ |
| 592 | { \ | 639 | if (! NULL_INTERVAL_P (i)) \ |
| 593 | XUNMARK (* (Lisp_Object *) (&(i)->parent)); \ | 640 | { \ |
| 594 | (i) = balance_intervals (i); \ | 641 | XUNMARK (* (Lisp_Object *) (&(i)->parent)); \ |
| 595 | } \ | 642 | (i) = balance_intervals (i); \ |
| 643 | } \ | ||
| 644 | } while (0) | ||
| 645 | |||
| 646 | |||
| 647 | /*********************************************************************** | ||
| 648 | String Allocation | ||
| 649 | ***********************************************************************/ | ||
| 650 | |||
| 651 | /* Lisp_Strings are allocated in string_block structures. When a new | ||
| 652 | string_block is allocated, all the Lisp_Strings it contains are | ||
| 653 | added to a free-list stiing_free_list. When a new Lisp_String is | ||
| 654 | needed, it is taken from that list. During the sweep phase of GC, | ||
| 655 | string_blocks that are entirely free are freed, except two which | ||
| 656 | we keep. | ||
| 657 | |||
| 658 | String data is allocated from sblock structures. Strings larger | ||
| 659 | than LARGE_STRING_BYTES, get their own sblock, data for smaller | ||
| 660 | strings is sub-allocated out of sblocks of size SBLOCK_SIZE. | ||
| 661 | |||
| 662 | Sblocks consist internally of sdata structures, one for each | ||
| 663 | Lisp_String. The sdata structure points to the Lisp_String it | ||
| 664 | belongs to. The Lisp_String points back to the `u.data' member of | ||
| 665 | its sdata structure. | ||
| 666 | |||
| 667 | When a Lisp_String is freed during GC, it is put back on | ||
| 668 | string_free_list, and its `data' member and its sdata's `string' | ||
| 669 | pointer is set to null. The size of the string is recorded in the | ||
| 670 | `u.nbytes' member of the sdata. So, sdata structures that are no | ||
| 671 | longer used, can be easily recognized, and it's easy to compact the | ||
| 672 | sblocks of small strings which we do in compact_small_strings. */ | ||
| 673 | |||
| 674 | /* Size in bytes of an sblock structure used for small strings. This | ||
| 675 | is 8192 minus malloc overhead. */ | ||
| 676 | |||
| 677 | #define SBLOCK_SIZE 8188 | ||
| 678 | |||
| 679 | /* Strings larger than this are considered large strings. String data | ||
| 680 | for large strings is allocated from individual sblocks. */ | ||
| 681 | |||
| 682 | #define LARGE_STRING_BYTES 1024 | ||
| 683 | |||
| 684 | /* Structure describing string memory sub-allocated from an sblock. | ||
| 685 | This is where the contents of Lisp strings are stored. */ | ||
| 686 | |||
| 687 | struct sdata | ||
| 688 | { | ||
| 689 | /* Back-pointer to the string this sdata belongs to. If null, this | ||
| 690 | structure is free, and the NBYTES member of the union below | ||
| 691 | contains the string byte size (the same value that STRING_BYTES | ||
| 692 | would return if STRING were non-null). If non-null, STRING_BYTES | ||
| 693 | (STRING) is the size of the data, and DATA contains the string's | ||
| 694 | contents. */ | ||
| 695 | struct Lisp_String *string; | ||
| 696 | |||
| 697 | union | ||
| 698 | { | ||
| 699 | /* When STRING in non-null. */ | ||
| 700 | unsigned char data[1]; | ||
| 701 | |||
| 702 | /* When STRING is null. */ | ||
| 703 | EMACS_INT nbytes; | ||
| 704 | } u; | ||
| 705 | }; | ||
| 706 | |||
| 707 | /* Structure describing a block of memory which is sub-allocated to | ||
| 708 | obtain string data memory for strings. Blocks for small strings | ||
| 709 | are of fixed size SBLOCK_SIZE. Blocks for large strings are made | ||
| 710 | as large as needed. */ | ||
| 711 | |||
| 712 | struct sblock | ||
| 713 | { | ||
| 714 | /* Next in list. */ | ||
| 715 | struct sblock *next; | ||
| 716 | |||
| 717 | /* Pointer to the next free sdata block. This points past the end | ||
| 718 | of the sblock if there isn't any space left in this block. */ | ||
| 719 | struct sdata *next_free; | ||
| 720 | |||
| 721 | /* Start of data. */ | ||
| 722 | struct sdata first_data; | ||
| 723 | }; | ||
| 724 | |||
| 725 | /* Number of Lisp strings in a string_block structure. The 1020 is | ||
| 726 | 1024 minus malloc overhead. */ | ||
| 727 | |||
| 728 | #define STRINGS_IN_STRING_BLOCK \ | ||
| 729 | ((1020 - sizeof (struct string_block *)) / sizeof (struct Lisp_String)) | ||
| 730 | |||
| 731 | /* Structure describing a block from which Lisp_String structures | ||
| 732 | are allocated. */ | ||
| 733 | |||
| 734 | struct string_block | ||
| 735 | { | ||
| 736 | struct string_block *next; | ||
| 737 | struct Lisp_String strings[STRINGS_IN_STRING_BLOCK]; | ||
| 738 | }; | ||
| 739 | |||
| 740 | /* Head and tail of the list of sblock structures holding Lisp string | ||
| 741 | data. We always allocate from current_sblock. The NEXT pointers | ||
| 742 | in the sblock structures go from oldest_sblock to current_sblock. */ | ||
| 743 | |||
| 744 | static struct sblock *oldest_sblock, *current_sblock; | ||
| 745 | |||
| 746 | /* List of sblocks for large strings. */ | ||
| 747 | |||
| 748 | static struct sblock *large_sblocks; | ||
| 749 | |||
| 750 | /* List of string_block structures, and how many there are. */ | ||
| 751 | |||
| 752 | static struct string_block *string_blocks; | ||
| 753 | static int n_string_blocks; | ||
| 754 | |||
| 755 | /* Free-list of Lisp_Strings. */ | ||
| 756 | |||
| 757 | static struct Lisp_String *string_free_list; | ||
| 758 | |||
| 759 | /* Number of live and free Lisp_Strings. */ | ||
| 760 | |||
| 761 | static int total_strings, total_free_strings; | ||
| 762 | |||
| 763 | /* Number of bytes used by live strings. */ | ||
| 764 | |||
| 765 | static int total_string_size; | ||
| 766 | |||
| 767 | /* Given a pointer to a Lisp_String S which is on the free-list | ||
| 768 | string_free_list, return a pointer to its successor in the | ||
| 769 | free-list. */ | ||
| 770 | |||
| 771 | #define NEXT_FREE_LISP_STRING(S) (*(struct Lisp_String **) (S)) | ||
| 772 | |||
| 773 | /* Return a pointer to the sdata structure belonging to Lisp string S. | ||
| 774 | S must be live, i.e. S->data must not be null. S->data is actually | ||
| 775 | a pointer to the `u.data' member of its sdata structure; the | ||
| 776 | structure starts at a constant offset in front of that. */ | ||
| 777 | |||
| 778 | #define SDATA_OF_STRING(S) \ | ||
| 779 | ((struct sdata *) ((S)->data - sizeof (struct Lisp_String *))) | ||
| 780 | |||
| 781 | /* Value is the size of an sdata structure large enough to hold NBYTES | ||
| 782 | bytes of string data. The value returned includes a terminating | ||
| 783 | NUL byte, the size of the sdata structure, and padding. */ | ||
| 784 | |||
| 785 | #define SDATA_SIZE(NBYTES) \ | ||
| 786 | ((sizeof (struct Lisp_String *) \ | ||
| 787 | + (NBYTES) + 1 \ | ||
| 788 | + sizeof (EMACS_INT) - 1) \ | ||
| 789 | & ~(sizeof (EMACS_INT) - 1)) | ||
| 790 | |||
| 791 | |||
| 792 | /* Initialize string allocation. Called from init_alloc_once. */ | ||
| 793 | |||
| 794 | void | ||
| 795 | init_strings () | ||
| 796 | { | ||
| 797 | total_strings = total_free_strings = total_string_size = 0; | ||
| 798 | oldest_sblock = current_sblock = large_sblocks = NULL; | ||
| 799 | string_blocks = NULL; | ||
| 800 | n_string_blocks = 0; | ||
| 801 | string_free_list = NULL; | ||
| 802 | } | ||
| 803 | |||
| 804 | |||
| 805 | /* Return a new Lisp_String. */ | ||
| 806 | |||
| 807 | static struct Lisp_String * | ||
| 808 | allocate_string () | ||
| 809 | { | ||
| 810 | struct Lisp_String *s; | ||
| 811 | |||
| 812 | /* If the free-list is empty, allocate a new string_block, and | ||
| 813 | add all the Lisp_Strings in it to the free-list. */ | ||
| 814 | if (string_free_list == NULL) | ||
| 815 | { | ||
| 816 | struct string_block *b; | ||
| 817 | int i; | ||
| 818 | |||
| 819 | b = (struct string_block *) lisp_malloc (sizeof *b); | ||
| 820 | VALIDATE_LISP_STORAGE (b, sizeof *b); | ||
| 821 | bzero (b, sizeof *b); | ||
| 822 | b->next = string_blocks; | ||
| 823 | string_blocks = b; | ||
| 824 | ++n_string_blocks; | ||
| 825 | |||
| 826 | for (i = STRINGS_IN_STRING_BLOCK - 1; i >= 0; --i) | ||
| 827 | { | ||
| 828 | s = b->strings + i; | ||
| 829 | NEXT_FREE_LISP_STRING (s) = string_free_list; | ||
| 830 | string_free_list = s; | ||
| 831 | } | ||
| 832 | |||
| 833 | total_free_strings += STRINGS_IN_STRING_BLOCK; | ||
| 834 | } | ||
| 835 | |||
| 836 | /* Pop a Lisp_String off the free-list. */ | ||
| 837 | s = string_free_list; | ||
| 838 | string_free_list = NEXT_FREE_LISP_STRING (s); | ||
| 839 | |||
| 840 | /* Probably not strictly necessary, but play it safe. */ | ||
| 841 | bzero (s, sizeof *s); | ||
| 842 | |||
| 843 | --total_free_strings; | ||
| 844 | ++total_strings; | ||
| 845 | ++strings_consed; | ||
| 846 | consing_since_gc += sizeof *s; | ||
| 847 | |||
| 848 | return s; | ||
| 849 | } | ||
| 850 | |||
| 851 | |||
| 852 | /* Set up Lisp_String S for holding NCHARS characters, NBYTES bytes, | ||
| 853 | plus a NUL byte at the end. Allocate an sdata structure for S, and | ||
| 854 | set S->data to its `u.data' member. Store a NUL byte at the end of | ||
| 855 | S->data. Set S->size to NCHARS and S->size_byte to NBYTES. Free | ||
| 856 | S->data if it was initially non-null. */ | ||
| 857 | |||
| 858 | void | ||
| 859 | allocate_string_data (s, nchars, nbytes) | ||
| 860 | struct Lisp_String *s; | ||
| 861 | int nchars, nbytes; | ||
| 862 | { | ||
| 863 | struct sdata *data; | ||
| 864 | struct sblock *b; | ||
| 865 | int needed; | ||
| 866 | |||
| 867 | /* Determine the number of bytes needed to store NBYTES bytes | ||
| 868 | of string data. */ | ||
| 869 | needed = SDATA_SIZE (nbytes); | ||
| 870 | |||
| 871 | if (nbytes > LARGE_STRING_BYTES) | ||
| 872 | { | ||
| 873 | int size = sizeof *b - sizeof (struct sdata) + needed; | ||
| 874 | |||
| 875 | #ifdef DOUG_LEA_MALLOC | ||
| 876 | /* Prevent mmap'ing the chunk (which is potentially very large). */ | ||
| 877 | mallopt (M_MMAP_MAX, 0); | ||
| 878 | #endif | ||
| 879 | |||
| 880 | b = (struct sblock *) lisp_malloc (size); | ||
| 881 | |||
| 882 | #ifdef DOUG_LEA_MALLOC | ||
| 883 | /* Back to a reasonable maximum of mmap'ed areas. */ | ||
| 884 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | ||
| 885 | #endif | ||
| 886 | |||
| 887 | b->next_free = &b->first_data; | ||
| 888 | b->first_data.string = NULL; | ||
| 889 | b->next = large_sblocks; | ||
| 890 | large_sblocks = b; | ||
| 891 | } | ||
| 892 | else if (current_sblock == NULL | ||
| 893 | || (((char *) current_sblock + SBLOCK_SIZE | ||
| 894 | - (char *) current_sblock->next_free) | ||
| 895 | < needed)) | ||
| 896 | { | ||
| 897 | /* Not enough room in the current sblock. */ | ||
| 898 | b = (struct sblock *) lisp_malloc (SBLOCK_SIZE); | ||
| 899 | b->next_free = &b->first_data; | ||
| 900 | b->first_data.string = NULL; | ||
| 901 | b->next = NULL; | ||
| 902 | |||
| 903 | if (current_sblock) | ||
| 904 | current_sblock->next = b; | ||
| 905 | else | ||
| 906 | oldest_sblock = b; | ||
| 907 | current_sblock = b; | ||
| 908 | } | ||
| 909 | else | ||
| 910 | b = current_sblock; | ||
| 911 | |||
| 912 | /* If S had already data assigned, mark that as free by setting | ||
| 913 | its string back-pointer to null, and recording the size of | ||
| 914 | the data in it.. */ | ||
| 915 | if (s->data) | ||
| 916 | { | ||
| 917 | data = SDATA_OF_STRING (s); | ||
| 918 | data->u.nbytes = GC_STRING_BYTES (s); | ||
| 919 | data->string = NULL; | ||
| 920 | } | ||
| 921 | |||
| 922 | data = b->next_free; | ||
| 923 | data->string = s; | ||
| 924 | s->data = data->u.data; | ||
| 925 | s->size = nchars; | ||
| 926 | s->size_byte = nbytes; | ||
| 927 | s->data[nbytes] = '\0'; | ||
| 928 | b->next_free = (struct sdata *) ((char *) data + needed); | ||
| 929 | |||
| 930 | consing_since_gc += needed; | ||
| 931 | } | ||
| 932 | |||
| 933 | |||
| 934 | /* Sweep and compact strings. */ | ||
| 935 | |||
| 936 | static void | ||
| 937 | sweep_strings () | ||
| 938 | { | ||
| 939 | struct string_block *b, *next; | ||
| 940 | struct string_block *live_blocks = NULL; | ||
| 941 | |||
| 942 | string_free_list = NULL; | ||
| 943 | total_strings = total_free_strings = 0; | ||
| 944 | total_string_size = 0; | ||
| 945 | |||
| 946 | /* Scan strings_blocks, free Lisp_Strings that aren't marked. */ | ||
| 947 | for (b = string_blocks; b; b = next) | ||
| 948 | { | ||
| 949 | int i, nfree = 0; | ||
| 950 | struct Lisp_String *free_list_before = string_free_list; | ||
| 951 | |||
| 952 | next = b->next; | ||
| 953 | |||
| 954 | for (i = 0; i < STRINGS_IN_STRING_BLOCK; ++i) | ||
| 955 | { | ||
| 956 | struct Lisp_String *s = b->strings + i; | ||
| 957 | |||
| 958 | if (s->data) | ||
| 959 | { | ||
| 960 | /* String was not on free-list before. */ | ||
| 961 | if (STRING_MARKED_P (s)) | ||
| 962 | { | ||
| 963 | /* String is live; unmark it and its intervals. */ | ||
| 964 | UNMARK_STRING (s); | ||
| 965 | |||
| 966 | if (!NULL_INTERVAL_P (s->intervals)) | ||
| 967 | UNMARK_BALANCE_INTERVALS (s->intervals); | ||
| 968 | |||
| 969 | ++total_strings; | ||
| 970 | total_string_size += STRING_BYTES (s); | ||
| 971 | } | ||
| 972 | else | ||
| 973 | { | ||
| 974 | /* String is dead. Put it on the free-list. */ | ||
| 975 | struct sdata *data = SDATA_OF_STRING (s); | ||
| 976 | |||
| 977 | /* Save the size of S in its sdata so that we know | ||
| 978 | how large that is. Reset the sdata's string | ||
| 979 | back-pointer so that we know it's free. */ | ||
| 980 | data->u.nbytes = GC_STRING_BYTES (s); | ||
| 981 | data->string = NULL; | ||
| 982 | |||
| 983 | /* Reset the strings's `data' member so that we | ||
| 984 | know it's free. */ | ||
| 985 | s->data = NULL; | ||
| 986 | |||
| 987 | /* Put the string on the free-list. */ | ||
| 988 | NEXT_FREE_LISP_STRING (s) = string_free_list; | ||
| 989 | string_free_list = s; | ||
| 990 | ++nfree; | ||
| 991 | } | ||
| 992 | } | ||
| 993 | else | ||
| 994 | { | ||
| 995 | /* S was on the free-list before. Put it there again. */ | ||
| 996 | NEXT_FREE_LISP_STRING (s) = string_free_list; | ||
| 997 | string_free_list = s; | ||
| 998 | ++nfree; | ||
| 999 | } | ||
| 1000 | } | ||
| 1001 | |||
| 1002 | /* Free blocks that are contain free Lisp_Strings only, except | ||
| 1003 | the first two of them. */ | ||
| 1004 | if (nfree == STRINGS_IN_STRING_BLOCK | ||
| 1005 | && total_free_strings > STRINGS_IN_STRING_BLOCK) | ||
| 1006 | { | ||
| 1007 | lisp_free (b); | ||
| 1008 | --n_string_blocks; | ||
| 1009 | string_free_list = free_list_before; | ||
| 1010 | } | ||
| 1011 | else | ||
| 1012 | { | ||
| 1013 | total_free_strings += nfree; | ||
| 1014 | b->next = live_blocks; | ||
| 1015 | live_blocks = b; | ||
| 1016 | } | ||
| 1017 | } | ||
| 1018 | |||
| 1019 | string_blocks = live_blocks; | ||
| 1020 | free_large_strings (); | ||
| 1021 | compact_small_strings (); | ||
| 1022 | } | ||
| 1023 | |||
| 1024 | |||
| 1025 | /* Free dead large strings. */ | ||
| 1026 | |||
| 1027 | static void | ||
| 1028 | free_large_strings () | ||
| 1029 | { | ||
| 1030 | struct sblock *b, *next; | ||
| 1031 | struct sblock *live_blocks = NULL; | ||
| 1032 | |||
| 1033 | for (b = large_sblocks; b; b = next) | ||
| 1034 | { | ||
| 1035 | next = b->next; | ||
| 1036 | |||
| 1037 | if (b->first_data.string == NULL) | ||
| 1038 | lisp_free (b); | ||
| 1039 | else | ||
| 1040 | { | ||
| 1041 | b->next = live_blocks; | ||
| 1042 | live_blocks = b; | ||
| 1043 | } | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | large_sblocks = live_blocks; | ||
| 1047 | } | ||
| 1048 | |||
| 1049 | |||
| 1050 | /* Compact data of small strings. Free sblocks that don't contain | ||
| 1051 | data of live strings after compaction. */ | ||
| 1052 | |||
| 1053 | static void | ||
| 1054 | compact_small_strings () | ||
| 1055 | { | ||
| 1056 | struct sblock *b, *tb, *next; | ||
| 1057 | struct sdata *from, *to, *end, *tb_end; | ||
| 1058 | struct sdata *to_end, *from_end; | ||
| 1059 | |||
| 1060 | /* TB is the sblock we copy to, TO is the sdata within TB we copy | ||
| 1061 | to, and TB_END is the end of TB. */ | ||
| 1062 | tb = oldest_sblock; | ||
| 1063 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | ||
| 1064 | to = &tb->first_data; | ||
| 1065 | |||
| 1066 | /* Step through the blocks from the oldest to the youngest. We | ||
| 1067 | expect that old blocks will stabilize over time, so that less | ||
| 1068 | copying will happen this way. */ | ||
| 1069 | for (b = oldest_sblock; b; b = b->next) | ||
| 1070 | { | ||
| 1071 | end = b->next_free; | ||
| 1072 | xassert ((char *) end <= (char *) b + SBLOCK_SIZE); | ||
| 1073 | |||
| 1074 | for (from = &b->first_data; from < end; from = from_end) | ||
| 1075 | { | ||
| 1076 | /* Compute the next FROM here because copying below may | ||
| 1077 | overwrite data we need to compute it. */ | ||
| 1078 | int nbytes; | ||
| 1079 | |||
| 1080 | if (from->string) | ||
| 1081 | nbytes = GC_STRING_BYTES (from->string); | ||
| 1082 | else | ||
| 1083 | nbytes = from->u.nbytes; | ||
| 1084 | |||
| 1085 | nbytes = SDATA_SIZE (nbytes); | ||
| 1086 | from_end = (struct sdata *) ((char *) from + nbytes); | ||
| 1087 | |||
| 1088 | /* FROM->string non-null means it's alive. Copy its data. */ | ||
| 1089 | if (from->string) | ||
| 1090 | { | ||
| 1091 | /* If TB is full, proceed with the next sblock. */ | ||
| 1092 | to_end = (struct sdata *) ((char *) to + nbytes); | ||
| 1093 | if (to_end > tb_end) | ||
| 1094 | { | ||
| 1095 | tb->next_free = to; | ||
| 1096 | tb = tb->next; | ||
| 1097 | tb_end = (struct sdata *) ((char *) tb + SBLOCK_SIZE); | ||
| 1098 | to = &tb->first_data; | ||
| 1099 | to_end = (struct sdata *) ((char *) to + nbytes); | ||
| 1100 | } | ||
| 1101 | |||
| 1102 | /* Copy, and update the string's `data' pointer. */ | ||
| 1103 | if (from != to) | ||
| 1104 | { | ||
| 1105 | bcopy (from, to, nbytes); | ||
| 1106 | to->string->data = to->u.data; | ||
| 1107 | } | ||
| 1108 | |||
| 1109 | /* Advance past the sdata we copied to. */ | ||
| 1110 | to = to_end; | ||
| 1111 | } | ||
| 1112 | } | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | /* The rest of the sblocks following TB don't contain live data, so | ||
| 1116 | we can free them. */ | ||
| 1117 | for (b = tb->next; b; b = next) | ||
| 1118 | { | ||
| 1119 | next = b->next; | ||
| 1120 | lisp_free (b); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | tb->next_free = to; | ||
| 1124 | tb->next = NULL; | ||
| 1125 | current_sblock = tb; | ||
| 1126 | } | ||
| 1127 | |||
| 1128 | |||
| 1129 | DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0, | ||
| 1130 | "Return a newly created string of length LENGTH, with each element being INIT.\n\ | ||
| 1131 | Both LENGTH and INIT must be numbers.") | ||
| 1132 | (length, init) | ||
| 1133 | Lisp_Object length, init; | ||
| 1134 | { | ||
| 1135 | register Lisp_Object val; | ||
| 1136 | register unsigned char *p, *end; | ||
| 1137 | int c, nbytes; | ||
| 1138 | |||
| 1139 | CHECK_NATNUM (length, 0); | ||
| 1140 | CHECK_NUMBER (init, 1); | ||
| 1141 | |||
| 1142 | c = XINT (init); | ||
| 1143 | if (SINGLE_BYTE_CHAR_P (c)) | ||
| 1144 | { | ||
| 1145 | nbytes = XINT (length); | ||
| 1146 | val = make_uninit_string (nbytes); | ||
| 1147 | p = XSTRING (val)->data; | ||
| 1148 | end = p + XSTRING (val)->size; | ||
| 1149 | while (p != end) | ||
| 1150 | *p++ = c; | ||
| 1151 | } | ||
| 1152 | else | ||
| 1153 | { | ||
| 1154 | unsigned char str[4]; | ||
| 1155 | int len = CHAR_STRING (c, str); | ||
| 1156 | |||
| 1157 | nbytes = len * XINT (length); | ||
| 1158 | val = make_uninit_multibyte_string (XINT (length), nbytes); | ||
| 1159 | p = XSTRING (val)->data; | ||
| 1160 | end = p + nbytes; | ||
| 1161 | while (p != end) | ||
| 1162 | { | ||
| 1163 | bcopy (str, p, len); | ||
| 1164 | p += len; | ||
| 1165 | } | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | *p = 0; | ||
| 1169 | return val; | ||
| 1170 | } | ||
| 1171 | |||
| 1172 | |||
| 1173 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | ||
| 1174 | "Return a new bool-vector of length LENGTH, using INIT for as each element.\n\ | ||
| 1175 | LENGTH must be a number. INIT matters only in whether it is t or nil.") | ||
| 1176 | (length, init) | ||
| 1177 | Lisp_Object length, init; | ||
| 1178 | { | ||
| 1179 | register Lisp_Object val; | ||
| 1180 | struct Lisp_Bool_Vector *p; | ||
| 1181 | int real_init, i; | ||
| 1182 | int length_in_chars, length_in_elts, bits_per_value; | ||
| 1183 | |||
| 1184 | CHECK_NATNUM (length, 0); | ||
| 1185 | |||
| 1186 | bits_per_value = sizeof (EMACS_INT) * BITS_PER_CHAR; | ||
| 1187 | |||
| 1188 | length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value; | ||
| 1189 | length_in_chars = ((XFASTINT (length) + BITS_PER_CHAR - 1) / BITS_PER_CHAR); | ||
| 1190 | |||
| 1191 | /* We must allocate one more elements than LENGTH_IN_ELTS for the | ||
| 1192 | slot `size' of the struct Lisp_Bool_Vector. */ | ||
| 1193 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); | ||
| 1194 | p = XBOOL_VECTOR (val); | ||
| 1195 | /* Get rid of any bits that would cause confusion. */ | ||
| 1196 | p->vector_size = 0; | ||
| 1197 | XSETBOOL_VECTOR (val, p); | ||
| 1198 | p->size = XFASTINT (length); | ||
| 1199 | |||
| 1200 | real_init = (NILP (init) ? 0 : -1); | ||
| 1201 | for (i = 0; i < length_in_chars ; i++) | ||
| 1202 | p->data[i] = real_init; | ||
| 1203 | /* Clear the extraneous bits in the last byte. */ | ||
| 1204 | if (XINT (length) != length_in_chars * BITS_PER_CHAR) | ||
| 1205 | XBOOL_VECTOR (val)->data[length_in_chars - 1] | ||
| 1206 | &= (1 << (XINT (length) % BITS_PER_CHAR)) - 1; | ||
| 1207 | |||
| 1208 | return val; | ||
| 1209 | } | ||
| 1210 | |||
| 1211 | |||
| 1212 | /* Make a string from NBYTES bytes at CONTENTS, and compute the number | ||
| 1213 | of characters from the contents. This string may be unibyte or | ||
| 1214 | multibyte, depending on the contents. */ | ||
| 1215 | |||
| 1216 | Lisp_Object | ||
| 1217 | make_string (contents, nbytes) | ||
| 1218 | char *contents; | ||
| 1219 | int nbytes; | ||
| 1220 | { | ||
| 1221 | register Lisp_Object val; | ||
| 1222 | int nchars = chars_in_text (contents, nbytes); | ||
| 1223 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1224 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1225 | if (STRING_BYTES (XSTRING (val)) == XSTRING (val)->size) | ||
| 1226 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1227 | return val; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | |||
| 1231 | /* Make an unibyte string from LENGTH bytes at CONTENTS. */ | ||
| 1232 | |||
| 1233 | Lisp_Object | ||
| 1234 | make_unibyte_string (contents, length) | ||
| 1235 | char *contents; | ||
| 1236 | int length; | ||
| 1237 | { | ||
| 1238 | register Lisp_Object val; | ||
| 1239 | val = make_uninit_string (length); | ||
| 1240 | bcopy (contents, XSTRING (val)->data, length); | ||
| 1241 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1242 | return val; | ||
| 1243 | } | ||
| 1244 | |||
| 1245 | |||
| 1246 | /* Make a multibyte string from NCHARS characters occupying NBYTES | ||
| 1247 | bytes at CONTENTS. */ | ||
| 1248 | |||
| 1249 | Lisp_Object | ||
| 1250 | make_multibyte_string (contents, nchars, nbytes) | ||
| 1251 | char *contents; | ||
| 1252 | int nchars, nbytes; | ||
| 1253 | { | ||
| 1254 | register Lisp_Object val; | ||
| 1255 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1256 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1257 | return val; | ||
| 596 | } | 1258 | } |
| 597 | 1259 | ||
| 1260 | |||
| 1261 | /* Make a string from NCHARS characters occupying NBYTES bytes at | ||
| 1262 | CONTENTS. It is a multibyte string if NBYTES != NCHARS. */ | ||
| 1263 | |||
| 1264 | Lisp_Object | ||
| 1265 | make_string_from_bytes (contents, nchars, nbytes) | ||
| 1266 | char *contents; | ||
| 1267 | int nchars, nbytes; | ||
| 1268 | { | ||
| 1269 | register Lisp_Object val; | ||
| 1270 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1271 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1272 | if (STRING_BYTES (XSTRING (val)) == XSTRING (val)->size) | ||
| 1273 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1274 | return val; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | |||
| 1278 | /* Make a string from NCHARS characters occupying NBYTES bytes at | ||
| 1279 | CONTENTS. The argument MULTIBYTE controls whether to label the | ||
| 1280 | string as multibyte. */ | ||
| 1281 | |||
| 1282 | Lisp_Object | ||
| 1283 | make_specified_string (contents, nchars, nbytes, multibyte) | ||
| 1284 | char *contents; | ||
| 1285 | int nchars, nbytes; | ||
| 1286 | int multibyte; | ||
| 1287 | { | ||
| 1288 | register Lisp_Object val; | ||
| 1289 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1290 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1291 | if (!multibyte) | ||
| 1292 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1293 | return val; | ||
| 1294 | } | ||
| 1295 | |||
| 1296 | |||
| 1297 | /* Make a string from the data at STR, treating it as multibyte if the | ||
| 1298 | data warrants. */ | ||
| 1299 | |||
| 1300 | Lisp_Object | ||
| 1301 | build_string (str) | ||
| 1302 | char *str; | ||
| 1303 | { | ||
| 1304 | return make_string (str, strlen (str)); | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | |||
| 1308 | /* Return an unibyte Lisp_String set up to hold LENGTH characters | ||
| 1309 | occupying LENGTH bytes. */ | ||
| 1310 | |||
| 1311 | Lisp_Object | ||
| 1312 | make_uninit_string (length) | ||
| 1313 | int length; | ||
| 1314 | { | ||
| 1315 | Lisp_Object val; | ||
| 1316 | val = make_uninit_multibyte_string (length, length); | ||
| 1317 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1318 | return val; | ||
| 1319 | } | ||
| 1320 | |||
| 1321 | |||
| 1322 | /* Return a multibyte Lisp_String set up to hold NCHARS characters | ||
| 1323 | which occupy NBYTES bytes. */ | ||
| 1324 | |||
| 1325 | Lisp_Object | ||
| 1326 | make_uninit_multibyte_string (nchars, nbytes) | ||
| 1327 | int nchars, nbytes; | ||
| 1328 | { | ||
| 1329 | Lisp_Object string; | ||
| 1330 | struct Lisp_String *s; | ||
| 1331 | |||
| 1332 | if (nchars < 0) | ||
| 1333 | abort (); | ||
| 1334 | |||
| 1335 | s = allocate_string (); | ||
| 1336 | allocate_string_data (s, nchars, nbytes); | ||
| 1337 | XSETSTRING (string, s); | ||
| 1338 | string_chars_consed += nbytes; | ||
| 1339 | return string; | ||
| 1340 | } | ||
| 1341 | |||
| 1342 | |||
| 598 | 1343 | ||
| 599 | /* Floating point allocation. */ | 1344 | /*********************************************************************** |
| 1345 | Float Allocation | ||
| 1346 | ***********************************************************************/ | ||
| 600 | 1347 | ||
| 601 | #ifdef LISP_FLOAT_TYPE | 1348 | #ifdef LISP_FLOAT_TYPE |
| 602 | /* Allocation of float cells, just like conses */ | 1349 | |
| 603 | /* We store float cells inside of float_blocks, allocating a new | 1350 | /* We store float cells inside of float_blocks, allocating a new |
| 604 | float_block with malloc whenever necessary. Float cells reclaimed by | 1351 | float_block with malloc whenever necessary. Float cells reclaimed |
| 605 | GC are put on a free list to be reallocated before allocating | 1352 | by GC are put on a free list to be reallocated before allocating |
| 606 | any new float cells from the latest float_block. | 1353 | any new float cells from the latest float_block. |
| 607 | 1354 | ||
| 608 | Each float_block is just under 1020 bytes long, | 1355 | Each float_block is just under 1020 bytes long, since malloc really |
| 609 | since malloc really allocates in units of powers of two | 1356 | allocates in units of powers of two and uses 4 bytes for its own |
| 610 | and uses 4 bytes for its own overhead. */ | 1357 | overhead. */ |
| 611 | 1358 | ||
| 612 | #define FLOAT_BLOCK_SIZE \ | 1359 | #define FLOAT_BLOCK_SIZE \ |
| 613 | ((1020 - sizeof (struct float_block *)) / sizeof (struct Lisp_Float)) | 1360 | ((1020 - sizeof (struct float_block *)) / sizeof (struct Lisp_Float)) |
| 614 | 1361 | ||
| 615 | struct float_block | 1362 | struct float_block |
| 616 | { | 1363 | { |
| 617 | struct float_block *next; | 1364 | struct float_block *next; |
| 618 | struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; | 1365 | struct Lisp_Float floats[FLOAT_BLOCK_SIZE]; |
| 619 | }; | 1366 | }; |
| 620 | 1367 | ||
| 621 | struct float_block *float_block; | 1368 | struct float_block *float_block; |
| 622 | int float_block_index; | 1369 | int float_block_index; |
| 623 | 1370 | ||
| 624 | /* Total number of float blocks now in use. */ | 1371 | /* Total number of float blocks now in use. */ |
| 1372 | |||
| 625 | int n_float_blocks; | 1373 | int n_float_blocks; |
| 626 | 1374 | ||
| 627 | struct Lisp_Float *float_free_list; | 1375 | struct Lisp_Float *float_free_list; |
| @@ -638,6 +1386,7 @@ init_float () | |||
| 638 | } | 1386 | } |
| 639 | 1387 | ||
| 640 | /* Explicitly free a float cell. */ | 1388 | /* Explicitly free a float cell. */ |
| 1389 | |||
| 641 | void | 1390 | void |
| 642 | free_float (ptr) | 1391 | free_float (ptr) |
| 643 | struct Lisp_Float *ptr; | 1392 | struct Lisp_Float *ptr; |
| @@ -674,6 +1423,7 @@ make_float (float_value) | |||
| 674 | } | 1423 | } |
| 675 | XSETFLOAT (val, &float_block->floats[float_block_index++]); | 1424 | XSETFLOAT (val, &float_block->floats[float_block_index++]); |
| 676 | } | 1425 | } |
| 1426 | |||
| 677 | XFLOAT_DATA (val) = float_value; | 1427 | XFLOAT_DATA (val) = float_value; |
| 678 | XSETFASTINT (XFLOAT (val)->type, 0); /* bug chasing -wsr */ | 1428 | XSETFASTINT (XFLOAT (val)->type, 0); /* bug chasing -wsr */ |
| 679 | consing_since_gc += sizeof (struct Lisp_Float); | 1429 | consing_since_gc += sizeof (struct Lisp_Float); |
| @@ -682,8 +1432,13 @@ make_float (float_value) | |||
| 682 | } | 1432 | } |
| 683 | 1433 | ||
| 684 | #endif /* LISP_FLOAT_TYPE */ | 1434 | #endif /* LISP_FLOAT_TYPE */ |
| 1435 | |||
| 1436 | |||
| 685 | 1437 | ||
| 686 | /* Allocation of cons cells */ | 1438 | /*********************************************************************** |
| 1439 | Cons Allocation | ||
| 1440 | ***********************************************************************/ | ||
| 1441 | |||
| 687 | /* We store cons cells inside of cons_blocks, allocating a new | 1442 | /* We store cons cells inside of cons_blocks, allocating a new |
| 688 | cons_block with malloc whenever necessary. Cons cells reclaimed by | 1443 | cons_block with malloc whenever necessary. Cons cells reclaimed by |
| 689 | GC are put on a free list to be reallocated before allocating | 1444 | GC are put on a free list to be reallocated before allocating |
| @@ -697,10 +1452,10 @@ make_float (float_value) | |||
| 697 | ((1020 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons)) | 1452 | ((1020 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons)) |
| 698 | 1453 | ||
| 699 | struct cons_block | 1454 | struct cons_block |
| 700 | { | 1455 | { |
| 701 | struct cons_block *next; | 1456 | struct cons_block *next; |
| 702 | struct Lisp_Cons conses[CONS_BLOCK_SIZE]; | 1457 | struct Lisp_Cons conses[CONS_BLOCK_SIZE]; |
| 703 | }; | 1458 | }; |
| 704 | 1459 | ||
| 705 | struct cons_block *cons_block; | 1460 | struct cons_block *cons_block; |
| 706 | int cons_block_index; | 1461 | int cons_block_index; |
| @@ -708,6 +1463,7 @@ int cons_block_index; | |||
| 708 | struct Lisp_Cons *cons_free_list; | 1463 | struct Lisp_Cons *cons_free_list; |
| 709 | 1464 | ||
| 710 | /* Total number of cons blocks now in use. */ | 1465 | /* Total number of cons blocks now in use. */ |
| 1466 | |||
| 711 | int n_cons_blocks; | 1467 | int n_cons_blocks; |
| 712 | 1468 | ||
| 713 | void | 1469 | void |
| @@ -759,12 +1515,14 @@ DEFUN ("cons", Fcons, Scons, 2, 2, 0, | |||
| 759 | } | 1515 | } |
| 760 | XSETCONS (val, &cons_block->conses[cons_block_index++]); | 1516 | XSETCONS (val, &cons_block->conses[cons_block_index++]); |
| 761 | } | 1517 | } |
| 1518 | |||
| 762 | XCAR (val) = car; | 1519 | XCAR (val) = car; |
| 763 | XCDR (val) = cdr; | 1520 | XCDR (val) = cdr; |
| 764 | consing_since_gc += sizeof (struct Lisp_Cons); | 1521 | consing_since_gc += sizeof (struct Lisp_Cons); |
| 765 | cons_cells_consed++; | 1522 | cons_cells_consed++; |
| 766 | return val; | 1523 | return val; |
| 767 | } | 1524 | } |
| 1525 | |||
| 768 | 1526 | ||
| 769 | /* Make a list of 2, 3, 4 or 5 specified objects. */ | 1527 | /* Make a list of 2, 3, 4 or 5 specified objects. */ |
| 770 | 1528 | ||
| @@ -831,12 +1589,17 @@ DEFUN ("make-list", Fmake_list, Smake_list, 2, 2, 0, | |||
| 831 | val = Fcons (init, val); | 1589 | val = Fcons (init, val); |
| 832 | return val; | 1590 | return val; |
| 833 | } | 1591 | } |
| 1592 | |||
| 1593 | |||
| 834 | 1594 | ||
| 835 | /* Allocation of vectors */ | 1595 | /*********************************************************************** |
| 1596 | Vector Allocation | ||
| 1597 | ***********************************************************************/ | ||
| 836 | 1598 | ||
| 837 | struct Lisp_Vector *all_vectors; | 1599 | struct Lisp_Vector *all_vectors; |
| 838 | 1600 | ||
| 839 | /* Total number of vectorlike objects now in use. */ | 1601 | /* Total number of vector-like objects now in use. */ |
| 1602 | |||
| 840 | int n_vectors; | 1603 | int n_vectors; |
| 841 | 1604 | ||
| 842 | struct Lisp_Vector * | 1605 | struct Lisp_Vector * |
| @@ -846,11 +1609,11 @@ allocate_vectorlike (len) | |||
| 846 | struct Lisp_Vector *p; | 1609 | struct Lisp_Vector *p; |
| 847 | 1610 | ||
| 848 | #ifdef DOUG_LEA_MALLOC | 1611 | #ifdef DOUG_LEA_MALLOC |
| 849 | /* Prevent mmap'ing the chunk (which is potentially very large). */ | 1612 | /* Prevent mmap'ing the chunk (which is potentially very large).. */ |
| 850 | mallopt (M_MMAP_MAX, 0); | 1613 | mallopt (M_MMAP_MAX, 0); |
| 851 | #endif | 1614 | #endif |
| 852 | p = (struct Lisp_Vector *)lisp_malloc (sizeof (struct Lisp_Vector) | 1615 | p = (struct Lisp_Vector *)lisp_malloc (sizeof (struct Lisp_Vector) |
| 853 | + (len - 1) * sizeof (Lisp_Object)); | 1616 | + (len - 1) * sizeof (Lisp_Object)); |
| 854 | #ifdef DOUG_LEA_MALLOC | 1617 | #ifdef DOUG_LEA_MALLOC |
| 855 | /* Back to a reasonable maximum of mmap'ed areas. */ | 1618 | /* Back to a reasonable maximum of mmap'ed areas. */ |
| 856 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | 1619 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); |
| @@ -978,22 +1741,24 @@ significance.") | |||
| 978 | XSETCOMPILED (val, p); | 1741 | XSETCOMPILED (val, p); |
| 979 | return val; | 1742 | return val; |
| 980 | } | 1743 | } |
| 1744 | |||
| 981 | 1745 | ||
| 982 | /* Allocation of symbols. | 1746 | /*********************************************************************** |
| 983 | Just like allocation of conses! | 1747 | Symbol Allocation |
| 1748 | ***********************************************************************/ | ||
| 984 | 1749 | ||
| 985 | Each symbol_block is just under 1020 bytes long, | 1750 | /* Each symbol_block is just under 1020 bytes long, since malloc |
| 986 | since malloc really allocates in units of powers of two | 1751 | really allocates in units of powers of two and uses 4 bytes for its |
| 987 | and uses 4 bytes for its own overhead. */ | 1752 | own overhead. */ |
| 988 | 1753 | ||
| 989 | #define SYMBOL_BLOCK_SIZE \ | 1754 | #define SYMBOL_BLOCK_SIZE \ |
| 990 | ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol)) | 1755 | ((1020 - sizeof (struct symbol_block *)) / sizeof (struct Lisp_Symbol)) |
| 991 | 1756 | ||
| 992 | struct symbol_block | 1757 | struct symbol_block |
| 993 | { | 1758 | { |
| 994 | struct symbol_block *next; | 1759 | struct symbol_block *next; |
| 995 | struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; | 1760 | struct Lisp_Symbol symbols[SYMBOL_BLOCK_SIZE]; |
| 996 | }; | 1761 | }; |
| 997 | 1762 | ||
| 998 | struct symbol_block *symbol_block; | 1763 | struct symbol_block *symbol_block; |
| 999 | int symbol_block_index; | 1764 | int symbol_block_index; |
| @@ -1001,6 +1766,7 @@ int symbol_block_index; | |||
| 1001 | struct Lisp_Symbol *symbol_free_list; | 1766 | struct Lisp_Symbol *symbol_free_list; |
| 1002 | 1767 | ||
| 1003 | /* Total number of symbol blocks now in use. */ | 1768 | /* Total number of symbol blocks now in use. */ |
| 1769 | |||
| 1004 | int n_symbol_blocks; | 1770 | int n_symbol_blocks; |
| 1005 | 1771 | ||
| 1006 | void | 1772 | void |
| @@ -1044,6 +1810,7 @@ Its value and function definition are void, and its property list is nil.") | |||
| 1044 | } | 1810 | } |
| 1045 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index++]); | 1811 | XSETSYMBOL (val, &symbol_block->symbols[symbol_block_index++]); |
| 1046 | } | 1812 | } |
| 1813 | |||
| 1047 | p = XSYMBOL (val); | 1814 | p = XSYMBOL (val); |
| 1048 | p->name = XSTRING (name); | 1815 | p->name = XSTRING (name); |
| 1049 | p->obarray = Qnil; | 1816 | p->obarray = Qnil; |
| @@ -1055,7 +1822,13 @@ Its value and function definition are void, and its property list is nil.") | |||
| 1055 | symbols_consed++; | 1822 | symbols_consed++; |
| 1056 | return val; | 1823 | return val; |
| 1057 | } | 1824 | } |
| 1825 | |||
| 1826 | |||
| 1058 | 1827 | ||
| 1828 | /*********************************************************************** | ||
| 1829 | Marker Allocation | ||
| 1830 | ***********************************************************************/ | ||
| 1831 | |||
| 1059 | /* Allocation of markers and other objects that share that structure. | 1832 | /* Allocation of markers and other objects that share that structure. |
| 1060 | Works like allocation of conses. */ | 1833 | Works like allocation of conses. */ |
| 1061 | 1834 | ||
| @@ -1064,9 +1837,9 @@ Its value and function definition are void, and its property list is nil.") | |||
| 1064 | 1837 | ||
| 1065 | struct marker_block | 1838 | struct marker_block |
| 1066 | { | 1839 | { |
| 1067 | struct marker_block *next; | 1840 | struct marker_block *next; |
| 1068 | union Lisp_Misc markers[MARKER_BLOCK_SIZE]; | 1841 | union Lisp_Misc markers[MARKER_BLOCK_SIZE]; |
| 1069 | }; | 1842 | }; |
| 1070 | 1843 | ||
| 1071 | struct marker_block *marker_block; | 1844 | struct marker_block *marker_block; |
| 1072 | int marker_block_index; | 1845 | int marker_block_index; |
| @@ -1074,6 +1847,7 @@ int marker_block_index; | |||
| 1074 | union Lisp_Misc *marker_free_list; | 1847 | union Lisp_Misc *marker_free_list; |
| 1075 | 1848 | ||
| 1076 | /* Total number of marker blocks now in use. */ | 1849 | /* Total number of marker blocks now in use. */ |
| 1850 | |||
| 1077 | int n_marker_blocks; | 1851 | int n_marker_blocks; |
| 1078 | 1852 | ||
| 1079 | void | 1853 | void |
| @@ -1088,6 +1862,7 @@ init_marker () | |||
| 1088 | } | 1862 | } |
| 1089 | 1863 | ||
| 1090 | /* Return a newly allocated Lisp_Misc object, with no substructure. */ | 1864 | /* Return a newly allocated Lisp_Misc object, with no substructure. */ |
| 1865 | |||
| 1091 | Lisp_Object | 1866 | Lisp_Object |
| 1092 | allocate_misc () | 1867 | allocate_misc () |
| 1093 | { | 1868 | { |
| @@ -1112,6 +1887,7 @@ allocate_misc () | |||
| 1112 | } | 1887 | } |
| 1113 | XSETMISC (val, &marker_block->markers[marker_block_index++]); | 1888 | XSETMISC (val, &marker_block->markers[marker_block_index++]); |
| 1114 | } | 1889 | } |
| 1890 | |||
| 1115 | consing_since_gc += sizeof (union Lisp_Misc); | 1891 | consing_since_gc += sizeof (union Lisp_Misc); |
| 1116 | misc_objects_consed++; | 1892 | misc_objects_consed++; |
| 1117 | return val; | 1893 | return val; |
| @@ -1149,336 +1925,7 @@ free_marker (marker) | |||
| 1149 | 1925 | ||
| 1150 | total_free_markers++; | 1926 | total_free_markers++; |
| 1151 | } | 1927 | } |
| 1152 | |||
| 1153 | /* Allocation of strings */ | ||
| 1154 | |||
| 1155 | /* Strings reside inside of string_blocks. The entire data of the string, | ||
| 1156 | both the size and the contents, live in part of the `chars' component of a string_block. | ||
| 1157 | The `pos' component is the index within `chars' of the first free byte. | ||
| 1158 | |||
| 1159 | first_string_block points to the first string_block ever allocated. | ||
| 1160 | Each block points to the next one with its `next' field. | ||
| 1161 | The `prev' fields chain in reverse order. | ||
| 1162 | The last one allocated is the one currently being filled. | ||
| 1163 | current_string_block points to it. | ||
| 1164 | |||
| 1165 | The string_blocks that hold individual large strings | ||
| 1166 | go in a separate chain, started by large_string_blocks. */ | ||
| 1167 | |||
| 1168 | |||
| 1169 | /* String blocks contain this many useful bytes. | ||
| 1170 | 8188 is power of 2, minus 4 for malloc overhead. */ | ||
| 1171 | #define STRING_BLOCK_SIZE (8188 - sizeof (struct string_block_head)) | ||
| 1172 | |||
| 1173 | /* A string bigger than this gets its own specially-made string block | ||
| 1174 | if it doesn't fit in the current one. */ | ||
| 1175 | #define STRING_BLOCK_OUTSIZE 1024 | ||
| 1176 | |||
| 1177 | struct string_block_head | ||
| 1178 | { | ||
| 1179 | struct string_block *next, *prev; | ||
| 1180 | EMACS_INT pos; | ||
| 1181 | }; | ||
| 1182 | |||
| 1183 | struct string_block | ||
| 1184 | { | ||
| 1185 | struct string_block *next, *prev; | ||
| 1186 | EMACS_INT pos; | ||
| 1187 | char chars[STRING_BLOCK_SIZE]; | ||
| 1188 | }; | ||
| 1189 | |||
| 1190 | /* This points to the string block we are now allocating strings. */ | ||
| 1191 | |||
| 1192 | struct string_block *current_string_block; | ||
| 1193 | |||
| 1194 | /* This points to the oldest string block, the one that starts the chain. */ | ||
| 1195 | |||
| 1196 | struct string_block *first_string_block; | ||
| 1197 | |||
| 1198 | /* Last string block in chain of those made for individual large strings. */ | ||
| 1199 | |||
| 1200 | struct string_block *large_string_blocks; | ||
| 1201 | |||
| 1202 | /* If SIZE is the length of a string, this returns how many bytes | ||
| 1203 | the string occupies in a string_block (including padding). */ | ||
| 1204 | |||
| 1205 | #define STRING_FULLSIZE(size) (((size) + 1 + STRING_BASE_SIZE + STRING_PAD - 1) \ | ||
| 1206 | & ~(STRING_PAD - 1)) | ||
| 1207 | /* Add 1 for the null terminator, | ||
| 1208 | and add STRING_PAD - 1 as part of rounding up. */ | ||
| 1209 | |||
| 1210 | #define STRING_PAD (sizeof (EMACS_INT)) | ||
| 1211 | /* Size of the stuff in the string not including its data. */ | ||
| 1212 | #define STRING_BASE_SIZE (((sizeof (struct Lisp_String) - 1) / STRING_PAD) * STRING_PAD) | ||
| 1213 | |||
| 1214 | #if 0 | ||
| 1215 | #define STRING_FULLSIZE(SIZE) \ | ||
| 1216 | (((SIZE) + 2 * sizeof (EMACS_INT)) & ~(sizeof (EMACS_INT) - 1)) | ||
| 1217 | #endif | ||
| 1218 | |||
| 1219 | /* Total number of string blocks now in use. */ | ||
| 1220 | int n_string_blocks; | ||
| 1221 | |||
| 1222 | void | ||
| 1223 | init_strings () | ||
| 1224 | { | ||
| 1225 | current_string_block = (struct string_block *) lisp_malloc (sizeof (struct string_block)); | ||
| 1226 | first_string_block = current_string_block; | ||
| 1227 | consing_since_gc += sizeof (struct string_block); | ||
| 1228 | current_string_block->next = 0; | ||
| 1229 | current_string_block->prev = 0; | ||
| 1230 | current_string_block->pos = 0; | ||
| 1231 | large_string_blocks = 0; | ||
| 1232 | n_string_blocks = 1; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | DEFUN ("make-string", Fmake_string, Smake_string, 2, 2, 0, | ||
| 1236 | "Return a newly created string of length LENGTH, with each element being INIT.\n\ | ||
| 1237 | Both LENGTH and INIT must be numbers.") | ||
| 1238 | (length, init) | ||
| 1239 | Lisp_Object length, init; | ||
| 1240 | { | ||
| 1241 | register Lisp_Object val; | ||
| 1242 | register unsigned char *p, *end; | ||
| 1243 | int c, nbytes; | ||
| 1244 | |||
| 1245 | CHECK_NATNUM (length, 0); | ||
| 1246 | CHECK_NUMBER (init, 1); | ||
| 1247 | |||
| 1248 | c = XINT (init); | ||
| 1249 | if (SINGLE_BYTE_CHAR_P (c)) | ||
| 1250 | { | ||
| 1251 | nbytes = XINT (length); | ||
| 1252 | val = make_uninit_string (nbytes); | ||
| 1253 | p = XSTRING (val)->data; | ||
| 1254 | end = p + XSTRING (val)->size; | ||
| 1255 | while (p != end) | ||
| 1256 | *p++ = c; | ||
| 1257 | } | ||
| 1258 | else | ||
| 1259 | { | ||
| 1260 | unsigned char str[4]; | ||
| 1261 | int len = CHAR_STRING (c, str); | ||
| 1262 | |||
| 1263 | nbytes = len * XINT (length); | ||
| 1264 | val = make_uninit_multibyte_string (XINT (length), nbytes); | ||
| 1265 | p = XSTRING (val)->data; | ||
| 1266 | end = p + nbytes; | ||
| 1267 | while (p != end) | ||
| 1268 | { | ||
| 1269 | bcopy (str, p, len); | ||
| 1270 | p += len; | ||
| 1271 | } | ||
| 1272 | } | ||
| 1273 | *p = 0; | ||
| 1274 | return val; | ||
| 1275 | } | ||
| 1276 | |||
| 1277 | DEFUN ("make-bool-vector", Fmake_bool_vector, Smake_bool_vector, 2, 2, 0, | ||
| 1278 | "Return a new bool-vector of length LENGTH, using INIT for as each element.\n\ | ||
| 1279 | LENGTH must be a number. INIT matters only in whether it is t or nil.") | ||
| 1280 | (length, init) | ||
| 1281 | Lisp_Object length, init; | ||
| 1282 | { | ||
| 1283 | register Lisp_Object val; | ||
| 1284 | struct Lisp_Bool_Vector *p; | ||
| 1285 | int real_init, i; | ||
| 1286 | int length_in_chars, length_in_elts, bits_per_value; | ||
| 1287 | |||
| 1288 | CHECK_NATNUM (length, 0); | ||
| 1289 | |||
| 1290 | bits_per_value = sizeof (EMACS_INT) * BITS_PER_CHAR; | ||
| 1291 | |||
| 1292 | length_in_elts = (XFASTINT (length) + bits_per_value - 1) / bits_per_value; | ||
| 1293 | length_in_chars = ((XFASTINT (length) + BITS_PER_CHAR - 1) / BITS_PER_CHAR); | ||
| 1294 | |||
| 1295 | /* We must allocate one more elements than LENGTH_IN_ELTS for the | ||
| 1296 | slot `size' of the struct Lisp_Bool_Vector. */ | ||
| 1297 | val = Fmake_vector (make_number (length_in_elts + 1), Qnil); | ||
| 1298 | p = XBOOL_VECTOR (val); | ||
| 1299 | /* Get rid of any bits that would cause confusion. */ | ||
| 1300 | p->vector_size = 0; | ||
| 1301 | XSETBOOL_VECTOR (val, p); | ||
| 1302 | p->size = XFASTINT (length); | ||
| 1303 | |||
| 1304 | real_init = (NILP (init) ? 0 : -1); | ||
| 1305 | for (i = 0; i < length_in_chars ; i++) | ||
| 1306 | p->data[i] = real_init; | ||
| 1307 | /* Clear the extraneous bits in the last byte. */ | ||
| 1308 | if (XINT (length) != length_in_chars * BITS_PER_CHAR) | ||
| 1309 | XBOOL_VECTOR (val)->data[length_in_chars - 1] | ||
| 1310 | &= (1 << (XINT (length) % BITS_PER_CHAR)) - 1; | ||
| 1311 | 1928 | ||
| 1312 | return val; | ||
| 1313 | } | ||
| 1314 | |||
| 1315 | /* Make a string from NBYTES bytes at CONTENTS, | ||
| 1316 | and compute the number of characters from the contents. | ||
| 1317 | This string may be unibyte or multibyte, depending on the contents. */ | ||
| 1318 | |||
| 1319 | Lisp_Object | ||
| 1320 | make_string (contents, nbytes) | ||
| 1321 | char *contents; | ||
| 1322 | int nbytes; | ||
| 1323 | { | ||
| 1324 | register Lisp_Object val; | ||
| 1325 | int nchars = chars_in_text (contents, nbytes); | ||
| 1326 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1327 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1328 | if (STRING_BYTES (XSTRING (val)) == XSTRING (val)->size) | ||
| 1329 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1330 | return val; | ||
| 1331 | } | ||
| 1332 | |||
| 1333 | /* Make a unibyte string from LENGTH bytes at CONTENTS. */ | ||
| 1334 | |||
| 1335 | Lisp_Object | ||
| 1336 | make_unibyte_string (contents, length) | ||
| 1337 | char *contents; | ||
| 1338 | int length; | ||
| 1339 | { | ||
| 1340 | register Lisp_Object val; | ||
| 1341 | val = make_uninit_string (length); | ||
| 1342 | bcopy (contents, XSTRING (val)->data, length); | ||
| 1343 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1344 | return val; | ||
| 1345 | } | ||
| 1346 | |||
| 1347 | /* Make a multibyte string from NCHARS characters | ||
| 1348 | occupying NBYTES bytes at CONTENTS. */ | ||
| 1349 | |||
| 1350 | Lisp_Object | ||
| 1351 | make_multibyte_string (contents, nchars, nbytes) | ||
| 1352 | char *contents; | ||
| 1353 | int nchars, nbytes; | ||
| 1354 | { | ||
| 1355 | register Lisp_Object val; | ||
| 1356 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1357 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1358 | return val; | ||
| 1359 | } | ||
| 1360 | |||
| 1361 | /* Make a string from NCHARS characters | ||
| 1362 | occupying NBYTES bytes at CONTENTS. | ||
| 1363 | It is a multibyte string if NBYTES != NCHARS. */ | ||
| 1364 | |||
| 1365 | Lisp_Object | ||
| 1366 | make_string_from_bytes (contents, nchars, nbytes) | ||
| 1367 | char *contents; | ||
| 1368 | int nchars, nbytes; | ||
| 1369 | { | ||
| 1370 | register Lisp_Object val; | ||
| 1371 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1372 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1373 | if (STRING_BYTES (XSTRING (val)) == XSTRING (val)->size) | ||
| 1374 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1375 | return val; | ||
| 1376 | } | ||
| 1377 | |||
| 1378 | /* Make a string from NCHARS characters | ||
| 1379 | occupying NBYTES bytes at CONTENTS. | ||
| 1380 | The argument MULTIBYTE controls whether to label the | ||
| 1381 | string as multibyte. */ | ||
| 1382 | |||
| 1383 | Lisp_Object | ||
| 1384 | make_specified_string (contents, nchars, nbytes, multibyte) | ||
| 1385 | char *contents; | ||
| 1386 | int nchars, nbytes; | ||
| 1387 | int multibyte; | ||
| 1388 | { | ||
| 1389 | register Lisp_Object val; | ||
| 1390 | val = make_uninit_multibyte_string (nchars, nbytes); | ||
| 1391 | bcopy (contents, XSTRING (val)->data, nbytes); | ||
| 1392 | if (!multibyte) | ||
| 1393 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1394 | return val; | ||
| 1395 | } | ||
| 1396 | |||
| 1397 | /* Make a string from the data at STR, | ||
| 1398 | treating it as multibyte if the data warrants. */ | ||
| 1399 | |||
| 1400 | Lisp_Object | ||
| 1401 | build_string (str) | ||
| 1402 | char *str; | ||
| 1403 | { | ||
| 1404 | return make_string (str, strlen (str)); | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | Lisp_Object | ||
| 1408 | make_uninit_string (length) | ||
| 1409 | int length; | ||
| 1410 | { | ||
| 1411 | Lisp_Object val; | ||
| 1412 | val = make_uninit_multibyte_string (length, length); | ||
| 1413 | SET_STRING_BYTES (XSTRING (val), -1); | ||
| 1414 | return val; | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | Lisp_Object | ||
| 1418 | make_uninit_multibyte_string (length, length_byte) | ||
| 1419 | int length, length_byte; | ||
| 1420 | { | ||
| 1421 | register Lisp_Object val; | ||
| 1422 | register int fullsize = STRING_FULLSIZE (length_byte); | ||
| 1423 | |||
| 1424 | if (length < 0) abort (); | ||
| 1425 | |||
| 1426 | if (fullsize <= STRING_BLOCK_SIZE - current_string_block->pos) | ||
| 1427 | /* This string can fit in the current string block */ | ||
| 1428 | { | ||
| 1429 | XSETSTRING (val, | ||
| 1430 | ((struct Lisp_String *) | ||
| 1431 | (current_string_block->chars + current_string_block->pos))); | ||
| 1432 | current_string_block->pos += fullsize; | ||
| 1433 | } | ||
| 1434 | else if (fullsize > STRING_BLOCK_OUTSIZE) | ||
| 1435 | /* This string gets its own string block */ | ||
| 1436 | { | ||
| 1437 | register struct string_block *new; | ||
| 1438 | #ifdef DOUG_LEA_MALLOC | ||
| 1439 | /* Prevent mmap'ing the chunk (which is potentially very large). */ | ||
| 1440 | mallopt (M_MMAP_MAX, 0); | ||
| 1441 | #endif | ||
| 1442 | new = (struct string_block *) lisp_malloc (sizeof (struct string_block_head) + fullsize); | ||
| 1443 | #ifdef DOUG_LEA_MALLOC | ||
| 1444 | /* Back to a reasonable maximum of mmap'ed areas. */ | ||
| 1445 | mallopt (M_MMAP_MAX, MMAP_MAX_AREAS); | ||
| 1446 | #endif | ||
| 1447 | n_string_blocks++; | ||
| 1448 | VALIDATE_LISP_STORAGE (new, 0); | ||
| 1449 | consing_since_gc += sizeof (struct string_block_head) + fullsize; | ||
| 1450 | new->pos = fullsize; | ||
| 1451 | new->next = large_string_blocks; | ||
| 1452 | large_string_blocks = new; | ||
| 1453 | XSETSTRING (val, | ||
| 1454 | ((struct Lisp_String *) | ||
| 1455 | ((struct string_block_head *)new + 1))); | ||
| 1456 | } | ||
| 1457 | else | ||
| 1458 | /* Make a new current string block and start it off with this string */ | ||
| 1459 | { | ||
| 1460 | register struct string_block *new; | ||
| 1461 | new = (struct string_block *) lisp_malloc (sizeof (struct string_block)); | ||
| 1462 | n_string_blocks++; | ||
| 1463 | VALIDATE_LISP_STORAGE (new, sizeof *new); | ||
| 1464 | consing_since_gc += sizeof (struct string_block); | ||
| 1465 | current_string_block->next = new; | ||
| 1466 | new->prev = current_string_block; | ||
| 1467 | new->next = 0; | ||
| 1468 | current_string_block = new; | ||
| 1469 | new->pos = fullsize; | ||
| 1470 | XSETSTRING (val, | ||
| 1471 | (struct Lisp_String *) current_string_block->chars); | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | string_chars_consed += fullsize; | ||
| 1475 | XSTRING (val)->size = length; | ||
| 1476 | SET_STRING_BYTES (XSTRING (val), length_byte); | ||
| 1477 | XSTRING (val)->data[length_byte] = 0; | ||
| 1478 | INITIALIZE_INTERVAL (XSTRING (val), NULL_INTERVAL); | ||
| 1479 | |||
| 1480 | return val; | ||
| 1481 | } | ||
| 1482 | 1929 | ||
| 1483 | /* Return a newly created vector or string with specified arguments as | 1930 | /* Return a newly created vector or string with specified arguments as |
| 1484 | elements. If all the arguments are characters that can fit | 1931 | elements. If all the arguments are characters that can fit |
| @@ -1518,40 +1965,57 @@ make_event_array (nargs, args) | |||
| 1518 | return result; | 1965 | return result; |
| 1519 | } | 1966 | } |
| 1520 | } | 1967 | } |
| 1968 | |||
| 1969 | |||
| 1521 | 1970 | ||
| 1522 | /* Pure storage management. */ | 1971 | /*********************************************************************** |
| 1972 | Pure Storage Management | ||
| 1973 | ***********************************************************************/ | ||
| 1974 | |||
| 1975 | /* Return a string allocated in pure space. DATA is a buffer holding | ||
| 1976 | NCHARS characters, and NBYTES bytes of string data. MULTIBYTE | ||
| 1977 | non-zero means make the result string multibyte. | ||
| 1523 | 1978 | ||
| 1524 | /* Must get an error if pure storage is full, | 1979 | Must get an error if pure storage is full, since if it cannot hold |
| 1525 | since if it cannot hold a large string | 1980 | a large string it may be able to hold conses that point to that |
| 1526 | it may be able to hold conses that point to that string; | 1981 | string; then the string is not protected from gc. */ |
| 1527 | then the string is not protected from gc. */ | ||
| 1528 | 1982 | ||
| 1529 | Lisp_Object | 1983 | Lisp_Object |
| 1530 | make_pure_string (data, length, length_byte, multibyte) | 1984 | make_pure_string (data, nchars, nbytes, multibyte) |
| 1531 | char *data; | 1985 | char *data; |
| 1532 | int length; | 1986 | int nchars, nbytes; |
| 1533 | int length_byte; | ||
| 1534 | int multibyte; | 1987 | int multibyte; |
| 1535 | { | 1988 | { |
| 1989 | Lisp_Object string; | ||
| 1990 | struct Lisp_String *s; | ||
| 1991 | int string_size, data_size; | ||
| 1536 | 1992 | ||
| 1537 | register Lisp_Object new; | 1993 | #define PAD(SZ) (((SZ) + sizeof (EMACS_INT) - 1) & ~(sizeof (EMACS_INT) - 1)) |
| 1538 | register int size = STRING_FULLSIZE (length_byte); | ||
| 1539 | 1994 | ||
| 1540 | if (pureptr + size > PURESIZE) | 1995 | string_size = PAD (sizeof (struct Lisp_String)); |
| 1996 | data_size = PAD (nbytes + 1); | ||
| 1997 | |||
| 1998 | #undef PAD | ||
| 1999 | |||
| 2000 | if (pureptr + string_size + data_size > PURESIZE) | ||
| 1541 | error ("Pure Lisp storage exhausted"); | 2001 | error ("Pure Lisp storage exhausted"); |
| 1542 | XSETSTRING (new, PUREBEG + pureptr); | 2002 | |
| 1543 | XSTRING (new)->size = length; | 2003 | s = (struct Lisp_String *) (PUREBEG + pureptr); |
| 1544 | SET_STRING_BYTES (XSTRING (new), (multibyte ? length_byte : -1)); | 2004 | pureptr += string_size; |
| 1545 | bcopy (data, XSTRING (new)->data, length_byte); | 2005 | s->data = (unsigned char *) (PUREBEG + pureptr); |
| 1546 | XSTRING (new)->data[length_byte] = 0; | 2006 | pureptr += data_size; |
| 1547 | 2007 | ||
| 1548 | /* We must give strings in pure storage some kind of interval. So we | 2008 | s->size = nchars; |
| 1549 | give them a null one. */ | 2009 | s->size_byte = multibyte ? nbytes : -1; |
| 1550 | XSTRING (new)->intervals = NULL_INTERVAL; | 2010 | bcopy (data, s->data, nbytes); |
| 1551 | pureptr += size; | 2011 | s->data[nbytes] = '\0'; |
| 1552 | return new; | 2012 | s->intervals = NULL_INTERVAL; |
| 2013 | |||
| 2014 | XSETSTRING (string, s); | ||
| 2015 | return string; | ||
| 1553 | } | 2016 | } |
| 1554 | 2017 | ||
| 2018 | |||
| 1555 | Lisp_Object | 2019 | Lisp_Object |
| 1556 | pure_cons (car, cdr) | 2020 | pure_cons (car, cdr) |
| 1557 | Lisp_Object car, cdr; | 2021 | Lisp_Object car, cdr; |
| @@ -1669,6 +2133,7 @@ Does not copy symbols.") | |||
| 1669 | else | 2133 | else |
| 1670 | return obj; | 2134 | return obj; |
| 1671 | } | 2135 | } |
| 2136 | |||
| 1672 | 2137 | ||
| 1673 | /* Recording what needs to be marked for gc. */ | 2138 | /* Recording what needs to be marked for gc. */ |
| 1674 | 2139 | ||
| @@ -1680,7 +2145,8 @@ Lisp_Object *staticvec[NSTATICS] = {0}; | |||
| 1680 | 2145 | ||
| 1681 | int staticidx = 0; | 2146 | int staticidx = 0; |
| 1682 | 2147 | ||
| 1683 | /* Put an entry in staticvec, pointing at the variable whose address is given */ | 2148 | /* Put an entry in staticvec, pointing at the variable with address |
| 2149 | VARADDRESS. */ | ||
| 1684 | 2150 | ||
| 1685 | void | 2151 | void |
| 1686 | staticpro (varaddress) | 2152 | staticpro (varaddress) |
| @@ -1692,24 +2158,26 @@ staticpro (varaddress) | |||
| 1692 | } | 2158 | } |
| 1693 | 2159 | ||
| 1694 | struct catchtag | 2160 | struct catchtag |
| 1695 | { | 2161 | { |
| 1696 | Lisp_Object tag; | 2162 | Lisp_Object tag; |
| 1697 | Lisp_Object val; | 2163 | Lisp_Object val; |
| 1698 | struct catchtag *next; | 2164 | struct catchtag *next; |
| 1699 | #if 0 /* We don't need this for GC purposes */ | 2165 | #if 0 /* We don't need this for GC purposes */ |
| 1700 | jmp_buf jmp; | 2166 | jmp_buf jmp; |
| 1701 | #endif | 2167 | #endif |
| 1702 | }; | 2168 | }; |
| 1703 | 2169 | ||
| 1704 | struct backtrace | 2170 | struct backtrace |
| 1705 | { | 2171 | { |
| 1706 | struct backtrace *next; | 2172 | struct backtrace *next; |
| 1707 | Lisp_Object *function; | 2173 | Lisp_Object *function; |
| 1708 | Lisp_Object *args; /* Points to vector of args. */ | 2174 | Lisp_Object *args; /* Points to vector of args. */ |
| 1709 | int nargs; /* length of vector */ | 2175 | int nargs; /* Length of vector. */ |
| 1710 | /* if nargs is UNEVALLED, args points to slot holding list of unevalled args */ | 2176 | /* If nargs is UNEVALLED, args points to slot holding list of |
| 1711 | char evalargs; | 2177 | unevalled args. */ |
| 1712 | }; | 2178 | char evalargs; |
| 2179 | }; | ||
| 2180 | |||
| 1713 | 2181 | ||
| 1714 | /* Garbage collection! */ | 2182 | /* Garbage collection! */ |
| 1715 | 2183 | ||
| @@ -1734,7 +2202,8 @@ DEFUN ("garbage-collect", Fgarbage_collect, Sgarbage_collect, 0, 0, "", | |||
| 1734 | Returns info on amount of space in use:\n\ | 2202 | Returns info on amount of space in use:\n\ |
| 1735 | ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\ | 2203 | ((USED-CONSES . FREE-CONSES) (USED-SYMS . FREE-SYMS)\n\ |
| 1736 | (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS\n\ | 2204 | (USED-MARKERS . FREE-MARKERS) USED-STRING-CHARS USED-VECTOR-SLOTS\n\ |
| 1737 | (USED-FLOATS . FREE-FLOATS) (USED-INTERVALS . FREE-INTERVALS))\n\ | 2205 | (USED-FLOATS . FREE-FLOATS) (USED-INTERVALS . FREE-INTERVALS\n\ |
| 2206 | (USED-STRINGS . FREE-STRINGS))\n\ | ||
| 1738 | Garbage collection happens automatically if you cons more than\n\ | 2207 | Garbage collection happens automatically if you cons more than\n\ |
| 1739 | `gc-cons-threshold' bytes of Lisp data since previous garbage collection.") | 2208 | `gc-cons-threshold' bytes of Lisp data since previous garbage collection.") |
| 1740 | () | 2209 | () |
| @@ -1747,6 +2216,7 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 1747 | char stack_top_variable; | 2216 | char stack_top_variable; |
| 1748 | register int i; | 2217 | register int i; |
| 1749 | int message_p; | 2218 | int message_p; |
| 2219 | Lisp_Object total[7]; | ||
| 1750 | 2220 | ||
| 1751 | /* In case user calls debug_print during GC, | 2221 | /* In case user calls debug_print during GC, |
| 1752 | don't let that cause a recursive GC. */ | 2222 | don't let that cause a recursive GC. */ |
| @@ -1807,14 +2277,6 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 1807 | 2277 | ||
| 1808 | /* clear_marks (); */ | 2278 | /* clear_marks (); */ |
| 1809 | 2279 | ||
| 1810 | /* In each "large string", set the MARKBIT of the size field. | ||
| 1811 | That enables mark_object to recognize them. */ | ||
| 1812 | { | ||
| 1813 | register struct string_block *b; | ||
| 1814 | for (b = large_string_blocks; b; b = b->next) | ||
| 1815 | ((struct Lisp_String *)(&b->chars[0]))->size |= MARKBIT; | ||
| 1816 | } | ||
| 1817 | |||
| 1818 | /* Mark all the special slots that serve as the roots of accessibility. | 2280 | /* Mark all the special slots that serve as the roots of accessibility. |
| 1819 | 2281 | ||
| 1820 | Usually the special slots to mark are contained in particular structures. | 2282 | Usually the special slots to mark are contained in particular structures. |
| @@ -1946,26 +2408,27 @@ Garbage collection happens automatically if you cons more than\n\ | |||
| 1946 | } | 2408 | } |
| 1947 | 2409 | ||
| 1948 | pop_message (); | 2410 | pop_message (); |
| 1949 | 2411 | ||
| 1950 | return Fcons (Fcons (make_number (total_conses), | 2412 | total[0] = Fcons (make_number (total_conses), |
| 1951 | make_number (total_free_conses)), | 2413 | make_number (total_free_conses)); |
| 1952 | Fcons (Fcons (make_number (total_symbols), | 2414 | total[1] = Fcons (make_number (total_symbols), |
| 1953 | make_number (total_free_symbols)), | 2415 | make_number (total_free_symbols)); |
| 1954 | Fcons (Fcons (make_number (total_markers), | 2416 | total[2] = Fcons (make_number (total_markers), |
| 1955 | make_number (total_free_markers)), | 2417 | make_number (total_free_markers)); |
| 1956 | Fcons (make_number (total_string_size), | 2418 | total[3] = Fcons (make_number (total_string_size), |
| 1957 | Fcons (make_number (total_vector_size), | 2419 | make_number (total_vector_size)); |
| 1958 | Fcons (Fcons | ||
| 1959 | #ifdef LISP_FLOAT_TYPE | 2420 | #ifdef LISP_FLOAT_TYPE |
| 1960 | (make_number (total_floats), | 2421 | total[4] = Fcons (make_number (total_floats), |
| 1961 | make_number (total_free_floats)), | 2422 | make_number (total_free_floats)); |
| 1962 | #else /* not LISP_FLOAT_TYPE */ | 2423 | #else |
| 1963 | (make_number (0), make_number (0)), | 2424 | total[4] = Fcons (make_number (0), make_number (0)); |
| 1964 | #endif /* not LISP_FLOAT_TYPE */ | 2425 | #endif |
| 1965 | Fcons (Fcons | 2426 | total[5] = Fcons (make_number (total_intervals), |
| 1966 | (make_number (total_intervals), | 2427 | make_number (total_free_intervals)); |
| 1967 | make_number (total_free_intervals)), | 2428 | total[6] = Fcons (make_number (total_strings), |
| 1968 | Qnil))))))); | 2429 | make_number (total_free_strings)); |
| 2430 | |||
| 2431 | return Flist (7, total); | ||
| 1969 | } | 2432 | } |
| 1970 | 2433 | ||
| 1971 | #if 0 | 2434 | #if 0 |
| @@ -2037,27 +2500,21 @@ mark_glyph_matrix (matrix) | |||
| 2037 | struct glyph_row *row = matrix->rows; | 2500 | struct glyph_row *row = matrix->rows; |
| 2038 | struct glyph_row *end = row + matrix->nrows; | 2501 | struct glyph_row *end = row + matrix->nrows; |
| 2039 | 2502 | ||
| 2040 | while (row < end) | 2503 | for (; row < end; ++row) |
| 2041 | { | 2504 | if (row->enabled_p) |
| 2042 | if (row->enabled_p) | 2505 | { |
| 2043 | { | 2506 | int area; |
| 2044 | int area; | 2507 | for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) |
| 2045 | for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) | 2508 | { |
| 2046 | { | 2509 | struct glyph *glyph = row->glyphs[area]; |
| 2047 | struct glyph *glyph = row->glyphs[area]; | 2510 | struct glyph *end_glyph = glyph + row->used[area]; |
| 2048 | struct glyph *end_glyph = glyph + row->used[area]; | 2511 | |
| 2049 | 2512 | for (; glyph < end_glyph; ++glyph) | |
| 2050 | while (glyph < end_glyph) | 2513 | if (GC_STRINGP (glyph->object) |
| 2051 | { | 2514 | && !STRING_MARKED_P (XSTRING (glyph->object))) |
| 2052 | if (GC_STRINGP (glyph->object)) | 2515 | mark_object (&glyph->object); |
| 2053 | mark_object (&glyph->object); | 2516 | } |
| 2054 | ++glyph; | 2517 | } |
| 2055 | } | ||
| 2056 | } | ||
| 2057 | } | ||
| 2058 | |||
| 2059 | ++row; | ||
| 2060 | } | ||
| 2061 | } | 2518 | } |
| 2062 | 2519 | ||
| 2063 | /* Mark Lisp faces in the face cache C. */ | 2520 | /* Mark Lisp faces in the face cache C. */ |
| @@ -2114,14 +2571,8 @@ mark_image_cache (f) | |||
| 2114 | 2571 | ||
| 2115 | 2572 | ||
| 2116 | /* Mark reference to a Lisp_Object. | 2573 | /* Mark reference to a Lisp_Object. |
| 2117 | If the object referred to has not been seen yet, recursively mark | 2574 | If the object referred to has not been seen yet, recursively mark |
| 2118 | all the references contained in it. | 2575 | all the references contained in it. */ |
| 2119 | |||
| 2120 | If the object referenced is a short string, the referencing slot | ||
| 2121 | is threaded into a chain of such slots, pointed to from | ||
| 2122 | the `size' field of the string. The actual string size | ||
| 2123 | lives in the last slot in the chain. We recognize the end | ||
| 2124 | because it is < (unsigned) STRING_BLOCK_SIZE. */ | ||
| 2125 | 2576 | ||
| 2126 | #define LAST_MARKED_SIZE 500 | 2577 | #define LAST_MARKED_SIZE 500 |
| 2127 | Lisp_Object *last_marked[LAST_MARKED_SIZE]; | 2578 | Lisp_Object *last_marked[LAST_MARKED_SIZE]; |
| @@ -2152,32 +2603,8 @@ mark_object (argptr) | |||
| 2152 | case Lisp_String: | 2603 | case Lisp_String: |
| 2153 | { | 2604 | { |
| 2154 | register struct Lisp_String *ptr = XSTRING (obj); | 2605 | register struct Lisp_String *ptr = XSTRING (obj); |
| 2155 | |||
| 2156 | MARK_INTERVAL_TREE (ptr->intervals); | 2606 | MARK_INTERVAL_TREE (ptr->intervals); |
| 2157 | if (ptr->size & MARKBIT) | 2607 | MARK_STRING (ptr); |
| 2158 | /* A large string. Just set ARRAY_MARK_FLAG. */ | ||
| 2159 | ptr->size |= ARRAY_MARK_FLAG; | ||
| 2160 | else | ||
| 2161 | { | ||
| 2162 | /* A small string. Put this reference | ||
| 2163 | into the chain of references to it. | ||
| 2164 | If the address includes MARKBIT, put that bit elsewhere | ||
| 2165 | when we store OBJPTR into the size field. */ | ||
| 2166 | |||
| 2167 | if (XMARKBIT (*objptr)) | ||
| 2168 | { | ||
| 2169 | XSETFASTINT (*objptr, ptr->size); | ||
| 2170 | XMARK (*objptr); | ||
| 2171 | } | ||
| 2172 | else | ||
| 2173 | XSETFASTINT (*objptr, ptr->size); | ||
| 2174 | |||
| 2175 | if ((EMACS_INT) objptr & DONT_COPY_FLAG) | ||
| 2176 | abort (); | ||
| 2177 | ptr->size = (EMACS_INT) objptr; | ||
| 2178 | if (ptr->size & MARKBIT) | ||
| 2179 | ptr->size ^= MARKBIT | DONT_COPY_FLAG; | ||
| 2180 | } | ||
| 2181 | } | 2608 | } |
| 2182 | break; | 2609 | break; |
| 2183 | 2610 | ||
| @@ -2190,9 +2617,9 @@ mark_object (argptr) | |||
| 2190 | else if (GC_SUBRP (obj)) | 2617 | else if (GC_SUBRP (obj)) |
| 2191 | break; | 2618 | break; |
| 2192 | else if (GC_COMPILEDP (obj)) | 2619 | else if (GC_COMPILEDP (obj)) |
| 2193 | /* We could treat this just like a vector, but it is better | 2620 | /* We could treat this just like a vector, but it is better to |
| 2194 | to save the COMPILED_CONSTANTS element for last and avoid recursion | 2621 | save the COMPILED_CONSTANTS element for last and avoid |
| 2195 | there. */ | 2622 | recursion there. */ |
| 2196 | { | 2623 | { |
| 2197 | register struct Lisp_Vector *ptr = XVECTOR (obj); | 2624 | register struct Lisp_Vector *ptr = XVECTOR (obj); |
| 2198 | register EMACS_INT size = ptr->size; | 2625 | register EMACS_INT size = ptr->size; |
| @@ -2360,8 +2787,9 @@ mark_object (argptr) | |||
| 2360 | mark_object ((Lisp_Object *) &ptr->value); | 2787 | mark_object ((Lisp_Object *) &ptr->value); |
| 2361 | mark_object (&ptr->function); | 2788 | mark_object (&ptr->function); |
| 2362 | mark_object (&ptr->plist); | 2789 | mark_object (&ptr->plist); |
| 2363 | XSETTYPE (*(Lisp_Object *) &ptr->name, Lisp_String); | 2790 | MARK_INTERVAL_TREE (ptr->name->intervals); |
| 2364 | mark_object ((Lisp_Object *) &ptr->name); | 2791 | MARK_STRING (ptr->name); |
| 2792 | |||
| 2365 | /* Note that we do not mark the obarray of the symbol. | 2793 | /* Note that we do not mark the obarray of the symbol. |
| 2366 | It is safe not to do so because nothing accesses that | 2794 | It is safe not to do so because nothing accesses that |
| 2367 | slot except to check whether it is nil. */ | 2795 | slot except to check whether it is nil. */ |
| @@ -2520,24 +2948,6 @@ mark_buffer (buf) | |||
| 2520 | else | 2948 | else |
| 2521 | mark_object (&buffer->undo_list); | 2949 | mark_object (&buffer->undo_list); |
| 2522 | 2950 | ||
| 2523 | #if 0 | ||
| 2524 | mark_object (buffer->syntax_table); | ||
| 2525 | |||
| 2526 | /* Mark the various string-pointers in the buffer object. | ||
| 2527 | Since the strings may be relocated, we must mark them | ||
| 2528 | in their actual slots. So gc_sweep must convert each slot | ||
| 2529 | back to an ordinary C pointer. */ | ||
| 2530 | XSETSTRING (*(Lisp_Object *)&buffer->upcase_table, buffer->upcase_table); | ||
| 2531 | mark_object ((Lisp_Object *)&buffer->upcase_table); | ||
| 2532 | XSETSTRING (*(Lisp_Object *)&buffer->downcase_table, buffer->downcase_table); | ||
| 2533 | mark_object ((Lisp_Object *)&buffer->downcase_table); | ||
| 2534 | |||
| 2535 | XSETSTRING (*(Lisp_Object *)&buffer->sort_table, buffer->sort_table); | ||
| 2536 | mark_object ((Lisp_Object *)&buffer->sort_table); | ||
| 2537 | XSETSTRING (*(Lisp_Object *)&buffer->folding_sort_table, buffer->folding_sort_table); | ||
| 2538 | mark_object ((Lisp_Object *)&buffer->folding_sort_table); | ||
| 2539 | #endif | ||
| 2540 | |||
| 2541 | for (ptr = &buffer->name + 1; | 2951 | for (ptr = &buffer->name + 1; |
| 2542 | (char *)ptr < (char *)buffer + sizeof (struct buffer); | 2952 | (char *)ptr < (char *)buffer + sizeof (struct buffer); |
| 2543 | ptr++) | 2953 | ptr++) |
| @@ -2630,11 +3040,7 @@ survives_gc_p (obj) | |||
| 2630 | case Lisp_String: | 3040 | case Lisp_String: |
| 2631 | { | 3041 | { |
| 2632 | struct Lisp_String *s = XSTRING (obj); | 3042 | struct Lisp_String *s = XSTRING (obj); |
| 2633 | 3043 | survives_p = STRING_MARKED_P (s); | |
| 2634 | if (s->size & MARKBIT) | ||
| 2635 | survives_p = s->size & ARRAY_MARK_FLAG; | ||
| 2636 | else | ||
| 2637 | survives_p = (s->size & ~DONT_COPY_FLAG) > STRING_BLOCK_SIZE; | ||
| 2638 | } | 3044 | } |
| 2639 | break; | 3045 | break; |
| 2640 | 3046 | ||
| @@ -2675,8 +3081,7 @@ gc_sweep () | |||
| 2675 | This must be done before any object is unmarked. */ | 3081 | This must be done before any object is unmarked. */ |
| 2676 | sweep_weak_hash_tables (); | 3082 | sweep_weak_hash_tables (); |
| 2677 | 3083 | ||
| 2678 | total_string_size = 0; | 3084 | sweep_strings (); |
| 2679 | compact_strings (); | ||
| 2680 | 3085 | ||
| 2681 | /* Put all unmarked conses on free list */ | 3086 | /* Put all unmarked conses on free list */ |
| 2682 | { | 3087 | { |
| @@ -2847,8 +3252,7 @@ gc_sweep () | |||
| 2847 | else | 3252 | else |
| 2848 | { | 3253 | { |
| 2849 | num_used++; | 3254 | num_used++; |
| 2850 | sblk->symbols[i].name | 3255 | UNMARK_STRING (sblk->symbols[i].name); |
| 2851 | = XSTRING (*(Lisp_Object *) &sblk->symbols[i].name); | ||
| 2852 | XUNMARK (sblk->symbols[i].plist); | 3256 | XUNMARK (sblk->symbols[i].plist); |
| 2853 | } | 3257 | } |
| 2854 | lim = SYMBOL_BLOCK_SIZE; | 3258 | lim = SYMBOL_BLOCK_SIZE; |
| @@ -2873,7 +3277,6 @@ gc_sweep () | |||
| 2873 | total_free_symbols = num_free; | 3277 | total_free_symbols = num_free; |
| 2874 | } | 3278 | } |
| 2875 | 3279 | ||
| 2876 | #ifndef standalone | ||
| 2877 | /* Put all unmarked misc's on free list. | 3280 | /* Put all unmarked misc's on free list. |
| 2878 | For a marker, first unchain it from the buffer it points into. */ | 3281 | For a marker, first unchain it from the buffer it points into. */ |
| 2879 | { | 3282 | { |
| @@ -2981,27 +3384,10 @@ gc_sweep () | |||
| 2981 | { | 3384 | { |
| 2982 | XUNMARK (buffer->name); | 3385 | XUNMARK (buffer->name); |
| 2983 | UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); | 3386 | UNMARK_BALANCE_INTERVALS (BUF_INTERVALS (buffer)); |
| 2984 | |||
| 2985 | #if 0 | ||
| 2986 | /* Each `struct Lisp_String *' was turned into a Lisp_Object | ||
| 2987 | for purposes of marking and relocation. | ||
| 2988 | Turn them back into C pointers now. */ | ||
| 2989 | buffer->upcase_table | ||
| 2990 | = XSTRING (*(Lisp_Object *)&buffer->upcase_table); | ||
| 2991 | buffer->downcase_table | ||
| 2992 | = XSTRING (*(Lisp_Object *)&buffer->downcase_table); | ||
| 2993 | buffer->sort_table | ||
| 2994 | = XSTRING (*(Lisp_Object *)&buffer->sort_table); | ||
| 2995 | buffer->folding_sort_table | ||
| 2996 | = XSTRING (*(Lisp_Object *)&buffer->folding_sort_table); | ||
| 2997 | #endif | ||
| 2998 | |||
| 2999 | prev = buffer, buffer = buffer->next; | 3387 | prev = buffer, buffer = buffer->next; |
| 3000 | } | 3388 | } |
| 3001 | } | 3389 | } |
| 3002 | 3390 | ||
| 3003 | #endif /* standalone */ | ||
| 3004 | |||
| 3005 | /* Free all unmarked vectors */ | 3391 | /* Free all unmarked vectors */ |
| 3006 | { | 3392 | { |
| 3007 | register struct Lisp_Vector *vector = all_vectors, *prev = 0, *next; | 3393 | register struct Lisp_Vector *vector = all_vectors, *prev = 0, *next; |
| @@ -3035,180 +3421,10 @@ gc_sweep () | |||
| 3035 | prev = vector, vector = vector->next; | 3421 | prev = vector, vector = vector->next; |
| 3036 | } | 3422 | } |
| 3037 | } | 3423 | } |
| 3038 | |||
| 3039 | /* Free all "large strings" not marked with ARRAY_MARK_FLAG. */ | ||
| 3040 | { | ||
| 3041 | register struct string_block *sb = large_string_blocks, *prev = 0, *next; | ||
| 3042 | struct Lisp_String *s; | ||
| 3043 | |||
| 3044 | while (sb) | ||
| 3045 | { | ||
| 3046 | s = (struct Lisp_String *) &sb->chars[0]; | ||
| 3047 | if (s->size & ARRAY_MARK_FLAG) | ||
| 3048 | { | ||
| 3049 | ((struct Lisp_String *)(&sb->chars[0]))->size | ||
| 3050 | &= ~ARRAY_MARK_FLAG & ~MARKBIT; | ||
| 3051 | UNMARK_BALANCE_INTERVALS (s->intervals); | ||
| 3052 | total_string_size += ((struct Lisp_String *)(&sb->chars[0]))->size; | ||
| 3053 | prev = sb, sb = sb->next; | ||
| 3054 | } | ||
| 3055 | else | ||
| 3056 | { | ||
| 3057 | if (prev) | ||
| 3058 | prev->next = sb->next; | ||
| 3059 | else | ||
| 3060 | large_string_blocks = sb->next; | ||
| 3061 | next = sb->next; | ||
| 3062 | lisp_free (sb); | ||
| 3063 | sb = next; | ||
| 3064 | n_string_blocks--; | ||
| 3065 | } | ||
| 3066 | } | ||
| 3067 | } | ||
| 3068 | } | 3424 | } |
| 3069 | |||
| 3070 | /* Compactify strings, relocate references, and free empty string blocks. */ | ||
| 3071 | |||
| 3072 | static void | ||
| 3073 | compact_strings () | ||
| 3074 | { | ||
| 3075 | /* String block of old strings we are scanning. */ | ||
| 3076 | register struct string_block *from_sb; | ||
| 3077 | /* A preceding string block (or maybe the same one) | ||
| 3078 | where we are copying the still-live strings to. */ | ||
| 3079 | register struct string_block *to_sb; | ||
| 3080 | int pos; | ||
| 3081 | int to_pos; | ||
| 3082 | |||
| 3083 | to_sb = first_string_block; | ||
| 3084 | to_pos = 0; | ||
| 3085 | |||
| 3086 | /* Scan each existing string block sequentially, string by string. */ | ||
| 3087 | for (from_sb = first_string_block; from_sb; from_sb = from_sb->next) | ||
| 3088 | { | ||
| 3089 | pos = 0; | ||
| 3090 | /* POS is the index of the next string in the block. */ | ||
| 3091 | while (pos < from_sb->pos) | ||
| 3092 | { | ||
| 3093 | register struct Lisp_String *nextstr | ||
| 3094 | = (struct Lisp_String *) &from_sb->chars[pos]; | ||
| 3095 | |||
| 3096 | register struct Lisp_String *newaddr; | ||
| 3097 | register EMACS_INT size = nextstr->size; | ||
| 3098 | EMACS_INT size_byte = nextstr->size_byte; | ||
| 3099 | |||
| 3100 | /* NEXTSTR is the old address of the next string. | ||
| 3101 | Just skip it if it isn't marked. */ | ||
| 3102 | if (((EMACS_UINT) size & ~DONT_COPY_FLAG) > STRING_BLOCK_SIZE) | ||
| 3103 | { | ||
| 3104 | /* It is marked, so its size field is really a chain of refs. | ||
| 3105 | Find the end of the chain, where the actual size lives. */ | ||
| 3106 | while (((EMACS_UINT) size & ~DONT_COPY_FLAG) > STRING_BLOCK_SIZE) | ||
| 3107 | { | ||
| 3108 | if (size & DONT_COPY_FLAG) | ||
| 3109 | size ^= MARKBIT | DONT_COPY_FLAG; | ||
| 3110 | size = *(EMACS_INT *)size & ~MARKBIT; | ||
| 3111 | } | ||
| 3112 | 3425 | ||
| 3113 | if (size_byte < 0) | ||
| 3114 | size_byte = size; | ||
| 3115 | 3426 | ||
| 3116 | total_string_size += size_byte; | ||
| 3117 | 3427 | ||
| 3118 | /* If it won't fit in TO_SB, close it out, | ||
| 3119 | and move to the next sb. Keep doing so until | ||
| 3120 | TO_SB reaches a large enough, empty enough string block. | ||
| 3121 | We know that TO_SB cannot advance past FROM_SB here | ||
| 3122 | since FROM_SB is large enough to contain this string. | ||
| 3123 | Any string blocks skipped here | ||
| 3124 | will be patched out and freed later. */ | ||
| 3125 | while (to_pos + STRING_FULLSIZE (size_byte) | ||
| 3126 | > max (to_sb->pos, STRING_BLOCK_SIZE)) | ||
| 3127 | { | ||
| 3128 | to_sb->pos = to_pos; | ||
| 3129 | to_sb = to_sb->next; | ||
| 3130 | to_pos = 0; | ||
| 3131 | } | ||
| 3132 | /* Compute new address of this string | ||
| 3133 | and update TO_POS for the space being used. */ | ||
| 3134 | newaddr = (struct Lisp_String *) &to_sb->chars[to_pos]; | ||
| 3135 | to_pos += STRING_FULLSIZE (size_byte); | ||
| 3136 | |||
| 3137 | /* Copy the string itself to the new place. */ | ||
| 3138 | if (nextstr != newaddr) | ||
| 3139 | bcopy (nextstr, newaddr, STRING_FULLSIZE (size_byte)); | ||
| 3140 | |||
| 3141 | /* Go through NEXTSTR's chain of references | ||
| 3142 | and make each slot in the chain point to | ||
| 3143 | the new address of this string. */ | ||
| 3144 | size = newaddr->size; | ||
| 3145 | while (((EMACS_UINT) size & ~DONT_COPY_FLAG) > STRING_BLOCK_SIZE) | ||
| 3146 | { | ||
| 3147 | register Lisp_Object *objptr; | ||
| 3148 | if (size & DONT_COPY_FLAG) | ||
| 3149 | size ^= MARKBIT | DONT_COPY_FLAG; | ||
| 3150 | objptr = (Lisp_Object *)size; | ||
| 3151 | |||
| 3152 | size = XFASTINT (*objptr) & ~MARKBIT; | ||
| 3153 | if (XMARKBIT (*objptr)) | ||
| 3154 | { | ||
| 3155 | XSETSTRING (*objptr, newaddr); | ||
| 3156 | XMARK (*objptr); | ||
| 3157 | } | ||
| 3158 | else | ||
| 3159 | XSETSTRING (*objptr, newaddr); | ||
| 3160 | } | ||
| 3161 | /* Store the actual size in the size field. */ | ||
| 3162 | newaddr->size = size; | ||
| 3163 | |||
| 3164 | /* Now that the string has been relocated, rebalance its | ||
| 3165 | interval tree, and update the tree's parent pointer. */ | ||
| 3166 | if (! NULL_INTERVAL_P (newaddr->intervals)) | ||
| 3167 | { | ||
| 3168 | UNMARK_BALANCE_INTERVALS (newaddr->intervals); | ||
| 3169 | XSETSTRING (* (Lisp_Object *) &newaddr->intervals->parent, | ||
| 3170 | newaddr); | ||
| 3171 | } | ||
| 3172 | } | ||
| 3173 | else if (size_byte < 0) | ||
| 3174 | size_byte = size; | ||
| 3175 | |||
| 3176 | pos += STRING_FULLSIZE (size_byte); | ||
| 3177 | } | ||
| 3178 | } | ||
| 3179 | |||
| 3180 | /* Close out the last string block still used and free any that follow. */ | ||
| 3181 | to_sb->pos = to_pos; | ||
| 3182 | current_string_block = to_sb; | ||
| 3183 | |||
| 3184 | from_sb = to_sb->next; | ||
| 3185 | to_sb->next = 0; | ||
| 3186 | while (from_sb) | ||
| 3187 | { | ||
| 3188 | to_sb = from_sb->next; | ||
| 3189 | lisp_free (from_sb); | ||
| 3190 | n_string_blocks--; | ||
| 3191 | from_sb = to_sb; | ||
| 3192 | } | ||
| 3193 | |||
| 3194 | /* Free any empty string blocks further back in the chain. | ||
| 3195 | This loop will never free first_string_block, but it is very | ||
| 3196 | unlikely that that one will become empty, so why bother checking? */ | ||
| 3197 | |||
| 3198 | from_sb = first_string_block; | ||
| 3199 | while ((to_sb = from_sb->next) != 0) | ||
| 3200 | { | ||
| 3201 | if (to_sb->pos == 0) | ||
| 3202 | { | ||
| 3203 | if ((from_sb->next = to_sb->next) != 0) | ||
| 3204 | from_sb->next->prev = from_sb; | ||
| 3205 | lisp_free (to_sb); | ||
| 3206 | n_string_blocks--; | ||
| 3207 | } | ||
| 3208 | else | ||
| 3209 | from_sb = to_sb; | ||
| 3210 | } | ||
| 3211 | } | ||
| 3212 | 3428 | ||
| 3213 | /* Debugging aids. */ | 3429 | /* Debugging aids. */ |
| 3214 | 3430 | ||
| @@ -3231,7 +3447,7 @@ Each of these counters increments for a certain kind of object.\n\ | |||
| 3231 | The counters wrap around from the largest positive integer to zero.\n\ | 3447 | The counters wrap around from the largest positive integer to zero.\n\ |
| 3232 | Garbage collection does not decrease them.\n\ | 3448 | Garbage collection does not decrease them.\n\ |
| 3233 | The elements of the value are as follows:\n\ | 3449 | The elements of the value are as follows:\n\ |
| 3234 | (CONSES FLOATS VECTOR-CELLS SYMBOLS STRING-CHARS MISCS INTERVALS)\n\ | 3450 | (CONSES FLOATS VECTOR-CELLS SYMBOLS STRING-CHARS MISCS INTERVALS STRINGS)\n\ |
| 3235 | All are in units of 1 = one object consed\n\ | 3451 | All are in units of 1 = one object consed\n\ |
| 3236 | except for VECTOR-CELLS and STRING-CHARS, which count the total length of\n\ | 3452 | except for VECTOR-CELLS and STRING-CHARS, which count the total length of\n\ |
| 3237 | objects consed.\n\ | 3453 | objects consed.\n\ |
| @@ -3240,37 +3456,26 @@ Frames, windows, buffers, and subprocesses count as vectors\n\ | |||
| 3240 | (but the contents of a buffer's text do not count here).") | 3456 | (but the contents of a buffer's text do not count here).") |
| 3241 | () | 3457 | () |
| 3242 | { | 3458 | { |
| 3243 | Lisp_Object lisp_cons_cells_consed; | 3459 | Lisp_Object consed[8]; |
| 3244 | Lisp_Object lisp_floats_consed; | ||
| 3245 | Lisp_Object lisp_vector_cells_consed; | ||
| 3246 | Lisp_Object lisp_symbols_consed; | ||
| 3247 | Lisp_Object lisp_string_chars_consed; | ||
| 3248 | Lisp_Object lisp_misc_objects_consed; | ||
| 3249 | Lisp_Object lisp_intervals_consed; | ||
| 3250 | 3460 | ||
| 3251 | XSETINT (lisp_cons_cells_consed, | 3461 | XSETINT (consed[0], |
| 3252 | cons_cells_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | 3462 | cons_cells_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); |
| 3253 | XSETINT (lisp_floats_consed, | 3463 | XSETINT (consed[1], |
| 3254 | floats_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | 3464 | floats_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); |
| 3255 | XSETINT (lisp_vector_cells_consed, | 3465 | XSETINT (consed[2], |
| 3256 | vector_cells_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | 3466 | vector_cells_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); |
| 3257 | XSETINT (lisp_symbols_consed, | 3467 | XSETINT (consed[3], |
| 3258 | symbols_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | 3468 | symbols_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); |
| 3259 | XSETINT (lisp_string_chars_consed, | 3469 | XSETINT (consed[4], |
| 3260 | string_chars_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | 3470 | string_chars_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); |
| 3261 | XSETINT (lisp_misc_objects_consed, | 3471 | XSETINT (consed[5], |
| 3262 | misc_objects_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | 3472 | misc_objects_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); |
| 3263 | XSETINT (lisp_intervals_consed, | 3473 | XSETINT (consed[6], |
| 3264 | intervals_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | 3474 | intervals_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); |
| 3475 | XSETINT (consed[7], | ||
| 3476 | strings_consed & ~(((EMACS_INT) 1) << (VALBITS - 1))); | ||
| 3265 | 3477 | ||
| 3266 | return Fcons (lisp_cons_cells_consed, | 3478 | return Flist (8, consed); |
| 3267 | Fcons (lisp_floats_consed, | ||
| 3268 | Fcons (lisp_vector_cells_consed, | ||
| 3269 | Fcons (lisp_symbols_consed, | ||
| 3270 | Fcons (lisp_string_chars_consed, | ||
| 3271 | Fcons (lisp_misc_objects_consed, | ||
| 3272 | Fcons (lisp_intervals_consed, | ||
| 3273 | Qnil))))))); | ||
| 3274 | } | 3479 | } |
| 3275 | 3480 | ||
| 3276 | /* Initialization */ | 3481 | /* Initialization */ |
| @@ -3361,6 +3566,9 @@ prevent garbage collection during a part of the program."); | |||
| 3361 | DEFVAR_INT ("intervals-consed", &intervals_consed, | 3566 | DEFVAR_INT ("intervals-consed", &intervals_consed, |
| 3362 | "Number of intervals that have been consed so far."); | 3567 | "Number of intervals that have been consed so far."); |
| 3363 | 3568 | ||
| 3569 | DEFVAR_INT ("strings-consed", &strings_consed, | ||
| 3570 | "Number of strings that have been consed so far."); | ||
| 3571 | |||
| 3364 | #if 0 | 3572 | #if 0 |
| 3365 | DEFVAR_INT ("data-bytes-used", &malloc_sbrk_used, | 3573 | DEFVAR_INT ("data-bytes-used", &malloc_sbrk_used, |
| 3366 | "Number of bytes of unshared memory allocated in this session."); | 3574 | "Number of bytes of unshared memory allocated in this session."); |