Mercurial > emacs
comparison src/alloc.c @ 29743:1d802b332e0d
(mark_object) [GC_CHECK_MARKED_OBJECTS]: Check that no
bogus objects are marked. This slows down GC by ~80 percent, but
it might be worth trying when debugging GC-related problems.
This feature requires conservative stack marking to be enabled.
| author | Gerd Moellmann <gerd@gnu.org> |
|---|---|
| date | Mon, 19 Jun 2000 15:58:43 +0000 |
| parents | fc8d42f77d4f |
| children | 4a3b0c2cbcd5 |
comparison
equal
deleted
inserted
replaced
| 29742:47ad175d6357 | 29743:1d802b332e0d |
|---|---|
| 3783 mark_object (argptr) | 3783 mark_object (argptr) |
| 3784 Lisp_Object *argptr; | 3784 Lisp_Object *argptr; |
| 3785 { | 3785 { |
| 3786 Lisp_Object *objptr = argptr; | 3786 Lisp_Object *objptr = argptr; |
| 3787 register Lisp_Object obj; | 3787 register Lisp_Object obj; |
| 3788 #ifdef GC_CHECK_MARKED_OBJECTS | |
| 3789 void *po; | |
| 3790 struct mem_node *m; | |
| 3791 #endif | |
| 3788 | 3792 |
| 3789 loop: | 3793 loop: |
| 3790 obj = *objptr; | 3794 obj = *objptr; |
| 3791 loop2: | 3795 loop2: |
| 3792 XUNMARK (obj); | 3796 XUNMARK (obj); |
| 3796 | 3800 |
| 3797 last_marked[last_marked_index++] = objptr; | 3801 last_marked[last_marked_index++] = objptr; |
| 3798 if (last_marked_index == LAST_MARKED_SIZE) | 3802 if (last_marked_index == LAST_MARKED_SIZE) |
| 3799 last_marked_index = 0; | 3803 last_marked_index = 0; |
| 3800 | 3804 |
| 3805 /* Perform some sanity checks on the objects marked here. Abort if | |
| 3806 we encounter an object we know is bogus. This increases GC time | |
| 3807 by ~80%, and requires compilation with GC_MARK_STACK != 0. */ | |
| 3808 #ifdef GC_CHECK_MARKED_OBJECTS | |
| 3809 | |
| 3810 po = (void *) XPNTR (obj); | |
| 3811 | |
| 3812 /* Check that the object pointed to by PO is known to be a Lisp | |
| 3813 structure allocated from the heap. */ | |
| 3814 #define CHECK_ALLOCATED() \ | |
| 3815 do { \ | |
| 3816 m = mem_find (po); \ | |
| 3817 if (m == MEM_NIL) \ | |
| 3818 abort (); \ | |
| 3819 } while (0) | |
| 3820 | |
| 3821 /* Check that the object pointed to by PO is live, using predicate | |
| 3822 function LIVEP. */ | |
| 3823 #define CHECK_LIVE(LIVEP) \ | |
| 3824 do { \ | |
| 3825 if (!LIVEP (m, po)) \ | |
| 3826 abort (); \ | |
| 3827 } while (0) | |
| 3828 | |
| 3829 /* Check both of the above conditions. */ | |
| 3830 #define CHECK_ALLOCATED_AND_LIVE(LIVEP) \ | |
| 3831 do { \ | |
| 3832 CHECK_ALLOCATED (); \ | |
| 3833 CHECK_LIVE (LIVEP); \ | |
| 3834 } while (0) \ | |
| 3835 | |
| 3836 #else /* not GC_CHECK_MARKED_OBJECTS */ | |
| 3837 | |
| 3838 #define CHECK_ALLOCATED() (void) 0 | |
| 3839 #define CHECK_LIVE(LIVEP) (void) 0 | |
| 3840 #define CHECK_ALLOCATED_AND_LIVE(LIVEP) (void) 0 | |
| 3841 | |
| 3842 #endif /* not GC_CHECK_MARKED_OBJECTS */ | |
| 3843 | |
| 3801 switch (SWITCH_ENUM_CAST (XGCTYPE (obj))) | 3844 switch (SWITCH_ENUM_CAST (XGCTYPE (obj))) |
| 3802 { | 3845 { |
| 3803 case Lisp_String: | 3846 case Lisp_String: |
| 3804 { | 3847 { |
| 3805 register struct Lisp_String *ptr = XSTRING (obj); | 3848 register struct Lisp_String *ptr = XSTRING (obj); |
| 3849 CHECK_ALLOCATED_AND_LIVE (live_string_p); | |
| 3806 MARK_INTERVAL_TREE (ptr->intervals); | 3850 MARK_INTERVAL_TREE (ptr->intervals); |
| 3807 MARK_STRING (ptr); | 3851 MARK_STRING (ptr); |
| 3808 } | 3852 } |
| 3809 break; | 3853 break; |
| 3810 | 3854 |
| 3811 case Lisp_Vectorlike: | 3855 case Lisp_Vectorlike: |
| 3856 #ifdef GC_CHECK_MARKED_OBJECTS | |
| 3857 m = mem_find (po); | |
| 3858 if (m == MEM_NIL && !GC_SUBRP (obj) | |
| 3859 && po != &buffer_defaults | |
| 3860 && po != &buffer_local_symbols) | |
| 3861 abort (); | |
| 3862 #endif /* GC_CHECK_MARKED_OBJECTS */ | |
| 3863 | |
| 3812 if (GC_BUFFERP (obj)) | 3864 if (GC_BUFFERP (obj)) |
| 3813 { | 3865 { |
| 3814 if (!XMARKBIT (XBUFFER (obj)->name)) | 3866 if (!XMARKBIT (XBUFFER (obj)->name)) |
| 3815 mark_buffer (obj); | 3867 { |
| 3868 #ifdef GC_CHECK_MARKED_OBJECTS | |
| 3869 if (po != &buffer_defaults && po != &buffer_local_symbols) | |
| 3870 { | |
| 3871 struct buffer *b; | |
| 3872 for (b = all_buffers; b && b != po; b = b->next) | |
| 3873 ; | |
| 3874 if (b == NULL) | |
| 3875 abort (); | |
| 3876 } | |
| 3877 #endif /* GC_CHECK_MARKED_OBJECTS */ | |
| 3878 mark_buffer (obj); | |
| 3879 } | |
| 3816 } | 3880 } |
| 3817 else if (GC_SUBRP (obj)) | 3881 else if (GC_SUBRP (obj)) |
| 3818 break; | 3882 break; |
| 3819 else if (GC_COMPILEDP (obj)) | 3883 else if (GC_COMPILEDP (obj)) |
| 3820 /* We could treat this just like a vector, but it is better to | 3884 /* We could treat this just like a vector, but it is better to |
| 3827 struct Lisp_Vector *volatile ptr1 = ptr; | 3891 struct Lisp_Vector *volatile ptr1 = ptr; |
| 3828 register int i; | 3892 register int i; |
| 3829 | 3893 |
| 3830 if (size & ARRAY_MARK_FLAG) | 3894 if (size & ARRAY_MARK_FLAG) |
| 3831 break; /* Already marked */ | 3895 break; /* Already marked */ |
| 3896 | |
| 3897 CHECK_LIVE (live_vector_p); | |
| 3832 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ | 3898 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ |
| 3833 size &= PSEUDOVECTOR_SIZE_MASK; | 3899 size &= PSEUDOVECTOR_SIZE_MASK; |
| 3834 for (i = 0; i < size; i++) /* and then mark its elements */ | 3900 for (i = 0; i < size; i++) /* and then mark its elements */ |
| 3835 { | 3901 { |
| 3836 if (i != COMPILED_CONSTANTS) | 3902 if (i != COMPILED_CONSTANTS) |
| 3848 register EMACS_INT size = ptr->size; | 3914 register EMACS_INT size = ptr->size; |
| 3849 | 3915 |
| 3850 if (size & ARRAY_MARK_FLAG) break; /* Already marked */ | 3916 if (size & ARRAY_MARK_FLAG) break; /* Already marked */ |
| 3851 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ | 3917 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ |
| 3852 | 3918 |
| 3919 CHECK_LIVE (live_vector_p); | |
| 3853 mark_object (&ptr->name); | 3920 mark_object (&ptr->name); |
| 3854 mark_object (&ptr->icon_name); | 3921 mark_object (&ptr->icon_name); |
| 3855 mark_object (&ptr->title); | 3922 mark_object (&ptr->title); |
| 3856 mark_object (&ptr->focus_frame); | 3923 mark_object (&ptr->focus_frame); |
| 3857 mark_object (&ptr->selected_window); | 3924 mark_object (&ptr->selected_window); |
| 3879 { | 3946 { |
| 3880 register struct Lisp_Vector *ptr = XVECTOR (obj); | 3947 register struct Lisp_Vector *ptr = XVECTOR (obj); |
| 3881 | 3948 |
| 3882 if (ptr->size & ARRAY_MARK_FLAG) | 3949 if (ptr->size & ARRAY_MARK_FLAG) |
| 3883 break; /* Already marked */ | 3950 break; /* Already marked */ |
| 3951 CHECK_LIVE (live_vector_p); | |
| 3884 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ | 3952 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ |
| 3885 } | 3953 } |
| 3886 else if (GC_WINDOWP (obj)) | 3954 else if (GC_WINDOWP (obj)) |
| 3887 { | 3955 { |
| 3888 register struct Lisp_Vector *ptr = XVECTOR (obj); | 3956 register struct Lisp_Vector *ptr = XVECTOR (obj); |
| 3900 /* Stop if already marked. */ | 3968 /* Stop if already marked. */ |
| 3901 if (size & ARRAY_MARK_FLAG) | 3969 if (size & ARRAY_MARK_FLAG) |
| 3902 break; | 3970 break; |
| 3903 | 3971 |
| 3904 /* Mark it. */ | 3972 /* Mark it. */ |
| 3973 CHECK_LIVE (live_vector_p); | |
| 3905 ptr->size |= ARRAY_MARK_FLAG; | 3974 ptr->size |= ARRAY_MARK_FLAG; |
| 3906 | 3975 |
| 3907 /* There is no Lisp data above The member CURRENT_MATRIX in | 3976 /* There is no Lisp data above The member CURRENT_MATRIX in |
| 3908 struct WINDOW. Stop marking when that slot is reached. */ | 3977 struct WINDOW. Stop marking when that slot is reached. */ |
| 3909 for (i = 0; | 3978 for (i = 0; |
| 3928 EMACS_INT size = h->size; | 3997 EMACS_INT size = h->size; |
| 3929 | 3998 |
| 3930 /* Stop if already marked. */ | 3999 /* Stop if already marked. */ |
| 3931 if (size & ARRAY_MARK_FLAG) | 4000 if (size & ARRAY_MARK_FLAG) |
| 3932 break; | 4001 break; |
| 3933 | 4002 |
| 3934 /* Mark it. */ | 4003 /* Mark it. */ |
| 4004 CHECK_LIVE (live_vector_p); | |
| 3935 h->size |= ARRAY_MARK_FLAG; | 4005 h->size |= ARRAY_MARK_FLAG; |
| 3936 | 4006 |
| 3937 /* Mark contents. */ | 4007 /* Mark contents. */ |
| 3938 mark_object (&h->test); | 4008 mark_object (&h->test); |
| 3939 mark_object (&h->weak); | 4009 mark_object (&h->weak); |
| 3965 Yes, this is a crock, but we have to do it. */ | 4035 Yes, this is a crock, but we have to do it. */ |
| 3966 struct Lisp_Vector *volatile ptr1 = ptr; | 4036 struct Lisp_Vector *volatile ptr1 = ptr; |
| 3967 register int i; | 4037 register int i; |
| 3968 | 4038 |
| 3969 if (size & ARRAY_MARK_FLAG) break; /* Already marked */ | 4039 if (size & ARRAY_MARK_FLAG) break; /* Already marked */ |
| 4040 CHECK_LIVE (live_vector_p); | |
| 3970 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ | 4041 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ |
| 3971 if (size & PSEUDOVECTOR_FLAG) | 4042 if (size & PSEUDOVECTOR_FLAG) |
| 3972 size &= PSEUDOVECTOR_SIZE_MASK; | 4043 size &= PSEUDOVECTOR_SIZE_MASK; |
| 3973 | 4044 |
| 3974 for (i = 0; i < size; i++) /* and then mark its elements */ | 4045 for (i = 0; i < size; i++) /* and then mark its elements */ |
| 3981 /* See comment above under Lisp_Vector for why this is volatile. */ | 4052 /* See comment above under Lisp_Vector for why this is volatile. */ |
| 3982 register struct Lisp_Symbol *volatile ptr = XSYMBOL (obj); | 4053 register struct Lisp_Symbol *volatile ptr = XSYMBOL (obj); |
| 3983 struct Lisp_Symbol *ptrx; | 4054 struct Lisp_Symbol *ptrx; |
| 3984 | 4055 |
| 3985 if (XMARKBIT (ptr->plist)) break; | 4056 if (XMARKBIT (ptr->plist)) break; |
| 4057 CHECK_ALLOCATED_AND_LIVE (live_symbol_p); | |
| 3986 XMARK (ptr->plist); | 4058 XMARK (ptr->plist); |
| 3987 mark_object ((Lisp_Object *) &ptr->value); | 4059 mark_object ((Lisp_Object *) &ptr->value); |
| 3988 mark_object (&ptr->function); | 4060 mark_object (&ptr->function); |
| 3989 mark_object (&ptr->plist); | 4061 mark_object (&ptr->plist); |
| 3990 | 4062 |
| 4008 } | 4080 } |
| 4009 } | 4081 } |
| 4010 break; | 4082 break; |
| 4011 | 4083 |
| 4012 case Lisp_Misc: | 4084 case Lisp_Misc: |
| 4085 CHECK_ALLOCATED_AND_LIVE (live_misc_p); | |
| 4013 switch (XMISCTYPE (obj)) | 4086 switch (XMISCTYPE (obj)) |
| 4014 { | 4087 { |
| 4015 case Lisp_Misc_Marker: | 4088 case Lisp_Misc_Marker: |
| 4016 XMARK (XMARKER (obj)->chain); | 4089 XMARK (XMARKER (obj)->chain); |
| 4017 /* DO NOT mark thru the marker's chain. | 4090 /* DO NOT mark thru the marker's chain. |
| 4072 | 4145 |
| 4073 case Lisp_Cons: | 4146 case Lisp_Cons: |
| 4074 { | 4147 { |
| 4075 register struct Lisp_Cons *ptr = XCONS (obj); | 4148 register struct Lisp_Cons *ptr = XCONS (obj); |
| 4076 if (XMARKBIT (ptr->car)) break; | 4149 if (XMARKBIT (ptr->car)) break; |
| 4150 CHECK_ALLOCATED_AND_LIVE (live_cons_p); | |
| 4077 XMARK (ptr->car); | 4151 XMARK (ptr->car); |
| 4078 /* If the cdr is nil, avoid recursion for the car. */ | 4152 /* If the cdr is nil, avoid recursion for the car. */ |
| 4079 if (EQ (ptr->cdr, Qnil)) | 4153 if (EQ (ptr->cdr, Qnil)) |
| 4080 { | 4154 { |
| 4081 objptr = &ptr->car; | 4155 objptr = &ptr->car; |
| 4086 objptr = &XCDR (obj); | 4160 objptr = &XCDR (obj); |
| 4087 goto loop; | 4161 goto loop; |
| 4088 } | 4162 } |
| 4089 | 4163 |
| 4090 case Lisp_Float: | 4164 case Lisp_Float: |
| 4165 CHECK_ALLOCATED_AND_LIVE (live_float_p); | |
| 4091 XMARK (XFLOAT (obj)->type); | 4166 XMARK (XFLOAT (obj)->type); |
| 4092 break; | 4167 break; |
| 4093 | 4168 |
| 4094 case Lisp_Int: | 4169 case Lisp_Int: |
| 4095 break; | 4170 break; |
| 4096 | 4171 |
| 4097 default: | 4172 default: |
| 4098 abort (); | 4173 abort (); |
| 4099 } | 4174 } |
| 4175 | |
| 4176 #undef CHECK_LIVE | |
| 4177 #undef CHECK_ALLOCATED | |
| 4178 #undef CHECK_ALLOCATED_AND_LIVE | |
| 4100 } | 4179 } |
| 4101 | 4180 |
| 4102 /* Mark the pointers in a buffer structure. */ | 4181 /* Mark the pointers in a buffer structure. */ |
| 4103 | 4182 |
| 4104 static void | 4183 static void |
