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)