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

Tim Peters tim_one@users.sourceforge.net
Thu, 13 Sep 2001 17:25:35 -0700


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

Modified Files:
	dictobject.c 
Log Message:
Changed the dict implementation to take "string shortcuts" only when
keys are true strings -- no subclasses need apply.  This may be debatable.

The problem is that a str subclass may very well want to override __eq__
and/or __hash__ (see the new example of case-insensitive strings in
test_descr), but go-fast shortcuts for strings are ubiquitous in our dicts
(and subclass overrides aren't even looked for then).  Another go-fast
reason for the change is that PyCheck_StringExact() is a quicker test
than PyCheck_String(), and we make such a test on virtually every access
to every dict.

OTOH, a str subclass may also be perfectly happy using the base str eq
and hash, and this change slows them a lot.  But those cases are still
hypothetical, while Python's own reliance on true-string dicts is not.


Index: dictobject.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Objects/dictobject.c,v
retrieving revision 2.112
retrieving revision 2.113
diff -C2 -d -r2.112 -r2.113
*** dictobject.c	2001/09/02 18:35:54	2.112
--- dictobject.c	2001/09/14 00:25:33	2.113
***************
*** 299,304 ****
   * _PyString_Eq directly.
   *
!  * This really only becomes meaningful if proper error handling in lookdict()
!  * is too expensive.
   */
  static dictentry *
--- 299,304 ----
   * _PyString_Eq directly.
   *
!  * This is valuable because the general-case error handling in lookdict() is
!  * expensive, and dicts with pure-string keys are very common.
   */
  static dictentry *
***************
*** 312,317 ****
  	register dictentry *ep;
  
! 	/* make sure this function doesn't have to handle non-string keys */
! 	if (!PyString_Check(key)) {
  #ifdef SHOW_CONVERSION_COUNTS
  		++converted;
--- 312,320 ----
  	register dictentry *ep;
  
! 	/* Make sure this function doesn't have to handle non-string keys,
! 	   including subclasses of str; e.g., one reason to subclass
! 	   strings is to override __eq__, and for speed we don't cater to
! 	   that here. */
! 	if (!PyString_CheckExact(key)) {
  #ifdef SHOW_CONVERSION_COUNTS
  		++converted;
***************
*** 479,483 ****
  	}
  #ifdef CACHE_HASH
! 	if (!PyString_Check(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
--- 482,486 ----
  	}
  #ifdef CACHE_HASH
! 	if (!PyString_CheckExact(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
***************
*** 511,515 ****
  	mp = (dictobject *)op;
  #ifdef CACHE_HASH
! 	if (PyString_Check(key)) {
  #ifdef INTERN_STRINGS
  		if (((PyStringObject *)key)->ob_sinterned != NULL) {
--- 514,518 ----
  	mp = (dictobject *)op;
  #ifdef CACHE_HASH
! 	if (PyString_CheckExact(key)) {
  #ifdef INTERN_STRINGS
  		if (((PyStringObject *)key)->ob_sinterned != NULL) {
***************
*** 563,567 ****
  	}
  #ifdef CACHE_HASH
! 	if (!PyString_Check(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
--- 566,570 ----
  	}
  #ifdef CACHE_HASH
! 	if (!PyString_CheckExact(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
***************
*** 821,825 ****
  		goto Done;
  	result = _PyString_Join(s, pieces);
! 	Py_DECREF(s);	
  
  Done:
--- 824,828 ----
  		goto Done;
  	result = _PyString_Join(s, pieces);
! 	Py_DECREF(s);
  
  Done:
***************
*** 843,847 ****
  	assert(mp->ma_table != NULL);
  #ifdef CACHE_HASH
! 	if (!PyString_Check(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
--- 846,850 ----
  	assert(mp->ma_table != NULL);
  #ifdef CACHE_HASH
! 	if (!PyString_CheckExact(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
***************
*** 1359,1363 ****
  	register long ok;
  #ifdef CACHE_HASH
! 	if (!PyString_Check(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
--- 1362,1366 ----
  	register long ok;
  #ifdef CACHE_HASH
! 	if (!PyString_CheckExact(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
***************
*** 1383,1387 ****
  
  #ifdef CACHE_HASH
! 	if (!PyString_Check(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
--- 1386,1390 ----
  
  #ifdef CACHE_HASH
! 	if (!PyString_CheckExact(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
***************
*** 1412,1416 ****
  
  #ifdef CACHE_HASH
! 	if (!PyString_Check(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
--- 1415,1419 ----
  
  #ifdef CACHE_HASH
! 	if (!PyString_CheckExact(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
***************
*** 1648,1652 ****
  
  #ifdef CACHE_HASH
! 	if (!PyString_Check(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif
--- 1651,1655 ----
  
  #ifdef CACHE_HASH
! 	if (!PyString_CheckExact(key) ||
  	    (hash = ((PyStringObject *) key)->ob_shash) == -1)
  #endif