diff -r 0f357cf011d3 Python/marshal.c --- a/Python/marshal.c Thu Feb 13 10:49:30 2014 +0200 +++ b/Python/marshal.c Thu Feb 13 22:23:51 2014 +0200 @@ -62,6 +62,13 @@ #define WFERR_NESTEDTOODEEP 2 #define WFERR_NOMEMORY 3 +#ifndef NSMALLPOSINTS +#define NSMALLPOSINTS 257 +#endif +#ifndef NSMALLNEGINTS +#define NSMALLNEGINTS 5 +#endif + typedef struct { FILE *fp; int error; /* see WFERR_* values */ @@ -75,6 +82,7 @@ char *buf; Py_ssize_t buf_size; PyObject *refs; /* dict on marshal, list on unmarshal */ + unsigned int small_ints_refs[NSMALLNEGINTS + NSMALLPOSINTS]; int version; } WFILE; @@ -235,6 +243,27 @@ if (Py_REFCNT(v) == 1) return 0; + if (PyLong_CheckExact(v) && Py_SIZE(v) <= 1 && Py_SIZE(v) >= -1) { + long ival = PyLong_AS_LONG(v); + if (-NSMALLNEGINTS <= ival && ival < NSMALLPOSINTS) { + unsigned long w = p->small_ints_refs[ival + NSMALLNEGINTS]; + if (w != 0) { + /* write the reference index to the stream */ + w--; + /* we don't store "long" indices in the dict */ + assert(0 <= w && w <= 0x7fffffff); + w_byte(TYPE_REF, p); + w_long(w, p); + return 1; + } else { + Py_ssize_t s = PyDict_Size(p->refs); + /* we don't support long indices */ + if (s < 0x7fffffff) { + p->small_ints_refs[ival + NSMALLNEGINTS] = (unsigned int)s + 1; + } + } + } + } id = PyLong_FromVoidPtr((void*)v); if (id == NULL) goto err; @@ -570,6 +599,7 @@ if (version >= 3) { if ((wf.refs = PyDict_New()) == NULL) return; /* caller mush check PyErr_Occurred() */ + memset(wf.small_ints_refs, 0, sizeof(wf.small_ints_refs)); } else wf.refs = NULL; wf.version = version; @@ -1524,6 +1554,7 @@ if (version >= 3) { if ((wf.refs = PyDict_New()) == NULL) return NULL; + memset(wf.small_ints_refs, 0, sizeof(wf.small_ints_refs)); } else wf.refs = NULL; w_object(x, &wf);