Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 361:7347b34c275b r21-1-10
Import from CVS: tag r21-1-10
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:58:40 +0200 |
parents | 8bec6624d99b |
children | 1d62742628b6 |
comparison
equal
deleted
inserted
replaced
360:0f00b38cfccb | 361:7347b34c275b |
---|---|
2082 ALIGNOF (struct Lisp_String *)) | 2082 ALIGNOF (struct Lisp_String *)) |
2083 | 2083 |
2084 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) | 2084 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) |
2085 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) | 2085 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) |
2086 | 2086 |
2087 #define CHARS_TO_STRING_CHAR(x) \ | |
2088 ((struct string_chars *) \ | |
2089 (((char *) (x)) - (slot_offset (struct string_chars, chars[0])))) | |
2090 | |
2091 | |
2092 struct string_chars | 2087 struct string_chars |
2093 { | 2088 { |
2094 struct Lisp_String *string; | 2089 struct Lisp_String *string; |
2095 unsigned char chars[1]; | 2090 unsigned char chars[1]; |
2096 }; | 2091 }; |
2115 allocate_string_chars_struct (struct Lisp_String *string_it_goes_with, | 2110 allocate_string_chars_struct (struct Lisp_String *string_it_goes_with, |
2116 EMACS_INT fullsize) | 2111 EMACS_INT fullsize) |
2117 { | 2112 { |
2118 struct string_chars *s_chars; | 2113 struct string_chars *s_chars; |
2119 | 2114 |
2120 /* Allocate the string's actual data */ | 2115 if (fullsize <= |
2121 if (BIG_STRING_FULLSIZE_P (fullsize)) | 2116 (countof (current_string_chars_block->string_chars) |
2122 { | 2117 - current_string_chars_block->pos)) |
2123 s_chars = (struct string_chars *) xmalloc (fullsize); | |
2124 } | |
2125 else if (fullsize <= | |
2126 (countof (current_string_chars_block->string_chars) | |
2127 - current_string_chars_block->pos)) | |
2128 { | 2118 { |
2129 /* This string can fit in the current string chars block */ | 2119 /* This string can fit in the current string chars block */ |
2130 s_chars = (struct string_chars *) | 2120 s_chars = (struct string_chars *) |
2131 (current_string_chars_block->string_chars | 2121 (current_string_chars_block->string_chars |
2132 + current_string_chars_block->pos); | 2122 + current_string_chars_block->pos); |
2155 | 2145 |
2156 Lisp_Object | 2146 Lisp_Object |
2157 make_uninit_string (Bytecount length) | 2147 make_uninit_string (Bytecount length) |
2158 { | 2148 { |
2159 struct Lisp_String *s; | 2149 struct Lisp_String *s; |
2160 struct string_chars *s_chars; | |
2161 EMACS_INT fullsize = STRING_FULLSIZE (length); | 2150 EMACS_INT fullsize = STRING_FULLSIZE (length); |
2162 Lisp_Object val; | 2151 Lisp_Object val; |
2163 | 2152 |
2164 if ((length < 0) || (fullsize <= 0)) | 2153 assert (length >= 0 && fullsize > 0); |
2165 abort (); | |
2166 | 2154 |
2167 /* Allocate the string header */ | 2155 /* Allocate the string header */ |
2168 ALLOCATE_FIXED_TYPE (string, struct Lisp_String, s); | 2156 ALLOCATE_FIXED_TYPE (string, struct Lisp_String, s); |
2169 #ifdef LRECORD_STRING | 2157 #ifdef LRECORD_STRING |
2170 set_lheader_implementation (&(s->lheader), lrecord_string); | 2158 set_lheader_implementation (&(s->lheader), lrecord_string); |
2171 #endif | 2159 #endif |
2172 | 2160 |
2173 s_chars = allocate_string_chars_struct (s, fullsize); | 2161 set_string_data (s, BIG_STRING_FULLSIZE_P (fullsize) |
2174 | 2162 ? xnew_array (Bufbyte, length + 1) |
2175 set_string_data (s, &(s_chars->chars[0])); | 2163 : allocate_string_chars_struct (s, fullsize)->chars); |
2164 | |
2176 set_string_length (s, length); | 2165 set_string_length (s, length); |
2177 s->plist = Qnil; | 2166 s->plist = Qnil; |
2178 | 2167 |
2179 set_string_byte (s, length, 0); | 2168 set_string_byte (s, length, 0); |
2180 | 2169 |
2193 */ | 2182 */ |
2194 | 2183 |
2195 void | 2184 void |
2196 resize_string (struct Lisp_String *s, Bytecount pos, Bytecount delta) | 2185 resize_string (struct Lisp_String *s, Bytecount pos, Bytecount delta) |
2197 { | 2186 { |
2187 Bytecount oldfullsize, newfullsize; | |
2198 #ifdef VERIFY_STRING_CHARS_INTEGRITY | 2188 #ifdef VERIFY_STRING_CHARS_INTEGRITY |
2199 verify_string_chars_integrity (); | 2189 verify_string_chars_integrity (); |
2200 #endif | 2190 #endif |
2201 | 2191 |
2202 #ifdef ERROR_CHECK_BUFPOS | 2192 #ifdef ERROR_CHECK_BUFPOS |
2211 if (delta < 0) | 2201 if (delta < 0) |
2212 assert ((-delta) <= string_length (s)); | 2202 assert ((-delta) <= string_length (s)); |
2213 } | 2203 } |
2214 #endif /* ERROR_CHECK_BUFPOS */ | 2204 #endif /* ERROR_CHECK_BUFPOS */ |
2215 | 2205 |
2216 if (pos >= 0 && delta < 0) | |
2217 /* If DELTA < 0, the functions below will delete the characters | |
2218 before POS. We want to delete characters *after* POS, however, | |
2219 so convert this to the appropriate form. */ | |
2220 pos += -delta; | |
2221 | |
2222 if (delta == 0) | 2206 if (delta == 0) |
2223 /* simplest case: no size change. */ | 2207 /* simplest case: no size change. */ |
2224 return; | 2208 return; |
2225 else | 2209 |
2226 { | 2210 if (pos >= 0 && delta < 0) |
2227 Bytecount oldfullsize = STRING_FULLSIZE (string_length (s)); | 2211 /* If DELTA < 0, the functions below will delete the characters |
2228 Bytecount newfullsize = STRING_FULLSIZE (string_length (s) + delta); | 2212 before POS. We want to delete characters *after* POS, however, |
2229 | 2213 so convert this to the appropriate form. */ |
2214 pos += -delta; | |
2215 | |
2216 oldfullsize = STRING_FULLSIZE (string_length (s)); | |
2217 newfullsize = STRING_FULLSIZE (string_length (s) + delta); | |
2218 | |
2219 if (BIG_STRING_FULLSIZE_P (oldfullsize)) | |
2220 { | |
2221 if (BIG_STRING_FULLSIZE_P (newfullsize)) | |
2222 { | |
2223 /* Both strings are big. We can just realloc(). | |
2224 But careful! If the string is shrinking, we have to | |
2225 memmove() _before_ realloc(), and if growing, we have to | |
2226 memmove() _after_ realloc() - otherwise the access is | |
2227 illegal, and we might crash. */ | |
2228 Bytecount len = string_length (s) + 1 - pos; | |
2229 | |
2230 if (delta < 0 && pos >= 0) | |
2231 memmove (string_data (s) + pos + delta, string_data (s) + pos, len); | |
2232 set_string_data (s, (Bufbyte *) xrealloc (string_data (s), | |
2233 string_length (s) + delta + 1)); | |
2234 if (delta > 0 && pos >= 0) | |
2235 memmove (string_data (s) + pos + delta, string_data (s) + pos, len); | |
2236 } | |
2237 else /* String has been demoted from BIG_STRING. */ | |
2238 { | |
2239 Bufbyte *new_data = | |
2240 allocate_string_chars_struct (s, newfullsize)->chars; | |
2241 Bufbyte *old_data = string_data (s); | |
2242 | |
2243 if (pos >= 0) | |
2244 { | |
2245 memcpy (new_data, old_data, pos); | |
2246 memcpy (new_data + pos + delta, old_data + pos, | |
2247 string_length (s) + 1 - pos); | |
2248 } | |
2249 set_string_data (s, new_data); | |
2250 xfree (old_data); | |
2251 } | |
2252 } | |
2253 else /* old string is small */ | |
2254 { | |
2230 if (oldfullsize == newfullsize) | 2255 if (oldfullsize == newfullsize) |
2231 { | 2256 { |
2232 /* next simplest case; size change but the necessary | 2257 /* special case; size change but the necessary |
2233 allocation size won't change (up or down; code somewhere | 2258 allocation size won't change (up or down; code |
2234 depends on there not being any unused allocation space, | 2259 somewhere depends on there not being any unused |
2235 modulo any alignment constraints). */ | 2260 allocation space, modulo any alignment |
2236 if (pos >= 0) | 2261 constraints). */ |
2237 { | |
2238 Bufbyte *addroff = pos + string_data (s); | |
2239 | |
2240 memmove (addroff + delta, addroff, | |
2241 /* +1 due to zero-termination. */ | |
2242 string_length (s) + 1 - pos); | |
2243 } | |
2244 } | |
2245 else if (BIG_STRING_FULLSIZE_P (oldfullsize) && | |
2246 BIG_STRING_FULLSIZE_P (newfullsize)) | |
2247 { | |
2248 /* next simplest case; the string is big enough to be malloc()ed | |
2249 itself, so we just realloc. | |
2250 | |
2251 It's important not to let the string get below the threshold | |
2252 for making big strings and still remain malloc()ed; if that | |
2253 were the case, repeated calls to this function on the same | |
2254 string could result in memory leakage. */ | |
2255 set_string_data (s, (Bufbyte *) xrealloc (string_data (s), | |
2256 newfullsize)); | |
2257 if (pos >= 0) | 2262 if (pos >= 0) |
2258 { | 2263 { |
2259 Bufbyte *addroff = pos + string_data (s); | 2264 Bufbyte *addroff = pos + string_data (s); |
2260 | 2265 |
2261 memmove (addroff + delta, addroff, | 2266 memmove (addroff + delta, addroff, |
2263 string_length (s) + 1 - pos); | 2268 string_length (s) + 1 - pos); |
2264 } | 2269 } |
2265 } | 2270 } |
2266 else | 2271 else |
2267 { | 2272 { |
2268 /* worst case. We make a new string_chars struct and copy | 2273 Bufbyte *old_data = string_data (s); |
2269 the string's data into it, inserting/deleting the delta | 2274 Bufbyte *new_data = |
2270 in the process. The old string data will either get | 2275 BIG_STRING_FULLSIZE_P (newfullsize) |
2271 freed by us (if it was malloc()ed) or will be reclaimed | 2276 ? xnew_array (Bufbyte, string_length (s) + delta + 1) |
2272 in the normal course of garbage collection. */ | 2277 : allocate_string_chars_struct (s, newfullsize)->chars; |
2273 struct string_chars *s_chars = | 2278 |
2274 allocate_string_chars_struct (s, newfullsize); | |
2275 Bufbyte *new_addr = &(s_chars->chars[0]); | |
2276 Bufbyte *old_addr = string_data (s); | |
2277 if (pos >= 0) | 2279 if (pos >= 0) |
2278 { | 2280 { |
2279 memcpy (new_addr, old_addr, pos); | 2281 memcpy (new_data, old_data, pos); |
2280 memcpy (new_addr + pos + delta, old_addr + pos, | 2282 memcpy (new_data + pos + delta, old_data + pos, |
2281 string_length (s) + 1 - pos); | 2283 string_length (s) + 1 - pos); |
2282 } | 2284 } |
2283 set_string_data (s, new_addr); | 2285 set_string_data (s, new_data); |
2284 if (BIG_STRING_FULLSIZE_P (oldfullsize)) | 2286 |
2285 xfree (old_addr); | 2287 { |
2286 else | 2288 /* We need to mark this chunk of the string_chars_block |
2287 { | 2289 as unused so that compact_string_chars() doesn't |
2288 /* We need to mark this chunk of the string_chars_block | 2290 freak. */ |
2289 as unused so that compact_string_chars() doesn't | 2291 struct string_chars *old_s_chars = (struct string_chars *) |
2290 freak. */ | 2292 ((char *) old_data - offsetof (struct string_chars, chars)); |
2291 struct string_chars *old_s_chars = | 2293 /* Sanity check to make sure we aren't hosed by strange |
2292 (struct string_chars *) ((char *) old_addr - | 2294 alignment/padding. */ |
2293 sizeof (struct Lisp_String *)); | 2295 assert (old_s_chars->string == s); |
2294 /* Sanity check to make sure we aren't hosed by strange | 2296 MARK_STRUCT_AS_FREE (old_s_chars); |
2295 alignment/padding. */ | 2297 ((struct unused_string_chars *) old_s_chars)->fullsize = |
2296 assert (old_s_chars->string == s); | 2298 oldfullsize; |
2297 MARK_STRUCT_AS_FREE (old_s_chars); | 2299 } |
2298 ((struct unused_string_chars *) old_s_chars)->fullsize = | |
2299 oldfullsize; | |
2300 } | |
2301 } | 2300 } |
2302 | 2301 } |
2303 set_string_length (s, string_length (s) + delta); | 2302 |
2304 /* If pos < 0, the string won't be zero-terminated. | 2303 set_string_length (s, string_length (s) + delta); |
2305 Terminate now just to make sure. */ | 2304 /* If pos < 0, the string won't be zero-terminated. |
2306 string_data (s)[string_length (s)] = '\0'; | 2305 Terminate now just to make sure. */ |
2307 | 2306 string_data (s)[string_length (s)] = '\0'; |
2308 if (pos >= 0) | 2307 |
2309 { | 2308 if (pos >= 0) |
2310 Lisp_Object string; | 2309 { |
2311 | 2310 Lisp_Object string; |
2312 XSETSTRING (string, s); | 2311 |
2313 /* We also have to adjust all of the extent indices after the | 2312 XSETSTRING (string, s); |
2314 place we did the change. We say "pos - 1" because | 2313 /* We also have to adjust all of the extent indices after the |
2315 adjust_extents() is exclusive of the starting position | 2314 place we did the change. We say "pos - 1" because |
2316 passed to it. */ | 2315 adjust_extents() is exclusive of the starting position |
2317 adjust_extents (string, pos - 1, string_length (s), | 2316 passed to it. */ |
2318 delta); | 2317 adjust_extents (string, pos - 1, string_length (s), |
2319 } | 2318 delta); |
2320 } | 2319 } |
2321 | 2320 |
2322 #ifdef VERIFY_STRING_CHARS_INTEGRITY | 2321 #ifdef VERIFY_STRING_CHARS_INTEGRITY |
2323 verify_string_chars_integrity (); | 2322 verify_string_chars_integrity (); |
2324 #endif | 2323 #endif |
4177 if (debug) debug_string_purity_print (p); \ | 4176 if (debug) debug_string_purity_print (p); \ |
4178 } while (0) | 4177 } while (0) |
4179 # define ADDITIONAL_FREE_string(p) \ | 4178 # define ADDITIONAL_FREE_string(p) \ |
4180 do { int size = string_length (p); \ | 4179 do { int size = string_length (p); \ |
4181 if (BIG_STRING_SIZE_P (size)) \ | 4180 if (BIG_STRING_SIZE_P (size)) \ |
4182 xfree_1 (CHARS_TO_STRING_CHAR (string_data (p))); \ | 4181 xfree (p->_data); \ |
4183 } while (0) | 4182 } while (0) |
4184 | 4183 |
4185 #else | 4184 #else |
4186 | 4185 |
4187 # define MARKED_string_P(ptr) XMARKBIT ((ptr)->plist) | 4186 # define MARKED_string_P(ptr) XMARKBIT ((ptr)->plist) |
4197 if (debug) debug_string_purity_print (p); \ | 4196 if (debug) debug_string_purity_print (p); \ |
4198 } while (0) | 4197 } while (0) |
4199 # define ADDITIONAL_FREE_string(p) \ | 4198 # define ADDITIONAL_FREE_string(p) \ |
4200 do { int size = string_length (p); \ | 4199 do { int size = string_length (p); \ |
4201 if (BIG_STRING_SIZE_P (size)) \ | 4200 if (BIG_STRING_SIZE_P (size)) \ |
4202 xfree_1 (CHARS_TO_STRING_CHAR (string_data (p))); \ | 4201 xfree (p->_data); \ |
4203 } while (0) | 4202 } while (0) |
4204 | 4203 |
4205 #endif /* ! LRECORD_STRING */ | 4204 #endif /* ! LRECORD_STRING */ |
4206 | 4205 |
4207 SWEEP_FIXED_TYPE_BLOCK (string, struct Lisp_String); | 4206 SWEEP_FIXED_TYPE_BLOCK (string, struct Lisp_String); |