=== modified file 'src/alloc.c' --- src/alloc.c 2012-09-07 07:24:08 +0000 +++ src/alloc.c 2012-09-10 15:04:15 +0000 @@ -6009,6 +6009,12 @@ { struct window *w = (struct window *) ptr; + /* Lisp code removes killed buffers from buffer lists + of live windows. For dead windows, we do it here + in attempt to help GC to reclaim killed buffers. */ + if (!WINDOW_VALID_P (obj)) + window_drain_buffer_lists (w); + mark_vectorlike (ptr); /* Mark glyphs for leaf windows. Marking window matrices is sufficient because frame matrices @@ -6081,10 +6087,10 @@ case SYMBOL_LOCALIZED: { struct Lisp_Buffer_Local_Value *blv = SYMBOL_BLV (ptr); - /* If the value is forwarded to a buffer or keyboard field, - these are marked when we see the corresponding object. - And if it's forwarded to a C variable, either it's not - a Lisp_Object var, or it's staticpro'd already. */ + /* If the value is set up for a killed buffer or deleted + frame, restore it's global binding. */ + if (orphaned_local_binding (blv)) + swap_in_global_binding (ptr); mark_object (blv->where); mark_object (blv->valcell); mark_object (blv->defcell); === modified file 'src/data.c' --- src/data.c 2012-09-09 16:06:33 +0000 +++ src/data.c 2012-09-10 15:11:42 +0000 @@ -1020,7 +1020,18 @@ store_symval_forwarding (blv->fwd, blv_value (blv), NULL); } } - + +/* True if binding is set up for a killed buffer or deleted frame. */ + +bool +orphaned_local_binding (struct Lisp_Buffer_Local_Value *blv) +{ + Lisp_Object where = blv->where; + + return ((BUFFERP (where) && NILP (BVAR (XBUFFER (where), name))) + || (FRAMEP (where) && !FRAME_LIVE_P (XFRAME (where)))); +} + /* Find the value of a symbol, returning Qunbound if it's not bound. This is helpful for code which just wants to get a variable's value if it has one, without signaling an error. === modified file 'src/lisp.h' --- src/lisp.h 2012-09-10 01:17:23 +0000 +++ src/lisp.h 2012-09-10 14:26:18 +0000 @@ -2615,6 +2615,7 @@ extern void set_internal (Lisp_Object, Lisp_Object, Lisp_Object, bool); extern void syms_of_data (void); extern void init_data (void); +extern bool orphaned_local_binding (struct Lisp_Buffer_Local_Value *); extern void swap_in_global_binding (struct Lisp_Symbol *); /* Defined in cmds.c */ === modified file 'src/window.c' --- src/window.c 2012-09-05 07:18:46 +0000 +++ src/window.c 2012-09-10 14:59:00 +0000 @@ -3002,7 +3002,42 @@ FOR_EACH_FRAME (tail, frame) window_loop (REPLACE_BUFFER_IN_WINDOWS_SAFELY, buffer, 1, frame); } - + +/* Change alist started at ALISTPTR so it doesn't contains an items whose + car is a killed buffer. */ + +static inline void +delete_killed_buffers (Lisp_Object *alistptr) +{ + Lisp_Object tail, prev, buffer; + + eassert (alistptr != NULL); + for (tail = *alistptr, prev = Qnil; CONSP (tail); tail = XCDR (tail)) + { + buffer = CAR (XCAR (tail)); + CHECK_BUFFER (buffer); + if (NILP (BVAR (XBUFFER (buffer), name))) + { + if (NILP (prev)) + *alistptr = XCDR (tail); + else + XSETCDR (prev, XCDR (tail)); + } + else + prev = tail; + } +} + +/* Delete killed buffers from both W's window lists. Called during GC + for dead windows only. */ + +void +window_drain_buffer_lists (struct window *w) +{ + delete_killed_buffers (&w->prev_buffers); + delete_killed_buffers (&w->next_buffers); +} + /* If *ROWS or *COLS are too small a size for FRAME, set them to the minimum allowable size. */ === modified file 'src/window.h' --- src/window.h 2012-09-05 17:05:32 +0000 +++ src/window.h 2012-09-10 14:59:27 +0000 @@ -978,6 +978,7 @@ extern void temp_output_buffer_show (Lisp_Object); extern void replace_buffer_in_windows (Lisp_Object); extern void replace_buffer_in_windows_safely (Lisp_Object); +extern void window_drain_buffer_lists (struct window *); extern void init_window_once (void); extern void init_window (void); extern void syms_of_window (void);