functions should be applied to nil objects.
*/
-/* Two speedup hacks. Caching the hash saves recalculation of a
- string's hash value. Interning strings (which requires hash
- caching) tries to ensure that only one string object with a given
- value exists, so equality tests are one pointer comparison.
- Together, these can speed the interpreter up by as much as 20%.
- Each costs the size of a long or pointer per string object. In
- addition, interned strings live until the end of times. If you are
- concerned about memory footprint, simply comment the #define out
- here (and rebuild everything!). */
-#define CACHE_HASH
-#ifdef CACHE_HASH
-#define INTERN_STRINGS
-#endif
+/* Caching the hash (ob_shash) saves recalculation of a string's hash value.
+ Interning strings (ob_sinterned) tries to ensure that only one string
+ object with a given value exists, so equality tests can be one pointer
+ comparison. This is generally restricted to strings that "look like"
+ Python identifiers, although the intern() builtin can be used to force
+ interning of any string.
+ Together, these sped the interpreter by up to 20%. */
typedef struct {
PyObject_VAR_HEAD
-#ifdef CACHE_HASH
long ob_shash;
-#endif
-#ifdef INTERN_STRINGS
PyObject *ob_sinterned;
-#endif
char ob_sval[1];
} PyStringObject;
extern DL_IMPORT(PyObject *) _PyString_FormatLong(PyObject*, int, int,
int, char**, int*);
-#ifdef INTERN_STRINGS
extern DL_IMPORT(void) PyString_InternInPlace(PyObject **);
extern DL_IMPORT(PyObject *) PyString_InternFromString(const char *);
extern DL_IMPORT(void) _Py_ReleaseInternedStrings(void);
-#else
-#define PyString_InternInPlace(p)
-#define PyString_InternFromString(cp) PyString_FromString(cp)
-#define _Py_ReleaseInternedStrings()
-#endif
/* Macro, trading safety for speed */
#define PyString_AS_STRING(op) (((PyStringObject *)(op))->ob_sval)
Build
+- References to the CACHE_HASH and INTERN_STRINGS preprocessor symbols
+ were eliminated. They were always defined, and the internal features
+ they enabled stopped being experimental long ago.
+
C API
- Objects allocated using the new PyMalloc_New and PyMalloc_NewVar
void *b_ptr;
int b_size;
int b_readonly;
-#ifdef CACHE_HASH
long b_hash;
-#endif
} PyBufferObject;
b->b_ptr = ptr;
b->b_size = size;
b->b_readonly = readonly;
-#ifdef CACHE_HASH
b->b_hash = -1;
-#endif
return (PyObject *) b;
}
b->b_ptr = (void *)(b + 1);
b->b_size = size;
b->b_readonly = 0;
-#ifdef CACHE_HASH
b->b_hash = -1;
-#endif
return o;
}
register unsigned char *p;
register long x;
-#ifdef CACHE_HASH
if ( self->b_hash != -1 )
return self->b_hash;
-#endif
if ( !self->b_readonly )
{
x ^= self->b_size;
if (x == -1)
x = -2;
-#ifdef CACHE_HASH
self->b_hash = x;
-#endif
return x;
}
if (!PyDict_Check(op)) {
return NULL;
}
-#ifdef CACHE_HASH
if (!PyString_CheckExact(key) ||
(hash = ((PyStringObject *) key)->ob_shash) == -1)
-#endif
{
hash = PyObject_Hash(key);
if (hash == -1) {
return -1;
}
mp = (dictobject *)op;
-#ifdef CACHE_HASH
if (PyString_CheckExact(key)) {
-#ifdef INTERN_STRINGS
if (((PyStringObject *)key)->ob_sinterned != NULL) {
key = ((PyStringObject *)key)->ob_sinterned;
hash = ((PyStringObject *)key)->ob_shash;
}
- else
-#endif
- {
+ else {
hash = ((PyStringObject *)key)->ob_shash;
if (hash == -1)
hash = PyObject_Hash(key);
}
}
- else
-#endif
- {
+ else {
hash = PyObject_Hash(key);
if (hash == -1)
return -1;
PyErr_BadInternalCall();
return -1;
}
-#ifdef CACHE_HASH
if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1)
-#endif
- {
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return -1;
PyObject *v;
long hash;
assert(mp->ma_table != NULL);
-#ifdef CACHE_HASH
if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1)
-#endif
- {
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return NULL;
{
long hash;
register long ok;
-#ifdef CACHE_HASH
if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1)
-#endif
- {
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return NULL;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &failobj))
return NULL;
-#ifdef CACHE_HASH
if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1)
-#endif
- {
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return NULL;
if (!PyArg_ParseTuple(args, "O|O:setdefault", &key, &failobj))
return NULL;
-#ifdef CACHE_HASH
if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1)
-#endif
- {
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return NULL;
{
long hash;
-#ifdef CACHE_HASH
if (!PyString_CheckExact(key) ||
- (hash = ((PyStringObject *) key)->ob_shash) == -1)
-#endif
- {
+ (hash = ((PyStringObject *) key)->ob_shash) == -1) {
hash = PyObject_Hash(key);
if (hash == -1)
return -1;
if (op == NULL)
return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyString_Type, size);
-#ifdef CACHE_HASH
op->ob_shash = -1;
-#endif
-#ifdef INTERN_STRINGS
op->ob_sinterned = NULL;
-#endif
if (str != NULL)
memcpy(op->ob_sval, str, size);
op->ob_sval[size] = '\0';
if (op == NULL)
return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyString_Type, size);
-#ifdef CACHE_HASH
op->ob_shash = -1;
-#endif
-#ifdef INTERN_STRINGS
op->ob_sinterned = NULL;
-#endif
memcpy(op->ob_sval, str, size+1);
#ifndef DONT_SHARE_SHORT_STRINGS
if (size == 0) {
if (op == NULL)
return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyString_Type, size);
-#ifdef CACHE_HASH
op->ob_shash = -1;
-#endif
-#ifdef INTERN_STRINGS
op->ob_sinterned = NULL;
-#endif
memcpy(op->ob_sval, a->ob_sval, (int) a->ob_size);
memcpy(op->ob_sval + a->ob_size, b->ob_sval, (int) b->ob_size);
op->ob_sval[size] = '\0';
if (op == NULL)
return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyString_Type, size);
-#ifdef CACHE_HASH
op->ob_shash = -1;
-#endif
-#ifdef INTERN_STRINGS
op->ob_sinterned = NULL;
-#endif
for (i = 0; i < size; i += a->ob_size)
memcpy(op->ob_sval+i, a->ob_sval, (int) a->ob_size);
op->ob_sval[size] = '\0';
register unsigned char *p;
register long x;
-#ifdef CACHE_HASH
if (a->ob_shash != -1)
return a->ob_shash;
-#ifdef INTERN_STRINGS
if (a->ob_sinterned != NULL)
return (a->ob_shash =
((PyStringObject *)(a->ob_sinterned))->ob_shash);
-#endif
-#endif
len = a->ob_size;
p = (unsigned char *) a->ob_sval;
x = *p << 7;
x ^= a->ob_size;
if (x == -1)
x = -2;
-#ifdef CACHE_HASH
a->ob_shash = x;
-#endif
return x;
}
pnew = type->tp_alloc(type, n);
if (pnew != NULL) {
memcpy(PyString_AS_STRING(pnew), PyString_AS_STRING(tmp), n+1);
-#ifdef CACHE_HASH
((PyStringObject *)pnew)->ob_shash =
((PyStringObject *)tmp)->ob_shash;
-#endif
-#ifdef INTERN_STRINGS
((PyStringObject *)pnew)->ob_sinterned =
((PyStringObject *)tmp)->ob_sinterned;
-#endif
}
Py_DECREF(tmp);
return pnew;
}
-#ifdef INTERN_STRINGS
/* This dictionary will leak at PyString_Fini() time. That's acceptable
* because PyString_Fini() specifically frees interned strings that are
return s;
}
-#endif
-
void
PyString_Fini(void)
{
Py_XDECREF(nullstring);
nullstring = NULL;
#endif
-#ifdef INTERN_STRINGS
if (interned) {
int pos, changed;
PyObject *key, *value;
}
} while (changed);
}
-#endif
}
-#ifdef INTERN_STRINGS
void _Py_ReleaseInternedStrings(void)
{
if (interned) {
interned = NULL;
}
}
-#endif /* INTERN_STRINGS */
if (strlen(buf) != len)
continue; /* v contains '\0' */
#ifdef macintosh
-#ifdef INTERN_STRINGS
/*
** Speedup: each sys.path item is interned, and
** FindResourceModule remembers which items refer to
*/
PyString_InternInPlace(&PyList_GET_ITEM(path, i));
v = PyList_GET_ITEM(path, i);
-#endif
if (PyMac_FindResourceModule((PyStringObject *)v, name, buf)) {
static struct filedescr resfiledescr =
{"", "", PY_RESOURCE};