static Tvalue *table_newkey(ktap_State *ks, Table *t, const Tvalue *key) { Node *mp; mp = mainposition(t, key); if (!isnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ Node *othern; Node *n = getfreepos(t); /* get a free place */ if (n == NULL) { /* cannot find a free place? */ rehash(ks, t, key); /* grow table */ /* whatever called 'newkey' take care of TM cache and GC barrier */ return kp_table_set(ks, t, key); /* insert key into grown table */ } othern = mainposition(t, gkey(mp)); if (othern != mp) { /* is colliding node out of its main position? */ /* yes; move colliding node into free position */ while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ gnext(mp) = NULL; /* now `mp' is free */ setnilvalue(gval(mp)); } else { /* colliding node is in its own main position */ /* new node will go into free position */ gnext(n) = gnext(mp); /* chain new position */ gnext(mp) = n; mp = n; } } setobj(ks, gkey(mp), key); return gval(mp); }
void kp_table_free(ktap_State *ks, Table *t) { if (t->sizearray > 0) kp_free(ks, t->array); if (!isdummy(t->node)) kp_free(ks, t->node); kp_free(ks, t); }
void kp_table_resize(ktap_State *ks, Table *t, int nasize, int nhsize) { int i; int oldasize = t->sizearray; int oldhsize = t->lsizenode; Node *nold = t->node; /* save old hash ... */ if (nasize > oldasize) /* array part must grow? */ setarrayvector(ks, t, nasize); /* create new hash part with appropriate size */ setnodevector(ks, t, nhsize); if (nasize < oldasize) { /* array part must shrink? */ t->sizearray = nasize; /* re-insert elements from vanishing slice */ for (i=nasize; i<oldasize; i++) { if (!ttisnil(&t->array[i])) kp_table_setint(ks, t, i + 1, &t->array[i]); } /* shrink array */ kp_realloc(ks, t->array, oldasize, nasize, Tvalue); } /* re-insert elements from hash part */ for (i = twoto(oldhsize) - 1; i >= 0; i--) { Node *old = nold+i; if (!ttisnil(gval(old))) { /* doesn't need barrier/invalidate cache, as entry was * already present in the table */ setobj(ks, kp_table_set(ks, t, gkey(old)), gval(old)); } } if (!isdummy(nold)) kp_free(ks, nold); /* free old array */ }
static void freehash (lua_State *L, Table *t) { if (!isdummy(t)) luaM_freearray(L, t->node, cast_sizet(sizenode(t))); }
void kp_table_resizearray(ktap_State *ks, Table *t, int nasize) { int nsize = isdummy(t->node) ? 0 : sizenode(t); kp_table_resize(ks, t, nasize, nsize); }