PyObject_HEAD
int ma_fill; /* # Active + # Dummy */
int ma_used; /* # Active */
- int ma_size; /* total # slots in ma_table */
+
+ /* The table contains ma_mask + 1 slots, and that's a power of 2.
+ * We store the mask instead of the size because the mask is more
+ * frequently needed.
+ */
+ int ma_mask;
+
/* ma_table points to ma_smalltable for small tables, else to
* additional malloc'ed memory. ma_table is never NULL! This rule
* saves repeated runtime null-tests in the workhorse getitem and
#define empty_to_minsize(mp) do { \
memset((mp)->ma_smalltable, 0, sizeof((mp)->ma_smalltable)); \
(mp)->ma_table = (mp)->ma_smalltable; \
- (mp)->ma_size = MINSIZE; \
+ (mp)->ma_mask = MINSIZE - 1; \
(mp)->ma_used = (mp)->ma_fill = 0; \
} while(0)
register int i;
register unsigned int perturb;
register dictentry *freeslot;
- register unsigned int mask = mp->ma_size-1;
+ register unsigned int mask = mp->ma_mask;
dictentry *ep0 = mp->ma_table;
register dictentry *ep;
register int restore_error;
register int i;
register unsigned int perturb;
register dictentry *freeslot;
- register unsigned int mask = mp->ma_size-1;
+ register unsigned int mask = mp->ma_mask;
dictentry *ep0 = mp->ma_table;
register dictentry *ep;
/* Make the dict empty, using the new table. */
assert(newtable != oldtable);
mp->ma_table = newtable;
- mp->ma_size = newsize;
+ mp->ma_mask = newsize - 1;
memset(newtable, 0, sizeof(dictentry) * newsize);
mp->ma_used = 0;
i = mp->ma_fill;
if (hash == -1)
return -1;
}
- assert(mp->ma_fill < mp->ma_size);
+ assert(mp->ma_fill <= mp->ma_mask); /* at least one empty slot */
n_used = mp->ma_used;
Py_INCREF(value);
Py_INCREF(key);
* much larger than ma_used, meaning a lot of dict keys have been
* deleted).
*/
- if (mp->ma_used > n_used && mp->ma_fill*3 >= mp->ma_size*2) {
+ if (mp->ma_used > n_used && mp->ma_fill*3 >= (mp->ma_mask+1)*2) {
if (dictresize(mp, mp->ma_used*2) != 0)
return -1;
}
return;
mp = (dictobject *)op;
#ifdef Py_DEBUG
- n = mp->ma_size;
+ n = mp->ma_mask + 1;
i = 0;
#endif
i = *ppos;
if (i < 0)
return 0;
- while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
+ while (i <= mp->ma_mask && mp->ma_table[i].me_value == NULL)
i++;
*ppos = i+1;
- if (i >= mp->ma_size)
+ if (i > mp->ma_mask)
return 0;
if (pkey)
*pkey = mp->ma_table[i].me_key;
fprintf(fp, "{");
any = 0;
- for (i = 0; i < mp->ma_size; i++) {
+ for (i = 0; i <= mp->ma_mask; i++) {
dictentry *ep = mp->ma_table + i;
PyObject *pvalue = ep->me_value;
if (pvalue != NULL) {
sepa = PyString_FromString(", ");
colon = PyString_FromString(": ");
any = 0;
- for (i = 0; i < mp->ma_size && v; i++) {
+ for (i = 0; i <= mp->ma_mask && v; i++) {
dictentry *ep = mp->ma_table + i;
PyObject *pvalue = ep->me_value;
if (pvalue != NULL) {
Py_DECREF(v);
goto again;
}
- for (i = 0, j = 0; i < mp->ma_size; i++) {
+ for (i = 0, j = 0; i <= mp->ma_mask; i++) {
if (mp->ma_table[i].me_value != NULL) {
PyObject *key = mp->ma_table[i].me_key;
Py_INCREF(key);
Py_DECREF(v);
goto again;
}
- for (i = 0, j = 0; i < mp->ma_size; i++) {
+ for (i = 0, j = 0; i <= mp->ma_mask; i++) {
if (mp->ma_table[i].me_value != NULL) {
PyObject *value = mp->ma_table[i].me_value;
Py_INCREF(value);
goto again;
}
/* Nothing we do below makes any function calls. */
- for (i = 0, j = 0; i < mp->ma_size; i++) {
+ for (i = 0, j = 0; i <= mp->ma_mask; i++) {
if (mp->ma_table[i].me_value != NULL) {
key = mp->ma_table[i].me_key;
value = mp->ma_table[i].me_value;
/* Do one big resize at the start, rather than incrementally
resizing as we insert new items. Expect that there will be
no (or few) overlapping keys. */
- if ((mp->ma_fill + other->ma_used)*3 >= mp->ma_size*2) {
+ if ((mp->ma_fill + other->ma_used)*3 >= (mp->ma_mask+1)*2) {
if (dictresize(mp, (mp->ma_used + other->ma_used)*3/2) != 0)
return NULL;
}
- for (i = 0; i < other->ma_size; i++) {
+ for (i = 0; i <= other->ma_mask; i++) {
entry = &other->ma_table[i];
if (entry->me_value != NULL) {
Py_INCREF(entry->me_key);
if (mp->ma_used > 0) {
if (dictresize(copy, mp->ma_used*3/2) != 0)
return NULL;
- for (i = 0; i < mp->ma_size; i++) {
+ for (i = 0; i <= mp->ma_mask; i++) {
entry = &mp->ma_table[i];
if (entry->me_value != NULL) {
Py_INCREF(entry->me_key);
PyObject *aval = NULL; /* a[akey] */
int i, cmp;
- for (i = 0; i < a->ma_size; i++) {
+ for (i = 0; i <= a->ma_mask; i++) {
PyObject *thiskey, *thisaval, *thisbval;
if (a->ma_table[i].me_value == NULL)
continue;
goto Fail;
}
if (cmp > 0 ||
- i >= a->ma_size ||
+ i > a->ma_mask ||
a->ma_table[i].me_value == NULL)
{
/* Not the *smallest* a key; or maybe it is
return 0;
/* Same # of entries -- check all of 'em. Exit early on any diff. */
- for (i = 0; i < a->ma_size; i++) {
+ for (i = 0; i <= a->ma_mask; i++) {
PyObject *aval = a->ma_table[i].me_value;
if (aval != NULL) {
int cmp;
* finger that's out of bounds now because it wrapped around
* or the table shrunk -- simply make sure it's in bounds now.
*/
- if (i >= mp->ma_size || i < 1)
+ if (i > mp->ma_mask || i < 1)
i = 1; /* skip slot 0 */
while ((ep = &mp->ma_table[i])->me_value == NULL) {
i++;
- if (i >= mp->ma_size)
+ if (i > mp->ma_mask)
i = 1;
}
}