Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 400:a86b2b5e0111 r21-2-30
Import from CVS: tag r21-2-30
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:14:34 +0200 |
parents | 74fd4e045ea6 |
children | 2f8bb876ab1d |
comparison
equal
deleted
inserted
replaced
399:376370fb5946 | 400:a86b2b5e0111 |
---|---|
381 void * | 381 void * |
382 alloc_lcrecord (size_t size, const struct lrecord_implementation *implementation) | 382 alloc_lcrecord (size_t size, const struct lrecord_implementation *implementation) |
383 { | 383 { |
384 struct lcrecord_header *lcheader; | 384 struct lcrecord_header *lcheader; |
385 | 385 |
386 #ifdef ERROR_CHECK_TYPECHECK | 386 type_checking_assert |
387 if (implementation->static_size == 0) | 387 ((implementation->static_size == 0 ? |
388 assert (implementation->size_in_bytes_method); | 388 implementation->size_in_bytes_method != NULL : |
389 else | 389 implementation->static_size == size) |
390 assert (implementation->static_size == size); | 390 && |
391 | 391 (! implementation->basic_p) |
392 assert (! implementation->basic_p); | 392 && |
393 | 393 (! (implementation->hash == NULL && implementation->equal != NULL))); |
394 if (implementation->hash == NULL) | |
395 assert (implementation->equal == NULL); | |
396 #endif | |
397 | 394 |
398 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); | 395 lcheader = (struct lcrecord_header *) allocate_lisp_storage (size); |
399 set_lheader_implementation (&(lcheader->lheader), implementation); | 396 set_lheader_implementation (&(lcheader->lheader), implementation); |
400 lcheader->next = all_lcrecords; | 397 lcheader->next = all_lcrecords; |
401 #if 1 /* mly prefers to see small ID numbers */ | 398 #if 1 /* mly prefers to see small ID numbers */ |
453 { | 450 { |
454 struct lcrecord_header *header; | 451 struct lcrecord_header *header; |
455 | 452 |
456 for (header = all_lcrecords; header; header = header->next) | 453 for (header = all_lcrecords; header; header = header->next) |
457 { | 454 { |
458 if (LHEADER_IMPLEMENTATION(&header->lheader)->finalizer && | 455 if (LHEADER_IMPLEMENTATION (&header->lheader)->finalizer && |
459 !header->free) | 456 !header->free) |
460 ((LHEADER_IMPLEMENTATION(&header->lheader)->finalizer) | 457 LHEADER_IMPLEMENTATION (&header->lheader)->finalizer (header, 1); |
461 (header, 1)); | 458 } |
462 } | |
463 } | |
464 | |
465 /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck | |
466 in const space and you get SEGV's if you attempt to mark them. | |
467 This sits in lheader->implementation->marker. */ | |
468 | |
469 Lisp_Object | |
470 this_one_is_unmarkable (Lisp_Object obj) | |
471 { | |
472 abort (); | |
473 return Qnil; | |
474 } | 459 } |
475 | 460 |
476 | 461 |
477 /************************************************************************/ | 462 /************************************************************************/ |
478 /* Debugger support */ | 463 /* Debugger support */ |
487 | 472 |
488 #ifdef USE_UNION_TYPE | 473 #ifdef USE_UNION_TYPE |
489 unsigned char dbg_USE_UNION_TYPE = 1; | 474 unsigned char dbg_USE_UNION_TYPE = 1; |
490 #else | 475 #else |
491 unsigned char dbg_USE_UNION_TYPE = 0; | 476 unsigned char dbg_USE_UNION_TYPE = 0; |
492 #endif | |
493 | |
494 unsigned char Lisp_Type_Int = 100; | |
495 unsigned char Lisp_Type_Cons = 101; | |
496 unsigned char Lisp_Type_String = 102; | |
497 unsigned char Lisp_Type_Vector = 103; | |
498 unsigned char Lisp_Type_Symbol = 104; | |
499 | |
500 #ifndef MULE | |
501 unsigned char lrecord_char_table_entry; | |
502 unsigned char lrecord_charset; | |
503 #ifndef FILE_CODING | |
504 unsigned char lrecord_coding_system; | |
505 #endif | |
506 #endif | |
507 | |
508 #if !((defined HAVE_X_WINDOWS) && \ | |
509 (defined (HAVE_MENUBARS) || \ | |
510 defined (HAVE_SCROLLBARS) || \ | |
511 defined (HAVE_DIALOGS) || \ | |
512 defined (HAVE_TOOLBARS) || \ | |
513 defined (HAVE_WIDGETS))) | |
514 unsigned char lrecord_popup_data; | |
515 #endif | |
516 | |
517 #ifndef HAVE_TOOLBARS | |
518 unsigned char lrecord_toolbar_button; | |
519 #endif | |
520 | |
521 #ifndef TOOLTALK | |
522 unsigned char lrecord_tooltalk_message; | |
523 unsigned char lrecord_tooltalk_pattern; | |
524 #endif | |
525 | |
526 #ifndef HAVE_DATABASE | |
527 unsigned char lrecord_database; | |
528 #endif | 477 #endif |
529 | 478 |
530 unsigned char dbg_valbits = VALBITS; | 479 unsigned char dbg_valbits = VALBITS; |
531 unsigned char dbg_gctypebits = GCTYPEBITS; | 480 unsigned char dbg_gctypebits = GCTYPEBITS; |
532 | 481 |
2270 { | 2219 { |
2271 struct lrecord_header *lheader = XRECORD_LHEADER (chain); | 2220 struct lrecord_header *lheader = XRECORD_LHEADER (chain); |
2272 struct free_lcrecord_header *free_header = | 2221 struct free_lcrecord_header *free_header = |
2273 (struct free_lcrecord_header *) lheader; | 2222 (struct free_lcrecord_header *) lheader; |
2274 | 2223 |
2275 #ifdef ERROR_CHECK_GC | 2224 gc_checking_assert |
2276 const struct lrecord_implementation *implementation | 2225 (/* There should be no other pointers to the free list. */ |
2277 = LHEADER_IMPLEMENTATION(lheader); | 2226 ! MARKED_RECORD_HEADER_P (lheader) |
2278 | 2227 && |
2279 /* There should be no other pointers to the free list. */ | 2228 /* Only lcrecords should be here. */ |
2280 assert (!MARKED_RECORD_HEADER_P (lheader)); | 2229 ! LHEADER_IMPLEMENTATION (lheader)->basic_p |
2281 /* Only lcrecords should be here. */ | 2230 && |
2282 assert (!implementation->basic_p); | 2231 /* Only free lcrecords should be here. */ |
2283 /* Only free lcrecords should be here. */ | 2232 free_header->lcheader.free |
2284 assert (free_header->lcheader.free); | 2233 && |
2285 /* The type of the lcrecord must be right. */ | 2234 /* The type of the lcrecord must be right. */ |
2286 assert (implementation == list->implementation); | 2235 LHEADER_IMPLEMENTATION (lheader) == list->implementation |
2287 /* So must the size. */ | 2236 && |
2288 assert (implementation->static_size == 0 | 2237 /* So must the size. */ |
2289 || implementation->static_size == list->size); | 2238 (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 || |
2290 #endif /* ERROR_CHECK_GC */ | 2239 LHEADER_IMPLEMENTATION (lheader)->static_size == list->size) |
2240 ); | |
2291 | 2241 |
2292 MARK_RECORD_HEADER (lheader); | 2242 MARK_RECORD_HEADER (lheader); |
2293 chain = free_header->chain; | 2243 chain = free_header->chain; |
2294 } | 2244 } |
2295 | 2245 |
2323 Lisp_Object val = list->free; | 2273 Lisp_Object val = list->free; |
2324 struct free_lcrecord_header *free_header = | 2274 struct free_lcrecord_header *free_header = |
2325 (struct free_lcrecord_header *) XPNTR (val); | 2275 (struct free_lcrecord_header *) XPNTR (val); |
2326 | 2276 |
2327 #ifdef ERROR_CHECK_GC | 2277 #ifdef ERROR_CHECK_GC |
2328 struct lrecord_header *lheader = | 2278 struct lrecord_header *lheader = &free_header->lcheader.lheader; |
2329 (struct lrecord_header *) free_header; | |
2330 const struct lrecord_implementation *implementation | |
2331 = LHEADER_IMPLEMENTATION (lheader); | |
2332 | 2279 |
2333 /* There should be no other pointers to the free list. */ | 2280 /* There should be no other pointers to the free list. */ |
2334 assert (!MARKED_RECORD_HEADER_P (lheader)); | 2281 assert (! MARKED_RECORD_HEADER_P (lheader)); |
2335 /* Only lcrecords should be here. */ | 2282 /* Only lcrecords should be here. */ |
2336 assert (!implementation->basic_p); | 2283 assert (! LHEADER_IMPLEMENTATION (lheader)->basic_p); |
2337 /* Only free lcrecords should be here. */ | 2284 /* Only free lcrecords should be here. */ |
2338 assert (free_header->lcheader.free); | 2285 assert (free_header->lcheader.free); |
2339 /* The type of the lcrecord must be right. */ | 2286 /* The type of the lcrecord must be right. */ |
2340 assert (implementation == list->implementation); | 2287 assert (LHEADER_IMPLEMENTATION (lheader) == list->implementation); |
2341 /* So must the size. */ | 2288 /* So must the size. */ |
2342 assert (implementation->static_size == 0 | 2289 assert (LHEADER_IMPLEMENTATION (lheader)->static_size == 0 || |
2343 || implementation->static_size == list->size); | 2290 LHEADER_IMPLEMENTATION (lheader)->static_size == list->size); |
2344 #endif /* ERROR_CHECK_GC */ | 2291 #endif /* ERROR_CHECK_GC */ |
2292 | |
2345 list->free = free_header->chain; | 2293 list->free = free_header->chain; |
2346 free_header->lcheader.free = 0; | 2294 free_header->lcheader.free = 0; |
2347 return val; | 2295 return val; |
2348 } | 2296 } |
2349 else | 2297 else |
2360 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord) | 2308 free_managed_lcrecord (Lisp_Object lcrecord_list, Lisp_Object lcrecord) |
2361 { | 2309 { |
2362 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list); | 2310 struct lcrecord_list *list = XLCRECORD_LIST (lcrecord_list); |
2363 struct free_lcrecord_header *free_header = | 2311 struct free_lcrecord_header *free_header = |
2364 (struct free_lcrecord_header *) XPNTR (lcrecord); | 2312 (struct free_lcrecord_header *) XPNTR (lcrecord); |
2365 struct lrecord_header *lheader = | 2313 struct lrecord_header *lheader = &free_header->lcheader.lheader; |
2366 (struct lrecord_header *) free_header; | |
2367 const struct lrecord_implementation *implementation | 2314 const struct lrecord_implementation *implementation |
2368 = LHEADER_IMPLEMENTATION (lheader); | 2315 = LHEADER_IMPLEMENTATION (lheader); |
2369 | 2316 |
2370 #ifdef ERROR_CHECK_GC | |
2371 /* Make sure the size is correct. This will catch, for example, | 2317 /* Make sure the size is correct. This will catch, for example, |
2372 putting a window configuration on the wrong free list. */ | 2318 putting a window configuration on the wrong free list. */ |
2373 if (implementation->size_in_bytes_method) | 2319 gc_checking_assert ((implementation->size_in_bytes_method ? |
2374 assert (implementation->size_in_bytes_method (lheader) == list->size); | 2320 implementation->size_in_bytes_method (lheader) : |
2375 else | 2321 implementation->static_size) |
2376 assert (implementation->static_size == list->size); | 2322 == list->size); |
2377 #endif /* ERROR_CHECK_GC */ | |
2378 | 2323 |
2379 if (implementation->finalizer) | 2324 if (implementation->finalizer) |
2380 implementation->finalizer (lheader, 0); | 2325 implementation->finalizer (lheader, 0); |
2381 free_header->chain = list->free; | 2326 free_header->chain = list->free; |
2382 free_header->lcheader.free = 1; | 2327 free_header->lcheader.free = 1; |
2396 (obj)) | 2341 (obj)) |
2397 { | 2342 { |
2398 return obj; | 2343 return obj; |
2399 } | 2344 } |
2400 | 2345 |
2401 | |
2402 | 2346 |
2403 /************************************************************************/ | 2347 /************************************************************************/ |
2404 /* Garbage Collection */ | 2348 /* Garbage Collection */ |
2405 /************************************************************************/ | 2349 /************************************************************************/ |
2406 | 2350 |
2407 /* This will be used more extensively In The Future */ | 2351 /* This will be used more extensively In The Future */ |
2408 static int last_lrecord_type_index_assigned; | 2352 static int last_lrecord_type_index_assigned; |
2409 | 2353 |
2410 const struct lrecord_implementation *lrecord_implementations_table[128]; | 2354 /* All the built-in lisp object types are enumerated in `enum lrecord_type'. |
2411 #define max_lrecord_type (countof (lrecord_implementations_table) - 1) | 2355 Additional ones may be defined by a module (none yet). We leave some |
2356 room in `lrecord_implementations_table' for such new lisp object types. */ | |
2357 #define MODULE_DEFINABLE_TYPE_COUNT 32 | |
2358 const struct lrecord_implementation *lrecord_implementations_table[lrecord_type_count + MODULE_DEFINABLE_TYPE_COUNT]; | |
2359 | |
2360 /* Object marker functions are in the lrecord_implementation structure. | |
2361 But copying them to a parallel array is much more cache-friendly. | |
2362 This hack speeds up (garbage-collect) by about 5%. */ | |
2363 Lisp_Object (*lrecord_markers[countof (lrecord_implementations_table)]) (Lisp_Object); | |
2412 | 2364 |
2413 struct gcpro *gcprolist; | 2365 struct gcpro *gcprolist; |
2414 | 2366 |
2415 /* 415 used Mly 29-Jun-93 */ | 2367 /* 415 used Mly 29-Jun-93 */ |
2416 /* 1327 used slb 28-Feb-98 */ | 2368 /* 1327 used slb 28-Feb-98 */ |
2523 if (pdump_wireidx_list >= countof (pdump_wirevec_list)) | 2475 if (pdump_wireidx_list >= countof (pdump_wirevec_list)) |
2524 abort (); | 2476 abort (); |
2525 pdump_wirevec_list[pdump_wireidx_list++] = varaddress; | 2477 pdump_wirevec_list[pdump_wireidx_list++] = varaddress; |
2526 } | 2478 } |
2527 | 2479 |
2480 #ifdef ERROR_CHECK_GC | |
2481 #define GC_CHECK_LHEADER_INVARIANTS(lheader) do { \ | |
2482 struct lrecord_header * GCLI_lh = (lheader); \ | |
2483 assert (GCLI_lh != 0); \ | |
2484 assert (GCLI_lh->type <= last_lrecord_type_index_assigned); \ | |
2485 assert (! C_READONLY_RECORD_HEADER_P (GCLI_lh) || \ | |
2486 (MARKED_RECORD_HEADER_P (GCLI_lh) && \ | |
2487 LISP_READONLY_RECORD_HEADER_P (GCLI_lh))); \ | |
2488 } while (0) | |
2489 #else | |
2490 #define GC_CHECK_LHEADER_INVARIANTS(lheader) | |
2491 #endif | |
2492 | |
2528 | 2493 |
2529 /* Mark reference to a Lisp_Object. If the object referred to has not been | 2494 /* Mark reference to a Lisp_Object. If the object referred to has not been |
2530 seen yet, recursively mark all the references contained in it. */ | 2495 seen yet, recursively mark all the references contained in it. */ |
2531 | 2496 |
2532 void | 2497 void |
2533 mark_object (Lisp_Object obj) | 2498 mark_object (Lisp_Object obj) |
2534 { | 2499 { |
2535 tail_recurse: | 2500 tail_recurse: |
2536 | 2501 |
2537 #ifdef ERROR_CHECK_GC | |
2538 assert (! (EQ (obj, Qnull_pointer))); | |
2539 #endif | |
2540 /* Checks we used to perform */ | 2502 /* Checks we used to perform */ |
2541 /* if (EQ (obj, Qnull_pointer)) return; */ | 2503 /* if (EQ (obj, Qnull_pointer)) return; */ |
2542 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ | 2504 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ |
2543 /* if (PURIFIED (XPNTR (obj))) return; */ | 2505 /* if (PURIFIED (XPNTR (obj))) return; */ |
2544 | 2506 |
2545 if (XTYPE (obj) == Lisp_Type_Record) | 2507 if (XTYPE (obj) == Lisp_Type_Record) |
2546 { | 2508 { |
2547 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | 2509 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
2548 #if defined (ERROR_CHECK_GC) | 2510 |
2549 assert (lheader->type <= last_lrecord_type_index_assigned); | 2511 GC_CHECK_LHEADER_INVARIANTS (lheader); |
2550 #endif | 2512 |
2551 if (C_READONLY_RECORD_HEADER_P (lheader)) | 2513 gc_checking_assert (LHEADER_IMPLEMENTATION (lheader)->basic_p || |
2552 return; | 2514 ! ((struct lcrecord_header *) lheader)->free); |
2553 | 2515 |
2554 if (! MARKED_RECORD_HEADER_P (lheader) && | 2516 /* All c_readonly objects have their mark bit set, |
2555 ! UNMARKABLE_RECORD_HEADER_P (lheader)) | 2517 so that we only need to check the mark bit here. */ |
2518 if (! MARKED_RECORD_HEADER_P (lheader)) | |
2556 { | 2519 { |
2557 const struct lrecord_implementation *implementation = | |
2558 LHEADER_IMPLEMENTATION (lheader); | |
2559 MARK_RECORD_HEADER (lheader); | 2520 MARK_RECORD_HEADER (lheader); |
2560 #ifdef ERROR_CHECK_GC | 2521 |
2561 if (!implementation->basic_p) | 2522 if (RECORD_MARKER (lheader)) |
2562 assert (! ((struct lcrecord_header *) lheader)->free); | |
2563 #endif | |
2564 if (implementation->marker) | |
2565 { | 2523 { |
2566 obj = implementation->marker (obj); | 2524 obj = RECORD_MARKER (lheader) (obj); |
2567 if (!NILP (obj)) goto tail_recurse; | 2525 if (!NILP (obj)) goto tail_recurse; |
2568 } | 2526 } |
2569 } | 2527 } |
2570 } | 2528 } |
2571 } | 2529 } |
2601 static int gc_count_short_string_total_size; | 2559 static int gc_count_short_string_total_size; |
2602 | 2560 |
2603 /* static int gc_count_total_records_used, gc_count_records_total_size; */ | 2561 /* static int gc_count_total_records_used, gc_count_records_total_size; */ |
2604 | 2562 |
2605 | 2563 |
2606 int | |
2607 lrecord_type_index (const struct lrecord_implementation *implementation) | |
2608 { | |
2609 int type_index = *(implementation->lrecord_type_index); | |
2610 /* Have to do this circuitous validation test because of problems | |
2611 dumping out initialized variables (ie can't set xxx_type_index to -1 | |
2612 because that would make xxx_type_index read-only in a dumped emacs. */ | |
2613 if (type_index < 0 || type_index > max_lrecord_type | |
2614 || lrecord_implementations_table[type_index] != implementation) | |
2615 { | |
2616 assert (last_lrecord_type_index_assigned < max_lrecord_type); | |
2617 type_index = ++last_lrecord_type_index_assigned; | |
2618 lrecord_implementations_table[type_index] = implementation; | |
2619 *(implementation->lrecord_type_index) = type_index; | |
2620 } | |
2621 return type_index; | |
2622 } | |
2623 | |
2624 /* stats on lcrecords in use - kinda kludgy */ | 2564 /* stats on lcrecords in use - kinda kludgy */ |
2625 | 2565 |
2626 static struct | 2566 static struct |
2627 { | 2567 { |
2628 int instances_in_use; | 2568 int instances_in_use; |
2633 } lcrecord_stats [countof (lrecord_implementations_table)]; | 2573 } lcrecord_stats [countof (lrecord_implementations_table)]; |
2634 | 2574 |
2635 static void | 2575 static void |
2636 tick_lcrecord_stats (const struct lrecord_header *h, int free_p) | 2576 tick_lcrecord_stats (const struct lrecord_header *h, int free_p) |
2637 { | 2577 { |
2638 const struct lrecord_implementation *implementation = | 2578 unsigned int type_index = h->type; |
2639 LHEADER_IMPLEMENTATION (h); | |
2640 int type_index = lrecord_type_index (implementation); | |
2641 | 2579 |
2642 if (((struct lcrecord_header *) h)->free) | 2580 if (((struct lcrecord_header *) h)->free) |
2643 { | 2581 { |
2644 assert (!free_p); | 2582 gc_checking_assert (!free_p); |
2645 lcrecord_stats[type_index].instances_on_free_list++; | 2583 lcrecord_stats[type_index].instances_on_free_list++; |
2646 } | 2584 } |
2647 else | 2585 else |
2648 { | 2586 { |
2649 size_t sz = (implementation->size_in_bytes_method | 2587 const struct lrecord_implementation *implementation = |
2650 ? implementation->size_in_bytes_method (h) | 2588 LHEADER_IMPLEMENTATION (h); |
2651 : implementation->static_size); | 2589 |
2652 | 2590 size_t sz = (implementation->size_in_bytes_method ? |
2591 implementation->size_in_bytes_method (h) : | |
2592 implementation->static_size); | |
2653 if (free_p) | 2593 if (free_p) |
2654 { | 2594 { |
2655 lcrecord_stats[type_index].instances_freed++; | 2595 lcrecord_stats[type_index].instances_freed++; |
2656 lcrecord_stats[type_index].bytes_freed += sz; | 2596 lcrecord_stats[type_index].bytes_freed += sz; |
2657 } | 2597 } |
2685 other object. */ | 2625 other object. */ |
2686 | 2626 |
2687 for (header = *prev; header; header = header->next) | 2627 for (header = *prev; header; header = header->next) |
2688 { | 2628 { |
2689 struct lrecord_header *h = &(header->lheader); | 2629 struct lrecord_header *h = &(header->lheader); |
2690 if (!C_READONLY_RECORD_HEADER_P(h) | 2630 |
2691 && !MARKED_RECORD_HEADER_P (h) | 2631 GC_CHECK_LHEADER_INVARIANTS (h); |
2692 && ! (header->free)) | 2632 |
2633 if (! MARKED_RECORD_HEADER_P (h) && ! header->free) | |
2693 { | 2634 { |
2694 if (LHEADER_IMPLEMENTATION (h)->finalizer) | 2635 if (LHEADER_IMPLEMENTATION (h)->finalizer) |
2695 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0); | 2636 LHEADER_IMPLEMENTATION (h)->finalizer (h, 0); |
2696 } | 2637 } |
2697 } | 2638 } |
2698 | 2639 |
2699 for (header = *prev; header; ) | 2640 for (header = *prev; header; ) |
2700 { | 2641 { |
2701 struct lrecord_header *h = &(header->lheader); | 2642 struct lrecord_header *h = &(header->lheader); |
2702 if (C_READONLY_RECORD_HEADER_P(h) || MARKED_RECORD_HEADER_P (h)) | 2643 if (MARKED_RECORD_HEADER_P (h)) |
2703 { | 2644 { |
2704 if (MARKED_RECORD_HEADER_P (h)) | 2645 if (! C_READONLY_RECORD_HEADER_P (h)) |
2705 UNMARK_RECORD_HEADER (h); | 2646 UNMARK_RECORD_HEADER (h); |
2706 num_used++; | 2647 num_used++; |
2707 /* total_size += n->implementation->size_in_bytes (h);*/ | 2648 /* total_size += n->implementation->size_in_bytes (h);*/ |
2708 /* #### May modify header->next on a C_READONLY lcrecord */ | 2649 /* #### May modify header->next on a C_READONLY lcrecord */ |
2709 prev = &(header->next); | 2650 prev = &(header->next); |
2738 their implementation */ | 2679 their implementation */ |
2739 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) | 2680 for (bit_vector = *prev; !EQ (bit_vector, Qzero); ) |
2740 { | 2681 { |
2741 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); | 2682 Lisp_Bit_Vector *v = XBIT_VECTOR (bit_vector); |
2742 int len = v->size; | 2683 int len = v->size; |
2743 if (C_READONLY_RECORD_HEADER_P(&(v->lheader)) || MARKED_RECORD_P (bit_vector)) | 2684 if (MARKED_RECORD_P (bit_vector)) |
2744 { | 2685 { |
2745 if (MARKED_RECORD_P (bit_vector)) | 2686 if (! C_READONLY_RECORD_HEADER_P(&(v->lheader))) |
2746 UNMARK_RECORD_HEADER (&(v->lheader)); | 2687 UNMARK_RECORD_HEADER (&(v->lheader)); |
2747 total_size += len; | 2688 total_size += len; |
2748 total_storage += | 2689 total_storage += |
2749 MALLOC_OVERHEAD + | 2690 MALLOC_OVERHEAD + |
2750 offsetof (Lisp_Bit_Vector, bits[BIT_VECTOR_LONG_STORAGE (len)]); | 2691 offsetof (Lisp_Bit_Vector, bits[BIT_VECTOR_LONG_STORAGE (len)]); |
2796 } \ | 2737 } \ |
2797 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2738 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2798 { \ | 2739 { \ |
2799 num_used++; \ | 2740 num_used++; \ |
2800 } \ | 2741 } \ |
2801 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2742 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2802 { \ | 2743 { \ |
2803 num_free++; \ | 2744 num_free++; \ |
2804 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ | 2745 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ |
2805 } \ | 2746 } \ |
2806 else \ | 2747 else \ |
2851 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2792 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2852 { \ | 2793 { \ |
2853 SFTB_empty = 0; \ | 2794 SFTB_empty = 0; \ |
2854 num_used++; \ | 2795 num_used++; \ |
2855 } \ | 2796 } \ |
2856 else if (!MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2797 else if (! MARKED_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
2857 { \ | 2798 { \ |
2858 num_free++; \ | 2799 num_free++; \ |
2859 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ | 2800 FREE_FIXED_TYPE (typename, obj_type, SFTB_victim); \ |
2860 } \ | 2801 } \ |
2861 else \ | 2802 else \ |
3030 | 2971 |
3031 /* Explicitly free a marker. */ | 2972 /* Explicitly free a marker. */ |
3032 void | 2973 void |
3033 free_marker (Lisp_Marker *ptr) | 2974 free_marker (Lisp_Marker *ptr) |
3034 { | 2975 { |
3035 #ifdef ERROR_CHECK_GC | |
3036 /* Perhaps this will catch freeing an already-freed marker. */ | 2976 /* Perhaps this will catch freeing an already-freed marker. */ |
3037 Lisp_Object temmy; | 2977 gc_checking_assert (ptr->lheader.type = lrecord_type_marker); |
3038 XSETMARKER (temmy, ptr); | |
3039 assert (MARKERP (temmy)); | |
3040 #endif /* ERROR_CHECK_GC */ | |
3041 | 2978 |
3042 #ifndef ALLOC_NO_POOLS | 2979 #ifndef ALLOC_NO_POOLS |
3043 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, ptr); | 2980 FREE_FIXED_TYPE_WHEN_NOT_IN_GC (marker, Lisp_Marker, ptr); |
3044 #endif /* ALLOC_NO_POOLS */ | 2981 #endif /* ALLOC_NO_POOLS */ |
3045 } | 2982 } |
3251 | 3188 |
3252 /* I hate duplicating all this crap! */ | 3189 /* I hate duplicating all this crap! */ |
3253 int | 3190 int |
3254 marked_p (Lisp_Object obj) | 3191 marked_p (Lisp_Object obj) |
3255 { | 3192 { |
3256 #ifdef ERROR_CHECK_GC | |
3257 assert (! (EQ (obj, Qnull_pointer))); | |
3258 #endif | |
3259 /* Checks we used to perform. */ | 3193 /* Checks we used to perform. */ |
3260 /* if (EQ (obj, Qnull_pointer)) return 1; */ | 3194 /* if (EQ (obj, Qnull_pointer)) return 1; */ |
3261 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ | 3195 /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ |
3262 /* if (PURIFIED (XPNTR (obj))) return 1; */ | 3196 /* if (PURIFIED (XPNTR (obj))) return 1; */ |
3263 | 3197 |
3264 if (XTYPE (obj) == Lisp_Type_Record) | 3198 if (XTYPE (obj) == Lisp_Type_Record) |
3265 { | 3199 { |
3266 struct lrecord_header *lheader = XRECORD_LHEADER (obj); | 3200 struct lrecord_header *lheader = XRECORD_LHEADER (obj); |
3267 #if defined (ERROR_CHECK_GC) | 3201 |
3268 assert (lheader->type <= last_lrecord_type_index_assigned); | 3202 GC_CHECK_LHEADER_INVARIANTS (lheader); |
3269 #endif | 3203 |
3270 return C_READONLY_RECORD_HEADER_P (lheader) || MARKED_RECORD_HEADER_P (lheader); | 3204 return MARKED_RECORD_HEADER_P (lheader); |
3271 } | 3205 } |
3272 return 1; | 3206 return 1; |
3273 } | 3207 } |
3274 | 3208 |
3275 static void | 3209 static void |
3343 p += sizeof (pdump_reloc_table); | 3277 p += sizeof (pdump_reloc_table); |
3344 if (rt->desc) | 3278 if (rt->desc) |
3345 { | 3279 { |
3346 for (i=0; i<rt->count; i++) | 3280 for (i=0; i<rt->count; i++) |
3347 { | 3281 { |
3348 UNMARK_RECORD_HEADER ((struct lrecord_header *)(*(EMACS_INT *)p)); | 3282 struct lrecord_header *lh = * (struct lrecord_header **) p; |
3283 if (! C_READONLY_RECORD_HEADER_P (lh)) | |
3284 UNMARK_RECORD_HEADER (lh); | |
3349 p += sizeof (EMACS_INT); | 3285 p += sizeof (EMACS_INT); |
3350 } | 3286 } |
3351 } else | 3287 } else |
3352 break; | 3288 break; |
3353 } | 3289 } |
3724 { | 3660 { |
3725 char buf [255]; | 3661 char buf [255]; |
3726 const char *name = lrecord_implementations_table[i]->name; | 3662 const char *name = lrecord_implementations_table[i]->name; |
3727 int len = strlen (name); | 3663 int len = strlen (name); |
3728 /* save this for the FSFmacs-compatible part of the summary */ | 3664 /* save this for the FSFmacs-compatible part of the summary */ |
3729 if (i == *lrecord_vector.lrecord_type_index) | 3665 if (i == lrecord_vector.lrecord_type_index) |
3730 gc_count_vector_total_size = | 3666 gc_count_vector_total_size = |
3731 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed; | 3667 lcrecord_stats[i].bytes_in_use + lcrecord_stats[i].bytes_freed; |
3732 | 3668 |
3733 sprintf (buf, "%s-storage", name); | 3669 sprintf (buf, "%s-storage", name); |
3734 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl); | 3670 pl = gc_plist_hack (buf, lcrecord_stats[i].bytes_in_use, pl); |
4053 } | 3989 } |
4054 | 3990 |
4055 void | 3991 void |
4056 init_alloc_once_early (void) | 3992 init_alloc_once_early (void) |
4057 { | 3993 { |
4058 int iii; | |
4059 | |
4060 reinit_alloc_once_early (); | 3994 reinit_alloc_once_early (); |
4061 | 3995 |
4062 last_lrecord_type_index_assigned = -1; | 3996 last_lrecord_type_index_assigned = lrecord_type_count - 1; |
4063 for (iii = 0; iii < countof (lrecord_implementations_table); iii++) | 3997 |
4064 { | 3998 { |
4065 lrecord_implementations_table[iii] = 0; | 3999 int i; |
4066 } | 4000 for (i = 0; i < countof (lrecord_implementations_table); i++) |
4067 | 4001 lrecord_implementations_table[i] = 0; |
4068 /* | 4002 } |
4069 * All the staticly | 4003 |
4070 * defined subr lrecords were initialized with lheader->type == 0. | 4004 INIT_LRECORD_IMPLEMENTATION (cons); |
4071 * See subr_lheader_initializer in lisp.h. Force type index 0 to be | 4005 INIT_LRECORD_IMPLEMENTATION (vector); |
4072 * assigned to lrecord_subr so that those predefined indexes match | 4006 INIT_LRECORD_IMPLEMENTATION (string); |
4073 * reality. | 4007 INIT_LRECORD_IMPLEMENTATION (lcrecord_list); |
4074 */ | |
4075 lrecord_type_index (&lrecord_subr); | |
4076 assert (*(lrecord_subr.lrecord_type_index) == 0); | |
4077 /* | |
4078 * The same is true for symbol_value_forward objects, except the | |
4079 * type is 1. | |
4080 */ | |
4081 lrecord_type_index (&lrecord_symbol_value_forward); | |
4082 assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1); | |
4083 | 4008 |
4084 staticidx = 0; | 4009 staticidx = 0; |
4085 } | 4010 } |
4086 | 4011 |
4087 int pure_bytes_used = 0; | 4012 int pure_bytes_used = 0; |
5188 | 5113 |
5189 /* Put back the lrecord_implementations_table */ | 5114 /* Put back the lrecord_implementations_table */ |
5190 memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table)); | 5115 memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table)); |
5191 p += sizeof (lrecord_implementations_table); | 5116 p += sizeof (lrecord_implementations_table); |
5192 | 5117 |
5193 /* Give back their numbers to the lrecord implementations */ | 5118 /* Reinitialize lrecord_markers from lrecord_implementations_table */ |
5194 for (i = 0; i < countof (lrecord_implementations_table); i++) | 5119 for (i=0; i < countof (lrecord_implementations_table); i++) |
5195 if (lrecord_implementations_table[i]) | 5120 if (lrecord_implementations_table[i]) |
5196 { | 5121 lrecord_markers[i] = lrecord_implementations_table[i]->marker; |
5197 *(lrecord_implementations_table[i]->lrecord_type_index) = i; | |
5198 last_lrecord_type_index_assigned = i; | |
5199 } | |
5200 | 5122 |
5201 /* Do the relocations */ | 5123 /* Do the relocations */ |
5202 pdump_rt_list = p; | 5124 pdump_rt_list = p; |
5203 count = 2; | 5125 count = 2; |
5204 for (;;) | 5126 for (;;) |
5254 | 5176 |
5255 return 1; | 5177 return 1; |
5256 } | 5178 } |
5257 | 5179 |
5258 #endif /* PDUMP */ | 5180 #endif /* PDUMP */ |
5181 |