|
13 | 13 | #endif /* DONT_HAVE_SYS_TYPES_H */ |
14 | 14 | #endif /* !STDC_HEADERS */ |
15 | 15 |
|
| 16 | +/* Shamelessy stolen from listobject.c */ |
| 17 | +static int |
| 18 | +roundupsize(int n) |
| 19 | +{ |
| 20 | + unsigned int nbits = 0; |
| 21 | + unsigned int n2 = (unsigned int)n >> 5; |
| 22 | + |
| 23 | + /* Round up: |
| 24 | + * If n < 256, to a multiple of 8. |
| 25 | + * If n < 2048, to a multiple of 64. |
| 26 | + * If n < 16384, to a multiple of 512. |
| 27 | + * If n < 131072, to a multiple of 4096. |
| 28 | + * If n < 1048576, to a multiple of 32768. |
| 29 | + * If n < 8388608, to a multiple of 262144. |
| 30 | + * If n < 67108864, to a multiple of 2097152. |
| 31 | + * If n < 536870912, to a multiple of 16777216. |
| 32 | + * ... |
| 33 | + * If n < 2**(5+3*i), to a multiple of 2**(3*i). |
| 34 | + * |
| 35 | + * This over-allocates proportional to the list size, making room |
| 36 | + * for additional growth. The over-allocation is mild, but is |
| 37 | + * enough to give linear-time amortized behavior over a long |
| 38 | + * sequence of appends() in the presence of a poorly-performing |
| 39 | + * system realloc() (which is a reality, e.g., across all flavors |
| 40 | + * of Windows, with Win9x behavior being particularly bad -- and |
| 41 | + * we've still got address space fragmentation problems on Win9x |
| 42 | + * even with this scheme, although it requires much longer lists to |
| 43 | + * provoke them than it used to). |
| 44 | + */ |
| 45 | + do { |
| 46 | + n2 >>= 3; |
| 47 | + nbits += 3; |
| 48 | + } while (n2); |
| 49 | + return ((n >> nbits) + 1) << nbits; |
| 50 | + } |
| 51 | + |
| 52 | +#define NRESIZE(var, type, nitems) \ |
| 53 | +do { \ |
| 54 | + size_t _new_size = roundupsize(nitems); \ |
| 55 | + if (_new_size <= ((~(size_t)0) / sizeof(type))) \ |
| 56 | + PyMem_RESIZE(var, type, _new_size); \ |
| 57 | + else \ |
| 58 | + var = NULL; \ |
| 59 | +} while (0) |
| 60 | +/* END SHAMELESSLY STOLEN CODE */ |
| 61 | + |
16 | 62 | struct arrayobject; /* Forward */ |
17 | 63 |
|
18 | 64 | /* All possible arraydescr values are defined in the vector "descriptors" |
@@ -419,8 +465,7 @@ ins1(arrayobject *self, int where, PyObject *v) |
419 | 465 | if ((*self->ob_descr->setitem)(self, -1, v) < 0) |
420 | 466 | return -1; |
421 | 467 | items = self->ob_item; |
422 | | - PyMem_RESIZE(items, char, |
423 | | - (self->ob_size+1) * self->ob_descr->itemsize); |
| 468 | + NRESIZE(items, char, (self->ob_size+1) * self->ob_descr->itemsize); |
424 | 469 | if (items == NULL) { |
425 | 470 | PyErr_NoMemory(); |
426 | 471 | return -1; |
|
0 commit comments