[Patches] Re: Garbage collection patches for Python

nascheme@enme.ucalgary.ca nascheme@enme.ucalgary.ca
Sat, 5 Feb 2000 09:28:23 -0700


--TB36FDmn/VVEgNH/
Content-Type: text/plain; charset=us-ascii

On Sat, Feb 05, 2000 at 03:00:59PM +0100, Vladimir Marangozov wrote:
> Neil, could you please resubmit your 1st GC patch with the disclaimer,
> so that we can focus on this 1st step, test the patch and fold it into
> CVS?

No problem.  I've included my Boehm-Demers-Weiser garbage
collector patch too as I have improved it to use autoconfig.  The
gc patch is small compared to the malloc cleanup.  It should work
on most Unix machines.  I haven't got it to work properly on
Windows yet.

I also added support for classes and instances in Toby's very
cool GC patch.  If anyone is interested I can make a new patch
for that.  I am planning to change it to use a hash table instead
of splay trees.  Please let me know if you have any comments
about that approach.


    Neil



I confirm that, to the best of my knowledge and belief, this
contribution is free of any claims of third parties under
copyright, patent or other rights or interests ("claims").  To
the extent that I have any such claims, I hereby grant to CNRI a
nonexclusive, irrevocable, royalty-free, worldwide license to
reproduce, distribute, perform and/or display publicly, prepare
derivative versions, and otherwise use this contribution as part
of the Python software and its related documentation, or any
derivative versions thereof, at no cost to CNRI or its licensed
users, and to authorize others to do so.

I acknowledge that CNRI may, at its sole discretion, decide
whether or not to incorporate this contribution in the Python
software and its related documentation.  I further grant CNRI
permission to use my name and other identifying information
provided to CNRI by me for use in connection with the Python
software and its related documentation.



--TB36FDmn/VVEgNH/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="malloc-cleanup.diff"

diff -cr Python-cvs/Include/mymalloc.h Python-gc/Include/mymalloc.h
*** Python-cvs/Include/mymalloc.h	Sat Jul 17 12:13:10 1999
--- Python-gc/Include/mymalloc.h	Sat Feb  5 09:07:54 2000
***************
*** 87,92 ****
--- 87,94 ----
  #define _PyMem_EXTRA 0
  #endif
  
+ #define PyMem_MALLOC(n) malloc(n)
+ #define PyMem_REALLOC(p, n) realloc(p, n)
  #define PyMem_NEW(type, n) \
  	( (type *) malloc(_PyMem_EXTRA + (n) * sizeof(type)) )
  #define PyMem_RESIZE(p, type, n) \
***************
*** 97,103 ****
  				       _PyMem_EXTRA + (n) * sizeof(type))
  #define PyMem_DEL(p) free((ANY *)p)
  #define PyMem_XDEL(p) if ((p) == NULL) ; else PyMem_DEL(p)
- 
  
  /* Two sets of function wrappers around malloc and friends; useful if
     you need to be sure that you are using the same memory allocator as
--- 99,104 ----
diff -cr Python-cvs/Modules/pypcre.c Python-gc/Modules/pypcre.c
*** Python-cvs/Modules/pypcre.c	Sat Jul 17 12:13:10 1999
--- Python-gc/Modules/pypcre.c	Sat Feb  5 09:00:47 2000
***************
*** 3057,3068 ****
  static int free_stack(match_data *md)
  {
  /* Free any stack space that was allocated by the call to match(). */
! if (md->off_num)    free(md->off_num); 
! if (md->offset_top) free(md->offset_top); 
! if (md->r1)         free(md->r1); 
! if (md->r2)         free(md->r2); 
! if (md->eptr)       free((char *)md->eptr); 
! if (md->ecode)      free((char *)md->ecode);
  return 0;
  }
  
--- 3057,3068 ----
  static int free_stack(match_data *md)
  {
  /* Free any stack space that was allocated by the call to match(). */
! if (md->off_num)    PyMem_DEL(md->off_num); 
! if (md->offset_top) PyMem_DEL(md->offset_top); 
! if (md->r1)         PyMem_DEL(md->r1); 
! if (md->r2)         PyMem_DEL(md->r2); 
! if (md->eptr)       PyMem_DEL((char *)md->eptr); 
! if (md->ecode)      PyMem_DEL((char *)md->ecode);
  return 0;
  }
  
diff -cr Python-cvs/Modules/readline.c Python-gc/Modules/readline.c
*** Python-cvs/Modules/readline.c	Sat Feb  5 09:00:14 2000
--- Python-gc/Modules/readline.c	Sat Feb  5 09:00:47 2000
***************
*** 41,46 ****
--- 41,63 ----
  extern int (*PyOS_InputHook)();
  extern char *(*PyOS_ReadlineFunctionPointer) Py_PROTO((char *));
  
