Index: ceval.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v retrieving revision 2.406 diff -c -r2.406 ceval.c *** ceval.c 26 Jun 2004 04:34:33 -0000 2.406 --- ceval.c 27 Jun 2004 20:37:59 -0000 *************** *** 87,92 **** --- 87,94 ---- static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *); static void reset_exc_info(PyThreadState *); static void format_exc_check_arg(PyObject *, char *, PyObject *); + static PyObject *string_concatenate(PyFrameObject *, PyObject *, PyObject *, + unsigned char *); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" *************** *** 552,557 **** --- 554,560 ---- #define INSTR_OFFSET() (next_instr - first_instr) #define NEXTOP() (*next_instr++) #define NEXTARG() (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2]) + #define PEEKARG() ((next_instr[2]<<8) + next_instr[1]) #define JUMPTO(x) (next_instr = first_instr + (x)) #define JUMPBY(x) (next_instr += (x)) *************** *** 582,589 **** #endif #define PREDICTED(op) PRED_##op: next_instr++ ! #define PREDICTED_WITH_ARG(op) PRED_##op: oparg = (next_instr[2]<<8) + \ ! next_instr[1]; next_instr += 3 /* Stack manipulation macros */ --- 585,591 ---- #endif #define PREDICTED(op) PRED_##op: next_instr++ ! #define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3 /* Stack manipulation macros */ *************** *** 1068,1073 **** --- 1070,1084 ---- goto slow_add; x = PyInt_FromLong(i); } + else if (PyString_CheckExact(v) && + PyString_CheckExact(w)) { + x = string_concatenate(f, v, w, next_instr); + /* Py_DECREF(v); done by string_concatenate */ + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) continue; + break; + } else { slow_add: x = PyNumber_Add(v, w); *************** *** 1263,1268 **** --- 1274,1288 ---- goto slow_iadd; x = PyInt_FromLong(i); } + else if (PyString_CheckExact(v) && + PyString_CheckExact(w)) { + x = string_concatenate(f, v, w, next_instr); + /* Py_DECREF(v); done by string_concatenate */ + Py_DECREF(w); + SET_TOP(x); + if (x != NULL) continue; + break; + } else { slow_iadd: x = PyNumber_InPlaceAdd(v, w); *************** *** 4188,4193 **** --- 4208,4292 ---- PyErr_Format(exc, format_str, obj_str); } + static int + fast_inplace_concat(PyObject **pv, PyObject *w) + { + int v_size = PyString_GET_SIZE(*pv); + int w_size = PyString_GET_SIZE(w); + int newsize = v_size + w_size; + PyStringObject *sv; + + /* We have to inline _PyString_Resize() to change a detail: + if memory runs out, we must not deallocate the old string. */ + + assert((*pv)->ob_refcnt == 1); + /* XXX UNREF/NEWREF interface should be more symmetrical */ + _Py_DEC_REFTOTAL; + _Py_ForgetReference(*pv); + sv = (PyStringObject *) + PyObject_REALLOC((char *)(*pv), + sizeof(PyStringObject) + newsize * sizeof(char)); + if (sv == NULL) { + _Py_NewReference(*pv); + PyErr_NoMemory(); + return -1; + } + _Py_NewReference((PyObject *)sv); + sv->ob_size = newsize; + sv->ob_sval[newsize] = '\0'; + memcpy(sv->ob_sval + v_size, PyString_AS_STRING(w), w_size); + *pv = (PyObject *)sv; + return 0; + } + + static PyObject * + string_concatenate(PyFrameObject *f, PyObject *v, PyObject *w, + unsigned char *next_instr) + { + if (v->ob_refcnt == 1) { + if (fast_inplace_concat(&v, w)) { + Py_DECREF(v); + return NULL; + } + return v; + } + if (v->ob_refcnt == 2) { + if (*next_instr == STORE_FAST) { + int oparg = PEEKARG(); + PyObject **fastlocals = f->f_localsplus; + if (GETLOCAL(oparg) != v) + goto fallback; + Py_DECREF(v); + if (fast_inplace_concat(&v, w)) + return NULL; + Py_INCREF(v); + GETLOCAL(oparg) = v; + return v; + } + else if (*next_instr == STORE_NAME) { + PyObject *names = f->f_code->co_names; + PyObject *name = GETITEM(names, PEEKARG()); + PyDictEntry *e; + PyDictObject *d = (PyDictObject *)f->f_locals; + long hash = ((PyStringObject *)name)->ob_shash; + if (d == NULL || hash == -1) + goto fallback; + e = d->ma_lookup(d, name, hash); + if (e->me_value != v) + goto fallback; + Py_DECREF(v); + if (fast_inplace_concat(&v, w)) + return NULL; + Py_INCREF(v); + e->me_value = v; + return v; + } + } + fallback: + PyString_Concat(&v, w); + return v; + } + #ifdef DYNAMIC_EXECUTION_PROFILE static PyObject *