diff options
| author | Gerd Moellmann | 2001-02-28 13:30:02 +0000 |
|---|---|---|
| committer | Gerd Moellmann | 2001-02-28 13:30:02 +0000 |
| commit | ece93c029103f1ec9c0801370afe260b791b008e (patch) | |
| tree | c786ed199e24550bd8c6be2eec1ec311a91def97 /src/alloc.c | |
| parent | 98423852fcb3050bdf43c67f383f9a94ac7d1b86 (diff) | |
| download | emacs-ece93c029103f1ec9c0801370afe260b791b008e.tar.gz emacs-ece93c029103f1ec9c0801370afe260b791b008e.zip | |
(toplevel): Include process.h.
(enum mem_type): Add MEM_TYPE_PROCESS, MEM_TYPE_HASH_TABLE,
MEM_TYPE_FRAME, MEM_TYPE_WINDOW enumerators.
(allocate_vectorlike): Make it a static function. Add parameter TYPE.
(allocate_vector, allocate_hash_table, allocate_window)
(allocate_frame, allocate_process, allocate_other_vector): New
functions.
(Fmake_vector): Call allocate_vector instead of allocate_vectorlike.
(mark_maybe_pointer): New function.
(mark_memory): Also mark Lisp data to which only pointers
remain and not Lisp_Objects.
(min_heap_address, max_heap_address): New variables.
(mem_find): Return MEM_NIL if START is below min_heap_address or
above max_heap_address.
(mem_insert): Compute min_heap_address and max_heap_address.
Diffstat (limited to 'src/alloc.c')
| -rw-r--r-- | src/alloc.c | 261 |
1 files changed, 252 insertions, 9 deletions
diff --git a/src/alloc.c b/src/alloc.c index 4affa42e683..4b473225f5c 100644 --- a/src/alloc.c +++ b/src/alloc.c | |||
| @@ -39,6 +39,7 @@ Boston, MA 02111-1307, USA. */ | |||
| 39 | 39 | ||
| 40 | #undef HIDE_LISP_IMPLEMENTATION | 40 | #undef HIDE_LISP_IMPLEMENTATION |
| 41 | #include "lisp.h" | 41 | #include "lisp.h" |
| 42 | #include "process.h" | ||
| 42 | #include "intervals.h" | 43 | #include "intervals.h" |
| 43 | #include "puresize.h" | 44 | #include "puresize.h" |
| 44 | #include "buffer.h" | 45 | #include "buffer.h" |
| @@ -276,7 +277,14 @@ enum mem_type | |||
| 276 | MEM_TYPE_MISC, | 277 | MEM_TYPE_MISC, |
| 277 | MEM_TYPE_SYMBOL, | 278 | MEM_TYPE_SYMBOL, |
| 278 | MEM_TYPE_FLOAT, | 279 | MEM_TYPE_FLOAT, |
| 279 | MEM_TYPE_VECTOR | 280 | /* Keep the following vector-like types together, with |
| 281 | MEM_TYPE_WINDOW being the last, and MEM_TYPE_VECTOR the | ||
| 282 | first. Or change the code of live_vector_p, for instance. */ | ||
| 283 | MEM_TYPE_VECTOR, | ||
| 284 | MEM_TYPE_PROCESS, | ||
| 285 | MEM_TYPE_HASH_TABLE, | ||
| 286 | MEM_TYPE_FRAME, | ||
| 287 | MEM_TYPE_WINDOW | ||
| 280 | }; | 288 | }; |
| 281 | 289 | ||
| 282 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK | 290 | #if GC_MARK_STACK || defined GC_MALLOC_CHECK |
| @@ -343,12 +351,17 @@ Lisp_Object *stack_base; | |||
| 343 | 351 | ||
| 344 | static struct mem_node *mem_root; | 352 | static struct mem_node *mem_root; |
| 345 | 353 | ||
| 354 | /* Lowest and highest known address in the heap. */ | ||
| 355 | |||
| 356 | static void *min_heap_address, *max_heap_address; | ||
| 357 | |||
| 346 | /* Sentinel node of the tree. */ | 358 | /* Sentinel node of the tree. */ |
| 347 | 359 | ||
| 348 | static struct mem_node mem_z; | 360 | static struct mem_node mem_z; |
| 349 | #define MEM_NIL &mem_z | 361 | #define MEM_NIL &mem_z |
| 350 | 362 | ||
| 351 | static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type)); | 363 | static POINTER_TYPE *lisp_malloc P_ ((size_t, enum mem_type)); |
| 364 | static struct Lisp_Vector *allocate_vectorlike P_ ((EMACS_INT, enum mem_type)); | ||
| 352 | static void lisp_free P_ ((POINTER_TYPE *)); | 365 | static void lisp_free P_ ((POINTER_TYPE *)); |
| 353 | static void mark_stack P_ ((void)); | 366 | static void mark_stack P_ ((void)); |
| 354 | static void init_stack P_ ((Lisp_Object *)); | 367 | static void init_stack P_ ((Lisp_Object *)); |
| @@ -398,6 +411,7 @@ static POINTER_TYPE *pure_alloc P_ ((size_t, int)); | |||
| 398 | #define ALIGN(SZ, ALIGNMENT) \ | 411 | #define ALIGN(SZ, ALIGNMENT) \ |
| 399 | (((SZ) + (ALIGNMENT) - 1) & ~((ALIGNMENT) - 1)) | 412 | (((SZ) + (ALIGNMENT) - 1) & ~((ALIGNMENT) - 1)) |
| 400 | 413 | ||
| 414 | |||
| 401 | 415 | ||
| 402 | /************************************************************************ | 416 | /************************************************************************ |
| 403 | Malloc | 417 | Malloc |
| @@ -2195,9 +2209,10 @@ int n_vectors; | |||
| 2195 | /* Value is a pointer to a newly allocated Lisp_Vector structure | 2209 | /* Value is a pointer to a newly allocated Lisp_Vector structure |
| 2196 | with room for LEN Lisp_Objects. */ | 2210 | with room for LEN Lisp_Objects. */ |
| 2197 | 2211 | ||
| 2198 | struct Lisp_Vector * | 2212 | static struct Lisp_Vector * |
| 2199 | allocate_vectorlike (len) | 2213 | allocate_vectorlike (len, type) |
| 2200 | EMACS_INT len; | 2214 | EMACS_INT len; |
| 2215 | enum mem_type type; | ||
| 2201 | { | 2216 | { |
| 2202 | struct Lisp_Vector *p; | 2217 | struct Lisp_Vector *p; |
| 2203 | size_t nbytes; | 2218 | size_t nbytes; |
| @@ -2210,7 +2225,7 @@ allocate_vectorlike (len) | |||
| 2210 | #endif | 2225 | #endif |
| 2211 | 2226 | ||
| 2212 | nbytes = sizeof *p + (len - 1) * sizeof p->contents[0]; | 2227 | nbytes = sizeof *p + (len - 1) * sizeof p->contents[0]; |
| 2213 | p = (struct Lisp_Vector *) lisp_malloc (nbytes, MEM_TYPE_VECTOR); | 2228 | p = (struct Lisp_Vector *) lisp_malloc (nbytes, type); |
| 2214 | 2229 | ||
| 2215 | #ifdef DOUG_LEA_MALLOC | 2230 | #ifdef DOUG_LEA_MALLOC |
| 2216 | /* Back to a reasonable maximum of mmap'ed areas. */ | 2231 | /* Back to a reasonable maximum of mmap'ed areas. */ |
| @@ -2228,6 +2243,94 @@ allocate_vectorlike (len) | |||
| 2228 | } | 2243 | } |
| 2229 | 2244 | ||
| 2230 | 2245 | ||
| 2246 | /* Allocate a vector with NSLOTS slots. */ | ||
| 2247 | |||
| 2248 | struct Lisp_Vector * | ||
| 2249 | allocate_vector (nslots) | ||
| 2250 | EMACS_INT nslots; | ||
| 2251 | { | ||
| 2252 | struct Lisp_Vector *v = allocate_vectorlike (nslots, MEM_TYPE_VECTOR); | ||
| 2253 | v->size = nslots; | ||
| 2254 | return v; | ||
| 2255 | } | ||
| 2256 | |||
| 2257 | |||
| 2258 | /* Allocate other vector-like structures. */ | ||
| 2259 | |||
| 2260 | struct Lisp_Hash_Table * | ||
| 2261 | allocate_hash_table () | ||
| 2262 | { | ||
| 2263 | EMACS_INT len = VECSIZE (struct Lisp_Hash_Table); | ||
| 2264 | struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_HASH_TABLE); | ||
| 2265 | EMACS_INT i; | ||
| 2266 | |||
| 2267 | v->size = len; | ||
| 2268 | for (i = 0; i < len; ++i) | ||
| 2269 | v->contents[i] = Qnil; | ||
| 2270 | |||
| 2271 | return (struct Lisp_Hash_Table *) v; | ||
| 2272 | } | ||
| 2273 | |||
| 2274 | |||
| 2275 | struct window * | ||
| 2276 | allocate_window () | ||
| 2277 | { | ||
| 2278 | EMACS_INT len = VECSIZE (struct window); | ||
| 2279 | struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_WINDOW); | ||
| 2280 | EMACS_INT i; | ||
| 2281 | |||
| 2282 | for (i = 0; i < len; ++i) | ||
| 2283 | v->contents[i] = Qnil; | ||
| 2284 | v->size = len; | ||
| 2285 | |||
| 2286 | return (struct window *) v; | ||
| 2287 | } | ||
| 2288 | |||
| 2289 | |||
| 2290 | struct frame * | ||
| 2291 | allocate_frame () | ||
| 2292 | { | ||
| 2293 | EMACS_INT len = VECSIZE (struct frame); | ||
| 2294 | struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_FRAME); | ||
| 2295 | EMACS_INT i; | ||
| 2296 | |||
| 2297 | for (i = 0; i < len; ++i) | ||
| 2298 | v->contents[i] = make_number (0); | ||
| 2299 | v->size = len; | ||
| 2300 | return (struct frame *) v; | ||
| 2301 | } | ||
| 2302 | |||
| 2303 | |||
| 2304 | struct Lisp_Process * | ||
| 2305 | allocate_process () | ||
| 2306 | { | ||
| 2307 | EMACS_INT len = VECSIZE (struct Lisp_Process); | ||
| 2308 | struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_PROCESS); | ||
| 2309 | EMACS_INT i; | ||
| 2310 | |||
| 2311 | for (i = 0; i < len; ++i) | ||
| 2312 | v->contents[i] = Qnil; | ||
| 2313 | v->size = len; | ||
| 2314 | |||
| 2315 | return (struct Lisp_Process *) v; | ||
| 2316 | } | ||
| 2317 | |||
| 2318 | |||
| 2319 | struct Lisp_Vector * | ||
| 2320 | allocate_other_vector (len) | ||
| 2321 | EMACS_INT len; | ||
| 2322 | { | ||
| 2323 | struct Lisp_Vector *v = allocate_vectorlike (len, MEM_TYPE_VECTOR); | ||
| 2324 | EMACS_INT i; | ||
| 2325 | |||
| 2326 | for (i = 0; i < len; ++i) | ||
| 2327 | v->contents[i] = Qnil; | ||
| 2328 | v->size = len; | ||
| 2329 | |||
| 2330 | return v; | ||
| 2331 | } | ||
| 2332 | |||
| 2333 | |||
| 2231 | DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, | 2334 | DEFUN ("make-vector", Fmake_vector, Smake_vector, 2, 2, 0, |
| 2232 | "Return a newly created vector of length LENGTH, with each element being INIT.\n\ | 2335 | "Return a newly created vector of length LENGTH, with each element being INIT.\n\ |
| 2233 | See also the function `vector'.") | 2336 | See also the function `vector'.") |
| @@ -2242,8 +2345,7 @@ See also the function `vector'.") | |||
| 2242 | CHECK_NATNUM (length, 0); | 2345 | CHECK_NATNUM (length, 0); |
| 2243 | sizei = XFASTINT (length); | 2346 | sizei = XFASTINT (length); |
| 2244 | 2347 | ||
| 2245 | p = allocate_vectorlike (sizei); | 2348 | p = allocate_vector (sizei); |
| 2246 | p->size = sizei; | ||
| 2247 | for (index = 0; index < sizei; index++) | 2349 | for (index = 0; index < sizei; index++) |
| 2248 | p->contents[index] = init; | 2350 | p->contents[index] = init; |
| 2249 | 2351 | ||
| @@ -2622,6 +2724,9 @@ mem_find (start) | |||
| 2622 | { | 2724 | { |
| 2623 | struct mem_node *p; | 2725 | struct mem_node *p; |
| 2624 | 2726 | ||
| 2727 | if (start < min_heap_address || start > max_heap_address) | ||
| 2728 | return MEM_NIL; | ||
| 2729 | |||
| 2625 | /* Make the search always successful to speed up the loop below. */ | 2730 | /* Make the search always successful to speed up the loop below. */ |
| 2626 | mem_z.start = start; | 2731 | mem_z.start = start; |
| 2627 | mem_z.end = (char *) start + 1; | 2732 | mem_z.end = (char *) start + 1; |
| @@ -2644,6 +2749,11 @@ mem_insert (start, end, type) | |||
| 2644 | { | 2749 | { |
| 2645 | struct mem_node *c, *parent, *x; | 2750 | struct mem_node *c, *parent, *x; |
| 2646 | 2751 | ||
| 2752 | if (start < min_heap_address) | ||
| 2753 | min_heap_address = start; | ||
| 2754 | if (end > max_heap_address) | ||
| 2755 | max_heap_address = end; | ||
| 2756 | |||
| 2647 | /* See where in the tree a node for START belongs. In this | 2757 | /* See where in the tree a node for START belongs. In this |
| 2648 | particular application, it shouldn't happen that a node is already | 2758 | particular application, it shouldn't happen that a node is already |
| 2649 | present. For debugging purposes, let's check that. */ | 2759 | present. For debugging purposes, let's check that. */ |
| @@ -3124,7 +3234,9 @@ live_vector_p (m, p) | |||
| 3124 | struct mem_node *m; | 3234 | struct mem_node *m; |
| 3125 | void *p; | 3235 | void *p; |
| 3126 | { | 3236 | { |
| 3127 | return m->type == MEM_TYPE_VECTOR && p == m->start; | 3237 | return (p == m->start |
| 3238 | && m->type >= MEM_TYPE_VECTOR | ||
| 3239 | && m->type <= MEM_TYPE_WINDOW); | ||
| 3128 | } | 3240 | } |
| 3129 | 3241 | ||
| 3130 | 3242 | ||
| @@ -3276,14 +3388,123 @@ mark_maybe_object (obj) | |||
| 3276 | } | 3388 | } |
| 3277 | } | 3389 | } |
| 3278 | } | 3390 | } |
| 3391 | |||
| 3392 | |||
| 3393 | /* If P points to Lisp data, mark that as live if it isn't already | ||
| 3394 | marked. */ | ||
| 3395 | |||
| 3396 | static INLINE void | ||
| 3397 | mark_maybe_pointer (p) | ||
| 3398 | void *p; | ||
| 3399 | { | ||
| 3400 | struct mem_node *m; | ||
| 3401 | |||
| 3402 | /* Quickly rule out some values which can't point to Lisp data. We | ||
| 3403 | assume that Lisp data is aligned on even addresses. */ | ||
| 3404 | if ((EMACS_INT) p & 1) | ||
| 3405 | return; | ||
| 3406 | |||
| 3407 | m = mem_find (p); | ||
| 3408 | if (m != MEM_NIL) | ||
| 3409 | { | ||
| 3410 | Lisp_Object obj = Qnil; | ||
| 3411 | |||
| 3412 | switch (m->type) | ||
| 3413 | { | ||
| 3414 | case MEM_TYPE_NON_LISP: | ||
| 3415 | /* NOthing to do; not a pointer to Lisp memory. */ | ||
| 3416 | break; | ||
| 3417 | |||
| 3418 | case MEM_TYPE_BUFFER: | ||
| 3419 | if (live_buffer_p (m, p) | ||
| 3420 | && !XMARKBIT (((struct buffer *) p)->name)) | ||
| 3421 | XSETVECTOR (obj, p); | ||
| 3422 | break; | ||
| 3423 | |||
| 3424 | case MEM_TYPE_CONS: | ||
| 3425 | if (live_cons_p (m, p) | ||
| 3426 | && !XMARKBIT (((struct Lisp_Cons *) p)->car)) | ||
| 3427 | XSETCONS (obj, p); | ||
| 3428 | break; | ||
| 3279 | 3429 | ||
| 3280 | /* Mark Lisp objects in the address range START..END. */ | 3430 | case MEM_TYPE_STRING: |
| 3431 | if (live_string_p (m, p) | ||
| 3432 | && !STRING_MARKED_P ((struct Lisp_String *) p)) | ||
| 3433 | XSETSTRING (obj, p); | ||
| 3434 | break; | ||
| 3435 | |||
| 3436 | case MEM_TYPE_MISC: | ||
| 3437 | if (live_misc_p (m, p)) | ||
| 3438 | { | ||
| 3439 | Lisp_Object tem; | ||
| 3440 | XSETMISC (tem, p); | ||
| 3441 | |||
| 3442 | switch (XMISCTYPE (tem)) | ||
| 3443 | { | ||
| 3444 | case Lisp_Misc_Marker: | ||
| 3445 | if (!XMARKBIT (XMARKER (tem)->chain)) | ||
| 3446 | obj = tem; | ||
| 3447 | break; | ||
| 3448 | |||
| 3449 | case Lisp_Misc_Buffer_Local_Value: | ||
| 3450 | case Lisp_Misc_Some_Buffer_Local_Value: | ||
| 3451 | if (!XMARKBIT (XBUFFER_LOCAL_VALUE (tem)->realvalue)) | ||
| 3452 | obj = tem; | ||
| 3453 | break; | ||
| 3454 | |||
| 3455 | case Lisp_Misc_Overlay: | ||
| 3456 | if (!XMARKBIT (XOVERLAY (tem)->plist)) | ||
| 3457 | obj = tem; | ||
| 3458 | break; | ||
| 3459 | } | ||
| 3460 | } | ||
| 3461 | break; | ||
| 3462 | |||
| 3463 | case MEM_TYPE_SYMBOL: | ||
| 3464 | if (live_symbol_p (m, p) | ||
| 3465 | && !XMARKBIT (((struct Lisp_Symbol *) p)->plist)) | ||
| 3466 | XSETSYMBOL (obj, p); | ||
| 3467 | break; | ||
| 3468 | |||
| 3469 | case MEM_TYPE_FLOAT: | ||
| 3470 | if (live_float_p (m, p) | ||
| 3471 | && !XMARKBIT (((struct Lisp_Float *) p)->type)) | ||
| 3472 | XSETFLOAT (obj, p); | ||
| 3473 | break; | ||
| 3474 | |||
| 3475 | case MEM_TYPE_VECTOR: | ||
| 3476 | case MEM_TYPE_PROCESS: | ||
| 3477 | case MEM_TYPE_HASH_TABLE: | ||
| 3478 | case MEM_TYPE_FRAME: | ||
| 3479 | case MEM_TYPE_WINDOW: | ||
| 3480 | if (live_vector_p (m, p)) | ||
| 3481 | { | ||
| 3482 | Lisp_Object tem; | ||
| 3483 | XSETVECTOR (tem, p); | ||
| 3484 | if (!GC_SUBRP (tem) | ||
| 3485 | && !(XVECTOR (tem)->size & ARRAY_MARK_FLAG)) | ||
| 3486 | obj = tem; | ||
| 3487 | } | ||
| 3488 | break; | ||
| 3489 | |||
| 3490 | default: | ||
| 3491 | abort (); | ||
| 3492 | } | ||
| 3493 | |||
| 3494 | if (!GC_NILP (obj)) | ||
| 3495 | mark_object (&obj); | ||
| 3496 | } | ||
| 3497 | } | ||
| 3498 | |||
| 3499 | |||
| 3500 | /* Mark Lisp objects referenced from the address range START..END. */ | ||
| 3281 | 3501 | ||
| 3282 | static void | 3502 | static void |
| 3283 | mark_memory (start, end) | 3503 | mark_memory (start, end) |
| 3284 | void *start, *end; | 3504 | void *start, *end; |
| 3285 | { | 3505 | { |
| 3286 | Lisp_Object *p; | 3506 | Lisp_Object *p; |
| 3507 | void **pp; | ||
| 3287 | 3508 | ||
| 3288 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES | 3509 | #if GC_MARK_STACK == GC_USE_GCPROS_CHECK_ZOMBIES |
| 3289 | nzombies = 0; | 3510 | nzombies = 0; |
| @@ -3297,9 +3518,31 @@ mark_memory (start, end) | |||
| 3297 | start = end; | 3518 | start = end; |
| 3298 | end = tem; | 3519 | end = tem; |
| 3299 | } | 3520 | } |
| 3300 | 3521 | ||
| 3522 | /* Mark Lisp_Objects. */ | ||
| 3301 | for (p = (Lisp_Object *) start; (void *) p < end; ++p) | 3523 | for (p = (Lisp_Object *) start; (void *) p < end; ++p) |
| 3302 | mark_maybe_object (*p); | 3524 | mark_maybe_object (*p); |
| 3525 | |||
| 3526 | /* Mark Lisp data pointed to. This is necessary because, in some | ||
| 3527 | situations, the C compiler optimizes Lisp objects away, so that | ||
| 3528 | only a pointer to them remains. Example: | ||
| 3529 | |||
| 3530 | DEFUN ("testme", Ftestme, Stestme, 0, 0, 0, "") | ||
| 3531 | () | ||
| 3532 | { | ||
| 3533 | Lisp_Object obj = build_string ("test"); | ||
| 3534 | struct Lisp_String *s = XSTRING (obj); | ||
| 3535 | Fgarbage_collect (); | ||
| 3536 | fprintf (stderr, "test `%s'\n", s->data); | ||
| 3537 | return Qnil; | ||
| 3538 | } | ||
| 3539 | |||
| 3540 | Here, `obj' isn't really used, and the compiler optimizes it | ||
| 3541 | away. The only reference to the life string is through the | ||
| 3542 | pointer `s'. */ | ||
| 3543 | |||
| 3544 | for (pp = (void **) start; (void *) pp < end; ++pp) | ||
| 3545 | mark_maybe_pointer (*pp); | ||
| 3303 | } | 3546 | } |
| 3304 | 3547 | ||
| 3305 | 3548 | ||