+ /* convert a string allocated by malloc to one allocated by PyMem_MALLOC */
+ static char *
+ malloc2PyMem(char *p)
+ {
+ 	char *py;
+ 	int n;
+ 	if (p == NULL) {
+ 		return p;
+ 	} else {
+ 		n = strlen(p);
+ 		py = PyMem_MALLOC(n);
+ 		strncpy(py, p, n+1);
+ 		free(p);
+ 		return py;
+ 	}
+ }
+ 
  
  /* Exported function to send one line to readline's init file parser */
  
***************
*** 392,398 ****
  	p = readline(prompt);
  	signal(SIGINT, old_inthandler);
  	if (p == NULL) {
! 		p = malloc(1);
  		if (p != NULL)
  			*p = '\0';
  		return p;
--- 409,415 ----
  	p = readline(prompt);
  	signal(SIGINT, old_inthandler);
  	if (p == NULL) {
! 		p = PyMem_MALLOC(1);
  		if (p != NULL)
  			*p = '\0';
  		return p;
***************
*** 404,410 ****
  		p[n] = '\n';
  		p[n+1] = '\0';
  	}
! 	return p;
  }
  
  
--- 421,427 ----
  		p[n] = '\n';
  		p[n+1] = '\0';
  	}
! 	return malloc2PyMem(p);
  }
  
  
diff -cr Python-cvs/Modules/regexpr.c Python-gc/Modules/regexpr.c
*** Python-cvs/Modules/regexpr.c	Sat Jul 17 12:13:10 1999
--- Python-gc/Modules/regexpr.c	Sat Feb  5 09:00:47 2000
***************
*** 175,181 ****
  { \
  	state.stack.current = state.stack.first.next; \
  	state.stack.first.next = state.stack.current->next; \
! 	free(state.stack.current); \
  }
  
  /* Discard the top 'count' stack items. */
--- 175,181 ----
  { \
  	state.stack.current = state.stack.first.next; \
  	state.stack.first.next = state.stack.current->next; \
! 	PyMem_DEL(state.stack.current); \
  }
  
  /* Discard the top 'count' stack items. */
***************
*** 215,221 ****
  { \
  	if (stack.current->next == NULL) \
  	{ \
! 		stack.current->next = (item_page_t *)malloc(sizeof(item_page_t)); \
  		if (stack.current->next == NULL) \
  			on_error; \
  		stack.current->next->prev = stack.current; \
--- 215,221 ----
  { \
  	if (stack.current->next == NULL) \
  	{ \
! 		stack.current->next = (item_page_t *)PyMem_MALLOC(sizeof(item_page_t)); \
  		if (stack.current->next == NULL) \
  			on_error; \
  		stack.current->next->prev = stack.current; \
***************
*** 723,729 ****
  		visited = small_visited;
  	else
  	{
! 		visited = malloc(used);
  		if (!visited)
  			return 0;
  	}
--- 723,729 ----
  		visited = small_visited;
  	else
  	{
! 		visited = PyMem_MALLOC(used);
  		if (!visited)
  			return 0;
  	}
***************
*** 732,738 ****
  	memset(visited, 0, used);
  	re_compile_fastmap_aux(buffer, pos, visited, can_be_null, fastmap);
  	if (visited != small_visited)
! 		free(visited);
  	return 1;
  }
  
--- 732,738 ----
  	memset(visited, 0, used);
  	re_compile_fastmap_aux(buffer, pos, visited, can_be_null, fastmap);
  	if (visited != small_visited)
! 		PyMem_DEL(visited);
  	return 1;
  }
  
***************
*** 1025,1031 ****
  	  if (pattern_offset+(amount) > alloc) \
  	  { \
  		  alloc += 256 + (amount); \
! 		  pattern = realloc(pattern, alloc); \
  		  if (!pattern) \
  			  goto out_of_memory; \
  	  } \
--- 1025,1031 ----
  	  if (pattern_offset+(amount) > alloc) \
  	  { \
  		  alloc += 256 + (amount); \
! 		  pattern = PyMem_REALLOC(pattern, alloc); \
  		  if (!pattern) \
  			  goto out_of_memory; \
  	  } \
***************
*** 1184,1190 ****
  	if (alloc == 0 || pattern == NULL)
  	{
  		alloc = 256;
! 		pattern = malloc(alloc);
  		if (!pattern)
  			goto out_of_memory;
  	}
--- 1184,1190 ----
  	if (alloc == 0 || pattern == NULL)
  	{
  		alloc = 256;
! 		pattern = PyMem_MALLOC(alloc);
  		if (!pattern)
  			goto out_of_memory;
  	}
diff -cr Python-cvs/Objects/bufferobject.c Python-gc/Objects/bufferobject.c
*** Python-cvs/Objects/bufferobject.c	Sat Feb  5 09:00:14 2000
--- Python-gc/Objects/bufferobject.c	Sat Feb  5 09:01:35 2000
***************
*** 188,194 ****
  				"size must be zero or positive");
  		return NULL;
  	}
! 	b = (PyBufferObject *)malloc(sizeof(*b) + size);
  	if ( b == NULL )
  		return PyErr_NoMemory();
  	b->ob_type = &PyBuffer_Type;
