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;