Index: Python/peephole.c =================================================================== --- Python/peephole.c (revision 61203) +++ Python/peephole.c (working copy) @@ -69,6 +69,55 @@ return 1; } +/* Replace LOAD_CONST c1. LOAD_CONST c2 ... LOAD_CONST cn BUILD_SLICE n + with LOAD_CONST slice(c1, c2, ... cn). + The consts table must still be in list form so that the + new constant slice(c1, c2, ... cn) can be appended. + Called with codestr pointing to the first LOAD_CONST. + Bails out with no change if one or more of the LOAD_CONSTs is missing. + Also works for BUILD_LIST when followed by an "in" or "not in" test. +*/ +static int +slice_of_constants(unsigned char *codestr, int n, PyObject *consts) +{ + PyObject *newconst, *sliceargs[3]; + Py_ssize_t i, arg, len_consts; + + /* Pre-conditions */ + assert(n == 2 || n == 3); + assert(PyList_CheckExact(consts)); + assert(codestr[n*3] == BUILD_SLICE); + assert(GETARG(codestr, (n*3)) == n); + for (i=0 ; i= 0 && + j <= lastlc && + (opcode == BUILD_SLICE && + ISBASICBLOCK(blocks, h, 3*(j+1))) && + slice_of_constants(&codestr[h], j, consts)) { + assert(codestr[i] == LOAD_CONST); + cumlc = 1; + } + break; + /* Fold binary ops on constants. LOAD_CONST c1 LOAD_CONST c2 BINOP --> LOAD_CONST binop(c1,c2) */ case BINARY_POWER: Index: Python/marshal.c =================================================================== --- Python/marshal.c (revision 61203) +++ Python/marshal.c (working copy) @@ -44,6 +44,7 @@ #define TYPE_UNKNOWN '?' #define TYPE_SET '<' #define TYPE_FROZENSET '>' +#define TYPE_SLICE ':' typedef struct { FILE *fp; @@ -359,6 +360,13 @@ if (pb->bf_releasebuffer != NULL) (*pb->bf_releasebuffer)(v, &view); } + else if (PySlice_Check(v)) { + w_byte(TYPE_SLICE, p); + w_long(3L, p); + w_object(((PySliceObject*)v)->start, p); + w_object(((PySliceObject*)v)->stop, p); + w_object(((PySliceObject*)v)->step, p); + } else { w_byte(TYPE_UNKNOWN, p); p->error = 1; @@ -547,7 +555,7 @@ n = r_long(p); if (n < -INT_MAX || n > INT_MAX) { PyErr_SetString(PyExc_ValueError, - "bad marshal data"); + "bad marshal data in a long"); retval = NULL; break; } @@ -563,7 +571,7 @@ if (digit < 0) { Py_DECREF(ob); PyErr_SetString(PyExc_ValueError, - "bad marshal data"); + "bad marshal data in a long"); ob = NULL; break; } @@ -679,7 +687,7 @@ case TYPE_STRING: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data in a string"); retval = NULL; break; } @@ -704,7 +712,7 @@ n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data in a unicode"); retval = NULL; break; } @@ -729,7 +737,7 @@ case TYPE_TUPLE: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data in a tuple"); retval = NULL; break; } @@ -738,7 +746,7 @@ retval = NULL; break; } - for (i = 0; i < n; i++) { + for (i = 0; i < n; i++) { v2 = r_object(p); if ( v2 == NULL ) { if (!PyErr_Occurred()) @@ -756,7 +764,7 @@ case TYPE_LIST: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data in a list"); retval = NULL; break; } @@ -808,7 +816,7 @@ case TYPE_FROZENSET: n = r_long(p); if (n < 0 || n > INT_MAX) { - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data in a set"); retval = NULL; break; } @@ -915,11 +923,39 @@ } retval = v; break; - + case TYPE_SLICE: { + PyObject *sliceargs[3]; + n = r_long(p); + if (n != 3) { + PyErr_SetString(PyExc_ValueError, "bad marshal data in a slice"); + retval = NULL; + break; + } + for (i = 0; i < 3; i++) { + v2 = r_object(p); + if ( v2 == NULL ) { + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_TypeError, + "NULL object in marshal data"); + Py_DECREF(v); + v = NULL; + break; + } + sliceargs[i] = v2; + } + v = PySlice_New(sliceargs[0], sliceargs[1], sliceargs[2]); + if (v == NULL) { + retval = NULL; + break; + } + retval = v; + break; + } + default: /* Bogus data got written, which isn't ideal. This will let you keep working and recover. */ - PyErr_SetString(PyExc_ValueError, "bad marshal data"); + PyErr_SetString(PyExc_ValueError, "bad marshal data (unexpected type)"); retval = NULL; break; Index: Objects/sliceobject.c =================================================================== --- Objects/sliceobject.c (revision 61203) +++ Objects/sliceobject.c (working copy) @@ -338,8 +338,37 @@ static long slice_hash(PySliceObject *v) { - PyErr_SetString(PyExc_TypeError, "unhashable type"); - return -1L; + /* reproduce tuple hash */ + register long x, y; + register Py_ssize_t len = Py_SIZE(v); + register PyObject **p; + long mult = 1000003L; + x = 0x345678L; + y = PyObject_Hash(v->start); + if (y == -1) + return -1; + x = (x ^ y) * mult; + /* the cast might truncate len; that doesn't change hash stability */ + mult += (long)(82520L + len + len); + + y = PyObject_Hash(v->stop); + if (y == -1) + return -1; + x = (x ^ y) * mult; + /* the cast might truncate len; that doesn't change hash stability */ + mult += (long)(82520L + len + len); + + y = PyObject_Hash(v->step); + if (y == -1) + return -1; + x = (x ^ y) * mult; + /* the cast might truncate len; that doesn't change hash stability */ + mult += (long)(82520L + len + len); + + x += 97531L; + if (x == -1) + x = -2; + return x; } PyTypeObject PySlice_Type = {