--- 188,194 ----
  				"size must be zero or positive");
  		return NULL;
  	}
! 	b = (PyBufferObject *)PyMem_MALLOC(sizeof(*b) + size);
  	if ( b == NULL )
  		return PyErr_NoMemory();
  	b->ob_type = &PyBuffer_Type;
***************
*** 212,218 ****
  	PyBufferObject *self;
  {
  	Py_XDECREF(self->b_base);
! 	free((void *)self);
  }
  
  static int
--- 212,218 ----
  	PyBufferObject *self;
  {
  	Py_XDECREF(self->b_base);
! 	PyMem_DEL((void *)self);
  }
  
  static int
diff -cr Python-cvs/Objects/classobject.c Python-gc/Objects/classobject.c
*** Python-cvs/Objects/classobject.c	Sat Feb  5 09:00:14 2000
--- Python-gc/Objects/classobject.c	Sat Feb  5 09:00:47 2000
***************
*** 146,152 ****
  	Py_XDECREF(op->cl_getattr);
  	Py_XDECREF(op->cl_setattr);
  	Py_XDECREF(op->cl_delattr);
! 	free((ANY *)op);
  }
  
  static PyObject *
--- 146,152 ----
  	Py_XDECREF(op->cl_getattr);
  	Py_XDECREF(op->cl_setattr);
  	Py_XDECREF(op->cl_delattr);
! 	PyMem_DEL((ANY *)op);
  }
  
  static PyObject *
***************
*** 561,567 ****
  #endif /* Py_TRACE_REFS */
  	Py_DECREF(inst->in_class);
  	Py_XDECREF(inst->in_dict);
! 	free((ANY *)inst);
  }
  
  static PyObject *
--- 561,567 ----
  #endif /* Py_TRACE_REFS */
  	Py_DECREF(inst->in_class);
  	Py_XDECREF(inst->in_dict);
! 	PyMem_DEL((ANY *)inst);
  }
  
  static PyObject *
diff -cr Python-cvs/Objects/complexobject.c Python-gc/Objects/complexobject.c
*** Python-cvs/Objects/complexobject.c	Sat Feb  5 09:00:14 2000
--- Python-gc/Objects/complexobject.c	Sat Feb  5 09:00:47 2000
***************
*** 167,173 ****
  	Py_complex cval;
  {
  	register PyComplexObject *op =
! 		(PyComplexObject *) malloc(sizeof(PyComplexObject));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyComplex_Type;
--- 167,173 ----
  	Py_complex cval;
  {
  	register PyComplexObject *op =
! 		(PyComplexObject *) PyMem_MALLOC(sizeof(PyComplexObject));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyComplex_Type;
diff -cr Python-cvs/Objects/dictobject.c Python-gc/Objects/dictobject.c
*** Python-cvs/Objects/dictobject.c	Sat Jul 17 12:13:10 1999
--- Python-gc/Objects/dictobject.c	Sat Feb  5 09:00:47 2000
***************
*** 277,283 ****
  			break;
  		}
  	}
! 	newtable = (dictentry *) malloc(sizeof(dictentry) * newsize);
  	if (newtable == NULL) {
  		PyErr_NoMemory();
  		return -1;
--- 277,283 ----
  			break;
  		}
  	}
! 	newtable = (dictentry *) PyMem_MALLOC(sizeof(dictentry) * newsize);
  	if (newtable == NULL) {
  		PyErr_NoMemory();
  		return -1;
diff -cr Python-cvs/Objects/fileobject.c Python-gc/Objects/fileobject.c
*** Python-cvs/Objects/fileobject.c	Sat Feb  5 09:00:14 2000
--- Python-gc/Objects/fileobject.c	Sat Feb  5 09:00:47 2000
***************
*** 209,215 ****
  	if (f->f_mode != NULL) {
  		Py_DECREF(f->f_mode);
  	}
! 	free((char *)f);
  }
  
  static PyObject *
--- 209,215 ----
  	if (f->f_mode != NULL) {
  		Py_DECREF(f->f_mode);
  	}
! 	PyMem_DEL((char *)f);
  }
  
  static PyObject *
diff -cr Python-cvs/Objects/floatobject.c Python-gc/Objects/floatobject.c
*** Python-cvs/Objects/floatobject.c	Sat Feb  5 09:00:15 2000
--- Python-gc/Objects/floatobject.c	Sat Feb  5 09:00:47 2000
***************
*** 98,106 ****
  #define BHEAD_SIZE	8	/* Enough for a 64-bit pointer */
  #define N_FLOATOBJECTS	((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyFloatObject))
  
- #define PyMem_MALLOC	malloc
- #define PyMem_FREE	free
- 
  struct _floatblock {
  	struct _floatblock *next;
  	PyFloatObject objects[N_FLOATOBJECTS];
--- 98,103 ----
***************
*** 756,762 ****
  			}
  		}
  		else {
! 			PyMem_FREE(list);
  			bf++;
  		}
  		fsum += frem;
