[Python-checkins] CVS: python/dist/src/Objects object.c,2.154,2.155 typeobject.c,2.91,2.92

Tim Peters tim_one@users.sourceforge.net
Sat, 06 Oct 2001 14:27:36 -0700


Update of /cvsroot/python/python/dist/src/Objects
In directory usw-pr-cvs1:/tmp/cvs-serv19908/python/Objects

Modified Files:
	object.c typeobject.c 
Log Message:
_PyObject_VAR_SIZE:  always round up to a multiple-of-pointer-size value.
As Guido suggested, this makes the new subclassing code substantially
simpler.  But the mechanics of doing it w/ C macro semantics are a mess,
and _PyObject_VAR_SIZE has a new calling sequence now.

Question:  The PyObject_NEW_VAR macro appears to be part of the public API.
Regardless of what it expands to, the notion that it has to round up the
memory it allocates is new, and extensions containing the old
PyObject_NEW_VAR macro expansion (which was embedded in the
PyObject_NEW_VAR expansion) won't do this rounding.  But the rounding
isn't actually *needed* except for new-style instances with dict pointers
after a variable-length blob of embedded data.  So my guess is that we do
not need to bump the API version for this (as the rounding isn't needed
for anything an extension can do unless it's recompiled anyway).  What's
your guess?


Index: object.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/object.c,v
retrieving revision 2.154
retrieving revision 2.155
diff -C2 -d -r2.154 -r2.155
*** object.c	2001/10/06 17:45:17	2.154
--- object.c	2001/10/06 21:27:34	2.155
***************
*** 128,138 ****
  
  PyVarObject *
! _PyObject_NewVar(PyTypeObject *tp, int size)
  {
  	PyVarObject *op;
! 	op = (PyVarObject *) PyObject_MALLOC(_PyObject_VAR_SIZE(tp, size));
  	if (op == NULL)
  		return (PyVarObject *)PyErr_NoMemory();
! 	return PyObject_INIT_VAR(op, tp, size);
  }
  
--- 128,141 ----
  
  PyVarObject *
! _PyObject_NewVar(PyTypeObject *tp, int nitems)
  {
  	PyVarObject *op;
! 	size_t size;
! 
! 	_PyObject_VAR_SIZE(size, tp, nitems);
! 	op = (PyVarObject *) PyObject_MALLOC(size);
  	if (op == NULL)
  		return (PyVarObject *)PyErr_NoMemory();
! 	return PyObject_INIT_VAR(op, tp, nitems);
  }
  
***************
*** 1147,1152 ****
  _PyObject_GetDictPtr(PyObject *obj)
  {
- #define PTRSIZE (sizeof(PyObject *))
- 
  	long dictoffset;
  	PyTypeObject *tp = obj->ob_type;
--- 1150,1153 ----
***************
*** 1158,1174 ****
  		return NULL;
  	if (dictoffset < 0) {
! 		/* dictoffset is positive by the time we're ready to round
! 		   it, and compilers can generate faster rounding code if
! 		   they know that. */
! 		unsigned long udo;  /* unsigned dictoffset */
! 		const long nitems = ((PyVarObject *)obj)->ob_size;
! 		const long size = _PyObject_VAR_SIZE(tp, nitems);
! 
! 		dictoffset += size;
! 		assert(dictoffset > 0); /* Sanity check */
! 		/* Round up to multiple of PTRSIZE. */
! 		udo = (unsigned long)dictoffset;
! 		udo = ((udo + PTRSIZE-1) / PTRSIZE) * PTRSIZE;
! 		dictoffset = (long)udo;
  	}
  	return (PyObject **) ((char *)obj + dictoffset);
--- 1159,1167 ----
  		return NULL;
  	if (dictoffset < 0) {
! 		size_t size;
! 		_PyObject_VAR_SIZE(size, tp, ((PyVarObject *)obj)->ob_size);
! 		dictoffset += (long)size;
! 		assert(dictoffset > 0);
! 		assert(dictoffset % SIZEOF_VOID_P == 0);
  	}
  	return (PyObject **) ((char *)obj + dictoffset);

Index: typeobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/typeobject.c,v
retrieving revision 2.91
retrieving revision 2.92
diff -C2 -d -r2.91 -r2.92
*** typeobject.c	2001/10/06 19:04:01	2.91
--- typeobject.c	2001/10/06 21:27:34	2.92
***************
*** 191,216 ****
  PyType_GenericAlloc(PyTypeObject *type, int nitems)
  {
- #define PTRSIZE (sizeof(PyObject *))
- 
- 	size_t size = (size_t)_PyObject_VAR_SIZE(type, nitems);
- 	size_t padding = 0;
  	PyObject *obj;
  
! 	/* Round up size, if necessary, so that the __dict__ pointer
! 	   following the variable part is properly aligned for the platform.
! 	   This is needed only for types with a vrbl number of items
! 	   before the __dict__ pointer == types that record the dict offset
! 	   as a negative offset from the end of the object.  If tp_dictoffset
! 	   is 0, there is no __dict__; if positive, tp_dict was declared in a C
! 	   struct so the compiler already took care of aligning it. */
!         if (type->tp_dictoffset < 0) {
! 		padding = PTRSIZE - size % PTRSIZE;
! 		if (padding == PTRSIZE)
! 			padding = 0;
! 		size += padding;
! 	}
  
  	if (PyType_IS_GC(type))
! 		obj = _PyObject_GC_Malloc(type, nitems, padding);
  	else
  		obj = PyObject_MALLOC(size);
--- 191,201 ----
  PyType_GenericAlloc(PyTypeObject *type, int nitems)
  {
  	PyObject *obj;
+ 	size_t size;
  
! 	_PyObject_VAR_SIZE(size, type, nitems);
  
  	if (PyType_IS_GC(type))
! 		obj = _PyObject_GC_Malloc(type, nitems);
  	else
  		obj = PyObject_MALLOC(size);