Mercurial > emacs
comparison src/alloc.c @ 32594:e0646c73bf81
(pure_bytes_used): Renamed from pureptr.
(ALIGN): New macro.
(pure_alloc): New function.
(make_pure_string, pure_cons, make_pure_float, make_pure_vector):
Use it.
(Fpurecopy): Use PURE_POINTER_P.
| author | Gerd Moellmann <gerd@gnu.org> |
|---|---|
| date | Tue, 17 Oct 2000 19:38:47 +0000 |
| parents | b3918817f15f |
| children | 350e0378e6f9 |
comparison
equal
deleted
inserted
replaced
| 32593:326836fbd4aa | 32594:e0646c73bf81 |
|---|---|
| 213 && ((PNTR_COMPARISON_TYPE) (P) \ | 213 && ((PNTR_COMPARISON_TYPE) (P) \ |
| 214 >= (PNTR_COMPARISON_TYPE) pure)) | 214 >= (PNTR_COMPARISON_TYPE) pure)) |
| 215 | 215 |
| 216 /* Index in pure at which next pure object will be allocated.. */ | 216 /* Index in pure at which next pure object will be allocated.. */ |
| 217 | 217 |
| 218 int pureptr; | 218 int pure_bytes_used; |
| 219 | 219 |
| 220 /* If nonzero, this is a warning delivered by malloc and not yet | 220 /* If nonzero, this is a warning delivered by malloc and not yet |
| 221 displayed. */ | 221 displayed. */ |
| 222 | 222 |
| 223 char *pending_malloc_warning; | 223 char *pending_malloc_warning; |
| 315 #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS | 315 #if GC_MARK_STACK == GC_MARK_STACK_CHECK_GCPROS |
| 316 static void check_gcpros P_ ((void)); | 316 static void check_gcpros P_ ((void)); |
| 317 #endif | 317 #endif |
| 318 | 318 |
| 319 #endif /* GC_MARK_STACK != 0 */ | 319 #endif /* GC_MARK_STACK != 0 */ |
| 320 | |
| 321 /* Recording what needs to be marked for gc. */ | |
| 322 | |
| 323 struct gcpro *gcprolist; | |
| 324 | |
| 325 /* Addresses of staticpro'd variables. */ | |
| 326 | |
| 327 #define NSTATICS 1024 | |
| 328 Lisp_Object *staticvec[NSTATICS] = {0}; | |
| 329 | |
| 330 /* Index of next unused slot in staticvec. */ | |
| 331 | |
| 332 int staticidx = 0; | |
| 333 | |
| 334 static POINTER_TYPE *pure_alloc P_ ((size_t, int)); | |
| 335 | |
| 336 | |
| 337 /* Value is SZ rounded up to the next multiple of ALIGNMENT. | |
| 338 ALIGNMENT must be a power of 2. */ | |
| 339 | |
| 340 #define ALIGN(SZ, ALIGNMENT) \ | |
| 341 (((SZ) + (ALIGNMENT) - 1) & ~((ALIGNMENT) - 1)) | |
| 320 | 342 |
| 321 | 343 |
| 322 /************************************************************************ | 344 /************************************************************************ |
| 323 Malloc | 345 Malloc |
| 324 ************************************************************************/ | 346 ************************************************************************/ |
| 3318 | 3340 |
| 3319 /*********************************************************************** | 3341 /*********************************************************************** |
| 3320 Pure Storage Management | 3342 Pure Storage Management |
| 3321 ***********************************************************************/ | 3343 ***********************************************************************/ |
| 3322 | 3344 |
| 3345 /* Allocate room for SIZE bytes from pure Lisp storage and return a | |
| 3346 pointer to it. TYPE is the Lisp type for which the memory is | |
| 3347 allocated. TYPE < 0 means it's not used for a Lisp object. | |
| 3348 | |
| 3349 If store_pure_type_info is set and TYPE is >= 0, the type of | |
| 3350 the allocated object is recorded in pure_types. */ | |
| 3351 | |
| 3352 static POINTER_TYPE * | |
| 3353 pure_alloc (size, type) | |
| 3354 size_t size; | |
| 3355 int type; | |
| 3356 { | |
| 3357 size_t nbytes; | |
| 3358 POINTER_TYPE *result; | |
| 3359 char *beg = PUREBEG; | |
| 3360 | |
| 3361 /* Give Lisp_Floats an extra alignment. */ | |
| 3362 if (type == Lisp_Float) | |
| 3363 { | |
| 3364 size_t alignment; | |
| 3365 #if defined __GNUC__ && __GNUC__ >= 2 | |
| 3366 alignment = __alignof (struct Lisp_Float); | |
| 3367 #else | |
| 3368 alignment = sizeof (struct Lisp_Float); | |
| 3369 #endif | |
| 3370 pure_bytes_used = ALIGN (pure_bytes_used, alignment); | |
| 3371 } | |
| 3372 | |
| 3373 nbytes = ALIGN (size, sizeof (EMACS_INT)); | |
| 3374 if (pure_bytes_used + nbytes > PURESIZE) | |
| 3375 error ("Pure Lisp storage exhausted"); | |
| 3376 | |
| 3377 result = (POINTER_TYPE *) (beg + pure_bytes_used); | |
| 3378 pure_bytes_used += nbytes; | |
| 3379 return result; | |
| 3380 } | |
| 3381 | |
| 3382 | |
| 3323 /* Return a string allocated in pure space. DATA is a buffer holding | 3383 /* Return a string allocated in pure space. DATA is a buffer holding |
| 3324 NCHARS characters, and NBYTES bytes of string data. MULTIBYTE | 3384 NCHARS characters, and NBYTES bytes of string data. MULTIBYTE |
| 3325 non-zero means make the result string multibyte. | 3385 non-zero means make the result string multibyte. |
| 3326 | 3386 |
| 3327 Must get an error if pure storage is full, since if it cannot hold | 3387 Must get an error if pure storage is full, since if it cannot hold |
| 3334 int nchars, nbytes; | 3394 int nchars, nbytes; |
| 3335 int multibyte; | 3395 int multibyte; |
| 3336 { | 3396 { |
| 3337 Lisp_Object string; | 3397 Lisp_Object string; |
| 3338 struct Lisp_String *s; | 3398 struct Lisp_String *s; |
| 3339 int string_size, data_size; | 3399 |
| 3340 | 3400 s = (struct Lisp_String *) pure_alloc (sizeof *s, Lisp_String); |
| 3341 #define PAD(SZ) (((SZ) + sizeof (EMACS_INT) - 1) & ~(sizeof (EMACS_INT) - 1)) | 3401 s->data = (unsigned char *) pure_alloc (nbytes + 1, -1); |
| 3342 | |
| 3343 string_size = PAD (sizeof (struct Lisp_String)); | |
| 3344 data_size = PAD (nbytes + 1); | |
| 3345 | |
| 3346 #undef PAD | |
| 3347 | |
| 3348 if (pureptr + string_size + data_size > PURESIZE) | |
| 3349 error ("Pure Lisp storage exhausted"); | |
| 3350 | |
| 3351 s = (struct Lisp_String *) (PUREBEG + pureptr); | |
| 3352 pureptr += string_size; | |
| 3353 s->data = (unsigned char *) (PUREBEG + pureptr); | |
| 3354 pureptr += data_size; | |
| 3355 | |
| 3356 s->size = nchars; | 3402 s->size = nchars; |
| 3357 s->size_byte = multibyte ? nbytes : -1; | 3403 s->size_byte = multibyte ? nbytes : -1; |
| 3358 bcopy (data, s->data, nbytes); | 3404 bcopy (data, s->data, nbytes); |
| 3359 s->data[nbytes] = '\0'; | 3405 s->data[nbytes] = '\0'; |
| 3360 s->intervals = NULL_INTERVAL; | 3406 s->intervals = NULL_INTERVAL; |
| 3361 | |
| 3362 XSETSTRING (string, s); | 3407 XSETSTRING (string, s); |
| 3363 return string; | 3408 return string; |
| 3364 } | 3409 } |
| 3365 | 3410 |
| 3366 | 3411 |
| 3370 Lisp_Object | 3415 Lisp_Object |
| 3371 pure_cons (car, cdr) | 3416 pure_cons (car, cdr) |
| 3372 Lisp_Object car, cdr; | 3417 Lisp_Object car, cdr; |
| 3373 { | 3418 { |
| 3374 register Lisp_Object new; | 3419 register Lisp_Object new; |
| 3375 | 3420 struct Lisp_Cons *p; |
| 3376 if (pureptr + sizeof (struct Lisp_Cons) > PURESIZE) | 3421 |
| 3377 error ("Pure Lisp storage exhausted"); | 3422 p = (struct Lisp_Cons *) pure_alloc (sizeof *p, Lisp_Cons); |
| 3378 XSETCONS (new, PUREBEG + pureptr); | 3423 XSETCONS (new, p); |
| 3379 pureptr += sizeof (struct Lisp_Cons); | |
| 3380 XCAR (new) = Fpurecopy (car); | 3424 XCAR (new) = Fpurecopy (car); |
| 3381 XCDR (new) = Fpurecopy (cdr); | 3425 XCDR (new) = Fpurecopy (cdr); |
| 3382 return new; | 3426 return new; |
| 3383 } | 3427 } |
| 3384 | 3428 |
| 3388 Lisp_Object | 3432 Lisp_Object |
| 3389 make_pure_float (num) | 3433 make_pure_float (num) |
| 3390 double num; | 3434 double num; |
| 3391 { | 3435 { |
| 3392 register Lisp_Object new; | 3436 register Lisp_Object new; |
| 3393 | 3437 struct Lisp_Float *p; |
| 3394 /* Make sure that PUREBEG + pureptr is aligned on at least a sizeof | 3438 |
| 3395 (double) boundary. Some architectures (like the sparc) require | 3439 p = (struct Lisp_Float *) pure_alloc (sizeof *p, Lisp_Float); |
| 3396 this, and I suspect that floats are rare enough that it's no | 3440 XSETFLOAT (new, p); |
| 3397 tragedy for those that do. */ | |
| 3398 { | |
| 3399 size_t alignment; | |
| 3400 char *p = PUREBEG + pureptr; | |
| 3401 | |
| 3402 #ifdef __GNUC__ | |
| 3403 #if __GNUC__ >= 2 | |
| 3404 alignment = __alignof (struct Lisp_Float); | |
| 3405 #else | |
| 3406 alignment = sizeof (struct Lisp_Float); | |
| 3407 #endif | |
| 3408 #else | |
| 3409 alignment = sizeof (struct Lisp_Float); | |
| 3410 #endif | |
| 3411 p = (char *) (((unsigned long) p + alignment - 1) & - alignment); | |
| 3412 pureptr = p - PUREBEG; | |
| 3413 } | |
| 3414 | |
| 3415 if (pureptr + sizeof (struct Lisp_Float) > PURESIZE) | |
| 3416 error ("Pure Lisp storage exhausted"); | |
| 3417 XSETFLOAT (new, PUREBEG + pureptr); | |
| 3418 pureptr += sizeof (struct Lisp_Float); | |
| 3419 XFLOAT_DATA (new) = num; | 3441 XFLOAT_DATA (new) = num; |
| 3420 XSETFASTINT (XFLOAT (new)->type, 0); /* bug chasing -wsr */ | |
| 3421 return new; | 3442 return new; |
| 3422 } | 3443 } |
| 3423 | 3444 |
| 3424 | 3445 |
| 3425 /* Return a vector with room for LEN Lisp_Objects allocated from | 3446 /* Return a vector with room for LEN Lisp_Objects allocated from |
| 3427 | 3448 |
| 3428 Lisp_Object | 3449 Lisp_Object |
| 3429 make_pure_vector (len) | 3450 make_pure_vector (len) |
| 3430 EMACS_INT len; | 3451 EMACS_INT len; |
| 3431 { | 3452 { |
| 3432 register Lisp_Object new; | 3453 Lisp_Object new; |
| 3433 register EMACS_INT size = (sizeof (struct Lisp_Vector) | 3454 struct Lisp_Vector *p; |
| 3434 + (len - 1) * sizeof (Lisp_Object)); | 3455 size_t size = sizeof *p + (len - 1) * sizeof (Lisp_Object); |
| 3435 | 3456 |
| 3436 if (pureptr + size > PURESIZE) | 3457 p = (struct Lisp_Vector *) pure_alloc (size, Lisp_Vectorlike); |
| 3437 error ("Pure Lisp storage exhausted"); | 3458 XSETVECTOR (new, p); |
| 3438 | |
| 3439 XSETVECTOR (new, PUREBEG + pureptr); | |
| 3440 pureptr += size; | |
| 3441 XVECTOR (new)->size = len; | 3459 XVECTOR (new)->size = len; |
| 3442 return new; | 3460 return new; |
| 3443 } | 3461 } |
| 3444 | 3462 |
| 3445 | 3463 |
| 3451 register Lisp_Object obj; | 3469 register Lisp_Object obj; |
| 3452 { | 3470 { |
| 3453 if (NILP (Vpurify_flag)) | 3471 if (NILP (Vpurify_flag)) |
| 3454 return obj; | 3472 return obj; |
| 3455 | 3473 |
| 3456 if ((PNTR_COMPARISON_TYPE) XPNTR (obj) < (PNTR_COMPARISON_TYPE) ((char *) pure + PURESIZE) | 3474 if (PURE_POINTER_P (XPNTR (obj))) |
| 3457 && (PNTR_COMPARISON_TYPE) XPNTR (obj) >= (PNTR_COMPARISON_TYPE) pure) | |
| 3458 return obj; | 3475 return obj; |
| 3459 | 3476 |
| 3460 if (CONSP (obj)) | 3477 if (CONSP (obj)) |
| 3461 return pure_cons (XCAR (obj), XCDR (obj)); | 3478 return pure_cons (XCAR (obj), XCDR (obj)); |
| 3462 else if (FLOATP (obj)) | 3479 else if (FLOATP (obj)) |
| 3491 | 3508 |
| 3492 | 3509 |
| 3493 /*********************************************************************** | 3510 /*********************************************************************** |
| 3494 Protection from GC | 3511 Protection from GC |
| 3495 ***********************************************************************/ | 3512 ***********************************************************************/ |
| 3496 | |
| 3497 /* Recording what needs to be marked for gc. */ | |
| 3498 | |
| 3499 struct gcpro *gcprolist; | |
| 3500 | |
| 3501 /* Addresses of staticpro'd variables. */ | |
| 3502 | |
| 3503 #define NSTATICS 1024 | |
| 3504 Lisp_Object *staticvec[NSTATICS] = {0}; | |
| 3505 | |
| 3506 /* Index of next unused slot in staticvec. */ | |
| 3507 | |
| 3508 int staticidx = 0; | |
| 3509 | |
| 3510 | 3513 |
| 3511 /* Put an entry in staticvec, pointing at the variable with address | 3514 /* Put an entry in staticvec, pointing at the variable with address |
| 3512 VARADDRESS. */ | 3515 VARADDRESS. */ |
| 3513 | 3516 |
| 3514 void | 3517 void |
| 3931 loop: | 3934 loop: |
| 3932 obj = *objptr; | 3935 obj = *objptr; |
| 3933 loop2: | 3936 loop2: |
| 3934 XUNMARK (obj); | 3937 XUNMARK (obj); |
| 3935 | 3938 |
| 3936 if (PURE_POINTER_P ((PNTR_COMPARISON_TYPE) XPNTR (obj))) | 3939 if (PURE_POINTER_P (XPNTR (obj))) |
| 3937 return; | 3940 return; |
| 3938 | 3941 |
| 3939 last_marked[last_marked_index++] = objptr; | 3942 last_marked[last_marked_index++] = objptr; |
| 3940 if (last_marked_index == LAST_MARKED_SIZE) | 3943 if (last_marked_index == LAST_MARKED_SIZE) |
| 3941 last_marked_index = 0; | 3944 last_marked_index = 0; |
| 4901 | 4904 |
| 4902 void | 4905 void |
| 4903 init_alloc_once () | 4906 init_alloc_once () |
| 4904 { | 4907 { |
| 4905 /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ | 4908 /* Used to do Vpurify_flag = Qt here, but Qt isn't set up yet! */ |
| 4906 pureptr = 0; | 4909 pure_bytes_used = 0; |
| 4907 #if GC_MARK_STACK | 4910 #if GC_MARK_STACK |
| 4908 mem_init (); | 4911 mem_init (); |
| 4909 Vdead = make_pure_string ("DEAD", 4, 4, 0); | 4912 Vdead = make_pure_string ("DEAD", 4, 4, 0); |
| 4910 #endif | 4913 #endif |
| 4911 #ifdef HAVE_SHM | 4914 #ifdef HAVE_SHM |
| 4966 allocated since the last garbage collection. All data types count.\n\n\ | 4969 allocated since the last garbage collection. All data types count.\n\n\ |
| 4967 Garbage collection happens automatically only when `eval' is called.\n\n\ | 4970 Garbage collection happens automatically only when `eval' is called.\n\n\ |
| 4968 By binding this temporarily to a large number, you can effectively\n\ | 4971 By binding this temporarily to a large number, you can effectively\n\ |
| 4969 prevent garbage collection during a part of the program."); | 4972 prevent garbage collection during a part of the program."); |
| 4970 | 4973 |
| 4971 DEFVAR_INT ("pure-bytes-used", &pureptr, | 4974 DEFVAR_INT ("pure-bytes-used", &pure_bytes_used, |
| 4972 "Number of bytes of sharable Lisp data allocated so far."); | 4975 "Number of bytes of sharable Lisp data allocated so far."); |
| 4973 | 4976 |
| 4974 DEFVAR_INT ("cons-cells-consed", &cons_cells_consed, | 4977 DEFVAR_INT ("cons-cells-consed", &cons_cells_consed, |
| 4975 "Number of cons cells that have been consed so far."); | 4978 "Number of cons cells that have been consed so far."); |
| 4976 | 4979 |