--- 753,759 ----
  			}
  		}
  		else {
! 			PyMem_DEL(list);
  			bf++;
  		}
  		fsum += frem;
diff -cr Python-cvs/Objects/frameobject.c Python-gc/Objects/frameobject.c
*** Python-cvs/Objects/frameobject.c	Sat Feb  5 09:00:15 2000
--- Python-gc/Objects/frameobject.c	Sat Feb  5 09:00:47 2000
***************
*** 179,185 ****
  		builtins = NULL;
  	if (free_list == NULL) {
  		f = (PyFrameObject *)
! 			malloc(sizeof(PyFrameObject) +
  			       extras*sizeof(PyObject *));
  		if (f == NULL)
  			return (PyFrameObject *)PyErr_NoMemory();
--- 179,185 ----
  		builtins = NULL;
  	if (free_list == NULL) {
  		f = (PyFrameObject *)
! 			PyMem_MALLOC(sizeof(PyFrameObject) +
  			       extras*sizeof(PyObject *));
  		if (f == NULL)
  			return (PyFrameObject *)PyErr_NoMemory();
***************
*** 191,197 ****
  		free_list = free_list->f_back;
  		if (f->f_nlocals + f->f_stacksize < extras) {
  			f = (PyFrameObject *)
! 				realloc(f, sizeof(PyFrameObject) +
  					extras*sizeof(PyObject *));
  			if (f == NULL)
  				return (PyFrameObject *)PyErr_NoMemory();
--- 191,197 ----
  		free_list = free_list->f_back;
  		if (f->f_nlocals + f->f_stacksize < extras) {
  			f = (PyFrameObject *)
! 				PyMem_REALLOC(f, sizeof(PyFrameObject) +
  					extras*sizeof(PyObject *));
  			if (f == NULL)
  				return (PyFrameObject *)PyErr_NoMemory();
diff -cr Python-cvs/Objects/intobject.c Python-gc/Objects/intobject.c
*** Python-cvs/Objects/intobject.c	Sat Feb  5 09:00:15 2000
--- Python-gc/Objects/intobject.c	Sat Feb  5 09:00:47 2000
***************
*** 94,102 ****
  #define BHEAD_SIZE	8	/* Enough for a 64-bit pointer */
  #define N_INTOBJECTS	((BLOCK_SIZE - BHEAD_SIZE) / sizeof(PyIntObject))
  
- #define PyMem_MALLOC	malloc
- #define PyMem_FREE	free
- 
  struct _intblock {
  	struct _intblock *next;
  	PyIntObject objects[N_INTOBJECTS];
--- 94,99 ----
***************
*** 915,921 ****
  			}
  		}
  		else {
! 			PyMem_FREE(list);
  			bf++;
  		}
  		isum += irem;
--- 912,918 ----
  			}
  		}
  		else {
! 			PyMem_DEL(list);
  			bf++;
  		}
  		isum += irem;
diff -cr Python-cvs/Objects/listobject.c Python-gc/Objects/listobject.c
*** Python-cvs/Objects/listobject.c	Sat Feb  5 09:00:15 2000
--- Python-gc/Objects/listobject.c	Sat Feb  5 09:00:47 2000
***************
*** 70,76 ****
  	if (nbytes / sizeof(PyObject *) != (size_t)size) {
  		return PyErr_NoMemory();
  	}
! 	op = (PyListObject *) malloc(sizeof(PyListObject));
  	if (op == NULL) {
  		return PyErr_NoMemory();
  	}
--- 70,76 ----
  	if (nbytes / sizeof(PyObject *) != (size_t)size) {
  		return PyErr_NoMemory();
  	}
! 	op = (PyListObject *) PyMem_MALLOC(sizeof(PyListObject));
  	if (op == NULL) {
  		return PyErr_NoMemory();
  	}
***************
*** 78,86 ****
  		op->ob_item = NULL;
  	}
  	else {
! 		op->ob_item = (PyObject **) malloc(nbytes);
  		if (op->ob_item == NULL) {
! 			free((ANY *)op);
  			return PyErr_NoMemory();
  		}
  	}
--- 78,86 ----
  		op->ob_item = NULL;
  	}
  	else {
! 		op->ob_item = (PyObject **) PyMem_MALLOC(nbytes);
  		if (op->ob_item == NULL) {
! 			PyMem_DEL((ANY *)op);
  			return PyErr_NoMemory();
  		}
  	}
***************
*** 224,232 ****
  		while (--i >= 0) {
  			Py_XDECREF(op->ob_item[i]);
  		}
! 		free((ANY *)op->ob_item);
  	}
! 	free((ANY *)op);
  }
  
  static int
--- 224,232 ----
  		while (--i >= 0) {
  			Py_XDECREF(op->ob_item[i]);
  		}
! 		PyMem_DEL((ANY *)op->ob_item);
  	}
! 	PyMem_DEL((ANY *)op);
  }
  
  static int
