changeset 5169:6c6d78781d59

cleanup of code related to xfree(), better KKCC backtrace capabilities, document XD_INLINE_LISP_OBJECT_BLOCK_PTR, fix some memory leaks, other code cleanup -------------------- ChangeLog entries follow: -------------------- src/ChangeLog addition: 2010-03-24 Ben Wing <ben@xemacs.org> * array.h: * array.h (XD_LISP_DYNARR_DESC): * dumper.c (pdump_register_sub): * dumper.c (pdump_store_new_pointer_offsets): * dumper.c (pdump_reloc_one_mc): * elhash.c: * gc.c (lispdesc_one_description_line_size): * gc.c (kkcc_marking): * lrecord.h: * lrecord.h (IF_NEW_GC): * lrecord.h (enum memory_description_type): * lrecord.h (enum data_description_entry_flags): * lrecord.h (struct opaque_convert_functions): Rename XD_LISP_OBJECT_BLOCK_PTR to XD_INLINE_LISP_OBJECT_BLOCK_PTR and document it in lrecord.h. * data.c: * data.c (finish_marking_weak_lists): * data.c (continue_marking_ephemerons): * data.c (finish_marking_ephemerons): * elhash.c (MARK_OBJ): * gc.c: * gc.c (lispdesc_indirect_count_1): * gc.c (struct): * gc.c (kkcc_bt_push): * gc.c (kkcc_gc_stack_push): * gc.c (kkcc_gc_stack_push_lisp_object): * gc.c (kkcc_gc_stack_repush_dirty_object): * gc.c (KKCC_DO_CHECK_FREE): * gc.c (mark_object_maybe_checking_free): * gc.c (mark_struct_contents): * gc.c (mark_lisp_object_block_contents): * gc.c (register_for_finalization): * gc.c (mark_object): * gc.h: * lisp.h: * profile.c: * profile.c (mark_profiling_info_maphash): Clean up KKCC code related to DEBUG_XEMACS. Rename kkcc_backtrace() to kkcc_backtrace_1() and add two params: a `size' arg to control how many stack elements to print and a `detailed' arg to control whether Lisp objects are printed using `debug_print()'. Create front-ends to kkcc_backtrace_1() -- kkcc_detailed_backtrace(), kkcc_short_backtrace(), kkcc_detailed_backtrace_full(), kkcc_short_backtrace_full(), as well as shortened versions kbt(), kbts(), kbtf(), kbtsf() -- to call it with various parameter values. Add an `is_lisp' field to the stack and backtrace structures and use it to keep track of whether an object pushed onto the stack is a Lisp object or a non-Lisp structure; in kkcc_backtrace_1(), don't try to print a non-Lisp structure as a Lisp object. * elhash.c: * extents.c: * file-coding.c: * lrecord.h: * lrecord.h (IF_NEW_GC): * marker.c: * marker.c (Fmarker_buffer): * mule-coding.c: * number.c: * rangetab.c: * specifier.c: New macros IF_OLD_GC(), IF_NEW_GC() to simplify declaration of Lisp objects when a finalizer may exist in one but not the other. Use them appropriately. * extents.c (finalize_extent_info): Don't zero out data->soe and data->extents before trying to free, else we get memory leaks. * lrecord.h (enum lrecord_type): Make the first lrecord type have value 1 not 0 so that 0 remains without implementation and attempts to interpret zeroed memory as a Lisp object will be more obvious. * array.c (Dynarr_free): * device-msw.c (msprinter_delete_device): * device-tty.c (free_tty_device_struct): * device-tty.c (tty_delete_device): * dialog-msw.c (handle_directory_dialog_box): * dialog-x.c: * emacs.c (free_argc_argv): * emodules.c (attempt_module_delete): * file-coding.c (chain_finalize_coding_stream_1): * file-coding.c (chain_finalize_coding_stream): * glyphs-eimage.c: * glyphs-eimage.c (jpeg_instantiate_unwind): * glyphs-eimage.c (gif_instantiate_unwind): * glyphs-eimage.c (png_instantiate_unwind): * glyphs-eimage.c (tiff_instantiate_unwind): * imgproc.c: * imgproc.c (build_EImage_quantable): * insdel.c (uninit_buffer_text): * mule-coding.c (iso2022_finalize_detection_state): * objects-tty.c (tty_finalize_color_instance): * objects-tty.c (tty_finalize_font_instance): * objects-tty.c (tty_font_list): * process.c: * process.c (finalize_process): * redisplay.c (add_propagation_runes): * scrollbar-gtk.c: * scrollbar-gtk.c (gtk_free_scrollbar_instance): * scrollbar-gtk.c (gtk_release_scrollbar_instance): * scrollbar-msw.c: * scrollbar-msw.c (mswindows_free_scrollbar_instance): * scrollbar-msw.c (unshow_that_mofo): * scrollbar-x.c (x_free_scrollbar_instance): * scrollbar-x.c (x_release_scrollbar_instance): * select-x.c: * select-x.c (x_handle_selection_request): * syntax.c: * syntax.c (uninit_buffer_syntax_cache): * text.h (eifree): If possible, whenever we call xfree() on a field in a structure, set the field to 0 afterwards. A lot of code is written so that it checks the value being freed to see if it is non-zero before freeing it -- doing this and setting the value to 0 afterwards ensures (a) we won't try to free twice if the cleanup code is called twice; (b) if the object itself stays around, KKCC won't crash when attempting to mark the freed field. * rangetab.c: Add a finalization method when not NEW_GC to avoid memory leaks. (#### We still get memory leaks when NEW_GC; need to convert gap array to Lisp object).
author Ben Wing <ben@xemacs.org>
date Wed, 24 Mar 2010 01:22:51 -0500
parents cf900a2f1fa3
children 5ddbab03b0e6
files src/ChangeLog src/array.c src/array.h src/data.c src/device-msw.c src/device-tty.c src/dialog-msw.c src/dialog-x.c src/dumper.c src/elhash.c src/emacs.c src/emodules.c src/extents.c src/file-coding.c src/gc.c src/gc.h src/glyphs-eimage.c src/imgproc.c src/insdel.c src/lisp.h src/lrecord.h src/marker.c src/mule-coding.c src/number.c src/objects-tty.c src/process.c src/profile.c src/rangetab.c src/redisplay.c src/scrollbar-gtk.c src/scrollbar-msw.c src/scrollbar-x.c src/select-x.c src/specifier.c src/syntax.c src/text.h
diffstat 36 files changed, 534 insertions(+), 288 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/ChangeLog	Wed Mar 24 01:22:51 2010 -0500
@@ -1,3 +1,132 @@
+2010-03-24  Ben Wing  <ben@xemacs.org>
+
+	* array.h:
+	* array.h (XD_LISP_DYNARR_DESC):
+	* dumper.c (pdump_register_sub):
+	* dumper.c (pdump_store_new_pointer_offsets):
+	* dumper.c (pdump_reloc_one_mc):
+	* elhash.c:
+	* gc.c (lispdesc_one_description_line_size):
+	* gc.c (kkcc_marking):
+	* lrecord.h:
+	* lrecord.h (IF_NEW_GC):
+	* lrecord.h (enum memory_description_type):
+	* lrecord.h (enum data_description_entry_flags):
+	* lrecord.h (struct opaque_convert_functions):
+	Rename XD_LISP_OBJECT_BLOCK_PTR to XD_INLINE_LISP_OBJECT_BLOCK_PTR
+	and document it in lrecord.h.
+
+	* data.c:
+	* data.c (finish_marking_weak_lists):
+	* data.c (continue_marking_ephemerons):
+	* data.c (finish_marking_ephemerons):
+	* elhash.c (MARK_OBJ):
+	* gc.c:
+	* gc.c (lispdesc_indirect_count_1):
+	* gc.c (struct):
+	* gc.c (kkcc_bt_push):
+	* gc.c (kkcc_gc_stack_push):
+	* gc.c (kkcc_gc_stack_push_lisp_object):
+	* gc.c (kkcc_gc_stack_repush_dirty_object):
+	* gc.c (KKCC_DO_CHECK_FREE):
+	* gc.c (mark_object_maybe_checking_free):
+	* gc.c (mark_struct_contents):
+	* gc.c (mark_lisp_object_block_contents):
+	* gc.c (register_for_finalization):
+	* gc.c (mark_object):
+	* gc.h:
+	* lisp.h:
+	* profile.c:
+	* profile.c (mark_profiling_info_maphash):
+	Clean up KKCC code related to DEBUG_XEMACS.  Rename
+	kkcc_backtrace() to kkcc_backtrace_1() and add two params: a
+	`size' arg to control how many stack elements to print and a
+	`detailed' arg to control whether Lisp objects are printed using
+	`debug_print()'.  Create front-ends to kkcc_backtrace_1() --
+	kkcc_detailed_backtrace(), kkcc_short_backtrace(),
+	kkcc_detailed_backtrace_full(), kkcc_short_backtrace_full(), as
+	well as shortened versions kbt(), kbts(), kbtf(), kbtsf() -- to
+	call it with various parameter values.  Add an `is_lisp' field to
+	the stack and backtrace structures and use it to keep track of
+	whether an object pushed onto the stack is a Lisp object or a
+	non-Lisp structure; in kkcc_backtrace_1(), don't try to print a
+	non-Lisp structure as a Lisp object.
+	
+	* elhash.c:
+	* extents.c:
+	* file-coding.c:
+	* lrecord.h:
+	* lrecord.h (IF_NEW_GC):
+	* marker.c:
+	* marker.c (Fmarker_buffer):
+	* mule-coding.c:
+	* number.c:
+	* rangetab.c:
+	* specifier.c:
+	New macros IF_OLD_GC(), IF_NEW_GC() to simplify declaration of
+	Lisp objects when a finalizer may exist in one but not the other.
+	Use them appropriately.
+
+	* extents.c (finalize_extent_info):
+	Don't zero out data->soe and data->extents before trying to free,
+	else we get memory leaks.
+	
+	* lrecord.h (enum lrecord_type):
+	Make the first lrecord type have value 1 not 0 so that 0 remains
+	without implementation and attempts to interpret zeroed memory
+	as a Lisp object will be more obvious.
+
+	* array.c (Dynarr_free):
+	* device-msw.c (msprinter_delete_device):
+	* device-tty.c (free_tty_device_struct):
+	* device-tty.c (tty_delete_device):
+	* dialog-msw.c (handle_directory_dialog_box):
+	* dialog-x.c:
+	* emacs.c (free_argc_argv):
+	* emodules.c (attempt_module_delete):
+	* file-coding.c (chain_finalize_coding_stream_1):
+	* file-coding.c (chain_finalize_coding_stream):
+	* glyphs-eimage.c:
+	* glyphs-eimage.c (jpeg_instantiate_unwind):
+	* glyphs-eimage.c (gif_instantiate_unwind):
+	* glyphs-eimage.c (png_instantiate_unwind):
+	* glyphs-eimage.c (tiff_instantiate_unwind):
+	* imgproc.c:
+	* imgproc.c (build_EImage_quantable):
+	* insdel.c (uninit_buffer_text):
+	* mule-coding.c (iso2022_finalize_detection_state):
+	* objects-tty.c (tty_finalize_color_instance):
+	* objects-tty.c (tty_finalize_font_instance):
+	* objects-tty.c (tty_font_list):
+	* process.c:
+	* process.c (finalize_process):
+	* redisplay.c (add_propagation_runes):
+	* scrollbar-gtk.c:
+	* scrollbar-gtk.c (gtk_free_scrollbar_instance):
+	* scrollbar-gtk.c (gtk_release_scrollbar_instance):
+	* scrollbar-msw.c:
+	* scrollbar-msw.c (mswindows_free_scrollbar_instance):
+	* scrollbar-msw.c (unshow_that_mofo):
+	* scrollbar-x.c (x_free_scrollbar_instance):
+	* scrollbar-x.c (x_release_scrollbar_instance):
+	* select-x.c:
+	* select-x.c (x_handle_selection_request):
+	* syntax.c:
+	* syntax.c (uninit_buffer_syntax_cache):
+	* text.h (eifree):
+	If possible, whenever we call xfree() on a field in a structure,
+	set the field to 0 afterwards.  A lot of code is written so that
+	it checks the value being freed to see if it is non-zero before
+	freeing it -- doing this and setting the value to 0 afterwards
+	ensures (a) we won't try to free twice if the cleanup code is
+	called twice; (b) if the object itself stays around, KKCC won't
+	crash when attempting to mark the freed field.
+
+	* rangetab.c:
+	Add a finalization method when not NEW_GC to avoid memory leaks.
+	(#### We still get memory leaks when NEW_GC; need to convert gap
+	array to Lisp object).
+
 2010-03-22  Ben Wing  <ben@xemacs.org>
 
 	* Makefile.in.in (objs):
--- a/src/array.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/array.c	Wed Mar 24 01:22:51 2010 -0500
@@ -403,16 +403,22 @@
   if (dy->base && !DUMPEDP (dy->base))
     {
       if (!dy->lisp_imp)
-	xfree (dy->base);
+	{
+	  xfree (dy->base);
+	  dy->base = 0;
+	}
     }
-  if(!DUMPEDP (dy))
+  if (!DUMPEDP (dy))
     {
       if (!dy->lisp_imp)
 	xfree (dy);
     }
 #else /* not NEW_GC */
   if (dy->base && !DUMPEDP (dy->base))
-    xfree (dy->base);
+    {
+      xfree (dy->base);
+      dy->base = 0;
+    }
   if(!DUMPEDP (dy))
     xfree (dy);
 #endif /* not NEW_GC */
--- a/src/array.h	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/array.h	Wed Mar 24 01:22:51 2010 -0500
@@ -72,7 +72,7 @@
 
 #ifdef NEW_GC
 #define XD_LISP_DYNARR_DESC(base_type, sub_desc)			\
-  { XD_LISP_OBJECT_BLOCK_PTR, offsetof (base_type, base),		\
+  { XD_INLINE_LISP_OBJECT_BLOCK_PTR, offsetof (base_type, base),		\
     XD_INDIRECT(1, 0), {sub_desc} },					\
   { XD_INT,        offsetof (base_type, len_) },			\
   { XD_INT_RESET,  offsetof (base_type, largest_), XD_INDIRECT(1, 0) },	\
@@ -764,4 +764,4 @@
 Gap_Array *gap_array_clone (Gap_Array *ga);
 void free_gap_array (Gap_Array *ga);
 
-#endif /* INCLUDED_lrecordt_h_ */
+#endif /* INCLUDED_array_h_ */
--- a/src/data.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/data.c	Wed Mar 24 01:22:51 2010 -0500
@@ -1,7 +1,7 @@
 /* Primitive operations on Lisp data types for XEmacs Lisp interpreter.
    Copyright (C) 1985, 1986, 1988, 1992, 1993, 1994, 1995
    Free Software Foundation, Inc.
-   Copyright (C) 2000, 2001, 2002, 2003, 2005 Ben Wing.
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -30,6 +30,7 @@
 
 #include "buffer.h"
 #include "bytecode.h"
+#include "gc.h"
 #include "syssignal.h"
 #include "sysfloat.h"
 
@@ -2804,7 +2805,7 @@
 	  if (need_to_mark_elem && ! marked_p (elem))
 	    {
 #ifdef USE_KKCC
-	      kkcc_gc_stack_push_lisp_object (elem, 0, -1);
+	      kkcc_gc_stack_push_lisp_object_0 (elem);
 #else /* NOT USE_KKCC */
 	      mark_object (elem);
 #endif /* NOT USE_KKCC */
@@ -2832,7 +2833,7 @@
       if (!NILP (rest2) && ! marked_p (rest2))
 	{
 #ifdef USE_KKCC
-	  kkcc_gc_stack_push_lisp_object (rest2, 0, -1);
+	  kkcc_gc_stack_push_lisp_object_0 (rest2);
 #else /* NOT USE_KKCC */
 	  mark_object (rest2);
 #endif /* NOT USE_KKCC */
@@ -3208,8 +3209,8 @@
 	  if (marked_p (XEPHEMERON (rest)->key))
 	    {
 #ifdef USE_KKCC
-	      kkcc_gc_stack_push_lisp_object 
-		(XCAR (XEPHEMERON (rest)->cons_chain), 0, -1);
+	      kkcc_gc_stack_push_lisp_object_0 
+		(XCAR (XEPHEMERON (rest)->cons_chain));
 #else /* NOT USE_KKCC */
 	      mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
 #endif /* NOT USE_KKCC */
@@ -3258,8 +3259,8 @@
 	    {
 	      MARK_CONS (XCONS (XEPHEMERON (rest)->cons_chain));
 #ifdef USE_KKCC
-	      kkcc_gc_stack_push_lisp_object 
-		(XCAR (XEPHEMERON (rest)->cons_chain), 0, -1);
+	      kkcc_gc_stack_push_lisp_object_0
+		(XCAR (XEPHEMERON (rest)->cons_chain));
 #else /* NOT USE_KKCC */
 	      mark_object (XCAR (XEPHEMERON (rest)->cons_chain));
 #endif /* NOT USE_KKCC */
--- a/src/device-msw.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/device-msw.c	Wed Mar 24 01:22:51 2010 -0500
@@ -574,6 +574,7 @@
 
 #ifndef NEW_GC
       xfree (d->device_data);
+      d->device_data = 0;
 #endif /* not NEW_GC */
     }
 }
--- a/src/device-tty.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/device-tty.c	Wed Mar 24 01:22:51 2010 -0500
@@ -116,7 +116,10 @@
 free_tty_device_struct (struct device *d)
 {
   if (d->device_data)
-    xfree (d->device_data);
+    {
+      xfree (d->device_data);
+      d->device_data = 0;
+    }
 }
 
 static void
--- a/src/dialog-msw.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/dialog-msw.c	Wed Mar 24 01:22:51 2010 -0500
@@ -441,6 +441,7 @@
 	{
 	  ret = tstr_to_local_file_format (pd.unknown_fname);
 	  xfree (pd.unknown_fname);
+	  pd.unknown_fname = 0;
 	}
       else while (1)
 	signal_quit ();
--- a/src/dialog-x.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/dialog-x.c	Wed Mar 24 01:22:51 2010 -0500
@@ -1,7 +1,7 @@
 /* Implements elisp-programmable dialog boxes -- X interface.
    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
    Copyright (C) 1995 Tinker Systems and INS Engineering Corp.
-   Copyright (C) 2000, 2002, 2003 Ben Wing.
+   Copyright (C) 2000, 2002, 2003, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
--- a/src/dumper.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/dumper.c	Wed Mar 24 01:22:51 2010 -0500
@@ -800,7 +800,7 @@
 	    break;
 	  }
 #ifdef NEW_GC
-	case XD_LISP_OBJECT_BLOCK_PTR:
+	case XD_INLINE_LISP_OBJECT_BLOCK_PTR:
 	  {
 	    EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
 						       data);
@@ -1073,7 +1073,7 @@
 		break;
 	      }
 #ifdef NEW_GC
-	    case XD_LISP_OBJECT_BLOCK_PTR:
+	    case XD_INLINE_LISP_OBJECT_BLOCK_PTR:
 #endif /* NEW_GC */
 	    case XD_OPAQUE_DATA_PTR:
 	    case XD_ASCII_STRING:
@@ -1314,7 +1314,7 @@
 	case XD_LONG:
 	case XD_INT_RESET:
 	  break;
-	case XD_LISP_OBJECT_BLOCK_PTR:
+	case XD_INLINE_LISP_OBJECT_BLOCK_PTR:
 	case XD_OPAQUE_DATA_PTR:
 	case XD_ASCII_STRING:
 	case XD_BLOCK_PTR:
--- a/src/elhash.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/elhash.c	Wed Mar 24 01:22:51 2010 -0500
@@ -81,6 +81,7 @@
 #include "lisp.h"
 #include "bytecode.h"
 #include "elhash.h"
+#include "gc.h"
 #include "opaque.h"
 
 Lisp_Object Qhash_tablep;
@@ -420,15 +421,16 @@
     write_fmt_string (printcharfun, " 0x%x>", LISP_OBJECT_UID (obj));
 }
 
+#ifdef ERROR_CHECK_STRUCTURES
+#define USED_IF_ERROR_CHECK_STRUCTURES(x) x
+#else
+#define USED_IF_ERROR_CHECK_STRUCTURES(x) UNUSED (x)
+#endif
+
 #ifndef NEW_GC
 static void
 free_hentries (htentry *hentries,
-#ifdef ERROR_CHECK_STRUCTURES
-	       Elemcount size
-#else /* not ERROR_CHECK_STRUCTURES) */
-	       Elemcount UNUSED (size)
-#endif /* not ERROR_CHECK_STRUCTURES) */
-	       )
+	       Elemcount USED_IF_ERROR_CHECK_STRUCTURES (size))
 {
 #ifdef ERROR_CHECK_STRUCTURES
   /* Ensure a crash if other code uses the discarded entries afterwards. */
@@ -481,9 +483,9 @@
   /* Note: XD_INDIRECT in this table refers to the surrounding table,
      and so this will work. */
 #ifdef NEW_GC
-  { XD_LISP_OBJECT_BLOCK_PTR, HASH_TABLE_NON_WEAK,
+  { XD_INLINE_LISP_OBJECT_BLOCK_PTR, HASH_TABLE_NON_WEAK,
     XD_INDIRECT (0, 1), { &htentry_description } },
-  { XD_LISP_OBJECT_BLOCK_PTR, 0, XD_INDIRECT (0, 1),
+  { XD_INLINE_LISP_OBJECT_BLOCK_PTR, 0, XD_INDIRECT (0, 1),
     { &htentry_weak_description }, XD_FLAG_UNION_DEFAULT_ENTRY },
 #else /* not NEW_GC */
   { XD_BLOCK_PTR, HASH_TABLE_NON_WEAK, XD_INDIRECT (0, 1),
@@ -508,20 +510,12 @@
   { XD_END }
 };
 
-#ifdef NEW_GC
 DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table,
 			     mark_hash_table, print_hash_table,
-			     0, hash_table_equal, hash_table_hash,
-			     hash_table_description,
-			     Lisp_Hash_Table);
-#else /* not NEW_GC */
-DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table,
-			     mark_hash_table, print_hash_table,
-			     finalize_hash_table,
+			     IF_OLD_GC (finalize_hash_table),
 			     hash_table_equal, hash_table_hash,
 			     hash_table_description,
 			     Lisp_Hash_Table);
-#endif /* not NEW_GC */
 
 static Lisp_Hash_Table *
 xhash_table (Lisp_Object hash_table)
@@ -1558,7 +1552,7 @@
   Lisp_Object mo_obj = (obj);				\
   if (!marked_p (mo_obj))				\
     {							\
-      kkcc_gc_stack_push_lisp_object (mo_obj, 0, -1);	\
+      kkcc_gc_stack_push_lisp_object_0 (mo_obj);	\
       did_mark = 1;					\
     }							\
 } while (0)
--- a/src/emacs.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/emacs.c	Wed Mar 24 01:22:51 2010 -0500
@@ -766,6 +766,7 @@
   while (argv[elt])
     {
       xfree (argv[elt]);
+      argv[elt] = 0;
       elt++;
     }
   xfree (argv);
--- a/src/emodules.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/emodules.c	Wed Mar 24 01:22:51 2010 -0500
@@ -257,9 +257,13 @@
   if (dll_close (modules[mod].dlhandle) == 0)
     {
       xfree (modules[mod].soname);
+      modules[mod].soname = 0;
       xfree (modules[mod].modname);
+      modules[mod].modname = 0;
       xfree (modules[mod].modver);
+      modules[mod].modver = 0;
       xfree (modules[mod].modtitle);
+      modules[mod].modtitle = 0;
       modules[mod].dlhandle = 0;
       modules[mod].used = 0;
     }
--- a/src/extents.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/extents.c	Wed Mar 24 01:22:51 2010 -0500
@@ -853,19 +853,13 @@
   return Qnil;
 }
 
-#ifdef NEW_GC
-DEFINE_NODUMP_INTERNAL_LISP_OBJECT ("extent-info", extent_info,
-				    mark_extent_info, 
-				    extent_info_description,
-				    struct extent_info);
-#else /* not NEW_GC */
+#ifndef NEW_GC
+
 static void
 finalize_extent_info (Lisp_Object obj)
 {
   struct extent_info *data = XEXTENT_INFO (obj);
 
-  data->soe = 0;
-  data->extents = 0;
   if (data->soe)
     {
       free_soe (data->soe);
@@ -878,12 +872,13 @@
     }
 }
 
+#endif /* not NEW_GC */
+
 DEFINE_NODUMP_LISP_OBJECT ("extent-info", extent_info,
 			   mark_extent_info, internal_object_printer,
-			   finalize_extent_info, 0, 0, 
+			   IF_OLD_GC (finalize_extent_info), 0, 0, 
 			   extent_info_description,
 			   struct extent_info);
-#endif /* not NEW_GC */
 
 static Lisp_Object
 allocate_extent_info (void)
--- a/src/file-coding.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/file-coding.c	Wed Mar 24 01:22:51 2010 -0500
@@ -377,22 +377,13 @@
   0, coding_system_empty_extra_description_1
 };
 
-#ifdef NEW_GC
 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("coding-system", coding_system,
 				     mark_coding_system,
 				     print_coding_system,
-				     0, 0, 0, coding_system_description,
-				     sizeof_coding_system,
-				     Lisp_Coding_System);
-#else /* not NEW_GC */
-DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("coding-system", coding_system,
-				     mark_coding_system,
-				     print_coding_system,
-				     finalize_coding_system,
+				     IF_OLD_GC (finalize_coding_system),
 				     0, 0, coding_system_description,
 				     sizeof_coding_system,
 				     Lisp_Coding_System);
-#endif /* not NEW_GC */
 
 /************************************************************************/
 /*                       Creating coding systems                        */
@@ -2713,6 +2704,7 @@
 	    Lstream_delete (XLSTREAM ((data->lstreams)[i]));
 	}
       xfree (data->lstreams);
+      data->lstreams = 0;
     }
 }
 
--- a/src/gc.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/gc.c	Wed Mar 24 01:22:51 2010 -0500
@@ -381,9 +381,9 @@
     default:
       stderr_out ("Unsupported count type : %d (line = %d, code = %ld)\n",
 		  idesc[line].type, line, (long) code);
-#if defined(USE_KKCC) && defined(DEBUG_XEMACS)
+#if defined (USE_KKCC) && defined (DEBUG_XEMACS)
       if (gc_in_progress)
-	kkcc_backtrace ();
+	kkcc_detailed_backtrace ();
 #endif
 #ifdef PDUMP
       if (in_pdump)
@@ -436,7 +436,7 @@
     case XD_OPAQUE_PTR:
       return sizeof (void *);
 #ifdef NEW_GC
-    case XD_LISP_OBJECT_BLOCK_PTR:
+    case XD_INLINE_LISP_OBJECT_BLOCK_PTR:
 #endif /* NEW_GC */
     case XD_BLOCK_PTR:
       {
@@ -616,6 +616,7 @@
   void *obj;
   const struct memory_description *desc;
   int pos;
+  int is_lisp;
 } kkcc_bt_stack_entry;
 
 static kkcc_bt_stack_entry *kkcc_bt;
@@ -637,25 +638,33 @@
     }
 }
 
+/* Workhorse backtrace function.  Not static because may potentially be
+   called from a debugger. */
+
+void kkcc_backtrace_1 (int size, int detailed);
 void
-kkcc_backtrace (void)
+kkcc_backtrace_1 (int size, int detailed)
 {
   int i;
   stderr_out ("KKCC mark stack backtrace :\n");
-  for (i = kkcc_bt_depth - 1; i >= 0; i--)
+  for (i = kkcc_bt_depth - 1; i >= kkcc_bt_depth - size && i >= 0; i--)
     {
       Lisp_Object obj = wrap_pointer_1 (kkcc_bt[i].obj);
-      stderr_out (" [%d]", i);
-      if ((XRECORD_LHEADER (obj)->type >= lrecord_type_last_built_in_type)
-	  || (!LRECORDP (obj))
-	  || (!XRECORD_LHEADER_IMPLEMENTATION (obj)))
+      stderr_out (" [%d] ", i);
+      if (!kkcc_bt[i].is_lisp)
+	stderr_out ("non Lisp Object");
+      else if (!LRECORDP (obj))
+	stderr_out ("Lisp Object, non-record");
+      else if (XRECORD_LHEADER (obj)->type >= lrecord_type_last_built_in_type
+	       || (!XRECORD_LHEADER_IMPLEMENTATION (obj)))
+	stderr_out ("WARNING! Bad Lisp Object type %d",
+		    XRECORD_LHEADER (obj)->type);
+      else
+	stderr_out ("%s", XRECORD_LHEADER_IMPLEMENTATION (obj)->name);
+      if (detailed && kkcc_bt[i].is_lisp)
 	{
-	  stderr_out (" non Lisp Object");
-	}
-      else
-	{
-	  stderr_out (" %s",
-		      XRECORD_LHEADER_IMPLEMENTATION (obj)->name);
+	  stderr_out (" ");
+	  debug_print (obj);
 	}
       stderr_out (" (addr: %p, desc: %p, ",
 		  (void *) kkcc_bt[i].obj,
@@ -670,6 +679,76 @@
     }
 }
 
+/* Various front ends onto kkcc_backtrace_1(), meant to be called from
+   a debugger.
+
+   The variants are:
+
+   normal vs _full(): Normal displays up to the topmost 100 items on the
+   stack, whereas full displays all items (even if there are thousands)
+
+   _detailed_() vs _short_(): Detailed here means print out the actual
+   Lisp objects on the stack using debug_print() in addition to their type,
+   whereas short means only show the type
+*/
+
+void
+kkcc_detailed_backtrace (void)
+{
+  kkcc_backtrace_1 (100, 1);
+}
+
+void kkcc_short_backtrace (void);
+void
+kkcc_short_backtrace (void)
+{
+  kkcc_backtrace_1 (100, 0);
+}
+
+void kkcc_detailed_backtrace_full (void);
+void
+kkcc_detailed_backtrace_full (void)
+{
+  kkcc_backtrace_1 (kkcc_bt_depth, 1);
+}
+
+void kkcc_short_backtrace_full (void);
+void
+kkcc_short_backtrace_full (void)
+{
+  kkcc_backtrace_1 (kkcc_bt_depth, 0);
+}
+
+/* Short versions for ease in calling from a debugger */
+
+void kbt (void);
+void
+kbt (void)
+{
+  kkcc_detailed_backtrace ();
+}
+
+void kbts (void);
+void
+kbts (void)
+{
+  kkcc_short_backtrace ();
+}
+
+void kbtf (void);
+void
+kbtf (void)
+{
+  kkcc_detailed_backtrace_full ();
+}
+
+void kbtsf (void);
+void
+kbtsf (void)
+{
+  kkcc_short_backtrace_full ();
+}
+
 static void
 kkcc_bt_stack_realloc (void)
 {
@@ -693,13 +772,14 @@
 }
 
 static void
-kkcc_bt_push (void *obj, const struct memory_description *desc, 
-	      int level, int pos)
+kkcc_bt_push (void *obj, const struct memory_description *desc,
+	      int is_lisp DECLARE_KKCC_DEBUG_ARGS)
 {
   kkcc_bt_depth = level;
   kkcc_bt[kkcc_bt_depth].obj = obj;
   kkcc_bt[kkcc_bt_depth].desc = desc;
   kkcc_bt[kkcc_bt_depth].pos = pos;
+  kkcc_bt[kkcc_bt_depth].is_lisp = is_lisp;
   kkcc_bt_depth++;
   if (kkcc_bt_depth >= kkcc_bt_stack_size)
     kkcc_bt_stack_realloc ();
@@ -707,7 +787,7 @@
 
 #else /* not DEBUG_XEMACS */
 #define kkcc_bt_init()
-#define kkcc_bt_push(obj, desc, level, pos)
+#define kkcc_bt_push(obj, desc)
 #endif /* not DEBUG_XEMACS */
 
 /* Object memory descriptions are in the lrecord_implementation structure.
@@ -724,6 +804,7 @@
 #ifdef DEBUG_XEMACS
   int level;
   int pos;
+  int is_lisp;
 #endif
 } kkcc_gc_stack_entry;
 
@@ -799,12 +880,8 @@
 }
 
 static void
-#ifdef DEBUG_XEMACS
-kkcc_gc_stack_push_1 (void *data, const struct memory_description *desc,
-		    int level, int pos)
-#else
-kkcc_gc_stack_push_1 (void *data, const struct memory_description *desc)
-#endif
+kkcc_gc_stack_push (void *data, const struct memory_description *desc
+		    DECLARE_KKCC_DEBUG_ARGS)
 {
 #ifdef NEW_GC
   GC_STAT_ENQUEUED;
@@ -821,12 +898,44 @@
 }
 
 #ifdef DEBUG_XEMACS
-#define kkcc_gc_stack_push(data, desc, level, pos)	\
-  kkcc_gc_stack_push_1 (data, desc, level, pos)
-#else
-#define kkcc_gc_stack_push(data, desc, level, pos)	\
-  kkcc_gc_stack_push_1 (data, desc)
-#endif
+
+static inline void
+kkcc_gc_stack_push_0 (void *data, const struct memory_description *desc,
+		      int is_lisp DECLARE_KKCC_DEBUG_ARGS)
+{
+  kkcc_gc_stack_push (data, desc KKCC_DEBUG_ARGS);
+  kkcc_gc_stack_ptr[kkcc_gc_stack_rear].is_lisp = is_lisp;
+}
+
+static inline void
+kkcc_gc_stack_push_lisp (void *data, const struct memory_description *desc
+			 DECLARE_KKCC_DEBUG_ARGS)
+{
+  kkcc_gc_stack_push_0 (data, desc, 1 KKCC_DEBUG_ARGS);
+}
+
+static inline void
+kkcc_gc_stack_push_nonlisp (void *data, const struct memory_description *desc
+			    DECLARE_KKCC_DEBUG_ARGS)
+{
+  kkcc_gc_stack_push_0 (data, desc, 0 KKCC_DEBUG_ARGS);
+}
+
+#else /* not DEBUG_XEMACS */
+
+static inline void
+kkcc_gc_stack_push_lisp (void *data, const struct memory_description *desc)
+{
+  kkcc_gc_stack_push (data, desc);
+}
+
+static inline void
+kkcc_gc_stack_push_nonlisp (void *data, const struct memory_description *desc)
+{
+  kkcc_gc_stack_push (data, desc);
+}
+
+#endif /* (not) DEBUG_XEMACS */
 
 static kkcc_gc_stack_entry *
 kkcc_gc_stack_pop (void)
@@ -850,11 +959,7 @@
 }
 
 void
-#ifdef DEBUG_XEMACS
-kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj, int level, int pos)
-#else
-kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj)
-#endif
+kkcc_gc_stack_push_lisp_object (Lisp_Object obj DECLARE_KKCC_DEBUG_ARGS)
 {
   if (XTYPE (obj) == Lisp_Type_Record)
     {
@@ -869,26 +974,15 @@
 #else /* not NEW_GC */
 	  MARK_RECORD_HEADER (lheader);
 #endif /* not NEW_GC */
-	  kkcc_gc_stack_push ((void *) lheader, desc, level, pos);
+	  kkcc_gc_stack_push_lisp ((void *) lheader, desc KKCC_DEBUG_ARGS);
 	}
     }
 }
 
 #ifdef NEW_GC
-#ifdef DEBUG_XEMACS
-#define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
-  kkcc_gc_stack_push_lisp_object_1 (obj, level, pos)
-#else
-#define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
-  kkcc_gc_stack_push_lisp_object_1 (obj)
-#endif
 
 void
-#ifdef DEBUG_XEMACS
-kkcc_gc_stack_repush_dirty_object_1 (Lisp_Object obj, int level, int pos)
-#else
-kkcc_gc_stack_repush_dirty_object_1 (Lisp_Object obj)
-#endif
+kkcc_gc_stack_repush_dirty_object (Lisp_Object obj DECLARE_KKCC_DEBUG_ARGS)
 {
   if (XTYPE (obj) == Lisp_Type_Record)
     {
@@ -898,7 +992,7 @@
       GC_CHECK_LHEADER_INVARIANTS (lheader);
       desc = RECORD_DESCRIPTION (lheader);
       MARK_GREY (lheader);
-      kkcc_gc_stack_push ((void*) lheader, desc, level, pos);
+      kkcc_gc_stack_push_lisp ((void*) lheader, desc KKCC_DEBUG_ARGS);
     }
 }
 #endif /* NEW_GC */
@@ -914,48 +1008,23 @@
     }								\
 } while (0)
 #else
-#define KKCC_DO_CHECK_FREE(obj, allow_free)
+#define KKCC_DO_CHECK_FREE(obj, allow_free) DO_NOTHING
 #endif
 
-#ifdef ERROR_CHECK_GC
-#ifdef DEBUG_XEMACS
-static void
-mark_object_maybe_checking_free_1 (Lisp_Object obj, int allow_free,
-				 int level, int pos)
-#else
-static void
-mark_object_maybe_checking_free_1 (Lisp_Object obj, int allow_free)
-#endif
+static inline void
+mark_object_maybe_checking_free (Lisp_Object obj, int allow_free
+				 DECLARE_KKCC_DEBUG_ARGS)
 {
   KKCC_DO_CHECK_FREE (obj, allow_free);
-  kkcc_gc_stack_push_lisp_object (obj, level, pos);
+  kkcc_gc_stack_push_lisp_object (obj KKCC_DEBUG_ARGS);
 }
 
-#ifdef DEBUG_XEMACS
-#define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
-  mark_object_maybe_checking_free_1 (obj, allow_free, level, pos)
-#else
-#define mark_object_maybe_checking_free(obj, allow_free, level, pos) \
-  mark_object_maybe_checking_free_1 (obj, allow_free)
-#endif
-#else /* not ERROR_CHECK_GC */
-#define mark_object_maybe_checking_free(obj, allow_free, level, pos) 	\
-  kkcc_gc_stack_push_lisp_object (obj, level, pos)
-#endif /* not ERROR_CHECK_GC */
-
-
 /* This function loops all elements of a struct pointer and calls 
    mark_with_description with each element. */
 static void
-#ifdef DEBUG_XEMACS
-mark_struct_contents_1 (const void *data,
+mark_struct_contents (const void *data,
 		      const struct sized_memory_description *sdesc,
-		      int count, int level, int pos)
-#else
-mark_struct_contents_1 (const void *data,
-		      const struct sized_memory_description *sdesc,
-		      int count)
-#endif
+		      int count DECLARE_KKCC_DEBUG_ARGS)
 {
   int i;
   Bytecount elsize;
@@ -963,33 +1032,19 @@
 
   for (i = 0; i < count; i++)
     {
-      kkcc_gc_stack_push (((char *) data) + elsize * i, sdesc->description,
-			  level, pos);
+      kkcc_gc_stack_push_nonlisp (((char *) data) + elsize * i,
+				  sdesc->description
+				  KKCC_DEBUG_ARGS);
     }
 }
 
-#ifdef DEBUG_XEMACS
-#define mark_struct_contents(data, sdesc, count, level, pos) \
-  mark_struct_contents_1 (data, sdesc, count, level, pos)
-#else
-#define mark_struct_contents(data, sdesc, count, level, pos) \
-  mark_struct_contents_1 (data, sdesc, count)
-#endif
-
-
 #ifdef NEW_GC
 /* This function loops all elements of a struct pointer and calls 
    mark_with_description with each element. */
 static void
-#ifdef DEBUG_XEMACS
-mark_lisp_object_block_contents_1 (const void *data,
-		      const struct sized_memory_description *sdesc,
-		      int count, int level, int pos)
-#else
-mark_lisp_object_block_contents_1 (const void *data,
-		      const struct sized_memory_description *sdesc,
-		      int count)
-#endif
+mark_lisp_object_block_contents (const void *data,
+				 const struct sized_memory_description *sdesc,
+				 int count DECLARE_KKCC_DEBUG_ARGS)
 {
   int i;
   Bytecount elsize;
@@ -1007,19 +1062,12 @@
 	  if (! MARKED_RECORD_HEADER_P (lheader)) 
 	    {
 	      MARK_GREY (lheader);
-	      kkcc_gc_stack_push ((void *) lheader, desc, level, pos);
+	      kkcc_gc_stack_push_lisp ((void *) lheader, desc KKCC_DEBUG_ARGS);
 	    }
 	}
     }
 }
 
-#ifdef DEBUG_XEMACS
-#define mark_lisp_object_block_contents(data, sdesc, count, level, pos) \
-  mark_lisp_object_block_contents_1 (data, sdesc, count, level, pos)
-#else
-#define mark_lisp_object_block_contents(data, sdesc, count, level, pos) \
-  mark_lisp_object_block_contents_1 (data, sdesc, count)
-#endif
 #endif /* not NEW_GC */
 
 /* This function implements the KKCC mark algorithm.
@@ -1046,8 +1094,11 @@
       desc = stack_entry->desc;
 #ifdef DEBUG_XEMACS
       level = stack_entry->level + 1;
+      kkcc_bt_push (data, desc, stack_entry->is_lisp, stack_entry->level,
+		    stack_entry->pos);
+#else
+      kkcc_bt_push (data, desc);
 #endif
-      kkcc_bt_push (data, desc, stack_entry->level, stack_entry->pos);
 
 #ifdef NEW_GC
       /* Mark black if object is currently grey.  This first checks,
@@ -1098,11 +1149,12 @@
 		if (EQ (*stored_obj, Qnull_pointer))
 		  break;
 #ifdef NEW_GC
-		mark_object_maybe_checking_free (*stored_obj, 0, level, pos);
+		mark_object_maybe_checking_free (*stored_obj, 0
+						 KKCC_DEBUG_ARGS);
 #else /* not NEW_GC */
 		mark_object_maybe_checking_free
-		  (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
-		   level, pos);
+		  (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT
+		   KKCC_DEBUG_ARGS);
 #endif /* not NEW_GC */
 		break;
 	      }
@@ -1121,17 +1173,17 @@
 		      break;
 #ifdef NEW_GC
 		    mark_object_maybe_checking_free 
-		      (*stored_obj, 0, level, pos);
+		      (*stored_obj, 0 KKCC_DEBUG_ARGS);
 #else /* not NEW_GC */
 		    mark_object_maybe_checking_free
-		      (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT,
-		       level, pos);
+		      (*stored_obj, (desc1->flags) & XD_FLAG_FREE_LISP_OBJECT
+		       KKCC_DEBUG_ARGS);
 #endif /* not NEW_GC */
 		  }
 		break;
 	      }
 #ifdef NEW_GC
-	    case XD_LISP_OBJECT_BLOCK_PTR:
+	    case XD_INLINE_LISP_OBJECT_BLOCK_PTR:
 	      {
 		EMACS_INT count = lispdesc_indirect_count (desc1->data1, desc,
 							   data);
@@ -1140,7 +1192,7 @@
 		const char *dobj = * (const char **) rdata;
 		if (dobj)
 		  mark_lisp_object_block_contents 
-		    (dobj, sdesc, count, level, pos);
+		    (dobj, sdesc, count KKCC_DEBUG_ARGS);
 		break;
 	      }
 #endif /* NEW_GC */
@@ -1152,7 +1204,7 @@
 		  lispdesc_indirect_description (data, desc1->data2.descr);
 		const char *dobj = * (const char **) rdata;
 		if (dobj)
-		  mark_struct_contents (dobj, sdesc, count, level, pos);
+		  mark_struct_contents (dobj, sdesc, count KKCC_DEBUG_ARGS);
 		break;
 	      }
 	    case XD_BLOCK_ARRAY:
@@ -1162,7 +1214,7 @@
 		const struct sized_memory_description *sdesc =
 		  lispdesc_indirect_description (data, desc1->data2.descr);
 		      
-		mark_struct_contents (rdata, sdesc, count, level, pos);
+		mark_struct_contents (rdata, sdesc, count KKCC_DEBUG_ARGS);
 		break;
 	      }
 	    case XD_UNION:
@@ -1174,7 +1226,7 @@
 		    
 	    default:
 	      stderr_out ("Unsupported description type : %d\n", desc1->type);
-	      kkcc_backtrace ();
+	      kkcc_detailed_backtrace ();
 	      ABORT ();
 	    }
 	}
@@ -1397,7 +1449,7 @@
     }
   /* Keep objects alive that need to be finalized by marking
      Vfinalizers_to_run transitively. */
-  kkcc_gc_stack_push_lisp_object (Vfinalizers_to_run, 0, -1);
+  kkcc_gc_stack_push_lisp_object_0 (Vfinalizers_to_run);
   kkcc_marking (0);
 }
 
@@ -1619,7 +1671,7 @@
   /* Mark all the special slots that serve as the roots of accessibility. */
 
 #ifdef USE_KKCC
-# define mark_object(obj) kkcc_gc_stack_push_lisp_object (obj, 0, -1)
+# define mark_object(obj) kkcc_gc_stack_push_lisp_object_0 (obj)
 #endif /* USE_KKCC */
 
   { /* staticpro() */
--- a/src/gc.h	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/gc.h	Wed Mar 24 01:22:51 2010 -0500
@@ -1,5 +1,6 @@
 /* New incremental garbage collector for XEmacs.
    Copyright (C) 2005 Marcus Crestani.
+   Copyright (C) 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -106,31 +107,42 @@
 
 void recompute_need_to_garbage_collect (void);
 
+#ifdef DEBUG_XEMACS
+#define KKCC_DEBUG_ARGS , level, pos
+#define DECLARE_KKCC_DEBUG_ARGS , int level, int pos
+#else
+#define KKCC_DEBUG_ARGS
+#define DECLARE_KKCC_DEBUG_ARGS
+#endif
+
 
 /* KKCC mark algorithm. */
+void kkcc_gc_stack_push_lisp_object (Lisp_Object obj DECLARE_KKCC_DEBUG_ARGS);
+void kkcc_gc_stack_repush_dirty_object (Lisp_Object obj
+					DECLARE_KKCC_DEBUG_ARGS);
+
 #ifdef DEBUG_XEMACS
-void kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj, int level, int pos);
-#define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
-  kkcc_gc_stack_push_lisp_object_1 (obj, level, pos)
-void kkcc_gc_stack_repush_dirty_object_1 (Lisp_Object obj, int level, int pos);
-#define kkcc_gc_stack_repush_dirty_object(obj) \
-  kkcc_gc_stack_repush_dirty_object_1 (obj, 0, -2)
-void kkcc_backtrace (void);
+#define kkcc_gc_stack_push_lisp_object_0(obj) \
+  kkcc_gc_stack_push_lisp_object (obj, 0, -1)
+void kkcc_backtrace_1 (int size, int detailed);
+void kkcc_short_backtrace (void);
+void kkcc_detailed_backtrace (void);
+void kkcc_short_backtrace_full (void);
+void kkcc_detailed_backtrace_full (void);
 #else
-void kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj);
-#define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
-  kkcc_gc_stack_push_lisp_object_1 (obj)
-void kkcc_gc_stack_repush_dirty_object_1 (Lisp_Object obj);
-#define kkcc_gc_stack_repush_dirty_object(obj) \
-  kkcc_gc_stack_repush_dirty_object_1 (obj)
-#define kkcc_backtrace()
+#define kkcc_gc_stack_push_lisp_object_0(obj) \
+  kkcc_gc_stack_push_lisp_object (obj)
+#define kkcc_detailed_backtrace()
 #endif
 
 #ifdef NEW_GC
 
 /* Repush objects that are caught by the write barrier. */
-#define gc_write_barrier(obj) kkcc_gc_stack_repush_dirty_object (obj);
-
+#ifdef DEBUG_XEMACS
+#define gc_write_barrier(obj) kkcc_gc_stack_repush_dirty_object (obj, 0, -2)
+#else
+#define gc_write_barrier(obj) kkcc_gc_stack_repush_dirty_object (obj)
+#endif
 
 /* GC functions: */
 
--- a/src/glyphs-eimage.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/glyphs-eimage.c	Wed Mar 24 01:22:51 2010 -0500
@@ -2,7 +2,7 @@
    Copyright (C) 1993, 1994, 1998 Free Software Foundation, Inc.
    Copyright (C) 1995 Board of Trustees, University of Illinois.
    Copyright (C) 1995 Tinker Systems
-   Copyright (C) 1995, 1996, 2001, 2002, 2004, 2005 Ben Wing
+   Copyright (C) 1995, 1996, 2001, 2002, 2004, 2005, 2010 Ben Wing
    Copyright (C) 1995 Sun Microsystems
 
 This file is part of XEmacs.
@@ -177,10 +177,16 @@
     jpeg_destroy_decompress (data->cinfo_ptr);
 
   if (data->instream)
-    retry_fclose (data->instream);
+    {
+      retry_fclose (data->instream);
+      data->instream = 0;
+    }
 
   if (data->eimage)
-    xfree (data->eimage);
+    {
+      xfree (data->eimage);
+      data->eimage = 0;
+    }
 
   return Qnil;
 }
@@ -577,10 +583,14 @@
   if (data->giffile)
     {
       DGifCloseFile (data->giffile);
-      FreeSavedImages(data->giffile);
+      FreeSavedImages (data->giffile);
+      data->giffile = 0;
     }
   if (data->eimage)
-    xfree (data->eimage);
+    {
+      xfree (data->eimage);
+      data->eimage = 0;
+    }
 
   return Qnil;
 }
@@ -878,10 +888,16 @@
     }
 
   if (data->instream)
-    retry_fclose (data->instream);
+    {
+      retry_fclose (data->instream);
+      data->instream = 0;
+    }
 
   if (data->eimage)
-    xfree (data->eimage);
+    {
+      xfree (data->eimage);
+      data->eimage = 0;
+    }
 
   return Qnil;
 }
@@ -1134,10 +1150,14 @@
   free_opaque_ptr (unwind_obj);
   if (data->tiff)
     {
-      TIFFClose(data->tiff);
+      TIFFClose (data->tiff);
+      data->tiff = 0;
     }
   if (data->eimage)
-    xfree (data->eimage);
+    {
+      xfree (data->eimage);
+      data->eimage = 0;
+    }
 
   return Qnil;
 }
--- a/src/imgproc.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/imgproc.c	Wed Mar 24 01:22:51 2010 -0500
@@ -27,6 +27,7 @@
 
    Copyright (c) 1988-1997 Sam Leffler
    Copyright (c) 1991-1997 Silicon Graphics, Inc.
+   Copyright (C) 2010 Ben Wing.
    
    Permission to use, copy, modify, distribute, and sell this software and 
    its documentation for any purpose is hereby granted without fee, provided
@@ -551,8 +552,12 @@
   /* 5c: done with ColorCells */
   for (i = 0; i < C_LEN*C_LEN*C_LEN; i++)
     if (qt->ColorCells[i])
-      xfree (qt->ColorCells[i]);
+      {
+	xfree (qt->ColorCells[i]);
+	qt->ColorCells[i] = 0;
+      }
   xfree (qt->ColorCells);
+  qt->ColorCells = 0;
   
   if (res)
     {
--- a/src/insdel.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/insdel.c	Wed Mar 24 01:22:51 2010 -0500
@@ -1838,8 +1838,10 @@
     {
       BUFFER_FREE (b->text->beg);
       xfree (b->text->changes);
+      b->text->changes = 0;
     }
   xfree (b->changes);
+  b->changes = 0;
 
 #ifdef REGION_CACHE_NEEDS_WORK
   if (b->newline_cache)
--- a/src/lisp.h	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/lisp.h	Wed Mar 24 01:22:51 2010 -0500
@@ -4233,21 +4233,6 @@
 void free_marker (Lisp_Object);
 int object_dead_p (Lisp_Object);
 void mark_object (Lisp_Object obj);
-#ifndef NEW_GC
-#ifdef USE_KKCC
-#ifdef DEBUG_XEMACS
-void kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj, int level, int pos);
-#define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
-  kkcc_gc_stack_push_lisp_object_1 (obj, level, pos)
-void kkcc_backtrace (void);
-#else
-void kkcc_gc_stack_push_lisp_object_1 (Lisp_Object obj);
-#define kkcc_gc_stack_push_lisp_object(obj, level, pos) \
-  kkcc_gc_stack_push_lisp_object_1 (obj)
-#define kkcc_backtrace()
-#endif
-#endif /* USE_KKCC */
-#endif /* not NEW_GC */
 int marked_p (Lisp_Object obj);
 extern int funcall_allocation_flag;
 extern int need_to_garbage_collect;
--- a/src/lrecord.h	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/lrecord.h	Wed Mar 24 01:22:51 2010 -0500
@@ -187,6 +187,8 @@
 #define NORMAL_LISP_OBJECT_HEADER struct lrecord_header
 #define FROB_BLOCK_LISP_OBJECT_HEADER struct lrecord_header
 #define LISP_OBJECT_FROB_BLOCK_P(obj) 0
+#define IF_NEW_GC(x) x
+#define IF_OLD_GC(x) 0
 #else /* not NEW_GC */
 #define ALLOC_NORMAL_LISP_OBJECT(type) alloc_automanaged_lcrecord (&lrecord_##type)
 #define ALLOC_SIZED_LISP_OBJECT(size, type) \
@@ -194,6 +196,8 @@
 #define NORMAL_LISP_OBJECT_HEADER struct old_lcrecord_header
 #define FROB_BLOCK_LISP_OBJECT_HEADER struct lrecord_header
 #define LISP_OBJECT_FROB_BLOCK_P(obj) (XRECORD_LHEADER_IMPLEMENTATION(obj)->frob_block_p)
+#define IF_NEW_GC(x) 0
+#define IF_OLD_GC(x) x
 #endif /* not NEW_GC */
 
 #define LISP_OBJECT_UID(obj) (XRECORD_LHEADER (obj)->uid)
@@ -310,7 +314,9 @@
   /* Symbol value magic types come first to make SYMBOL_VALUE_MAGIC_P fast.
      #### This should be replaced by a symbol_value_magic_p flag
      in the Lisp_Symbol lrecord_header. */
-  lrecord_type_symbol_value_forward,      /*  0 */
+  /* Don't assign any type to 0, so in case we come across zeroed memory
+     it will be more obvious when printed */
+  lrecord_type_symbol_value_forward = 1,
   lrecord_type_symbol_value_varalias,
   lrecord_type_symbol_value_lisp_magic,
   lrecord_type_symbol_value_buffer_local,
@@ -974,17 +980,28 @@
 
     XD_LISP_OBJECT
 
-  A Lisp object.  This is also the type to use for pointers to other lrecords
+  A Lisp_Object.  This is also the type to use for pointers to other lrecords
   (e.g. struct frame *).
 
     XD_LISP_OBJECT_ARRAY
 
-  An array of Lisp objects or (equivalently) pointers to lrecords.
+  An array of Lisp_Objects or (equivalently) pointers to lrecords.
   The parameter (i.e. third element) is the count.  This would be declared
   as Lisp_Object foo[666].  For something declared as Lisp_Object *foo,
   use XD_BLOCK_PTR, whose description parameter is a sized_memory_description
   consisting of only XD_LISP_OBJECT and XD_END.
 
+    XD_INLINE_LISP_OBJECT_BLOCK_PTR
+
+  An pointer to a contiguous block of inline Lisp objects -- i.e., the Lisp
+  object itself rather than a Lisp_Object pointer is stored in the block.
+  This is used only under NEW_GC and is useful for increased efficiency when
+  an array of the same kind of object is needed.  Examples of the use of this
+  type are Lisp dynarrs, where the array elements are inline Lisp objects
+  rather than non-Lisp structures, as is normally the case; and hash tables,
+  where the key/value pairs are encapsulated as hash-table-entry objects and
+  an array of inline hash-table-entry objects is stored.
+
     XD_LO_LINK
 
   Weak link in a linked list of objects of the same type.  This is a
@@ -1150,7 +1167,7 @@
   XD_LISP_OBJECT_ARRAY,
   XD_LISP_OBJECT,
 #ifdef NEW_GC
-  XD_LISP_OBJECT_BLOCK_PTR,
+  XD_INLINE_LISP_OBJECT_BLOCK_PTR,
 #endif /* NEW_GC */
   XD_LO_LINK,
   XD_OPAQUE_PTR,
@@ -1200,10 +1217,9 @@
      lcrecord-lists, where the objects have had their type changed to
      lrecord_type_free and also have had their free bit set, but we mark
      them as normal. */
-  XD_FLAG_FREE_LISP_OBJECT = 8
+  XD_FLAG_FREE_LISP_OBJECT = 8,
 #endif /* not NEW_GC */
 #if 0
-  ,
   /* Suggestions for other possible flags: */
 
   /* Eliminate XD_UNION_DYNAMIC_SIZE and replace it with a flag, like this. */
@@ -1215,7 +1231,7 @@
      expanded and we need to stick a pointer in the second slot (although
      we could still ensure that the second slot in the first entry was NULL
      or <0). */
-  XD_FLAG_DESCRIPTION_MAP = 32
+  XD_FLAG_DESCRIPTION_MAP = 32,
 #endif
 };
 
@@ -1258,20 +1274,20 @@
 
      This function must put a pointer to the opaque result in *data
      and its size in *size. */
-  void (*convert)(const void *object, void **data, Bytecount *size);
+  void (*convert) (const void *object, void **data, Bytecount *size);
 
   /* Post-conversion cleanup.  Optional (null if not provided).
 
      When provided it will be called post-dumping to free any storage
      allocated for the conversion results. */
-  void (*convert_free)(const void *object, void *data, Bytecount size);
+  void (*convert_free) (const void *object, void *data, Bytecount size);
 
   /* De-conversion.
 
      At reload time, rebuilds the object from the converted form.
      "object" is 0 for the PTR case, return is ignored in the DATA
      case. */
-  void *(*deconvert)(void *object, void *data, Bytecount size);
+  void *(*deconvert) (void *object, void *data, Bytecount size);
 
 };
 
--- a/src/marker.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/marker.c	Wed Mar 24 01:22:51 2010 -0500
@@ -111,18 +111,13 @@
 {
   unchain_marker (obj);
 }
+#endif /* NEW_GC */
 
 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("marker", marker,
 					mark_marker, print_marker,
-					finalize_marker,
+					IF_NEW_GC (finalize_marker),
 					marker_equal, marker_hash,
 					marker_description, Lisp_Marker);
-#else /* not NEW_GC */
-DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("marker", marker,
-					mark_marker, print_marker, 0,
-					marker_equal, marker_hash,
-					marker_description, Lisp_Marker);
-#endif /* not NEW_GC */
 
 /* Operations on markers. */
 
--- a/src/mule-coding.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/mule-coding.c	Wed Mar 24 01:22:51 2010 -0500
@@ -2839,14 +2839,15 @@
   return 1;
 }
 
+#ifdef ENABLE_COMPOSITE_CHARS
+#define USED_IF_COMPOSITE_CHARS(x) x
+#else
+#define USED_IF_COMPOSITE_CHARS(x) UNUSED (x)
+#endif
+
 static void
-iso2022_finalize_coding_stream (
-#ifdef ENABLE_COMPOSITE_CHARS
-				struct coding_stream *str
-#else
-				struct coding_stream *UNUSED (str)
-#endif
-				)
+iso2022_finalize_coding_stream (struct coding_stream *
+				USED_IF_COMPOSITE_CHARS (str))
 {
 #ifdef ENABLE_COMPOSITE_CHARS
   struct iso2022_coding_stream *data =
@@ -3247,7 +3248,10 @@
 {
   struct iso2022_detector *data = DETECTION_STATE_DATA (st, iso2022);
   if (data->iso)
-    xfree (data->iso);
+    {
+      xfree (data->iso);
+      data->iso = 0;
+    }
 }
 
 
--- a/src/number.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/number.c	Wed Mar 24 01:22:51 2010 -0500
@@ -70,9 +70,6 @@
      zero after finalizing. */
   bignum_fini (num->data);
 }
-#define BIGNUM_FINALIZE bignum_finalize
-#else
-#define BIGNUM_FINALIZE 0
 #endif
 
 static int
@@ -125,10 +122,9 @@
 };
 
 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("bignum", bignum, 0, bignum_print,
-					BIGNUM_FINALIZE, bignum_equal,
-					bignum_hash, bignum_description,
-					Lisp_Bignum);
-
+					IF_NEW_GC (bignum_finalize),
+					bignum_equal, bignum_hash,
+					bignum_description, Lisp_Bignum); 
 #endif /* HAVE_BIGNUM */
 
 Lisp_Object Qbignump;
@@ -164,10 +160,7 @@
      zero after finalizing. */
   ratio_fini (num->data);
 }
-#define RATIO_FINALIZE ratio_finalize
-#else
-#define RATIO_FINALIZE 0
-#endif
+#endif /* not NEW_GC */
 
 static int
 ratio_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth),
@@ -188,7 +181,8 @@
 };
 
 DEFINE_NODUMP_FROB_BLOCK_LISP_OBJECT ("ratio", ratio, 0, ratio_print,
-				      RATIO_FINALIZE, ratio_equal, ratio_hash,
+				      IF_NEW_GC (ratio_finalize),
+				      ratio_equal, ratio_hash,
 				      ratio_description, Lisp_Ratio);
 
 #endif /* HAVE_RATIO */
@@ -270,10 +264,7 @@
      zero after finalizing. */
   bigfloat_fini (num->bf);
 }
-#define BIGFLOAT_FINALIZE bigfloat_finalize
-#else
-#define BIGFLOAT_FINALIZE 0
-#endif
+#endif /* not NEW_GC */
 
 static int
 bigfloat_equal (Lisp_Object obj1, Lisp_Object obj2, int UNUSED (depth),
@@ -294,7 +285,8 @@
 };
 
 DEFINE_DUMPABLE_FROB_BLOCK_LISP_OBJECT ("bigfloat", bigfloat, 0,
-					bigfloat_print, BIGFLOAT_FINALIZE,
+					bigfloat_print,
+					IF_NEW_GC (bigfloat_finalize),
 					bigfloat_equal, bigfloat_hash,
 					bigfloat_description, Lisp_Bigfloat);
 
--- a/src/objects-tty.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/objects-tty.c	Wed Mar 24 01:22:51 2010 -0500
@@ -219,7 +219,10 @@
 {
 #ifndef NEW_GC
   if (c->data)
-    xfree (c->data);
+    {
+      xfree (c->data);
+      c->data = 0;
+    }
 #endif /* not NEW_GC */
 }
 
@@ -314,7 +317,10 @@
 {
 #ifndef NEW_GC
   if (f->data)
-    xfree (f->data);
+    {
+      xfree (f->data);
+      f->data = 0;
+    }
 #endif /* not NEW_GC */
 }
 
--- a/src/process.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/process.c	Wed Mar 24 01:22:51 2010 -0500
@@ -189,6 +189,7 @@
     {
       MAYBE_PROCMETH (finalize_process_data, (p));
       xfree (p->process_data);
+      p->process_data = 0;
     }
 }
 
--- a/src/profile.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/profile.c	Wed Mar 24 01:22:51 2010 -0500
@@ -1,5 +1,5 @@
 /* Why the hell is XEmacs so fucking slow?
-   Copyright (C) 1996, 2002, 2003, 2004 Ben Wing.
+   Copyright (C) 1996, 2002, 2003, 2004, 2010 Ben Wing.
    Copyright (C) 1998 Free Software Foundation, Inc.
 
 This file is part of XEmacs.
@@ -25,6 +25,7 @@
 #include "backtrace.h"
 #include "bytecode.h"
 #include "elhash.h"
+#include "gc.h"
 #include "hash.h"
 #include "profile.h"
 
@@ -609,7 +610,7 @@
 			     void *UNUSED (void_closure))
 {
 #ifdef USE_KKCC
-  kkcc_gc_stack_push_lisp_object (GET_LISP_FROM_VOID (void_key), 0, -1);
+  kkcc_gc_stack_push_lisp_object_0 (GET_LISP_FROM_VOID (void_key));
 #else /* NOT USE_KKCC */
   mark_object (GET_LISP_FROM_VOID (void_key));
 #endif /* NOT USE_KKCC */
--- a/src/rangetab.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/rangetab.c	Wed Mar 24 01:22:51 2010 -0500
@@ -196,6 +196,25 @@
   return hash;
 }
 
+#ifndef NEW_GC
+
+/* #### This leaks memory under NEW_GC.  To fix this, convert to Lisp object
+   gap array. */
+
+static void
+finalize_range_table (Lisp_Object obj)
+{
+  Lisp_Range_Table *rt = XRANGE_TABLE (obj);
+  if (rt->entries)
+    {
+      if (!DUMPEDP (rt->entries))
+	free_gap_array (rt->entries);
+      rt->entries = 0;
+    }
+}
+
+#endif /* not NEW_GC */
+
 static const struct memory_description rte_description_1[] = {
   { XD_LISP_OBJECT, offsetof (range_table_entry, val) },
   { XD_END }
@@ -222,7 +241,8 @@
 };
 
 DEFINE_DUMPABLE_LISP_OBJECT ("range-table", range_table,
-			     mark_range_table, print_range_table, 0,
+			     mark_range_table, print_range_table,
+			     IF_OLD_GC (finalize_range_table),
 			     range_table_equal, range_table_hash,
 			     range_table_description,
 			     Lisp_Range_Table);
--- a/src/redisplay.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/redisplay.c	Wed Mar 24 01:22:51 2010 -0500
@@ -1686,7 +1686,10 @@
 	  break;
 	case PROP_STRING:
 	  if (pb->data.p_string.str)
-	    xfree (pb->data.p_string.str);
+	    {
+	      xfree (pb->data.p_string.str);
+	      pb->data.p_string.str = 0;
+	    }
 	  /* #### bogus bogus -- this doesn't do anything!
 	     Should probably call add_ibyte_string_runes(),
 	     once that function is fixed. */
--- a/src/scrollbar-gtk.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/scrollbar-gtk.c	Wed Mar 24 01:22:51 2010 -0500
@@ -3,6 +3,7 @@
    Copyright (C) 1994 Amdhal Corporation.
    Copyright (C) 1995 Sun Microsystems, Inc.
    Copyright (C) 1995 Darrell Kindred <dkindred+@cmu.edu>.
+   Copyright (C) 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -65,6 +66,7 @@
 	}
 
       xfree (instance->scrollbar_data);
+      instance->scrollbar_data = 0;
     }
 }
 
--- a/src/scrollbar-msw.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/scrollbar-msw.c	Wed Mar 24 01:22:51 2010 -0500
@@ -3,7 +3,7 @@
    Copyright (C) 1994 Amdahl Corporation.
    Copyright (C) 1995 Sun Microsystems, Inc.
    Copyright (C) 1995 Darrell Kindred <dkindred+@cmu.edu>.
-   Copyright (C) 2001, 2002 Ben Wing.
+   Copyright (C) 2001, 2002, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -102,6 +102,7 @@
       assert (!NILP (ptr));
       DestroyWindow (SCROLLBAR_MSW_HANDLE (sb));
       xfree (sb->scrollbar_data);
+      sb->scrollbar_data = 0;
     }
 }
 
--- a/src/scrollbar-x.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/scrollbar-x.c	Wed Mar 24 01:22:51 2010 -0500
@@ -76,7 +76,10 @@
   if (instance->scrollbar_data)
     {
       if (SCROLLBAR_X_NAME (instance))
-	xfree (SCROLLBAR_X_NAME (instance));
+	{
+	  xfree (SCROLLBAR_X_NAME (instance));
+	  SCROLLBAR_X_NAME (instance) = 0;
+	}
 
       if (SCROLLBAR_X_WIDGET (instance))
 	{
@@ -87,6 +90,7 @@
 	}
 
       xfree (instance->scrollbar_data);
+      instance->scrollbar_data = 0;
     }
 }
 
--- a/src/select-x.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/select-x.c	Wed Mar 24 01:22:51 2010 -0500
@@ -1,6 +1,6 @@
 /* X Selection processing for XEmacs
    Copyright (C) 1990, 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
-   Copyright (C) 2001, 2002 Ben Wing.
+   Copyright (C) 2001, 2002, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -691,10 +691,8 @@
     event->type = 0;
     /* Data need not have been allocated; cf. select-convert-to-delete in
        lisp/select.el . */
-    if ((Rawbyte *)0 != data)
-    {
+    if (data)
       xfree (data);
-    }
   }
 
   unbind_to (count);
--- a/src/specifier.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/specifier.c	Wed Mar 24 01:22:51 2010 -0500
@@ -442,22 +442,13 @@
   0, specifier_empty_extra_description_1
 };
 
-#ifdef NEW_GC
 DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("specifier", specifier,
 				     mark_specifier, print_specifier,
-				     0, specifier_equal, specifier_hash,
-				     specifier_description,
-				     sizeof_specifier,
-				     Lisp_Specifier);
-#else /* not NEW_GC */
-DEFINE_DUMPABLE_SIZABLE_LISP_OBJECT ("specifier", specifier,
-				     mark_specifier, print_specifier,
-				     finalize_specifier,
+				     IF_OLD_GC (finalize_specifier),
 				     specifier_equal, specifier_hash,
 				     specifier_description,
 				     sizeof_specifier,
 				     Lisp_Specifier);
-#endif /* not NEW_GC */
 
 /************************************************************************/
 /*                       Creating specifiers                            */
--- a/src/syntax.c	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/syntax.c	Wed Mar 24 01:22:51 2010 -0500
@@ -1,7 +1,7 @@
 /* XEmacs routines to deal with syntax tables; also word and list parsing.
    Copyright (C) 1985-1994 Free Software Foundation, Inc.
    Copyright (C) 1995 Sun Microsystems, Inc.
-   Copyright (C) 2001, 2002, 2003 Ben Wing.
+   Copyright (C) 2001, 2002, 2003, 2010 Ben Wing.
 
 This file is part of XEmacs.
 
@@ -542,8 +542,11 @@
 uninit_buffer_syntax_cache (struct buffer *UNUSED_IF_NEW_GC (buf))
 {
 #ifndef NEW_GC
-  xfree (buf->syntax_cache);
-  buf->syntax_cache = 0;
+  if (buf->syntax_cache)
+    {
+      xfree (buf->syntax_cache);
+      buf->syntax_cache = 0;
+    }
 #endif /* not NEW_GC */
 }
 
--- a/src/text.h	Mon Mar 22 19:12:15 2010 -0500
+++ b/src/text.h	Wed Mar 24 01:22:51 2010 -0500
@@ -2060,9 +2060,15 @@
   if ((ei)->mallocp_)				\
     {						\
       if ((ei)->data_)				\
-	xfree ((ei)->data_);			\
+        {					\
+  	  xfree ((ei)->data_);			\
+	  (ei)->data_ = 0;			\
+	}					\
       if ((ei)->extdata_)			\
-	xfree ((ei)->extdata_);			\
+	{					\
+	  xfree ((ei)->extdata_);		\
+	  (ei)->extdata_ = 0;			\
+	}					\
       eiinit_malloc (ei);			\
     }						\
   else						\