[Python-checkins] CVS: python/dist/src/Objects dictobject.c,2.92,2.93

Tim Peters tim_one@users.sourceforge.net
Wed, 23 May 2001 16:34:00 -0700


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

Modified Files:
	dictobject.c 
Log Message:
Jack Jansen hit a bug in the new dict code, reported on python-dev.

dictresize() was too aggressive about never ever resizing small dicts.
If a small dict is entirely full, it needs to rebuild it despite that
it won't actually resize it, in order to purge old dummy entries thus
creating at least one virgin slot (lookdict assumes at least one such
exists).

Also took the opportunity to add some high-level comments to dictresize.


Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.92
retrieving revision 2.93
diff -C2 -r2.92 -r2.93
*** dictobject.c	2001/05/22 22:36:52	2.92
--- dictobject.c	2001/05/23 23:33:57	2.93
***************
*** 396,407 ****
  dictresize(dictobject *mp, int minused)
  {
! 	register int newsize, newpoly;
! 	register dictentry *oldtable = mp->ma_table;
! 	register dictentry *newtable;
! 	register dictentry *ep;
! 	register int i;
  
  	assert(minused >= 0);
! 	assert(oldtable != NULL);
  	newpoly = 0;
  	newsize = MINSIZE;
--- 396,408 ----
  dictresize(dictobject *mp, int minused)
  {
! 	int newsize, newpoly;
! 	dictentry *oldtable, *newtable, *ep;
! 	int i;
! 	int is_oldtable_malloced;
! 	dictentry small_copy[MINSIZE];
  
  	assert(minused >= 0);
! 
! 	/* Find the smallest table size > minused, and its poly[] entry. */
  	newpoly = 0;
  	newsize = MINSIZE;
***************
*** 420,427 ****
  		return -1;
  	}
  	if (newsize == MINSIZE) {
  		newtable = mp->ma_smalltable;
! 		if (newtable == oldtable)
! 			return 0;
  	}
  	else {
--- 421,444 ----
  		return -1;
  	}
+ 
+ 	/* Get space for a new table. */
+ 	oldtable = mp->ma_table;
+ 	assert(oldtable != NULL);
+ 	is_oldtable_malloced = oldtable != mp->ma_smalltable;
+ 
  	if (newsize == MINSIZE) {
+ 		/* Either a large table is shrinking, or we can't get any
+ 		   smaller. */
  		newtable = mp->ma_smalltable;
! 		if (newtable == oldtable) {
! 			if (mp->ma_fill < mp->ma_size)
! 				return 0;
! 			/* The small table is entirely full.  We're not
! 			   going to resise it, but need to rebuild it
! 			   anyway to purge old dummy entries. */
! 			assert(mp->ma_fill > mp->ma_used); /* a dummy exists */
! 			memcpy(small_copy, oldtable, sizeof(small_copy));
! 			oldtable = small_copy;
! 		}
  	}
  	else {
***************
*** 432,435 ****
--- 449,454 ----
  		}
  	}
+ 
+ 	/* Make the dict empty, using the new table. */
  	assert(newtable != oldtable);
  	mp->ma_table = newtable;
***************
*** 456,460 ****
  	}
  
! 	if (oldtable != mp->ma_smalltable)
  		PyMem_DEL(oldtable);
  	return 0;
--- 475,479 ----
  	}
  
! 	if (is_oldtable_malloced)
  		PyMem_DEL(oldtable);
  	return 0;