diff -cr Python-cvs/Objects/moduleobject.c Python-gc/Objects/moduleobject.c
*** Python-cvs/Objects/moduleobject.c	Sat Jul 17 12:13:10 1999
--- Python-gc/Objects/moduleobject.c	Sat Feb  5 09:00:47 2000
***************
*** 170,176 ****
  		_PyModule_Clear((PyObject *)m);
  		Py_DECREF(m->md_dict);
  	}
! 	free((char *)m);
  }
  
  static PyObject *
--- 170,176 ----
  		_PyModule_Clear((PyObject *)m);
  		Py_DECREF(m->md_dict);
  	}
! 	PyMem_DEL((char *)m);
  }
  
  static PyObject *
diff -cr Python-cvs/Objects/object.c Python-gc/Objects/object.c
*** Python-cvs/Objects/object.c	Sat Feb  5 09:00:18 2000
--- Python-gc/Objects/object.c	Sat Feb  5 09:07:54 2000
***************
*** 33,38 ****
--- 33,39 ----
  
  #include "Python.h"
  
+ 
  #if defined( Py_TRACE_REFS ) || defined( Py_REF_DEBUG )
  DL_IMPORT(long) _Py_RefTotal;
  #endif
***************
*** 119,125 ****
  #endif
  {
  #ifndef MS_COREDLL
! 	PyObject *op = (PyObject *) malloc(tp->tp_basicsize);
  #endif
  	if (op == NULL)
  		return PyErr_NoMemory();
--- 120,126 ----
  #endif
  {
  #ifndef MS_COREDLL
! 	PyObject *op = (PyObject *) PyMem_MALLOC(tp->tp_basicsize);
  #endif
  	if (op == NULL)
  		return PyErr_NoMemory();
***************
*** 143,149 ****
  {
  #ifndef MS_COREDLL
  	PyVarObject *op = (PyVarObject *)
! 		malloc(tp->tp_basicsize + size * tp->tp_itemsize);
  #endif
  	if (op == NULL)
  		return (PyVarObject *)PyErr_NoMemory();
--- 144,150 ----
  {
  #ifndef MS_COREDLL
  	PyVarObject *op = (PyVarObject *)
! 		PyMem_MALLOC(tp->tp_basicsize + size * tp->tp_itemsize);
  #endif
  	if (op == NULL)
  		return (PyVarObject *)PyErr_NoMemory();
***************
*** 754,760 ****
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	p = malloc(nbytes);
  	if (p != NULL)
  		return p;
  	else {
--- 755,761 ----
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	p = PyMem_MALLOC(nbytes);
  	if (p != NULL)
  		return p;
  	else {
***************
*** 772,778 ****
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	p = realloc(p, nbytes);
  	if (p != NULL)
  		return p;
  	else {
--- 773,779 ----
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	p = PyMem_REALLOC(p, nbytes);
  	if (p != NULL)
  		return p;
  	else {
***************
*** 785,791 ****
  Py_Free(p)
  	ANY *p;
  {
! 	free(p);
  }
  
  /* The PyMem_{Malloc,Realloc} wrappers don't call anything on failure */
--- 786,792 ----
  Py_Free(p)
  	ANY *p;
  {
! 	PyMem_DEL(p);
  }
  
  /* The PyMem_{Malloc,Realloc} wrappers don't call anything on failure */
***************
*** 798,804 ****
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	return malloc(nbytes);
  }
  
  ANY *
--- 799,805 ----
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	return PyMem_MALLOC(nbytes);
  }
  
  ANY *
***************
*** 810,823 ****
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	return realloc(p, nbytes);
  }
  
  void
  PyMem_Free(p)
  	ANY *p;
  {
! 	free(p);
  }
  
  
--- 811,824 ----
  	if (nbytes == 0)
  		nbytes = _PyMem_EXTRA;
  #endif
! 	return PyMem_REALLOC(p, nbytes);
  }
  
  void
  PyMem_Free(p)
  	ANY *p;
  {
! 	PyMem_DEL(p);
  }
  
  
diff -cr Python-cvs/Objects/stringobject.c Python-gc/Objects/stringobject.c
*** Python-cvs/Objects/stringobject.c	Sat Feb  5 09:00:18 2000
--- Python-gc/Objects/stringobject.c	Sat Feb  5 09:00:47 2000
***************
*** 93,99 ****
  	}
  #endif /* DONT_SHARE_SHORT_STRINGS */
  	op = (PyStringObject *)
! 		malloc(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
--- 93,99 ----
  	}
  #endif /* DONT_SHARE_SHORT_STRINGS */
  	op = (PyStringObject *)
! 		PyMem_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
***************
*** 143,149 ****
  	}
  #endif /* DONT_SHARE_SHORT_STRINGS */
  	op = (PyStringObject *)
! 		malloc(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
--- 143,149 ----
  	}
  #endif /* DONT_SHARE_SHORT_STRINGS */
  	op = (PyStringObject *)
! 		PyMem_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
***************
*** 306,312 ****
  	}
  	size = a->ob_size + b->ob_size;
  	op = (PyStringObject *)
! 		malloc(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
--- 306,312 ----
  	}
  	size = a->ob_size + b->ob_size;
  	op = (PyStringObject *)
! 		PyMem_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
***************
*** 341,347 ****
  		return (PyObject *)a;
  	}
  	op = (PyStringObject *)
