Mercurial > hg > xemacs-beta
comparison src/alloc.c @ 454:d7a9135ec789 r21-2-42
Import from CVS: tag r21-2-42
| author | cvs |
|---|---|
| date | Mon, 13 Aug 2007 11:40:54 +0200 |
| parents | 3d3049ae1304 |
| children | e7ef97881643 |
comparison
equal
deleted
inserted
replaced
| 453:270b05afd845 | 454:d7a9135ec789 |
|---|---|
| 542 (e.g. the obarray, where are all symbols are stored; the | 542 (e.g. the obarray, where are all symbols are stored; the |
| 543 current catches and condition-cases; the backtrace list of | 543 current catches and condition-cases; the backtrace list of |
| 544 currently executing functions; the gcpro list; etc.) and | 544 currently executing functions; the gcpro list; etc.) and |
| 545 recursively marking all objects that are accessible. | 545 recursively marking all objects that are accessible. |
| 546 | 546 |
| 547 At the beginning of the sweep stage, the conses in the cons | 547 At the beginning of the sweep stage, the conses in the cons blocks |
| 548 blocks are in one of three states: in use and marked, in use | 548 are in one of three states: in use and marked, in use but not |
| 549 but not marked, and not in use (already freed). Any conses | 549 marked, and not in use (already freed). Any conses that are marked |
| 550 that are marked have been marked in the mark stage just | 550 have been marked in the mark stage just executed, because as part |
| 551 executed, because as part of the sweep stage we unmark any | 551 of the sweep stage we unmark any marked objects. The way we tell |
| 552 marked objects. The way we tell whether or not a cons cell | 552 whether or not a cons cell is in use is through the LRECORD_FREE_P |
| 553 is in use is through the FREE_STRUCT_P macro. This basically | 553 macro. This uses a special lrecord type `lrecord_type_free', |
| 554 looks at the first 4 bytes (or however many bytes a pointer | 554 which is never associated with any valid object. |
| 555 fits in) to see if all the bits in those bytes are 1. The | 555 |
| 556 resulting value (0xFFFFFFFF) is not a valid pointer and is | 556 Conses on the free_cons_list are threaded through a pointer stored |
| 557 not a valid Lisp_Object. All current fixed-size types have | 557 in the conses themselves. Because the cons is still in a |
| 558 a pointer or Lisp_Object as their first element with the | 558 cons_block and needs to remain marked as not in use for the next |
| 559 exception of strings; they have a size value, which can | 559 time that GC happens, we need room to store both the "free" |
| 560 never be less than zero, and so 0xFFFFFFFF is invalid for | 560 indicator and the chaining pointer. So this pointer is stored |
| 561 strings as well. Now assuming that a cons cell is in use, | 561 after the lrecord header (actually where C places a pointer after |
| 562 the way we tell whether or not it is marked is to look at | 562 the lrecord header; they are not necessarily contiguous). This |
| 563 the mark bit of its car (each Lisp_Object has one bit | 563 implies that all fixed-size types must be big enough to contain at |
| 564 reserved as a mark bit, in case it's needed). Note that | 564 least one pointer. This is true for all current fixed-size types, |
| 565 different types of objects use different fields to indicate | 565 with the possible exception of Lisp_Floats, for which we define the |
| 566 whether the object is marked, but the principle is the same. | 566 meat of the struct using a union of a pointer and a double to |
| 567 | 567 ensure adequate space for the free list chain pointer. |
| 568 Conses on the free_cons_list are threaded through a pointer | |
| 569 stored in the bytes directly after the bytes that are set | |
| 570 to 0xFFFFFFFF (we cannot overwrite these because the cons | |
| 571 is still in a cons_block and needs to remain marked as | |
| 572 not in use for the next time that GC happens). This | |
| 573 implies that all fixed-size types must be at least big | |
| 574 enough to store two pointers, which is indeed the case | |
| 575 for all current fixed-size types. | |
| 576 | 568 |
| 577 Some types of objects need additional "finalization" done | 569 Some types of objects need additional "finalization" done |
| 578 when an object is converted from in use to not in use; | 570 when an object is converted from in use to not in use; |
| 579 this is the purpose of the ADDITIONAL_FREE_type macro. | 571 this is the purpose of the ADDITIONAL_FREE_type macro. |
| 580 For example, markers need to be removed from the chain | 572 For example, markers need to be removed from the chain |
| 584 apply to extents, however). | 576 apply to extents, however). |
| 585 | 577 |
| 586 WARNING: Things are in an extremely bizarre state when | 578 WARNING: Things are in an extremely bizarre state when |
| 587 the ADDITIONAL_FREE_type macros are called, so beware! | 579 the ADDITIONAL_FREE_type macros are called, so beware! |
| 588 | 580 |
| 589 When ERROR_CHECK_GC is defined, we do things differently | 581 When ERROR_CHECK_GC is defined, we do things differently so as to |
| 590 so as to maximize our chances of catching places where | 582 maximize our chances of catching places where there is insufficient |
| 591 there is insufficient GCPROing. The thing we want to | 583 GCPROing. The thing we want to avoid is having an object that |
| 592 avoid is having an object that we're using but didn't | 584 we're using but didn't GCPRO get freed by GC and then reallocated |
| 593 GCPRO get freed by GC and then reallocated while we're | 585 while we're in the process of using it -- this will result in |
| 594 in the process of using it -- this will result in something | 586 something seemingly unrelated getting trashed, and is extremely |
| 595 seemingly unrelated getting trashed, and is extremely | 587 difficult to track down. If the object gets freed but not |
| 596 difficult to track down. If the object gets freed but | 588 reallocated, we can usually catch this because we set most of the |
| 597 not reallocated, we can usually catch this because we | 589 bytes of a freed object to 0xDEADBEEF. (The lisp object type is set |
| 598 set all bytes of a freed object to 0xDEADBEEF. (The | 590 to the invalid type `lrecord_type_free', however, and a pointer |
| 599 first four bytes, however, are 0xFFFFFFFF, and the next | 591 used to chain freed objects together is stored after the lrecord |
| 600 four are a pointer used to chain freed objects together; | 592 header; we play some tricks with this pointer to make it more |
| 601 we play some tricks with this pointer to make it more | |
| 602 bogus, so crashes are more likely to occur right away.) | 593 bogus, so crashes are more likely to occur right away.) |
| 603 | 594 |
| 604 We want freed objects to stay free as long as possible, | 595 We want freed objects to stay free as long as possible, |
| 605 so instead of doing what we do above, we maintain the | 596 so instead of doing what we do above, we maintain the |
| 606 free objects in a first-in first-out queue. We also | 597 free objects in a first-in first-out queue. We also |
| 661 }; \ | 652 }; \ |
| 662 \ | 653 \ |
| 663 static struct type##_block *current_##type##_block; \ | 654 static struct type##_block *current_##type##_block; \ |
| 664 static int current_##type##_block_index; \ | 655 static int current_##type##_block_index; \ |
| 665 \ | 656 \ |
| 666 static structtype *type##_free_list; \ | 657 static Lisp_Free *type##_free_list; \ |
| 667 static structtype *type##_free_list_tail; \ | 658 static Lisp_Free *type##_free_list_tail; \ |
| 668 \ | 659 \ |
| 669 static void \ | 660 static void \ |
| 670 init_##type##_alloc (void) \ | 661 init_##type##_alloc (void) \ |
| 671 { \ | 662 { \ |
| 672 current_##type##_block = 0; \ | 663 current_##type##_block = 0; \ |
| 702 /* Note: if you get crashes in this function, suspect incorrect calls | 693 /* Note: if you get crashes in this function, suspect incorrect calls |
| 703 to free_cons() and friends. This happened once because the cons | 694 to free_cons() and friends. This happened once because the cons |
| 704 cell was not GC-protected and was getting collected before | 695 cell was not GC-protected and was getting collected before |
| 705 free_cons() was called. */ | 696 free_cons() was called. */ |
| 706 | 697 |
| 707 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result) \ | 698 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result) do { \ |
| 708 do \ | 699 if (gc_count_num_##type##_freelist > \ |
| 709 { \ | 700 MINIMUM_ALLOWED_FIXED_TYPE_CELLS_##type) \ |
| 710 if (gc_count_num_##type##_freelist > \ | |
| 711 MINIMUM_ALLOWED_FIXED_TYPE_CELLS_##type) \ | |
| 712 { \ | |
| 713 result = type##_free_list; \ | |
| 714 /* Before actually using the chain pointer, we complement all its \ | |
| 715 bits; see FREE_FIXED_TYPE(). */ \ | |
| 716 type##_free_list = \ | |
| 717 (structtype *) ~(unsigned long) \ | |
| 718 (* (structtype **) ((char *) result + sizeof (void *))); \ | |
| 719 gc_count_num_##type##_freelist--; \ | |
| 720 } \ | |
| 721 else \ | |
| 722 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ | |
| 723 MARK_STRUCT_AS_NOT_FREE (result); \ | |
| 724 } while (0) | |
| 725 | |
| 726 #else /* !ERROR_CHECK_GC */ | |
| 727 | |
| 728 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result) \ | |
| 729 do \ | |
| 730 { \ | |
| 731 if (type##_free_list) \ | |
| 732 { \ | 701 { \ |
| 733 result = type##_free_list; \ | 702 result = (structtype *) type##_free_list; \ |
| 734 type##_free_list = \ | 703 /* Before actually using the chain pointer, \ |
| 735 * (structtype **) ((char *) result + sizeof (void *)); \ | 704 we complement all its bits; see FREE_FIXED_TYPE(). */ \ |
| 705 type##_free_list = (Lisp_Free *) \ | |
| 706 (~ (EMACS_UINT) (type##_free_list->chain)); \ | |
| 707 gc_count_num_##type##_freelist--; \ | |
| 736 } \ | 708 } \ |
| 737 else \ | 709 else \ |
| 738 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ | 710 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ |
| 739 MARK_STRUCT_AS_NOT_FREE (result); \ | 711 MARK_LRECORD_AS_NOT_FREE (result); \ |
| 740 } while (0) | 712 } while (0) |
| 741 | 713 |
| 714 #else /* !ERROR_CHECK_GC */ | |
| 715 | |
| 716 #define ALLOCATE_FIXED_TYPE_1(type, structtype, result) do { \ | |
| 717 if (type##_free_list) \ | |
| 718 { \ | |
| 719 result = (structtype *) type##_free_list; \ | |
| 720 type##_free_list = type##_free_list->chain; \ | |
| 721 } \ | |
| 722 else \ | |
| 723 ALLOCATE_FIXED_TYPE_FROM_BLOCK (type, result); \ | |
| 724 MARK_LRECORD_AS_NOT_FREE (result); \ | |
| 725 } while (0) | |
| 726 | |
| 742 #endif /* !ERROR_CHECK_GC */ | 727 #endif /* !ERROR_CHECK_GC */ |
| 728 | |
| 743 | 729 |
| 744 #define ALLOCATE_FIXED_TYPE(type, structtype, result) \ | 730 #define ALLOCATE_FIXED_TYPE(type, structtype, result) \ |
| 745 do \ | 731 do \ |
| 746 { \ | 732 { \ |
| 747 ALLOCATE_FIXED_TYPE_1 (type, structtype, result); \ | 733 ALLOCATE_FIXED_TYPE_1 (type, structtype, result); \ |
| 753 { \ | 739 { \ |
| 754 ALLOCATE_FIXED_TYPE_1 (type, structtype, result); \ | 740 ALLOCATE_FIXED_TYPE_1 (type, structtype, result); \ |
| 755 NOSEEUM_INCREMENT_CONS_COUNTER (sizeof (structtype), #type); \ | 741 NOSEEUM_INCREMENT_CONS_COUNTER (sizeof (structtype), #type); \ |
| 756 } while (0) | 742 } while (0) |
| 757 | 743 |
| 758 /* INVALID_POINTER_VALUE should be a value that is invalid as a pointer | 744 |
| 759 to a Lisp object and invalid as an actual Lisp_Object value. We have | 745 /* Lisp_Free is the type to represent a free list member inside a frob |
| 760 to make sure that this value cannot be an integer in Lisp_Object form. | 746 block of any lisp object type. */ |
| 761 0xFFFFFFFF could be so on a 64-bit system, so we extend it to 64 bits. | 747 typedef struct Lisp_Free |
| 762 On a 32-bit system, the type bits will be non-zero, making the value | 748 { |
| 763 be a pointer, and the pointer will be misaligned. | 749 struct lrecord_header lheader; |
| 764 | 750 struct Lisp_Free *chain; |
| 765 Even if Emacs is run on some weirdo system that allows and allocates | 751 } Lisp_Free; |
| 766 byte-aligned pointers, this pointer is at the very top of the address | 752 |
| 767 space and so it's almost inconceivable that it could ever be valid. */ | 753 #define LRECORD_FREE_P(ptr) \ |
| 768 | 754 ((ptr)->lheader.type == lrecord_type_free) |
| 769 #if INTBITS == 32 | 755 |
| 770 # define INVALID_POINTER_VALUE 0xFFFFFFFF | 756 #define MARK_LRECORD_AS_FREE(ptr) \ |
| 771 #elif INTBITS == 48 | 757 ((void) ((ptr)->lheader.type = lrecord_type_free)) |
| 772 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFF | 758 |
| 773 #elif INTBITS == 64 | 759 #ifdef ERROR_CHECK_GC |
| 774 # define INVALID_POINTER_VALUE 0xFFFFFFFFFFFFFFFF | 760 #define MARK_LRECORD_AS_NOT_FREE(ptr) \ |
| 761 ((void) ((ptr)->lheader.type = lrecord_type_undefined)) | |
| 775 #else | 762 #else |
| 776 You have some weird system and need to supply a reasonable value here. | 763 #define MARK_LRECORD_AS_NOT_FREE(ptr) DO_NOTHING |
| 777 #endif | 764 #endif |
| 778 | 765 |
| 779 /* The construct (* (void **) (ptr)) would cause aliasing problems | |
| 780 with modern optimizing compilers like `gcc -O3 -fstrict-aliasing'. | |
| 781 But `char *' can legally alias any pointer. Hence this union trick... | |
| 782 | |
| 783 It turned out that the union trick was not good enough for xlC -O3; | |
| 784 and it is questionable whether it really complies with the C standard. | |
| 785 so we use memset instead, which should be safe from optimizations. */ | |
| 786 typedef union { char c; void *p; } *aliasing_voidpp; | |
| 787 #define ALIASING_VOIDPP_DEREFERENCE(ptr) \ | |
| 788 (((aliasing_voidpp) (ptr))->p) | |
| 789 #define FREE_STRUCT_P(ptr) \ | |
| 790 (ALIASING_VOIDPP_DEREFERENCE (ptr) == (void *) INVALID_POINTER_VALUE) | |
| 791 #define MARK_STRUCT_AS_FREE(ptr) memset (ptr, 0xff, sizeof (void *)) | |
| 792 #define MARK_STRUCT_AS_NOT_FREE(ptr) memset (ptr, 0x00, sizeof (void *)) | |
| 793 | |
| 794 #ifdef ERROR_CHECK_GC | 766 #ifdef ERROR_CHECK_GC |
| 795 | 767 |
| 796 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ | 768 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) do { \ |
| 797 do { if (type##_free_list_tail) \ | 769 if (type##_free_list_tail) \ |
| 798 { \ | 770 { \ |
| 799 /* When we store the chain pointer, we complement all \ | 771 /* When we store the chain pointer, we complement all \ |
| 800 its bits; this should significantly increase its \ | 772 its bits; this should significantly increase its \ |
| 801 bogosity in case someone tries to use the value, and \ | 773 bogosity in case someone tries to use the value, and \ |
| 802 should make us dump faster if someone stores something \ | 774 should make us crash faster if someone overwrites the \ |
| 803 over the pointer because when it gets un-complemented in \ | 775 pointer because when it gets un-complemented in \ |
| 804 ALLOCATED_FIXED_TYPE(), the resulting pointer will be \ | 776 ALLOCATED_FIXED_TYPE(), the resulting pointer will be \ |
| 805 extremely bogus. */ \ | 777 extremely bogus. */ \ |
| 806 * (structtype **) \ | 778 type##_free_list_tail->chain = \ |
| 807 ((char *) type##_free_list_tail + sizeof (void *)) = \ | 779 (Lisp_Free *) ~ (EMACS_UINT) (ptr); \ |
| 808 (structtype *) ~(unsigned long) ptr; \ | 780 } \ |
| 809 } \ | 781 else \ |
| 810 else \ | 782 type##_free_list = (Lisp_Free *) (ptr); \ |
| 811 type##_free_list = ptr; \ | 783 type##_free_list_tail = (Lisp_Free *) (ptr); \ |
| 812 type##_free_list_tail = ptr; \ | 784 } while (0) |
| 813 } while (0) | |
| 814 | 785 |
| 815 #else /* !ERROR_CHECK_GC */ | 786 #else /* !ERROR_CHECK_GC */ |
| 816 | 787 |
| 817 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) \ | 788 #define PUT_FIXED_TYPE_ON_FREE_LIST(type, structtype, ptr) do { \ |
| 818 do { * (structtype **) ((char *) (ptr) + sizeof (void *)) = \ | 789 ((Lisp_Free *) (ptr))->chain = type##_free_list; \ |
| 819 type##_free_list; \ | 790 type##_free_list = (Lisp_Free *) (ptr); \ |
| 820 type##_free_list = (ptr); \ | 791 } while (0) \ |
| 821 } while (0) | |
| 822 | 792 |
| 823 #endif /* !ERROR_CHECK_GC */ | 793 #endif /* !ERROR_CHECK_GC */ |
| 824 | 794 |
| 825 /* TYPE and STRUCTTYPE are the same as in ALLOCATE_FIXED_TYPE(). */ | 795 /* TYPE and STRUCTTYPE are the same as in ALLOCATE_FIXED_TYPE(). */ |
| 826 | 796 |
| 827 #define FREE_FIXED_TYPE(type, structtype, ptr) do { \ | 797 #define FREE_FIXED_TYPE(type, structtype, ptr) do { \ |
| 828 structtype *FFT_ptr = (ptr); \ | 798 structtype *FFT_ptr = (ptr); \ |
| 829 ADDITIONAL_FREE_##type (FFT_ptr); \ | 799 ADDITIONAL_FREE_##type (FFT_ptr); \ |
| 830 deadbeef_memory (FFT_ptr, sizeof (structtype)); \ | 800 deadbeef_memory (FFT_ptr, sizeof (structtype)); \ |
| 831 PUT_FIXED_TYPE_ON_FREE_LIST (type, structtype, FFT_ptr); \ | 801 PUT_FIXED_TYPE_ON_FREE_LIST (type, structtype, FFT_ptr); \ |
| 832 MARK_STRUCT_AS_FREE (FFT_ptr); \ | 802 MARK_LRECORD_AS_FREE (FFT_ptr); \ |
| 833 } while (0) | 803 } while (0) |
| 834 | 804 |
| 835 /* Like FREE_FIXED_TYPE() but used when we are explicitly | 805 /* Like FREE_FIXED_TYPE() but used when we are explicitly |
| 836 freeing a structure through free_cons(), free_marker(), etc. | 806 freeing a structure through free_cons(), free_marker(), etc. |
| 837 rather than through the normal process of sweeping. | 807 rather than through the normal process of sweeping. |
| 1779 ALIGNOF (Lisp_String *)) | 1749 ALIGNOF (Lisp_String *)) |
| 1780 | 1750 |
| 1781 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) | 1751 #define BIG_STRING_FULLSIZE_P(fullsize) ((fullsize) >= STRING_CHARS_BLOCK_SIZE) |
| 1782 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) | 1752 #define BIG_STRING_SIZE_P(size) (BIG_STRING_FULLSIZE_P (STRING_FULLSIZE(size))) |
| 1783 | 1753 |
| 1754 #define STRING_CHARS_FREE_P(ptr) ((ptr)->string == NULL) | |
| 1755 #define MARK_STRING_CHARS_AS_FREE(ptr) ((void) ((ptr)->string = NULL)) | |
| 1756 | |
| 1784 struct string_chars | 1757 struct string_chars |
| 1785 { | 1758 { |
| 1786 Lisp_String *string; | 1759 Lisp_String *string; |
| 1787 unsigned char chars[1]; | 1760 unsigned char chars[1]; |
| 1788 }; | 1761 }; |
| 1986 struct string_chars *old_s_chars = (struct string_chars *) | 1959 struct string_chars *old_s_chars = (struct string_chars *) |
| 1987 ((char *) old_data - offsetof (struct string_chars, chars)); | 1960 ((char *) old_data - offsetof (struct string_chars, chars)); |
| 1988 /* Sanity check to make sure we aren't hosed by strange | 1961 /* Sanity check to make sure we aren't hosed by strange |
| 1989 alignment/padding. */ | 1962 alignment/padding. */ |
| 1990 assert (old_s_chars->string == s); | 1963 assert (old_s_chars->string == s); |
| 1991 MARK_STRUCT_AS_FREE (old_s_chars); | 1964 MARK_STRING_CHARS_AS_FREE (old_s_chars); |
| 1992 ((struct unused_string_chars *) old_s_chars)->fullsize = | 1965 ((struct unused_string_chars *) old_s_chars)->fullsize = |
| 1993 oldfullsize; | 1966 oldfullsize; |
| 1994 } | 1967 } |
| 1995 } | 1968 } |
| 1996 } | 1969 } |
| 2642 \ | 2615 \ |
| 2643 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ | 2616 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ |
| 2644 { \ | 2617 { \ |
| 2645 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ | 2618 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ |
| 2646 \ | 2619 \ |
| 2647 if (FREE_STRUCT_P (SFTB_victim)) \ | 2620 if (LRECORD_FREE_P (SFTB_victim)) \ |
| 2648 { \ | 2621 { \ |
| 2649 num_free++; \ | 2622 num_free++; \ |
| 2650 } \ | 2623 } \ |
| 2651 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2624 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
| 2652 { \ | 2625 { \ |
| 2688 SFTB_current; \ | 2661 SFTB_current; \ |
| 2689 ) \ | 2662 ) \ |
| 2690 { \ | 2663 { \ |
| 2691 int SFTB_iii; \ | 2664 int SFTB_iii; \ |
| 2692 int SFTB_empty = 1; \ | 2665 int SFTB_empty = 1; \ |
| 2693 obj_type *SFTB_old_free_list = typename##_free_list; \ | 2666 Lisp_Free *SFTB_old_free_list = typename##_free_list; \ |
| 2694 \ | 2667 \ |
| 2695 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ | 2668 for (SFTB_iii = 0; SFTB_iii < SFTB_limit; SFTB_iii++) \ |
| 2696 { \ | 2669 { \ |
| 2697 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ | 2670 obj_type *SFTB_victim = &(SFTB_current->block[SFTB_iii]); \ |
| 2698 \ | 2671 \ |
| 2699 if (FREE_STRUCT_P (SFTB_victim)) \ | 2672 if (LRECORD_FREE_P (SFTB_victim)) \ |
| 2700 { \ | 2673 { \ |
| 2701 num_free++; \ | 2674 num_free++; \ |
| 2702 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \ | 2675 PUT_FIXED_TYPE_ON_FREE_LIST (typename, obj_type, SFTB_victim); \ |
| 2703 } \ | 2676 } \ |
| 2704 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ | 2677 else if (C_READONLY_RECORD_HEADER_P (&SFTB_victim->lheader)) \ |
| 2912 (struct string_chars *) &(sb->string_chars[pos]); | 2885 (struct string_chars *) &(sb->string_chars[pos]); |
| 2913 Lisp_String *string; | 2886 Lisp_String *string; |
| 2914 int size; | 2887 int size; |
| 2915 int fullsize; | 2888 int fullsize; |
| 2916 | 2889 |
| 2917 /* If the string_chars struct is marked as free (i.e. the STRING | 2890 /* If the string_chars struct is marked as free (i.e. the |
| 2918 pointer is 0xFFFFFFFF) then this is an unused chunk of string | 2891 STRING pointer is NULL) then this is an unused chunk of |
| 2919 storage. (See below.) */ | 2892 string storage. (See below.) */ |
| 2920 | 2893 |
| 2921 if (FREE_STRUCT_P (s_chars)) | 2894 if (STRING_CHARS_FREE_P (s_chars)) |
| 2922 { | 2895 { |
| 2923 fullsize = ((struct unused_string_chars *) s_chars)->fullsize; | 2896 fullsize = ((struct unused_string_chars *) s_chars)->fullsize; |
| 2924 pos += fullsize; | 2897 pos += fullsize; |
| 2925 continue; | 2898 continue; |
| 2926 } | 2899 } |
| 2963 struct string_chars *to_s_chars; | 2936 struct string_chars *to_s_chars; |
| 2964 Lisp_String *string; | 2937 Lisp_String *string; |
| 2965 int size; | 2938 int size; |
| 2966 int fullsize; | 2939 int fullsize; |
| 2967 | 2940 |
| 2968 /* If the string_chars struct is marked as free (i.e. the STRING | 2941 /* If the string_chars struct is marked as free (i.e. the |
| 2969 pointer is 0xFFFFFFFF) then this is an unused chunk of string | 2942 STRING pointer is NULL) then this is an unused chunk of |
| 2970 storage. This happens under Mule when a string's size changes | 2943 string storage. This happens under Mule when a string's |
| 2971 in such a way that its fullsize changes. (Strings can change | 2944 size changes in such a way that its fullsize changes. |
| 2972 size because a different-length character can be substituted | 2945 (Strings can change size because a different-length |
| 2973 for another character.) In this case, after the bogus string | 2946 character can be substituted for another character.) |
| 2974 pointer is the "fullsize" of this entry, i.e. how many bytes | 2947 In this case, after the bogus string pointer is the |
| 2975 to skip. */ | 2948 "fullsize" of this entry, i.e. how many bytes to skip. */ |
| 2976 | 2949 |
| 2977 if (FREE_STRUCT_P (from_s_chars)) | 2950 if (STRING_CHARS_FREE_P (from_s_chars)) |
| 2978 { | 2951 { |
| 2979 fullsize = ((struct unused_string_chars *) from_s_chars)->fullsize; | 2952 fullsize = ((struct unused_string_chars *) from_s_chars)->fullsize; |
| 2980 from_pos += fullsize; | 2953 from_pos += fullsize; |
| 2981 continue; | 2954 continue; |
| 2982 } | 2955 } |
| 2983 | 2956 |
| 2984 string = from_s_chars->string; | 2957 string = from_s_chars->string; |
| 2985 assert (!(FREE_STRUCT_P (string))); | 2958 assert (!(LRECORD_FREE_P (string))); |
| 2986 | 2959 |
| 2987 size = string_length (string); | 2960 size = string_length (string); |
| 2988 fullsize = STRING_FULLSIZE (size); | 2961 fullsize = STRING_FULLSIZE (size); |
| 2989 | 2962 |
| 2990 gc_checking_assert (! BIG_STRING_FULLSIZE_P (fullsize)); | 2963 gc_checking_assert (! BIG_STRING_FULLSIZE_P (fullsize)); |
