Mercurial > emacs
comparison src/alloc.c @ 51938:20d4eb1de9b0
Use bitmaps for cons cells, as was done for floats.
(init_float, init_cons): Let the normal code allocate the first block.
(CONS_BLOCK_SIZE): Redefine based on BLOCK_BYTES and bitmap size.
(CONS_BLOCK, CONS_INDEX, CONS_MARKED_P, CONS_MARK, CONS_UNMARK): New macros.
(struct cons_block): Move conses to the beginning. Add gcmarkbits.
(Fcons): Use lisp_align_malloc and CONS_UNMARK.
(live_cons_p): Check the pointer is not past the `conses' array.
(mark_maybe_object, mark_maybe_pointer): Use CONS_MARKED_P.
(mark_object, mark_buffer): Use CONS_MARKED_P and CONS_MARK.
(survives_gc_p): Use CONS_MARKED_P and simplify.
(gc_sweep): Use CONS_MARKED_P, CONS_UNMARK, and lisp_align_free.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Tue, 15 Jul 2003 19:19:59 +0000 |
parents | cb3976b5e59f |
children | 111cc76606c6 |
comparison
equal
deleted
inserted
replaced
51937:2378c0aad975 | 51938:20d4eb1de9b0 |
---|---|
2181 /* Initialize float allocation. */ | 2181 /* Initialize float allocation. */ |
2182 | 2182 |
2183 void | 2183 void |
2184 init_float () | 2184 init_float () |
2185 { | 2185 { |
2186 float_block = (struct float_block *) lisp_align_malloc (sizeof *float_block, | 2186 float_block = NULL; |
2187 MEM_TYPE_FLOAT); | 2187 float_block_index = FLOAT_BLOCK_SIZE; /* Force alloc of new float_block. */ |
2188 float_block->next = 0; | |
2189 bzero ((char *) float_block->floats, sizeof float_block->floats); | |
2190 bzero ((char *) float_block->gcmarkbits, sizeof float_block->gcmarkbits); | |
2191 float_block_index = 0; | |
2192 float_free_list = 0; | 2188 float_free_list = 0; |
2193 n_float_blocks = 1; | 2189 n_float_blocks = 0; |
2194 } | 2190 } |
2195 | 2191 |
2196 | 2192 |
2197 /* Explicitly free a float cell by putting it on the free-list. */ | 2193 /* Explicitly free a float cell by putting it on the free-list. */ |
2198 | 2194 |
2250 ***********************************************************************/ | 2246 ***********************************************************************/ |
2251 | 2247 |
2252 /* We store cons cells inside of cons_blocks, allocating a new | 2248 /* We store cons cells inside of cons_blocks, allocating a new |
2253 cons_block with malloc whenever necessary. Cons cells reclaimed by | 2249 cons_block with malloc whenever necessary. Cons cells reclaimed by |
2254 GC are put on a free list to be reallocated before allocating | 2250 GC are put on a free list to be reallocated before allocating |
2255 any new cons cells from the latest cons_block. | 2251 any new cons cells from the latest cons_block. */ |
2256 | |
2257 Each cons_block is just under 1020 bytes long, | |
2258 since malloc really allocates in units of powers of two | |
2259 and uses 4 bytes for its own overhead. */ | |
2260 | 2252 |
2261 #define CONS_BLOCK_SIZE \ | 2253 #define CONS_BLOCK_SIZE \ |
2262 ((1020 - sizeof (struct cons_block *)) / sizeof (struct Lisp_Cons)) | 2254 (((BLOCK_BYTES - sizeof (struct cons_block *)) * CHAR_BIT) \ |
2255 / (sizeof (struct Lisp_Cons) * CHAR_BIT + 1)) | |
2256 | |
2257 #define CONS_BLOCK(fptr) \ | |
2258 ((struct cons_block *)(((EMACS_UINT)(fptr)) & ~(BLOCK_ALIGN - 1))) | |
2259 | |
2260 #define CONS_INDEX(fptr) \ | |
2261 ((((EMACS_UINT)(fptr)) & (BLOCK_ALIGN - 1)) / sizeof (struct Lisp_Cons)) | |
2263 | 2262 |
2264 struct cons_block | 2263 struct cons_block |
2265 { | 2264 { |
2265 /* Place `conses' at the beginning, to ease up CONS_INDEX's job. */ | |
2266 struct Lisp_Cons conses[CONS_BLOCK_SIZE]; | |
2267 int gcmarkbits[1 + CONS_BLOCK_SIZE / (sizeof(int) * CHAR_BIT)]; | |
2266 struct cons_block *next; | 2268 struct cons_block *next; |
2267 struct Lisp_Cons conses[CONS_BLOCK_SIZE]; | |
2268 }; | 2269 }; |
2270 | |
2271 #define CONS_MARKED_P(fptr) \ | |
2272 GETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr))) | |
2273 | |
2274 #define CONS_MARK(fptr) \ | |
2275 SETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr))) | |
2276 | |
2277 #define CONS_UNMARK(fptr) \ | |
2278 UNSETMARKBIT (CONS_BLOCK (fptr), CONS_INDEX ((fptr))) | |
2269 | 2279 |
2270 /* Current cons_block. */ | 2280 /* Current cons_block. */ |
2271 | 2281 |
2272 struct cons_block *cons_block; | 2282 struct cons_block *cons_block; |
2273 | 2283 |
2287 /* Initialize cons allocation. */ | 2297 /* Initialize cons allocation. */ |
2288 | 2298 |
2289 void | 2299 void |
2290 init_cons () | 2300 init_cons () |
2291 { | 2301 { |
2292 cons_block = (struct cons_block *) lisp_malloc (sizeof *cons_block, | 2302 cons_block = NULL; |
2293 MEM_TYPE_CONS); | 2303 cons_block_index = CONS_BLOCK_SIZE; /* Force alloc of new cons_block. */ |
2294 cons_block->next = 0; | |
2295 bzero ((char *) cons_block->conses, sizeof cons_block->conses); | |
2296 cons_block_index = 0; | |
2297 cons_free_list = 0; | 2304 cons_free_list = 0; |
2298 n_cons_blocks = 1; | 2305 n_cons_blocks = 0; |
2299 } | 2306 } |
2300 | 2307 |
2301 | 2308 |
2302 /* Explicitly free a cons cell by putting it on the free-list. */ | 2309 /* Explicitly free a cons cell by putting it on the free-list. */ |
2303 | 2310 |
2330 else | 2337 else |
2331 { | 2338 { |
2332 if (cons_block_index == CONS_BLOCK_SIZE) | 2339 if (cons_block_index == CONS_BLOCK_SIZE) |
2333 { | 2340 { |
2334 register struct cons_block *new; | 2341 register struct cons_block *new; |
2335 new = (struct cons_block *) lisp_malloc (sizeof *new, | 2342 new = (struct cons_block *) lisp_align_malloc (sizeof *new, |
2336 MEM_TYPE_CONS); | 2343 MEM_TYPE_CONS); |
2337 new->next = cons_block; | 2344 new->next = cons_block; |
2338 cons_block = new; | 2345 cons_block = new; |
2339 cons_block_index = 0; | 2346 cons_block_index = 0; |
2340 n_cons_blocks++; | 2347 n_cons_blocks++; |
2341 } | 2348 } |
2342 XSETCONS (val, &cons_block->conses[cons_block_index++]); | 2349 XSETCONS (val, &cons_block->conses[cons_block_index++]); |
2343 } | 2350 } |
2344 | 2351 |
2345 XSETCAR (val, car); | 2352 XSETCAR (val, car); |
2346 XSETCDR (val, cdr); | 2353 XSETCDR (val, cdr); |
2354 CONS_UNMARK (XCONS (val)); | |
2347 consing_since_gc += sizeof (struct Lisp_Cons); | 2355 consing_since_gc += sizeof (struct Lisp_Cons); |
2348 cons_cells_consed++; | 2356 cons_cells_consed++; |
2349 return val; | 2357 return val; |
2350 } | 2358 } |
2351 | 2359 |
3433 | 3441 |
3434 /* P must point to the start of a Lisp_Cons, not be | 3442 /* P must point to the start of a Lisp_Cons, not be |
3435 one of the unused cells in the current cons block, | 3443 one of the unused cells in the current cons block, |
3436 and not be on the free-list. */ | 3444 and not be on the free-list. */ |
3437 return (offset >= 0 | 3445 return (offset >= 0 |
3446 && offset < (CONS_BLOCK_SIZE * sizeof b->conses[0]) | |
3438 && offset % sizeof b->conses[0] == 0 | 3447 && offset % sizeof b->conses[0] == 0 |
3439 && (b != cons_block | 3448 && (b != cons_block |
3440 || offset / sizeof b->conses[0] < cons_block_index) | 3449 || offset / sizeof b->conses[0] < cons_block_index) |
3441 && !EQ (((struct Lisp_Cons *) p)->car, Vdead)); | 3450 && !EQ (((struct Lisp_Cons *) p)->car, Vdead)); |
3442 } | 3451 } |
3627 mark_p = (live_string_p (m, po) | 3636 mark_p = (live_string_p (m, po) |
3628 && !STRING_MARKED_P ((struct Lisp_String *) po)); | 3637 && !STRING_MARKED_P ((struct Lisp_String *) po)); |
3629 break; | 3638 break; |
3630 | 3639 |
3631 case Lisp_Cons: | 3640 case Lisp_Cons: |
3632 mark_p = (live_cons_p (m, po) | 3641 mark_p = (live_cons_p (m, po) && !CONS_MARKED_P (XCONS (obj))); |
3633 && !XMARKBIT (XCONS (obj)->car)); | |
3634 break; | 3642 break; |
3635 | 3643 |
3636 case Lisp_Symbol: | 3644 case Lisp_Symbol: |
3637 mark_p = (live_symbol_p (m, po) && !XSYMBOL (obj)->gcmarkbit); | 3645 mark_p = (live_symbol_p (m, po) && !XSYMBOL (obj)->gcmarkbit); |
3638 break; | 3646 break; |
3702 if (live_buffer_p (m, p) && !VECTOR_MARKED_P((struct buffer *)p)) | 3710 if (live_buffer_p (m, p) && !VECTOR_MARKED_P((struct buffer *)p)) |
3703 XSETVECTOR (obj, p); | 3711 XSETVECTOR (obj, p); |
3704 break; | 3712 break; |
3705 | 3713 |
3706 case MEM_TYPE_CONS: | 3714 case MEM_TYPE_CONS: |
3707 if (live_cons_p (m, p) | 3715 if (live_cons_p (m, p) && !CONS_MARKED_P ((struct Lisp_Cons *) p)) |
3708 && !XMARKBIT (((struct Lisp_Cons *) p)->car)) | |
3709 XSETCONS (obj, p); | 3716 XSETCONS (obj, p); |
3710 break; | 3717 break; |
3711 | 3718 |
3712 case MEM_TYPE_STRING: | 3719 case MEM_TYPE_STRING: |
3713 if (live_string_p (m, p) | 3720 if (live_string_p (m, p) |
4403 register struct gcpro *tail; | 4410 register struct gcpro *tail; |
4404 for (tail = gcprolist; tail; tail = tail->next) | 4411 for (tail = gcprolist; tail; tail = tail->next) |
4405 for (i = 0; i < tail->nvars; i++) | 4412 for (i = 0; i < tail->nvars; i++) |
4406 if (!XMARKBIT (tail->var[i])) | 4413 if (!XMARKBIT (tail->var[i])) |
4407 { | 4414 { |
4408 /* Explicit casting prevents compiler warning about | |
4409 discarding the `volatile' qualifier. */ | |
4410 mark_object (tail->var[i]); | 4415 mark_object (tail->var[i]); |
4411 XMARK (tail->var[i]); | 4416 XMARK (tail->var[i]); |
4412 } | 4417 } |
4413 } | 4418 } |
4414 #endif | 4419 #endif |
4415 | 4420 |
4416 mark_byte_stack (); | 4421 mark_byte_stack (); |
4417 for (bind = specpdl; bind != specpdl_ptr; bind++) | 4422 for (bind = specpdl; bind != specpdl_ptr; bind++) |
4418 { | 4423 { |
4419 /* These casts avoid a warning for discarding `volatile'. */ | |
4420 mark_object (bind->symbol); | 4424 mark_object (bind->symbol); |
4421 mark_object (bind->old_value); | 4425 mark_object (bind->old_value); |
4422 } | 4426 } |
4423 for (catch = catchlist; catch; catch = catch->next) | 4427 for (catch = catchlist; catch; catch = catch->next) |
4424 { | 4428 { |
5042 break; | 5046 break; |
5043 | 5047 |
5044 case Lisp_Cons: | 5048 case Lisp_Cons: |
5045 { | 5049 { |
5046 register struct Lisp_Cons *ptr = XCONS (obj); | 5050 register struct Lisp_Cons *ptr = XCONS (obj); |
5047 if (XMARKBIT (ptr->car)) break; | 5051 if (CONS_MARKED_P (ptr)) break; |
5048 CHECK_ALLOCATED_AND_LIVE (live_cons_p); | 5052 CHECK_ALLOCATED_AND_LIVE (live_cons_p); |
5049 XMARK (ptr->car); | 5053 CONS_MARK (ptr); |
5050 /* If the cdr is nil, avoid recursion for the car. */ | 5054 /* If the cdr is nil, avoid recursion for the car. */ |
5051 if (EQ (ptr->cdr, Qnil)) | 5055 if (EQ (ptr->cdr, Qnil)) |
5052 { | 5056 { |
5053 obj = ptr->car; | 5057 obj = ptr->car; |
5054 cdr_count = 0; | 5058 cdr_count = 0; |
5103 | 5107 |
5104 while (CONSP (tail)) | 5108 while (CONSP (tail)) |
5105 { | 5109 { |
5106 register struct Lisp_Cons *ptr = XCONS (tail); | 5110 register struct Lisp_Cons *ptr = XCONS (tail); |
5107 | 5111 |
5108 if (XMARKBIT (ptr->car)) | 5112 if (CONS_MARKED_P (ptr)) |
5109 break; | 5113 break; |
5110 XMARK (ptr->car); | 5114 CONS_MARK (ptr); |
5111 if (GC_CONSP (ptr->car) | 5115 if (GC_CONSP (ptr->car) |
5112 && ! XMARKBIT (XCAR (ptr->car)) | 5116 && !CONS_MARKED_P (XCONS (ptr->car)) |
5113 && GC_MARKERP (XCAR (ptr->car))) | 5117 && GC_MARKERP (XCAR (ptr->car))) |
5114 { | 5118 { |
5115 XMARK (XCAR_AS_LVALUE (ptr->car)); | 5119 CONS_MARK (XCONS (ptr->car)); |
5116 mark_object (XCDR (ptr->car)); | 5120 mark_object (XCDR (ptr->car)); |
5117 } | 5121 } |
5118 else | 5122 else |
5119 mark_object (ptr->car); | 5123 mark_object (ptr->car); |
5120 | 5124 |
5176 case Lisp_Misc: | 5180 case Lisp_Misc: |
5177 survives_p = XMARKER (obj)->gcmarkbit; | 5181 survives_p = XMARKER (obj)->gcmarkbit; |
5178 break; | 5182 break; |
5179 | 5183 |
5180 case Lisp_String: | 5184 case Lisp_String: |
5181 { | 5185 survives_p = STRING_MARKED_P (XSTRING (obj)); |
5182 struct Lisp_String *s = XSTRING (obj); | |
5183 survives_p = STRING_MARKED_P (s); | |
5184 } | |
5185 break; | 5186 break; |
5186 | 5187 |
5187 case Lisp_Vectorlike: | 5188 case Lisp_Vectorlike: |
5188 if (GC_BUFFERP (obj)) | 5189 survives_p = GC_SUBRP (obj) || VECTOR_MARKED_P (XVECTOR (obj)); |
5189 survives_p = VECTOR_MARKED_P (XBUFFER (obj)); | |
5190 else if (GC_SUBRP (obj)) | |
5191 survives_p = 1; | |
5192 else | |
5193 survives_p = VECTOR_MARKED_P (XVECTOR (obj)); | |
5194 break; | 5190 break; |
5195 | 5191 |
5196 case Lisp_Cons: | 5192 case Lisp_Cons: |
5197 survives_p = XMARKBIT (XCAR (obj)); | 5193 survives_p = CONS_MARKED_P (XCONS (obj)); |
5198 break; | 5194 break; |
5199 | 5195 |
5200 case Lisp_Float: | 5196 case Lisp_Float: |
5201 survives_p = FLOAT_MARKED_P (XFLOAT (obj)); | 5197 survives_p = FLOAT_MARKED_P (XFLOAT (obj)); |
5202 break; | 5198 break; |
5237 for (cblk = cons_block; cblk; cblk = *cprev) | 5233 for (cblk = cons_block; cblk; cblk = *cprev) |
5238 { | 5234 { |
5239 register int i; | 5235 register int i; |
5240 int this_free = 0; | 5236 int this_free = 0; |
5241 for (i = 0; i < lim; i++) | 5237 for (i = 0; i < lim; i++) |
5242 if (!XMARKBIT (cblk->conses[i].car)) | 5238 if (!CONS_MARKED_P (&cblk->conses[i])) |
5243 { | 5239 { |
5244 this_free++; | 5240 this_free++; |
5245 *(struct Lisp_Cons **)&cblk->conses[i].cdr = cons_free_list; | 5241 *(struct Lisp_Cons **)&cblk->conses[i].cdr = cons_free_list; |
5246 cons_free_list = &cblk->conses[i]; | 5242 cons_free_list = &cblk->conses[i]; |
5247 #if GC_MARK_STACK | 5243 #if GC_MARK_STACK |
5249 #endif | 5245 #endif |
5250 } | 5246 } |
5251 else | 5247 else |
5252 { | 5248 { |
5253 num_used++; | 5249 num_used++; |
5254 XUNMARK (cblk->conses[i].car); | 5250 CONS_UNMARK (&cblk->conses[i]); |
5255 } | 5251 } |
5256 lim = CONS_BLOCK_SIZE; | 5252 lim = CONS_BLOCK_SIZE; |
5257 /* If this block contains only free conses and we have already | 5253 /* If this block contains only free conses and we have already |
5258 seen more than two blocks worth of free conses then deallocate | 5254 seen more than two blocks worth of free conses then deallocate |
5259 this block. */ | 5255 this block. */ |
5260 if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE) | 5256 if (this_free == CONS_BLOCK_SIZE && num_free > CONS_BLOCK_SIZE) |
5261 { | 5257 { |
5262 *cprev = cblk->next; | 5258 *cprev = cblk->next; |
5263 /* Unhook from the free list. */ | 5259 /* Unhook from the free list. */ |
5264 cons_free_list = *(struct Lisp_Cons **) &cblk->conses[0].cdr; | 5260 cons_free_list = *(struct Lisp_Cons **) &cblk->conses[0].cdr; |
5265 lisp_free (cblk); | 5261 lisp_align_free (cblk); |
5266 n_cons_blocks--; | 5262 n_cons_blocks--; |
5267 } | 5263 } |
5268 else | 5264 else |
5269 { | 5265 { |
5270 num_free += this_free; | 5266 num_free += this_free; |