! 		malloc(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
--- 341,347 ----
  		return (PyObject *)a;
  	}
  	op = (PyStringObject *)
! 		PyMem_MALLOC(sizeof(PyStringObject) + size * sizeof(char));
  	if (op == NULL)
  		return PyErr_NoMemory();
  	op->ob_type = &PyString_Type;
***************
*** 1646,1652 ****
  #endif
  	_Py_ForgetReference(v);
  	*pv = (PyObject *)
! 		realloc((char *)v,
  			sizeof(PyStringObject) + newsize * sizeof(char));
  	if (*pv == NULL) {
  		PyMem_DEL(v);
--- 1646,1652 ----
  #endif
  	_Py_ForgetReference(v);
  	*pv = (PyObject *)
! 		PyMem_REALLOC((char *)v,
  			sizeof(PyStringObject) + newsize * sizeof(char));
  	if (*pv == NULL) {
  		PyMem_DEL(v);
diff -cr Python-cvs/Objects/tupleobject.c Python-gc/Objects/tupleobject.c
*** Python-cvs/Objects/tupleobject.c	Sat Feb  5 09:00:18 2000
--- Python-gc/Objects/tupleobject.c	Sat Feb  5 09:02:17 2000
***************
*** 91,97 ****
  			return PyErr_NoMemory();
  		}
  		;
! 		op = (PyTupleObject *) malloc(nbytes);
  		if (op == NULL)
  			return PyErr_NoMemory();
  
--- 91,97 ----
  			return PyErr_NoMemory();
  		}
  		;
! 		op = (PyTupleObject *) PyMem_MALLOC(nbytes);
  		if (op == NULL)
  			return PyErr_NoMemory();
  
***************
*** 184,190 ****
  		}
  #endif
  	}
! 	free((ANY *)op);
  }
  
  static int
--- 184,190 ----
  		}
  #endif
  	}
! 	PyMem_DEL(op);
  }
  
  static int
***************
*** 467,473 ****
  		v->ob_item[i] = NULL;
  	}
  	sv = (PyTupleObject *)
! 		realloc((char *)v,
  			sizeof(PyTupleObject) + newsize * sizeof(PyObject *));
  	*pv = (PyObject *) sv;
  	if (sv == NULL) {
--- 467,473 ----
  		v->ob_item[i] = NULL;
  	}
  	sv = (PyTupleObject *)
! 		PyMem_REALLOC((char *)v,
  			sizeof(PyTupleObject) + newsize * sizeof(PyObject *));
  	*pv = (PyObject *) sv;
  	if (sv == NULL) {
diff -cr Python-cvs/Parser/myreadline.c Python-gc/Parser/myreadline.c
*** Python-cvs/Parser/myreadline.c	Sat Jul 17 12:13:10 1999
--- Python-gc/Parser/myreadline.c	Sat Feb  5 09:00:47 2000
***************
*** 89,95 ****
  	int n;
  	char *p;
  	n = 100;
! 	if ((p = malloc(n)) == NULL)
  		return NULL;
  	fflush(stdout);
  	if (prompt)
--- 89,95 ----
  	int n;
  	char *p;
  	n = 100;
! 	if ((p = PyMem_MALLOC(n)) == NULL)
  		return NULL;
  	fflush(stdout);
  	if (prompt)
***************
*** 99,105 ****
  	case 0: /* Normal case */
  		break;
  	case 1: /* Interrupt */
! 		free(p);
  		return NULL;
  	case -1: /* EOF */
  	case -2: /* Error */
--- 99,105 ----
  	case 0: /* Normal case */
  		break;
  	case 1: /* Interrupt */
! 		PyMem_DEL(p);
  		return NULL;
  	case -1: /* EOF */
  	case -2: /* Error */
***************
*** 117,130 ****
  	n = strlen(p);
  	while (n > 0 && p[n-1] != '\n') {
  		int incr = n+2;
! 		p = realloc(p, n + incr);
  		if (p == NULL)
  			return NULL;
  		if (my_fgets(p+n, incr, stdin) != 0)
  			break;
  		n += strlen(p+n);
  	}
! 	return realloc(p, n+1);
  }
  
  
--- 117,130 ----
  	n = strlen(p);
  	while (n > 0 && p[n-1] != '\n') {
  		int incr = n+2;
! 		p = PyMem_REALLOC(p, n + incr);
  		if (p == NULL)
  			return NULL;
  		if (my_fgets(p+n, incr, stdin) != 0)
  			break;
  		n += strlen(p+n);
  	}
! 	return PyMem_REALLOC(p, n+1);
  }
  
  
