From bb93f04d87cfc093757dc712905e1fe3fbe65f58 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 5 Dec 2024 14:27:58 -0300 Subject: [PATCH] Refactoring of 'luaH_newkey' Function broke in two and some checks moved to the caller. (We may want to call it without the checks.) --- lobject.h | 5 +-- ltable.c | 130 ++++++++++++++++++++++++++++++++---------------------- 2 files changed, 79 insertions(+), 56 deletions(-) diff --git a/lobject.h b/lobject.h index 4a0835a8..8c06a224 100644 --- a/lobject.h +++ b/lobject.h @@ -750,10 +750,9 @@ typedef union Node { /* copy a value into a key */ -#define setnodekey(L,node,obj) \ +#define setnodekey(node,obj) \ { Node *n_=(node); const TValue *io_=(obj); \ - n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \ - checkliveness(L,io_); } + n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; } /* copy a value from a key */ diff --git a/ltable.c b/ltable.c index 6ea382a1..735ae873 100644 --- a/ltable.c +++ b/ltable.c @@ -294,14 +294,34 @@ static const TValue *getgeneric (Table *t, const TValue *key, int deadok) { /* -** returns the index for 'k' if 'k' is an appropriate key to live in -** the array part of a table, 0 otherwise. +** Return the index 'k' (converted to an unsigned) if it is inside +** the range [1, limit]. */ -static unsigned int arrayindex (lua_Integer k) { - if (l_castS2U(k) - 1u < MAXASIZE) /* 'k' in [1, MAXASIZE]? */ - return cast_uint(k); /* 'key' is an appropriate array index */ - else - return 0; +static unsigned checkrange (lua_Integer k, unsigned limit) { + return (l_castS2U(k) - 1u < limit) ? cast_uint(k) : 0; +} + + +/* +** Return the index 'k' if 'k' is an appropriate key to live in the +** array part of a table, 0 otherwise. +*/ +#define arrayindex(k) checkrange(k, MAXASIZE) + + +/* +** Check whether an integer key is in the array part of a table and +** return its index there, or zero. +*/ +#define ikeyinarray(t,k) checkrange(k, t->asize) + + +/* +** Check whether a key is in the array part of a table and return its +** index there, or zero. +*/ +static unsigned keyinarray (Table *t, const TValue *key) { + return (ttisinteger(key)) ? ikeyinarray(t, ivalue(key)) : 0; } @@ -314,8 +334,8 @@ static unsigned findindex (lua_State *L, Table *t, TValue *key, unsigned asize) { unsigned int i; if (ttisnil(key)) return 0; /* first iteration */ - i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; - if (i - 1u < asize) /* is 'key' inside array part? */ + i = keyinarray(t, key); + if (i != 0) /* is 'key' inside array part? */ return i; /* yes; that's the index */ else { const TValue *n = getgeneric(t, key, 1); @@ -369,14 +389,6 @@ static void freehash (lua_State *L, Table *t) { } -/* -** Check whether an integer key is in the array part of a table. -*/ -l_sinline int keyinarray (Table *t, lua_Integer key) { - return (l_castS2U(key) - 1u < t->asize); /* 'key' in [1, t->asize]? */ -} - - /* ** {============================================================= ** Rehash @@ -829,36 +841,18 @@ static Node *getfreepos (Table *t) { ** position is free. If not, check whether colliding node is in its main ** position or not: if it is not, move colliding node to an empty place ** and put new key in its main position; otherwise (colliding node is in -** its main position), new key goes to an empty position. +** its main position), new key goes to an empty position. Return 0 if +** could not insert key (could not find a free space). */ -static void luaH_newkey (lua_State *L, Table *t, const TValue *key, - TValue *value) { - Node *mp; - TValue aux; - if (l_unlikely(ttisnil(key))) - luaG_runerror(L, "table index is nil"); - else if (ttisfloat(key)) { - lua_Number f = fltvalue(key); - lua_Integer k; - if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */ - setivalue(&aux, k); - key = &aux; /* insert it as an integer */ - } - else if (l_unlikely(luai_numisnan(f))) - luaG_runerror(L, "table index is NaN"); - } - if (ttisnil(value)) - return; /* do not insert nil values */ - mp = mainpositionTV(t, key); +static int insertkey (Table *t, const TValue *key, TValue *value) { + Node *mp = mainpositionTV(t, key); + /* table cannot already contain the key */ + lua_assert(isabstkey(getgeneric(t, key, 0))); if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ Node *othern; Node *f = getfreepos(t); /* get a free place */ - if (f == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' takes care of TM cache */ - luaH_set(L, t, key, value); /* insert key into grown table */ - return; - } + if (f == NULL) /* cannot find a free place? */ + return 0; lua_assert(!isdummy(t)); othern = mainpositionfromnode(t, mp); if (othern != mp) { /* is colliding node out of its main position? */ @@ -882,16 +876,31 @@ static void luaH_newkey (lua_State *L, Table *t, const TValue *key, mp = f; } } - setnodekey(L, mp, key); - luaC_barrierback(L, obj2gco(t), key); + setnodekey(mp, key); lua_assert(isempty(gval(mp))); - setobj2t(L, gval(mp), value); + setobj2t(cast(lua_State *, 0), gval(mp), value); + return 1; +} + + +static void luaH_newkey (lua_State *L, Table *t, const TValue *key, + TValue *value) { + if (!ttisnil(value)) { /* do not insert nil values */ + int done = insertkey(t, key, value); + if (done) + luaC_barrierback(L, obj2gco(t), key); + else { /* could not find a free place? */ + rehash(L, t, key); /* grow table */ + /* whatever called 'newkey' takes care of TM cache */ + luaH_set(L, t, key, value); /* insert key into grown table */ + } + } } static const TValue *getintfromhash (Table *t, lua_Integer key) { Node *n = hashint(t, key); - lua_assert(!keyinarray(t, key)); + lua_assert(!ikeyinarray(t, key)); for (;;) { /* check whether 'key' is somewhere in the chain */ if (keyisinteger(n) && keyival(n) == key) return gval(n); /* that's it */ @@ -920,10 +929,11 @@ static lu_byte finishnodeget (const TValue *val, TValue *res) { lu_byte luaH_getint (Table *t, lua_Integer key, TValue *res) { - if (keyinarray(t, key)) { - lu_byte tag = *getArrTag(t, key - 1); + unsigned k = ikeyinarray(t, key); + if (k > 0) { + lu_byte tag = *getArrTag(t, k - 1); if (!tagisempty(tag)) - farr2val(t, cast_uint(key) - 1, tag, res); + farr2val(t, k - 1, tag, res); return tag; } else @@ -1031,7 +1041,7 @@ static int rawfinishnodeset (const TValue *slot, TValue *val) { int luaH_psetint (Table *t, lua_Integer key, TValue *val) { - lua_assert(!keyinarray(t, key)); + lua_assert(!ikeyinarray(t, key)); return finishnodeset(t, getintfromhash(t, key), val); } @@ -1081,6 +1091,19 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key, TValue *value, int hres) { lua_assert(hres != HOK); if (hres == HNOTFOUND) { + TValue aux; + if (l_unlikely(ttisnil(key))) + luaG_runerror(L, "table index is nil"); + else if (ttisfloat(key)) { + lua_Number f = fltvalue(key); + lua_Integer k; + if (luaV_flttointeger(f, &k, F2Ieq)) { + setivalue(&aux, k); /* key is equal to an integer */ + key = &aux; /* insert it as an integer */ + } + else if (l_unlikely(luai_numisnan(f))) + luaG_runerror(L, "table index is NaN"); + } luaH_newkey(L, t, key, value); } else if (hres > 0) { /* regular Node? */ @@ -1109,8 +1132,9 @@ void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) { ** integers cannot be keys to metamethods.) */ void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { - if (keyinarray(t, key)) - obj2arr(t, cast_uint(key) - 1, value); + unsigned ik = ikeyinarray(t, key); + if (ik > 0) + obj2arr(t, ik - 1, value); else { int ok = rawfinishnodeset(getintfromhash(t, key), value); if (!ok) {