diff -ur Python-1.5.1/Include/classobject.h Python-1.5.1.vt/Include/classobject.h --- Python-1.5.1/Include/classobject.h Fri Mar 14 05:25:22 1997 +++ Python-1.5.1.vt/Include/classobject.h Sun Jul 19 15:06:05 1998 @@ -48,6 +48,7 @@ PyObject *cl_getattr; PyObject *cl_setattr; PyObject *cl_delattr; + struct vtable *cl_vt; } PyClassObject; typedef struct { diff -ur Python-1.5.1/Include/stringobject.h Python-1.5.1.vt/Include/stringobject.h --- Python-1.5.1/Include/stringobject.h Sat Jan 18 08:53:23 1997 +++ Python-1.5.1.vt/Include/stringobject.h Wed Sep 9 18:24:14 1998 @@ -91,11 +91,18 @@ extern PyObject *PyString_Format Py_PROTO((PyObject *, PyObject *)); #ifdef INTERN_STRINGS -extern void PyString_InternInPlace Py_PROTO((PyObject **)); -extern PyObject *PyString_InternFromString Py_PROTO((const char *)); +extern void PyString_InternInPlace Py_PROTO((PyObject **, int)); +extern PyObject *PyString_InternFromString Py_PROTO((const char *, int)); +extern PyObject *PyString_GetInterned Py_PROTO((PyObject*)); +extern long PyString_ClassIndex Py_PROTO((PyObject *)); +extern int PyString_UnsetClassIndex Py_PROTO((PyObject *)); +extern int PyString_SetInstanceAssigned Py_PROTO((PyObject *)); +extern int PyString_IsInstanceAssigned Py_PROTO((PyObject*)); +#define INTERNED_ATTRIBUTE 1 +#define VT_SIZE 64 #else -#define PyString_InternInPlace(p) -#define PyString_InternFromString(cp) PyString_FromString(cp) +#define PyString_InternInPlace(p,f) +#define PyString_InternFromString(cp,f) PyString_FromString(cp) #endif /* Macro, trading safety for speed */ diff -ur Python-1.5.1/Modules/cPickle.c Python-1.5.1.vt/Modules/cPickle.c --- Python-1.5.1/Modules/cPickle.c Fri Apr 3 23:13:02 1998 +++ Python-1.5.1.vt/Modules/cPickle.c Wed Sep 9 19:39:46 1998 @@ -2550,6 +2550,7 @@ Py_DECREF(inst); goto err; } + /* FIXME: set change callback. */ return (PyObject *)inst; } diff -ur Python-1.5.1/Modules/newmodule.c Python-1.5.1.vt/Modules/newmodule.c --- Python-1.5.1/Modules/newmodule.c Fri Jan 24 04:58:52 1997 +++ Python-1.5.1.vt/Modules/newmodule.c Wed Sep 9 19:40:19 1998 @@ -56,6 +56,7 @@ Py_INCREF(dict); inst->in_class = (PyClassObject *)klass; inst->in_dict = dict; + /* FIXME: Set change callback. */ return (PyObject *)inst; } diff -ur Python-1.5.1/Objects/classobject.c Python-1.5.1.vt/Objects/classobject.c --- Python-1.5.1/Objects/classobject.c Wed Dec 3 01:06:02 1997 +++ Python-1.5.1.vt/Objects/classobject.c Wed Sep 9 19:37:38 1998 @@ -38,6 +38,21 @@ static PyObject *class_lookup Py_PROTO((PyClassObject *, PyObject *, PyClassObject **)); static PyObject *instance_getattr1 Py_PROTO((PyInstanceObject *, PyObject *)); +static int class_changed Py_PROTO((PyObject*, PyObject*, PyObject*)); +static int instance_changed Py_PROTO((PyObject*, PyObject*, PyObject*)); +static void class_makevt Py_PROTO((PyClassObject*)); +static void class_delvt Py_PROTO((PyClassObject*)); +static void class_nextgeneration Py_PROTO((PyClassObject*)); + +struct vtable { + struct vtable *next, *prev; + PyObject *generation; + PyObject *values[2*VT_SIZE]; +}; +extern PyObject* vtable_generation; + +static int uninterned_attributes; + PyObject * PyClass_New(bases, dict, name) @@ -49,17 +64,17 @@ static PyObject *getattrstr, *setattrstr, *delattrstr; static PyObject *docstr, *modstr, *namestr; if (docstr == NULL) { - docstr= PyString_InternFromString("__doc__"); + docstr= PyString_InternFromString("__doc__", INTERNED_ATTRIBUTE); if (docstr == NULL) return NULL; } if (modstr == NULL) { - modstr= PyString_InternFromString("__module__"); + modstr= PyString_InternFromString("__module__", INTERNED_ATTRIBUTE); if (modstr == NULL) return NULL; } if (namestr == NULL) { - namestr= PyString_InternFromString("__name__"); + namestr= PyString_InternFromString("__name__", INTERNED_ATTRIBUTE); if (namestr == NULL) return NULL; } @@ -120,16 +135,18 @@ Py_XINCREF(name); op->cl_name = name; if (getattrstr == NULL) { - getattrstr = PyString_InternFromString("__getattr__"); - setattrstr = PyString_InternFromString("__setattr__"); - delattrstr = PyString_InternFromString("__delattr__"); + getattrstr = PyString_InternFromString("__getattr__", INTERNED_ATTRIBUTE); + setattrstr = PyString_InternFromString("__setattr__", INTERNED_ATTRIBUTE); + delattrstr = PyString_InternFromString("__delattr__", INTERNED_ATTRIBUTE); } + op->cl_vt = NULL; op->cl_getattr = class_lookup(op, getattrstr, &dummy); op->cl_setattr = class_lookup(op, setattrstr, &dummy); op->cl_delattr = class_lookup(op, delattrstr, &dummy); Py_XINCREF(op->cl_getattr); Py_XINCREF(op->cl_setattr); Py_XINCREF(op->cl_delattr); + PyDict_SetChange(dict, op, class_changed); return (PyObject *) op; } @@ -139,9 +156,12 @@ class_dealloc(op) PyClassObject *op; { + int i; + PyDict_SetChange(op->cl_dict, NULL, NULL); Py_DECREF(op->cl_bases); Py_DECREF(op->cl_dict); Py_XDECREF(op->cl_name); + class_delvt(op); free((ANY *)op); } @@ -170,6 +190,43 @@ } static PyObject * +class_lookup1(op, name, pclass) + PyClassObject *op; + PyObject *name; + PyClassObject **pclass; +{ + PyObject *v; +#ifdef INTERN_STRINGS + long h = -1; + register struct vtable* vt = op->cl_vt; + if (!vt) { + class_makevt (op); + vt = op->cl_vt; + } + if (vt && (h = PyString_ClassIndex(name)) != -1) { + if (vt->generation != vtable_generation) + class_nextgeneration (op); + v = op->cl_vt->values[2*h]; + if (v) { + *pclass = (PyClassObject*)op->cl_vt->values[2*h+1]; + return v; + } + + } +#endif + v = class_lookup(op, name, pclass); +#ifdef INTERN_STRINGS + if (v && h != -1) { + Py_INCREF(v); + op->cl_vt->values[2*h] = v; + Py_INCREF(*pclass); + op->cl_vt->values[2*h+1] = (PyObject*)*pclass; + } +#endif + return v; +} + +static PyObject * class_getattr(op, name) register PyClassObject *op; PyObject *name; @@ -327,6 +384,87 @@ (setattrofunc)class_setattr, /*tp_setattro*/ }; +/* Virtual table management */ + +static struct vtable *vtfirst; + +static void +class_makevt(op) + PyClassObject *op; +{ + int i; + register struct vtable *vt; + op->cl_vt = vt = Py_Malloc(sizeof(struct vtable)); + if (!vt) + return; + vt->prev = 0; + vt->next = vtfirst; + if (vtfirst) + vtfirst->prev = vt; + vtfirst = vt; + Py_INCREF (vtable_generation); + vt->generation = vtable_generation; + for (i = 0; i < 2*VT_SIZE; i++) + op->cl_vt->values[i] = 0; +} + +static void +class_delvt(op) + PyClassObject *op; +{ + int i; + register struct vtable *vt; + vt = op->cl_vt; + if (!vt) + return; + if (vt->prev) + vt->prev->next = vt->next; + else + vtfirst = vt->next; + if (vt->next) + vt->next->prev = vt->prev; + for (i=0; i<2*VT_SIZE; i++) + Py_XDECREF(vt->values[i]); + Py_DECREF (vt->generation); + Py_Free (vt); +} + +static void +class_nextgeneration(op) + PyClassObject *op; +{ + int i; + register struct vtable *vt = op->cl_vt; + for (i = 0; i<2*VT_SIZE; i++) + if (vt->values[i]) { + Py_DECREF(vt->values[i]); + vt->values[i] = 0; + } + Py_DECREF (vt->generation); + Py_INCREF (vtable_generation); + vt->generation = vtable_generation; +} + +static int +class_changed(cl, n, v) + PyObject *cl; + PyObject *n; + PyObject *v; +{ +#ifdef INTERN_STRINGS + int old; + if ((old = PyString_UnsetClassIndex(n)) != -1){ + register struct vtable *p; + for (p = vtfirst; p; p = p->next) + if (p->values[old]) { + Py_DECREF (p->values[old]); + p->values[old] = 0; + } + } +#endif + return 0; +} + int PyClass_IsSubclass(class, base) PyObject *class; @@ -373,8 +511,9 @@ Py_DECREF(inst); return NULL; } + PyDict_SetChange(inst->in_dict, inst, instance_changed); if (initstr == NULL) - initstr = PyString_InternFromString("__init__"); + initstr = PyString_InternFromString("__init__", INTERNED_ATTRIBUTE); init = instance_getattr1(inst, initstr); if (init == NULL) { PyErr_Clear(); @@ -433,7 +572,7 @@ #endif /* !Py_TRACE_REFS */ PyErr_Fetch(&error_type, &error_value, &error_traceback); if (delstr == NULL) - delstr = PyString_InternFromString("__del__"); + delstr = PyString_InternFromString("__del__", INTERNED_ATTRIBUTE); if ((del = instance_getattr1(inst, delstr)) != NULL) { PyObject *res = PyEval_CallObject(del, (PyObject *)NULL); if (res == NULL) { @@ -507,9 +646,13 @@ } } class = NULL; - v = PyDict_GetItem(inst->in_dict, name); + if (!uninterned_attributes && !PyString_IsInstanceAssigned (name)) + /* No instances have this attribute. */ + v = NULL; + else + v = PyDict_GetItem(inst->in_dict, name); if (v == NULL) { - v = class_lookup(inst->in_class, name, &class); + v = class_lookup1(inst->in_class, name, &class); if (v == NULL) { PyErr_SetObject(PyExc_AttributeError, name); return NULL; @@ -597,8 +740,10 @@ return -1; } tmp = inst->in_dict; + /* FIXME: clear change for old dict. */ Py_INCREF(v); inst->in_dict = v; + PyDict_SetChange(v, inst, instance_changed); Py_DECREF(tmp); return 0; } @@ -650,7 +795,7 @@ static PyObject *reprstr; if (reprstr == NULL) - reprstr = PyString_InternFromString("__repr__"); + reprstr = PyString_InternFromString("__repr__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, reprstr); if (func == NULL) { char buf[140]; @@ -719,14 +864,14 @@ static PyObject *hashstr, *cmpstr; if (hashstr == NULL) - hashstr = PyString_InternFromString("__hash__"); + hashstr = PyString_InternFromString("__hash__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, hashstr); if (func == NULL) { /* If there is no __cmp__ method, we hash on the address. If a __cmp__ method exists, there must be a __hash__. */ PyErr_Clear(); if (cmpstr == NULL) - cmpstr = PyString_InternFromString("__cmp__"); + cmpstr = PyString_InternFromString("__cmp__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, cmpstr); if (func == NULL) { PyErr_Clear(); @@ -767,7 +912,7 @@ int outcome; if (lenstr == NULL) - lenstr = PyString_InternFromString("__len__"); + lenstr = PyString_InternFromString("__len__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, lenstr); if (func == NULL) return -1; @@ -800,7 +945,7 @@ PyObject *res; if (getitemstr == NULL) - getitemstr = PyString_InternFromString("__getitem__"); + getitemstr = PyString_InternFromString("__getitem__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, getitemstr); if (func == NULL) return NULL; @@ -827,12 +972,12 @@ if (value == NULL) { if (delitemstr == NULL) - delitemstr = PyString_InternFromString("__delitem__"); + delitemstr = PyString_InternFromString("__delitem__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, delitemstr); } else { if (setitemstr == NULL) - setitemstr = PyString_InternFromString("__setitem__"); + setitemstr = PyString_InternFromString("__setitem__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, setitemstr); } if (func == NULL) @@ -868,7 +1013,7 @@ PyObject *func, *arg, *res; if (getitemstr == NULL) - getitemstr = PyString_InternFromString("__getitem__"); + getitemstr = PyString_InternFromString("__getitem__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, getitemstr); if (func == NULL) return NULL; @@ -892,7 +1037,7 @@ static PyObject *getslicestr; if (getslicestr == NULL) - getslicestr = PyString_InternFromString("__getslice__"); + getslicestr = PyString_InternFromString("__getslice__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, getslicestr); if (func == NULL) return NULL; @@ -917,12 +1062,12 @@ if (item == NULL) { if (delitemstr == NULL) - delitemstr = PyString_InternFromString("__delitem__"); + delitemstr = PyString_InternFromString("__delitem__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, delitemstr); } else { if (setitemstr == NULL) - setitemstr = PyString_InternFromString("__setitem__"); + setitemstr = PyString_InternFromString("__setitem__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, setitemstr); } if (func == NULL) @@ -956,13 +1101,13 @@ if (value == NULL) { if (delslicestr == NULL) delslicestr = - PyString_InternFromString("__delslice__"); + PyString_InternFromString("__delslice__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, delslicestr); } else { if (setslicestr == NULL) setslicestr = - PyString_InternFromString("__setslice__"); + PyString_InternFromString("__setslice__", INTERNED_ATTRIBUTE); func = instance_getattr(inst, setslicestr); } if (func == NULL) @@ -1068,7 +1213,7 @@ if (!PyInstance_Check(v)) return 1; if (coerce_obj == NULL) { - coerce_obj = PyString_InternFromString("__coerce__"); + coerce_obj = PyString_InternFromString("__coerce__", INTERNED_ATTRIBUTE); if (coerce_obj == NULL) return -1; } @@ -1145,7 +1290,7 @@ PyObject *coerced; if (coerce_obj == NULL) { - coerce_obj = PyString_InternFromString("__coerce__"); + coerce_obj = PyString_InternFromString("__coerce__", INTERNED_ATTRIBUTE); if (coerce_obj == NULL) return -1; } @@ -1194,7 +1339,7 @@ #define UNARY(funcname, methodname) \ static PyObject *funcname(self) PyInstanceObject *self; { \ static PyObject *o; \ - if (o == NULL) o = PyString_InternFromString(methodname); \ + if (o == NULL) o = PyString_InternFromString(methodname, INTERNED_ATTRIBUTE); \ return generic_unary_op(self, o); \ } @@ -1211,11 +1356,11 @@ static PyObject *nonzerostr; if (nonzerostr == NULL) - nonzerostr = PyString_InternFromString("__nonzero__"); + nonzerostr = PyString_InternFromString("__nonzero__", INTERNED_ATTRIBUTE); if ((func = instance_getattr(self, nonzerostr)) == NULL) { PyErr_Clear(); if (lenstr == NULL) - lenstr = PyString_InternFromString("__len__"); + lenstr = PyString_InternFromString("__len__", INTERNED_ATTRIBUTE); if ((func = instance_getattr(self, lenstr)) == NULL) { PyErr_Clear(); /* Fall back to the default behavior: @@ -1264,7 +1409,7 @@ static PyObject *powstr; if (powstr == NULL) - powstr = PyString_InternFromString("__pow__"); + powstr = PyString_InternFromString("__pow__", INTERNED_ATTRIBUTE); func = PyObject_GetAttr(v, powstr); if (func == NULL) return NULL; @@ -1325,7 +1470,23 @@ 0, /*tp_str*/ (getattrofunc)instance_getattr, /*tp_getattro*/ (setattrofunc)instance_setattr, /*tp_setattro*/ + 0 /*tp_as_buffer*/ }; + +static int +instance_changed(cl, n, v) + PyObject *cl; + PyObject *n; + PyObject *v; +{ +#ifdef INTERN_STRINGS + if (uninterned_attributes) + return 0; + if (PyString_SetInstanceAssigned (n) == -1) + uninterned_attributes = 1; +#endif + return 0; +} /* Instance method objects are used for two purposes: diff -ur Python-1.5.1/Objects/dictobject.c Python-1.5.1.vt/Objects/dictobject.c --- Python-1.5.1/Objects/dictobject.c Sat Apr 11 00:47:14 1998 +++ Python-1.5.1.vt/Objects/dictobject.c Sun Jul 19 14:48:57 1998 @@ -110,6 +110,8 @@ int ma_size; int ma_poly; dictentry *ma_table; + setattrofunc onchange; + PyObject* chdest; } dictobject; PyObject * @@ -129,6 +131,8 @@ mp->ma_table = NULL; mp->ma_fill = 0; mp->ma_used = 0; + mp->onchange = 0; + mp->chdest = 0; return (PyObject *)mp; } @@ -351,7 +355,7 @@ if (PyString_Check(key)) { #ifdef INTERN_STRINGS if (((PyStringObject *)key)->ob_sinterned != NULL) { - key = ((PyStringObject *)key)->ob_sinterned; + key = PyString_GetInterned (key); hash = ((PyStringObject *)key)->ob_shash; } else @@ -379,6 +383,8 @@ Py_INCREF(value); Py_INCREF(key); insertdict(mp, key, hash, value); + if (mp->onchange) + mp->onchange(mp->chdest, key, value); return 0; } @@ -420,6 +426,8 @@ old_value = ep->me_value; ep->me_value = NULL; mp->ma_used--; + if (mp->onchange) + mp->onchange(mp->chdest, old_key, NULL); Py_DECREF(old_value); Py_DECREF(old_key); return 0; @@ -442,6 +450,8 @@ mp->ma_size = mp->ma_used = mp->ma_fill = 0; mp->ma_table = NULL; for (i = 0; i < n; i++) { + if (mp->onchange) + mp->onchange(mp->chdest, table[i].me_key, NULL); Py_XDECREF(table[i].me_key); Py_XDECREF(table[i].me_value); } @@ -1088,7 +1098,7 @@ kv = PyString_FromString(key); if (kv == NULL) return -1; - PyString_InternInPlace(&kv); /* XXX Should we really? */ + PyString_InternInPlace(&kv, 0); /* XXX Should we really? */ err = PyDict_SetItem(v, kv, item); Py_DECREF(kv); return err; @@ -1107,4 +1117,22 @@ err = PyDict_DelItem(v, kv); Py_DECREF(kv); return err; +} + +int +PyDict_SetChange(v, o, m) + PyObject *v; + PyObject *o; + setattrofunc m; +{ + register dictobject *d = (dictobject*)v; + if (!PyDict_Check(d)) { + PyErr_BadInternalCall(); + return -1; + } + if(d->onchange) + return -1; + d->onchange = m; + d->chdest = o; + return 0; } diff -ur Python-1.5.1/Objects/frameobject.c Python-1.5.1.vt/Objects/frameobject.c --- Python-1.5.1/Objects/frameobject.c Thu Feb 19 21:48:26 1998 +++ Python-1.5.1.vt/Objects/frameobject.c Sun Jul 19 14:35:01 1998 @@ -153,7 +153,7 @@ int extras = code->co_stacksize + code->co_nlocals; if (builtin_object == NULL) { - builtin_object = PyString_InternFromString("__builtins__"); + builtin_object = PyString_InternFromString("__builtins__", 0); if (builtin_object == NULL) return NULL; } diff -ur Python-1.5.1/Objects/object.c Python-1.5.1.vt/Objects/object.c --- Python-1.5.1/Objects/object.c Sat Apr 11 17:17:34 1998 +++ Python-1.5.1.vt/Objects/object.c Sun Jul 19 14:35:53 1998 @@ -339,7 +339,7 @@ { if (v->ob_type->tp_getattro != NULL) { PyObject *w, *res; - w = PyString_InternFromString(name); + w = PyString_InternFromString(name, INTERNED_ATTRIBUTE); if (w == NULL) return NULL; res = (*v->ob_type->tp_getattro)(v, w); @@ -382,7 +382,7 @@ if (v->ob_type->tp_setattro != NULL) { PyObject *s; int res; - s = PyString_InternFromString(name); + s = PyString_InternFromString(name, INTERNED_ATTRIBUTE); if (s == NULL) return -1; res = (*v->ob_type->tp_setattro)(v, s, w); @@ -437,7 +437,7 @@ { int err; Py_INCREF(name); - PyString_InternInPlace(&name); + PyString_InternInPlace(&name, INTERNED_ATTRIBUTE); if (v->ob_type->tp_setattro != NULL) err = (*v->ob_type->tp_setattro)(v, name, value); else diff -ur Python-1.5.1/Objects/stringobject.c Python-1.5.1.vt/Objects/stringobject.c --- Python-1.5.1/Objects/stringobject.c Sat Apr 11 00:16:39 1998 +++ Python-1.5.1.vt/Objects/stringobject.c Wed Sep 9 21:17:46 1998 @@ -1034,15 +1034,76 @@ static PyObject *interned; +/* Value found at interned string. */ +typedef struct { + PyObject_HEAD + PyObject *string; + PyObject *generation; + long class_index; + long instance_assigned; +} PyInterned; + +static PyTypeObject PyInterned_Type; +PyObject *vtable_generation; +static long current_classindex; + +#define PyInterned_Check(op) ((op)->ob_type == &PyInterned_Type) + +static PyInterned * +PyInterned_FromString(string) + PyObject *string; +{ + PyInterned *i = PyObject_NEW(PyInterned, &PyInterned_Type); + if (i == NULL) + return NULL; + Py_INCREF (string); + i->string = string; + i->generation = NULL; + i->class_index = 0; + i->instance_assigned = 0; + return i; +} + +static void +PyInterned_Dealloc(i) + PyInterned *i; +{ + Py_DECREF (i->string); + Py_XDECREF (i->generation); + PyMem_DEL (i); +} + +PyObject* +PyString_GetInterned(i) + PyObject *i; +{ + i = ((PyStringObject*)i) -> ob_sinterned; + if (PyInterned_Check(i)) + return ((PyInterned*)i)->string; + return i; +} + +static PyTypeObject PyInterned_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, + "interned string", + sizeof(PyInterned), + 0, + (destructor)PyInterned_Dealloc, /* tp_dealloc */ +}; + void -PyString_InternInPlace(p) +PyString_InternInPlace(p, flags) PyObject **p; + int flags; { register PyStringObject *s = (PyStringObject *)(*p); PyObject *t; if (s == NULL || !PyString_Check(s)) Py_FatalError("PyString_InternInPlace: strings only please!"); if ((t = s->ob_sinterned) != NULL) { + if (PyInterned_Check (t)) + t = ((PyInterned*)t)->string; if (t == (PyObject *)s) return; Py_INCREF(t); @@ -1051,36 +1112,156 @@ return; } if (interned == NULL) { + /* Initialization of generation is triggered by initialization + of interned */ + vtable_generation = PyLong_FromLong(1); + if (vtable_generation == NULL) + return; interned = PyDict_New(); if (interned == NULL) return; } if ((t = PyDict_GetItem(interned, (PyObject *)s)) != NULL) { + s->ob_sinterned = t; + if (PyInterned_Check (t)) + t = ((PyInterned*)t)->string; Py_INCREF(t); - *p = s->ob_sinterned = t; + *p = t; Py_DECREF(s); return; } - t = (PyObject *)s; - if (PyDict_SetItem(interned, t, t) == 0) { + if (flags == INTERNED_ATTRIBUTE) + t = (PyObject *)PyInterned_FromString(s); + else + t = (PyObject *)s; + if (PyDict_SetItem(interned, (PyObject*)s, t) == 0) { s->ob_sinterned = t; return; } PyErr_Clear(); } +/* Add an interned object if none was assigned originally. */ +static int +add_interned(o) + PyObject *o; +{ + PyObject *i = (PyObject*)PyInterned_FromString(o); + if (!i) + return -1; + if (PyDict_SetItem (interned, o, i) < 0) + return -1; + ((PyStringObject*)o)->ob_sinterned = i; + return 0; +} + +static PyInterned* +get_interned(o) + PyStringObject* o; +{ + register PyObject *res = o->ob_sinterned; + if (!res || PyInterned_Check (res)) + return (PyInterned*)res; + /* We have still a string. Move one more level. */ + res = ((PyStringObject*)res)->ob_sinterned; + if (!PyInterned_Check (res)) + /* Not associated with interned object. */ + return NULL; + return (PyInterned*)res; +} PyObject * -PyString_InternFromString(cp) +PyString_InternFromString(cp, flags) const char *cp; + int flags; { PyObject *s = PyString_FromString(cp); if (s == NULL) return NULL; - PyString_InternInPlace(&s); + PyString_InternInPlace(&s, flags); return s; } +long +PyString_ClassIndex(o) + PyObject *o; +{ + PyInterned *p = get_interned ((PyStringObject*)o); + if (!p) + return -1; + if (p->generation == vtable_generation) + return p->class_index; + if (p->class_index == -1) + /* This is a changing attribute. */ + return -1; + if (current_classindex == VT_SIZE) { + PyObject_Print (vtable_generation, stderr, 0); + fprintf(stderr,"\n"); + vtable_generation = PyNumber_Add (vtable_generation, PyInt_FromLong (1)); + current_classindex = 0; + } + //fprintf(stderr,"Assigning %d to %s\n",current_classindex, &s->ob_sval); + p->class_index = current_classindex++; + p->generation = vtable_generation; + return p->class_index; +} + +/* Return old index. */ + +int +PyString_UnsetClassIndex(o) + PyObject *o; +{ + int i; + PyInterned *p = get_interned ((PyStringObject*)o); + if (!p) + return -1; + i = p->class_index; + p->class_index = -1; + return i; +} + +/* Set the assigned flag. If the string is not interned, return an error. */ +static int unrecordable_assigned; + +int +PyString_SetInstanceAssigned(o) + PyObject *o; +{ + PyInterned *p = (PyInterned*)(((PyStringObject*)o)->ob_sinterned); + /* This is not interned. */ + if (!p) { + unrecordable_assigned = 1; + return -1; + } + /* This is not known as an instance attribute. */ + if (!PyInterned_Check(p)) { + if (add_interned (p) < 0) + return -1; + /* We just successfully put an interned object in there. */ + p = get_interned (o); + } + p->instance_assigned = 1; + return 0; +} + +int +PyString_IsInstanceAssigned(o) + PyObject *o; +{ + PyInterned *p = (PyInterned*)(((PyStringObject*)o)->ob_sinterned); + if (unrecordable_assigned) + /* Assume the worst. */ + return 1; + /* We know nothing about it. */ + if (!p) + return 1; + /* We have not recorded assignments for this interned string. */ + if (!PyInterned_Check (p)) + return 1; + return p->instance_assigned; +} + #endif void @@ -1103,7 +1284,8 @@ changed = 0; pos = 0; while (PyDict_Next(interned, &pos, &key, &value)) { - if (key->ob_refcnt == 2 && key == value) { + PyInterned *i = (PyInterned*)value; + if (key->ob_refcnt == 2 && key == i->string) { PyDict_DelItem(interned, key); changed = 1; } diff -ur Python-1.5.1/Python/bltinmodule.c Python-1.5.1.vt/Python/bltinmodule.c --- Python-1.5.1/Python/bltinmodule.c Sat Apr 11 00:25:25 1998 +++ Python-1.5.1.vt/Python/bltinmodule.c Sun Jul 19 14:35:53 1998 @@ -328,7 +328,7 @@ static PyObject *complexstr; PyObject *f; if (complexstr == NULL) { - complexstr = PyString_InternFromString("__complex__"); + complexstr = PyString_InternFromString("__complex__", INTERNED_ATTRIBUTE); if (complexstr == NULL) return NULL; } @@ -902,7 +902,7 @@ if (!PyArg_ParseTuple(args, "S", &s)) return NULL; Py_INCREF(s); - PyString_InternInPlace(&s); + PyString_InternInPlace(&s, 0); return s; } diff -ur Python-1.5.1/Python/compile.c Python-1.5.1.vt/Python/compile.c --- Python-1.5.1/Python/compile.c Thu Apr 9 23:39:07 1998 +++ Python-1.5.1.vt/Python/compile.c Sun Jul 19 14:51:37 1998 @@ -235,7 +235,7 @@ PyErr_BadInternalCall(); return NULL; } - PyString_InternInPlace(&PyTuple_GET_ITEM(names, i)); + PyString_InternInPlace(&PyTuple_GET_ITEM(names, i), INTERNED_ATTRIBUTE); } for (i = PyTuple_Size(varnames); --i >= 0; ) { PyObject *v = PyTuple_GetItem(varnames, i); @@ -243,7 +243,7 @@ PyErr_BadInternalCall(); return NULL; } - PyString_InternInPlace(&PyTuple_GET_ITEM(varnames, i)); + PyString_InternInPlace(&PyTuple_GET_ITEM(varnames, i), 0); } /* Intern selected string constants */ for (i = PyTuple_Size(consts); --i >= 0; ) { @@ -255,7 +255,7 @@ if ((int)strspn(p, NAME_CHARS) != PyString_Size(v)) continue; - PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i)); + PyString_InternInPlace(&PyTuple_GET_ITEM(consts, i), 0); } co = PyObject_NEW(PyCodeObject, &PyCode_Type); if (co != NULL) { @@ -738,7 +738,7 @@ com_mangle(c, name, buffer, (int)sizeof(buffer))) name = buffer; #endif - if (name == NULL || (v = PyString_InternFromString(name)) == NULL) { + if (name == NULL || (v = PyString_InternFromString(name, 0)) == NULL) { c->c_errors++; i = 255; } @@ -1126,7 +1126,7 @@ "keyword can't be an expression"); } else { - PyObject *v = PyString_InternFromString(STR(m)); + PyObject *v = PyString_InternFromString(STR(m), 0); if (v != NULL && *pkeywords == NULL) *pkeywords = PyDict_New(); if (v == NULL || *pkeywords == NULL) @@ -2165,7 +2165,7 @@ struct compiling *c; char *name; { - PyObject *nameval = PyString_InternFromString(name); + PyObject *nameval = PyString_InternFromString(name, 0); int i; if (nameval == NULL) { c->c_errors++; @@ -2782,7 +2782,7 @@ PyObject *v; REQ(n, classdef); /* classdef: class NAME ['(' testlist ')'] ':' suite */ - if ((v = PyString_InternFromString(STR(CHILD(n, 1)))) == NULL) { + if ((v = PyString_InternFromString(STR(CHILD(n, 1)), 0)) == NULL) { c->c_errors++; return; } @@ -3407,8 +3407,8 @@ consts = PyList_AsTuple(sc.c_consts); names = PyList_AsTuple(sc.c_names); varnames = PyList_AsTuple(sc.c_varnames); - filename = PyString_InternFromString(sc.c_filename); - name = PyString_InternFromString(sc.c_name); + filename = PyString_InternFromString(sc.c_filename, 0); + name = PyString_InternFromString(sc.c_name, 0); if (!PyErr_Occurred()) co = PyCode_New(sc.c_argcount, sc.c_nlocals, diff -ur Python-1.5.1/Python/import.c Python-1.5.1.vt/Python/import.c --- Python-1.5.1/Python/import.c Wed Aug 26 13:19:51 1998 +++ Python-1.5.1.vt/Python/import.c Sun Jul 19 14:35:53 1998 @@ -898,7 +898,7 @@ ** folders (so we don't have to bother trying to look ** into them for resources). */ - PyString_InternInPlace(&PyList_GET_ITEM(path, i)); + PyString_InternInPlace(&PyList_GET_ITEM(path, i), 0); v = PyList_GET_ITEM(path, i); #endif if (PyMac_FindResourceModule((PyStringObject *)v, name, buf)) { @@ -1314,7 +1314,7 @@ if (m == NULL) return -1; d = PyModule_GetDict(m); - s = PyString_InternFromString(name); + s = PyString_InternFromString(name, 0); if (s == NULL) return -1; err = PyDict_SetItemString(d, "__path__", s); @@ -1438,12 +1438,12 @@ return Py_None; if (namestr == NULL) { - namestr = PyString_InternFromString("__name__"); + namestr = PyString_InternFromString("__name__", INTERNED_ATTRIBUTE); if (namestr == NULL) return NULL; } if (pathstr == NULL) { - pathstr = PyString_InternFromString("__path__"); + pathstr = PyString_InternFromString("__path__", 0); if (pathstr == NULL) return NULL; } @@ -1774,10 +1774,10 @@ /* Initialize constant string objects */ if (silly_list == NULL) { - import_str = PyString_InternFromString("__import__"); + import_str = PyString_InternFromString("__import__", 0); if (import_str == NULL) return NULL; - builtins_str = PyString_InternFromString("__builtins__"); + builtins_str = PyString_InternFromString("__builtins__", 0); if (builtins_str == NULL) return NULL; silly_list = Py_BuildValue("[s]", "__doc__");