diff -cr Python-cvs/Parser/tokenizer.c Python-gc/Parser/tokenizer.c
*** Python-cvs/Parser/tokenizer.c	Sat Jul 17 12:13:10 1999
--- Python-gc/Parser/tokenizer.c	Sat Feb  5 09:00:47 2000
***************
*** 219,225 ****
  			if (new == NULL)
  				tok->done = E_INTR;
  			else if (*new == '\0') {
! 				free(new);
  				tok->done = E_EOF;
  			}
  			else if (tok->start != NULL) {
--- 219,225 ----
  			if (new == NULL)
  				tok->done = E_INTR;
  			else if (*new == '\0') {
! 				PyMem_DEL(new);
  				tok->done = E_EOF;
  			}
  			else if (tok->start != NULL) {
***************
*** 229,244 ****
  				char *buf = realloc(tok->buf, newlen+1);
  				tok->lineno++;
  				if (buf == NULL) {
! 					free(tok->buf);
  					tok->buf = NULL;
! 					free(new);
  					tok->done = E_NOMEM;
  					return EOF;
  				}
  				tok->buf = buf;
  				tok->cur = tok->buf + oldlen;
  				strcpy(tok->buf + oldlen, new);
! 				free(new);
  				tok->inp = tok->buf + newlen;
  				tok->end = tok->inp + 1;
  				tok->start = tok->buf + start;
--- 229,244 ----
  				char *buf = realloc(tok->buf, newlen+1);
  				tok->lineno++;
  				if (buf == NULL) {
! 					PyMem_DEL(tok->buf);
  					tok->buf = NULL;
! 					PyMem_DEL(new);
  					tok->done = E_NOMEM;
  					return EOF;
  				}
  				tok->buf = buf;
  				tok->cur = tok->buf + oldlen;
  				strcpy(tok->buf + oldlen, new);
! 				PyMem_DEL(new);
  				tok->inp = tok->buf + newlen;
  				tok->end = tok->inp + 1;
  				tok->start = tok->buf + start;
***************
*** 246,252 ****
  			else {
  				tok->lineno++;
  				if (tok->buf != NULL)
! 					free(tok->buf);
  				tok->buf = new;
  				tok->cur = tok->buf;
  				tok->inp = strchr(tok->buf, '\0');
--- 246,252 ----
  			else {
  				tok->lineno++;
  				if (tok->buf != NULL)
! 					PyMem_DEL(tok->buf);
  				tok->buf = new;
  				tok->cur = tok->buf;
  				tok->inp = strchr(tok->buf, '\0');

--TB36FDmn/VVEgNH/
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="gc-autoconfig.diff"

diff -cr Python-malloc/Include/mymalloc.h Python-gc/Include/mymalloc.h
*** Python-malloc/Include/mymalloc.h	Sat Feb  5 09:11:36 2000
--- Python-gc/Include/mymalloc.h	Sat Feb  5 09:11:54 2000
***************
*** 87,92 ****
--- 87,110 ----
  #define _PyMem_EXTRA 0
  #endif
  
+ #ifdef WITH_GC
+ 
+ #include <gc.h>
+ #define PyMem_MALLOC(n) GC_MALLOC(n)
+ #define PyMem_REALLOC(p, n) GC_REALLOC(p, n)
+ #define PyMem_NEW(type, n) \
+ 	( (type *) GC_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)) )
+ #define PyMem_RESIZE(p, type, n) \
+ 	if ((p) == NULL) \
+ 		(p) =  (type *) GC_MALLOC(_PyMem_EXTRA + (n) * sizeof(type)); \
+ 	else \
+ 		(p) = (type *) GC_REALLOC((ANY *)(p), \
+ 				       _PyMem_EXTRA + (n) * sizeof(type))
+ #define PyMem_DEL(p) GC_FREE((ANY *)p)
+ #define PyMem_XDEL(p) if ((p) == NULL) ; else PyMem_DEL(p)
+ 
+ #else /* ! WITH_GC */
+ 
  #define PyMem_MALLOC(n) malloc(n)
  #define PyMem_REALLOC(p, n) realloc(p, n)
  #define PyMem_NEW(type, n) \
***************
*** 99,104 ****
--- 117,124 ----
  				       _PyMem_EXTRA + (n) * sizeof(type))
  #define PyMem_DEL(p) free((ANY *)p)
  #define PyMem_XDEL(p) if ((p) == NULL) ; else PyMem_DEL(p)
+ 
+ #endif /* WITH_GC */
  
  /* Two sets of function wrappers around malloc and friends; useful if
     you need to be sure that you are using the same memory allocator as
diff -cr Python-malloc/Modules/_tkinter.c Python-gc/Modules/_tkinter.c
*** Python-malloc/Modules/_tkinter.c	Sat Feb  5 09:11:36 2000
--- Python-gc/Modules/_tkinter.c	Sat Feb  5 09:11:54 2000
***************
*** 1268,1274 ****
--- 1268,1281 ----
  		return NULL;
  	}
  
+ #ifdef WITH_GC
+ 	/* If we use GC_malloc then the gc thinks that there are no more
+ 	 * references to the callback and collects it */
+ 	data = (PythonCmd_ClientData*)
+ 			GC_malloc_uncollectable(sizeof(PythonCmd_ClientData));
+ #else
  	data = PyMem_NEW(PythonCmd_ClientData, 1);
+ #endif
  	if (!data)
  		return NULL;
  	Py_XINCREF(self);
***************
*** 1334,1340 ****
--- 1341,1354 ----
  	int id;
  {
  	FileHandler_ClientData *p;
+ #ifdef WITH_GC
+ 	/* If we use GC_malloc then the gc thinks that there are no more
+ 	 * references to the callback and collects it */
+ 	p = (FileHandler_ClientData*)
+ 			GC_malloc_uncollectable(sizeof(FileHandler_ClientData));
+ #else
  	p = PyMem_NEW(FileHandler_ClientData, 1);
+ #endif
  	if (p != NULL) {
  		Py_XINCREF(func);
  		Py_XINCREF(file);
diff -cr Python-malloc/Objects/object.c Python-gc/Objects/object.c
*** Python-malloc/Objects/object.c	Sat Feb  5 09:11:36 2000
--- Python-gc/Objects/object.c	Sat Feb  5 09:11:54 2000
***************
*** 108,113 ****
--- 108,124 ----
  }
  #endif
  
+ /*
+ #ifdef WITH_GC
+ static void 
+ _PyObject_Finalizer(GC_PTR *op, GC_PTR *client_data)
+ {
+ 	destructor dealloc = ((PyObject*)op)->ob_type->tp_dealloc;
+ 	(*dealloc)(op);
+ }
+ #endif
+ */
+ 
  #ifndef MS_COREDLL
  PyObject *
  _PyObject_New(tp)
***************
*** 124,129 ****
--- 135,145 ----
  #endif
  	if (op == NULL)
  		return PyErr_NoMemory();
+ /*
+ #ifdef WITH_GC
+ 	GC_register_finalizer(op, _PyObject_Finalizer, 0, 0, 0);
+ #endif
+ */
  	op->ob_type = tp;
  	_Py_NewReference(op);
  	return op;
***************
*** 148,153 ****
--- 164,174 ----
  #endif
  	if (op == NULL)
  		return (PyVarObject *)PyErr_NoMemory();
+ /*
+ #ifdef WITH_GC
+ 	GC_register_finalizer(op, _PyObject_Finalizer, 0, 0, 0);
+ #endif
+ */
  	op->ob_type = tp;
  	op->ob_size = size;
  	_Py_NewReference((PyObject *)op);
diff -cr Python-malloc/acconfig.h Python-gc/acconfig.h
*** Python-malloc/acconfig.h	Sat Feb  5 09:11:36 2000
--- Python-gc/acconfig.h	Sat Feb  5 09:11:54 2000
***************
*** 126,131 ****
--- 126,134 ----
  /* Define if you want to compile in rudimentary thread support */
  #undef WITH_THREAD
  
+ /* Define if you want to use the garbage collector */
+ #undef WITH_GC
+ 
  /* Define if you want to produce an OpenStep/Rhapsody framework
     (shared library plus accessory files). */
  #undef WITH_NEXT_FRAMEWORK
diff -cr Python-malloc/config.h.in Python-gc/config.h.in
*** Python-malloc/config.h.in	Sat Feb  5 09:11:36 2000
--- Python-gc/config.h.in	Sat Feb  5 09:11:54 2000
***************
*** 181,186 ****
--- 181,189 ----
  /* Define if you want to compile in rudimentary thread support */
  #undef WITH_THREAD
  
+ /* Define if you want to use the garbage collector */
+ #undef WITH_GC
+ 
  /* Define if you want to produce an OpenStep/Rhapsody framework
     (shared library plus accessory files). */
  #undef WITH_NEXT_FRAMEWORK
diff -cr Python-malloc/configure.in Python-gc/configure.in
*** Python-malloc/configure.in	Sat Feb  5 09:11:36 2000
--- Python-gc/configure.in	Sat Feb  5 09:11:54 2000
***************
*** 687,692 ****
--- 687,704 ----
  AC_SUBST(DLINCLDIR)
  DLINCLDIR=/
  
+ AC_MSG_CHECKING(for --with-gc)
+ AC_SUBST(LDLAST)
+ AC_ARG_WITH(gc,
+ [--with-gc		   use the Boehm-Demers-Weiser garbage collector],
+ [AC_MSG_RESULT($withval)
+ AC_DEFINE(WITH_GC)
+ LIBS="$LIBS -lgc"
+ if test "${with_gc+set}" != set; then
+    with_gc="$withval";
+ fi],
+ AC_MSG_RESULT(no))
+ 
  AC_MSG_CHECKING(for --with-sgi-dl)
  AC_ARG_WITH(sgi-dl, [--with-sgi-dl=DIRECTORY   IRIX 4 dynamic linking], [
  AC_MSG_RESULT($withval)

--TB36FDmn/VVEgNH/--