Mercurial > emacs
comparison src/alloc.c @ 25024:3bb745067f0e
(gc_sweep): Call sweep_weak_hash_tables.
(survives_gc_p): New.
(mark_object): Mark objects referenced from glyphs, hash tables,
toolbar date, toolbar window, face caches, menu bar window.
Mark windows specially.
(Fgarbage_collect): Use message3_nolog.
(mark_face_cache): New.
(NSTATICS): Increased to 1024.
(mark_glyph_matrix): New.
author | Gerd Moellmann <gerd@gnu.org> |
---|---|
date | Wed, 21 Jul 1999 21:43:52 +0000 |
parents | 2eb9e2f5aa33 |
children | 11070f3c5b59 |
comparison
equal
deleted
inserted
replaced
25023:6e3de2f65704 | 25024:3bb745067f0e |
---|---|
190 /* Non-zero means ignore malloc warnings. Set during initialization. */ | 190 /* Non-zero means ignore malloc warnings. Set during initialization. */ |
191 int ignore_warnings; | 191 int ignore_warnings; |
192 | 192 |
193 Lisp_Object Qgc_cons_threshold, Qchar_table_extra_slots; | 193 Lisp_Object Qgc_cons_threshold, Qchar_table_extra_slots; |
194 | 194 |
195 static void mark_object (), mark_buffer (), mark_kboards (); | 195 static void mark_buffer (), mark_kboards (); |
196 static void clear_marks (), gc_sweep (); | 196 static void clear_marks (), gc_sweep (); |
197 static void compact_strings (); | 197 static void compact_strings (); |
198 static void mark_glyph_matrix P_ ((struct glyph_matrix *)); | |
199 static void mark_face_cache P_ ((struct face_cache *)); | |
200 | |
201 #ifdef HAVE_WINDOW_SYSTEM | |
202 static void mark_image P_ ((struct image *)); | |
203 static void mark_image_cache P_ ((struct frame *)); | |
204 #endif /* HAVE_WINDOW_SYSTEM */ | |
205 | |
198 | 206 |
199 extern int message_enable_multibyte; | 207 extern int message_enable_multibyte; |
200 | 208 |
201 /* Versions of malloc and realloc that print warnings as memory gets full. */ | 209 /* Versions of malloc and realloc that print warnings as memory gets full. */ |
202 | 210 |
1665 | 1673 |
1666 /* Recording what needs to be marked for gc. */ | 1674 /* Recording what needs to be marked for gc. */ |
1667 | 1675 |
1668 struct gcpro *gcprolist; | 1676 struct gcpro *gcprolist; |
1669 | 1677 |
1670 #define NSTATICS 768 | 1678 #define NSTATICS 1024 |
1671 | 1679 |
1672 Lisp_Object *staticvec[NSTATICS] = {0}; | 1680 Lisp_Object *staticvec[NSTATICS] = {0}; |
1673 | 1681 |
1674 int staticidx = 0; | 1682 int staticidx = 0; |
1675 | 1683 |
1737 struct catchtag *catch; | 1745 struct catchtag *catch; |
1738 struct handler *handler; | 1746 struct handler *handler; |
1739 register struct backtrace *backlist; | 1747 register struct backtrace *backlist; |
1740 register Lisp_Object tem; | 1748 register Lisp_Object tem; |
1741 char *omessage = echo_area_glyphs; | 1749 char *omessage = echo_area_glyphs; |
1750 Lisp_Object omessage_string = echo_area_message; | |
1742 int omessage_length = echo_area_glyphs_length; | 1751 int omessage_length = echo_area_glyphs_length; |
1743 int oldmultibyte = message_enable_multibyte; | 1752 int oldmultibyte = message_enable_multibyte; |
1744 char stack_top_variable; | 1753 char stack_top_variable; |
1745 register int i; | 1754 register int i; |
1755 struct gcpro gcpro1; | |
1746 | 1756 |
1747 /* In case user calls debug_print during GC, | 1757 /* In case user calls debug_print during GC, |
1748 don't let that cause a recursive GC. */ | 1758 don't let that cause a recursive GC. */ |
1749 consing_since_gc = 0; | 1759 consing_since_gc = 0; |
1760 | |
1761 GCPRO1 (omessage_string); | |
1750 | 1762 |
1751 /* Save a copy of the contents of the stack, for debugging. */ | 1763 /* Save a copy of the contents of the stack, for debugging. */ |
1752 #if MAX_SAVE_STACK > 0 | 1764 #if MAX_SAVE_STACK > 0 |
1753 if (NILP (Vpurify_flag)) | 1765 if (NILP (Vpurify_flag)) |
1754 { | 1766 { |
1928 if (gc_cons_threshold < 10000) | 1940 if (gc_cons_threshold < 10000) |
1929 gc_cons_threshold = 10000; | 1941 gc_cons_threshold = 10000; |
1930 | 1942 |
1931 if (garbage_collection_messages) | 1943 if (garbage_collection_messages) |
1932 { | 1944 { |
1945 if (STRINGP (omessage_string)) | |
1946 message3_nolog (omessage_string, omessage_length, oldmultibyte); | |
1933 if (omessage || minibuf_level > 0) | 1947 if (omessage || minibuf_level > 0) |
1934 message2_nolog (omessage, omessage_length, oldmultibyte); | 1948 message2_nolog (omessage, omessage_length, oldmultibyte); |
1935 else | 1949 else |
1936 message1_nolog ("Garbage collecting...done"); | 1950 message1_nolog ("Garbage collecting...done"); |
1937 } | 1951 } |
1938 | 1952 |
1953 UNGCPRO; | |
1939 return Fcons (Fcons (make_number (total_conses), | 1954 return Fcons (Fcons (make_number (total_conses), |
1940 make_number (total_free_conses)), | 1955 make_number (total_free_conses)), |
1941 Fcons (Fcons (make_number (total_symbols), | 1956 Fcons (Fcons (make_number (total_symbols), |
1942 make_number (total_free_symbols)), | 1957 make_number (total_free_symbols)), |
1943 Fcons (Fcons (make_number (total_markers), | 1958 Fcons (Fcons (make_number (total_markers), |
2017 nextb = nextb->next; | 2032 nextb = nextb->next; |
2018 } | 2033 } |
2019 } | 2034 } |
2020 } | 2035 } |
2021 #endif | 2036 #endif |
2037 | |
2038 /* Mark Lisp objects in glyph matrix MATRIX. */ | |
2039 | |
2040 static void | |
2041 mark_glyph_matrix (matrix) | |
2042 struct glyph_matrix *matrix; | |
2043 { | |
2044 struct glyph_row *row = matrix->rows; | |
2045 struct glyph_row *end = row + matrix->nrows; | |
2046 | |
2047 while (row < end) | |
2048 { | |
2049 if (row->enabled_p) | |
2050 { | |
2051 int area; | |
2052 for (area = LEFT_MARGIN_AREA; area < LAST_AREA; ++area) | |
2053 { | |
2054 struct glyph *glyph = row->glyphs[area]; | |
2055 struct glyph *end_glyph = glyph + row->used[area]; | |
2056 | |
2057 while (glyph < end_glyph) | |
2058 { | |
2059 if (/* OBJECT Is zero for face extending glyphs, padding | |
2060 spaces and such. */ | |
2061 glyph->object | |
2062 /* Marking the buffer itself should not be necessary. */ | |
2063 && !BUFFERP (glyph->object)) | |
2064 mark_object (&glyph->object); | |
2065 ++glyph; | |
2066 } | |
2067 } | |
2068 } | |
2069 | |
2070 ++row; | |
2071 } | |
2072 } | |
2073 | |
2074 /* Mark Lisp faces in the face cache C. */ | |
2075 | |
2076 static void | |
2077 mark_face_cache (c) | |
2078 struct face_cache *c; | |
2079 { | |
2080 if (c) | |
2081 { | |
2082 int i, j; | |
2083 for (i = 0; i < c->used; ++i) | |
2084 { | |
2085 struct face *face = FACE_FROM_ID (c->f, i); | |
2086 | |
2087 if (face) | |
2088 { | |
2089 for (j = 0; j < LFACE_VECTOR_SIZE; ++j) | |
2090 mark_object (&face->lface[j]); | |
2091 mark_object (&face->registry); | |
2092 } | |
2093 } | |
2094 } | |
2095 } | |
2096 | |
2097 | |
2098 #ifdef HAVE_WINDOW_SYSTEM | |
2099 | |
2100 /* Mark Lisp objects in image IMG. */ | |
2101 | |
2102 static void | |
2103 mark_image (img) | |
2104 struct image *img; | |
2105 { | |
2106 mark_object (&img->spec); | |
2107 | |
2108 if (!NILP (img->data.lisp_val)) | |
2109 mark_object (&img->data.lisp_val); | |
2110 } | |
2111 | |
2112 | |
2113 /* Mark Lisp objects in image cache of frame F. It's done this way so | |
2114 that we don't have to include xterm.h here. */ | |
2115 | |
2116 static void | |
2117 mark_image_cache (f) | |
2118 struct frame *f; | |
2119 { | |
2120 forall_images_in_image_cache (f, mark_image); | |
2121 } | |
2122 | |
2123 #endif /* HAVE_X_WINDOWS */ | |
2124 | |
2125 | |
2022 | 2126 |
2023 /* Mark reference to a Lisp_Object. | 2127 /* Mark reference to a Lisp_Object. |
2024 If the object referred to has not been seen yet, recursively mark | 2128 If the object referred to has not been seen yet, recursively mark |
2025 all the references contained in it. | 2129 all the references contained in it. |
2026 | 2130 |
2032 | 2136 |
2033 #define LAST_MARKED_SIZE 500 | 2137 #define LAST_MARKED_SIZE 500 |
2034 Lisp_Object *last_marked[LAST_MARKED_SIZE]; | 2138 Lisp_Object *last_marked[LAST_MARKED_SIZE]; |
2035 int last_marked_index; | 2139 int last_marked_index; |
2036 | 2140 |
2037 static void | 2141 void |
2038 mark_object (argptr) | 2142 mark_object (argptr) |
2039 Lisp_Object *argptr; | 2143 Lisp_Object *argptr; |
2040 { | 2144 { |
2041 Lisp_Object *objptr = argptr; | 2145 Lisp_Object *objptr = argptr; |
2042 register Lisp_Object obj; | 2146 register Lisp_Object obj; |
2142 mark_object (&ptr->menu_bar_items); | 2246 mark_object (&ptr->menu_bar_items); |
2143 mark_object (&ptr->face_alist); | 2247 mark_object (&ptr->face_alist); |
2144 mark_object (&ptr->menu_bar_vector); | 2248 mark_object (&ptr->menu_bar_vector); |
2145 mark_object (&ptr->buffer_predicate); | 2249 mark_object (&ptr->buffer_predicate); |
2146 mark_object (&ptr->buffer_list); | 2250 mark_object (&ptr->buffer_list); |
2251 mark_object (&ptr->menu_bar_window); | |
2252 mark_object (&ptr->toolbar_window); | |
2253 mark_face_cache (ptr->face_cache); | |
2254 #ifdef HAVE_WINDOW_SYSTEM | |
2255 mark_image_cache (ptr); | |
2256 mark_object (&ptr->desired_toolbar_items); | |
2257 mark_object (&ptr->current_toolbar_items); | |
2258 mark_object (&ptr->desired_toolbar_string); | |
2259 mark_object (&ptr->current_toolbar_string); | |
2260 #endif /* HAVE_WINDOW_SYSTEM */ | |
2147 } | 2261 } |
2148 else if (GC_BOOL_VECTOR_P (obj)) | 2262 else if (GC_BOOL_VECTOR_P (obj)) |
2149 { | 2263 { |
2150 register struct Lisp_Vector *ptr = XVECTOR (obj); | 2264 register struct Lisp_Vector *ptr = XVECTOR (obj); |
2151 | 2265 |
2152 if (ptr->size & ARRAY_MARK_FLAG) | 2266 if (ptr->size & ARRAY_MARK_FLAG) |
2153 break; /* Already marked */ | 2267 break; /* Already marked */ |
2154 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ | 2268 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ |
2269 } | |
2270 else if (GC_WINDOWP (obj)) | |
2271 { | |
2272 register struct Lisp_Vector *ptr = XVECTOR (obj); | |
2273 struct window *w = XWINDOW (obj); | |
2274 register EMACS_INT size = ptr->size; | |
2275 /* The reason we use ptr1 is to avoid an apparent hardware bug | |
2276 that happens occasionally on the FSF's HP 300s. | |
2277 The bug is that a2 gets clobbered by recursive calls to mark_object. | |
2278 The clobberage seems to happen during function entry, | |
2279 perhaps in the moveml instruction. | |
2280 Yes, this is a crock, but we have to do it. */ | |
2281 struct Lisp_Vector *volatile ptr1 = ptr; | |
2282 register int i; | |
2283 | |
2284 /* Stop if already marked. */ | |
2285 if (size & ARRAY_MARK_FLAG) | |
2286 break; | |
2287 | |
2288 /* Mark it. */ | |
2289 ptr->size |= ARRAY_MARK_FLAG; | |
2290 | |
2291 /* There is no Lisp data above The member CURRENT_MATRIX in | |
2292 struct WINDOW. Stop marking when that slot is reached. */ | |
2293 for (i = 0; | |
2294 (char *) &ptr1->contents[i] < (char *) &w->current_matrix; | |
2295 i++) | |
2296 mark_object (&ptr1->contents[i]); | |
2297 | |
2298 /* Mark glyphs for leaf windows. Marking window matrices is | |
2299 sufficient because frame matrices use the same glyph | |
2300 memory. */ | |
2301 if (NILP (w->hchild) | |
2302 && NILP (w->vchild) | |
2303 && w->current_matrix) | |
2304 { | |
2305 mark_glyph_matrix (w->current_matrix); | |
2306 mark_glyph_matrix (w->desired_matrix); | |
2307 } | |
2308 } | |
2309 else if (GC_HASH_TABLE_P (obj)) | |
2310 { | |
2311 struct Lisp_Hash_Table *h = XHASH_TABLE (obj); | |
2312 EMACS_INT size = h->size; | |
2313 | |
2314 /* Stop if already marked. */ | |
2315 if (size & ARRAY_MARK_FLAG) | |
2316 break; | |
2317 | |
2318 /* Mark it. */ | |
2319 h->size |= ARRAY_MARK_FLAG; | |
2320 | |
2321 /* Mark contents. */ | |
2322 mark_object (&h->test); | |
2323 mark_object (&h->weak); | |
2324 mark_object (&h->rehash_size); | |
2325 mark_object (&h->rehash_threshold); | |
2326 mark_object (&h->hash); | |
2327 mark_object (&h->next); | |
2328 mark_object (&h->index); | |
2329 mark_object (&h->user_hash_function); | |
2330 mark_object (&h->user_cmp_function); | |
2331 | |
2332 /* If hash table is not weak, mark all keys and values. | |
2333 For weak tables, mark only the vector. */ | |
2334 if (GC_NILP (h->weak)) | |
2335 mark_object (&h->key_and_value); | |
2336 else | |
2337 XVECTOR (h->key_and_value)->size |= ARRAY_MARK_FLAG; | |
2338 | |
2155 } | 2339 } |
2156 else | 2340 else |
2157 { | 2341 { |
2158 register struct Lisp_Vector *ptr = XVECTOR (obj); | 2342 register struct Lisp_Vector *ptr = XVECTOR (obj); |
2159 register EMACS_INT size = ptr->size; | 2343 register EMACS_INT size = ptr->size; |
2168 | 2352 |
2169 if (size & ARRAY_MARK_FLAG) break; /* Already marked */ | 2353 if (size & ARRAY_MARK_FLAG) break; /* Already marked */ |
2170 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ | 2354 ptr->size |= ARRAY_MARK_FLAG; /* Else mark it */ |
2171 if (size & PSEUDOVECTOR_FLAG) | 2355 if (size & PSEUDOVECTOR_FLAG) |
2172 size &= PSEUDOVECTOR_SIZE_MASK; | 2356 size &= PSEUDOVECTOR_SIZE_MASK; |
2357 | |
2173 for (i = 0; i < size; i++) /* and then mark its elements */ | 2358 for (i = 0; i < size; i++) /* and then mark its elements */ |
2174 mark_object (&ptr1->contents[i]); | 2359 mark_object (&ptr1->contents[i]); |
2175 } | 2360 } |
2176 break; | 2361 break; |
2177 | 2362 |
2185 XMARK (ptr->plist); | 2370 XMARK (ptr->plist); |
2186 mark_object ((Lisp_Object *) &ptr->value); | 2371 mark_object ((Lisp_Object *) &ptr->value); |
2187 mark_object (&ptr->function); | 2372 mark_object (&ptr->function); |
2188 mark_object (&ptr->plist); | 2373 mark_object (&ptr->plist); |
2189 XSETTYPE (*(Lisp_Object *) &ptr->name, Lisp_String); | 2374 XSETTYPE (*(Lisp_Object *) &ptr->name, Lisp_String); |
2190 mark_object (&ptr->name); | 2375 mark_object ((Lisp_Object *) &ptr->name); |
2191 /* Note that we do not mark the obarray of the symbol. | 2376 /* Note that we do not mark the obarray of the symbol. |
2192 It is safe not to do so because nothing accesses that | 2377 It is safe not to do so because nothing accesses that |
2193 slot except to check whether it is nil. */ | 2378 slot except to check whether it is nil. */ |
2194 ptr = ptr->next; | 2379 ptr = ptr->next; |
2195 if (ptr) | 2380 if (ptr) |
2401 mark_object (&kb->Vsystem_key_alist); | 2586 mark_object (&kb->Vsystem_key_alist); |
2402 mark_object (&kb->system_key_syms); | 2587 mark_object (&kb->system_key_syms); |
2403 mark_object (&kb->Vdefault_minibuffer_frame); | 2588 mark_object (&kb->Vdefault_minibuffer_frame); |
2404 } | 2589 } |
2405 } | 2590 } |
2591 | |
2592 | |
2593 /* Value is non-zero if OBJ will survive the current GC because it's | |
2594 either marked or does not need to be marked to survive. */ | |
2595 | |
2596 int | |
2597 survives_gc_p (obj) | |
2598 Lisp_Object obj; | |
2599 { | |
2600 int survives_p; | |
2601 | |
2602 switch (XGCTYPE (obj)) | |
2603 { | |
2604 case Lisp_Int: | |
2605 survives_p = 1; | |
2606 break; | |
2607 | |
2608 case Lisp_Symbol: | |
2609 survives_p = XMARKBIT (XSYMBOL (obj)->plist); | |
2610 break; | |
2611 | |
2612 case Lisp_Misc: | |
2613 switch (XMISCTYPE (obj)) | |
2614 { | |
2615 case Lisp_Misc_Marker: | |
2616 survives_p = XMARKBIT (obj); | |
2617 break; | |
2618 | |
2619 case Lisp_Misc_Buffer_Local_Value: | |
2620 case Lisp_Misc_Some_Buffer_Local_Value: | |
2621 survives_p = XMARKBIT (XBUFFER_LOCAL_VALUE (obj)->realvalue); | |
2622 break; | |
2623 | |
2624 case Lisp_Misc_Intfwd: | |
2625 case Lisp_Misc_Boolfwd: | |
2626 case Lisp_Misc_Objfwd: | |
2627 case Lisp_Misc_Buffer_Objfwd: | |
2628 case Lisp_Misc_Kboard_Objfwd: | |
2629 survives_p = 1; | |
2630 break; | |
2631 | |
2632 case Lisp_Misc_Overlay: | |
2633 survives_p = XMARKBIT (XOVERLAY (obj)->plist); | |
2634 break; | |
2635 | |
2636 default: | |
2637 abort (); | |
2638 } | |
2639 break; | |
2640 | |
2641 case Lisp_String: | |
2642 { | |
2643 struct Lisp_String *s = XSTRING (obj); | |
2644 | |
2645 if (s->size & MARKBIT) | |
2646 survives_p = s->size & ARRAY_MARK_FLAG; | |
2647 else | |
2648 survives_p = (s->size & ~DONT_COPY_FLAG) > STRING_BLOCK_SIZE; | |
2649 } | |
2650 break; | |
2651 | |
2652 case Lisp_Vectorlike: | |
2653 if (GC_BUFFERP (obj)) | |
2654 survives_p = XMARKBIT (XBUFFER (obj)->name); | |
2655 else if (GC_SUBRP (obj)) | |
2656 survives_p = 1; | |
2657 else | |
2658 survives_p = XVECTOR (obj)->size & ARRAY_MARK_FLAG; | |
2659 break; | |
2660 | |
2661 case Lisp_Cons: | |
2662 survives_p = XMARKBIT (XCAR (obj)); | |
2663 break; | |
2664 | |
2665 #ifdef LISP_FLOAT_TYPE | |
2666 case Lisp_Float: | |
2667 survives_p = XMARKBIT (XFLOAT (obj)->type); | |
2668 break; | |
2669 #endif /* LISP_FLOAT_TYPE */ | |
2670 | |
2671 default: | |
2672 abort (); | |
2673 } | |
2674 | |
2675 return survives_p; | |
2676 } | |
2677 | |
2678 | |
2406 | 2679 |
2407 /* Sweep: find all structures not marked, and free them. */ | 2680 /* Sweep: find all structures not marked, and free them. */ |
2408 | 2681 |
2409 static void | 2682 static void |
2410 gc_sweep () | 2683 gc_sweep () |
2411 { | 2684 { |
2685 /* Remove or mark entries in weak hash tables. | |
2686 This must be done before any object is unmarked. */ | |
2687 sweep_weak_hash_tables (); | |
2688 | |
2412 total_string_size = 0; | 2689 total_string_size = 0; |
2413 compact_strings (); | 2690 compact_strings (); |
2414 | 2691 |
2415 /* Put all unmarked conses on free list */ | 2692 /* Put all unmarked conses on free list */ |
2416 { | 2693 { |
2744 total_vector_size = 0; | 3021 total_vector_size = 0; |
2745 | 3022 |
2746 while (vector) | 3023 while (vector) |
2747 if (!(vector->size & ARRAY_MARK_FLAG)) | 3024 if (!(vector->size & ARRAY_MARK_FLAG)) |
2748 { | 3025 { |
3026 #if 0 | |
3027 if ((vector->size & (PSEUDOVECTOR_FLAG | PVEC_HASH_TABLE)) | |
3028 == (PSEUDOVECTOR_FLAG | PVEC_HASH_TABLE)) | |
3029 fprintf (stderr, "Freeing hash table %p\n", vector); | |
3030 #endif | |
2749 if (prev) | 3031 if (prev) |
2750 prev->next = vector->next; | 3032 prev->next = vector->next; |
2751 else | 3033 else |
2752 all_vectors = vector->next; | 3034 all_vectors = vector->next; |
2753 next = vector->next; | 3035 next = vector->next; |
2754 lisp_free (vector); | 3036 lisp_free (vector); |
2755 n_vectors--; | 3037 n_vectors--; |
2756 vector = next; | 3038 vector = next; |
3039 | |
2757 } | 3040 } |
2758 else | 3041 else |
2759 { | 3042 { |
2760 vector->size &= ~ARRAY_MARK_FLAG; | 3043 vector->size &= ~ARRAY_MARK_FLAG; |
2761 if (vector->size & PSEUDOVECTOR_FLAG) | 3044 if (vector->size & PSEUDOVECTOR_FLAG) |