diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-11-07 10:38:35 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2016-11-07 10:38:35 -0200 |
| commit | 7b1fba69b7a887e37e57744309299d134e76e06e (patch) | |
| tree | e5743e7f4792f065bb9644e827e43eb9a9c03a22 | |
| parent | 697593d8d5b2e2287919423006c53dcac31d2b70 (diff) | |
| download | lua-7b1fba69b7a887e37e57744309299d134e76e06e.tar.gz lua-7b1fba69b7a887e37e57744309299d134e76e06e.tar.bz2 lua-7b1fba69b7a887e37e57744309299d134e76e06e.zip | |
using 'lastfree == NULL' to signal that table is using the dummy
node for its hash part + new macro 'allocsizenode'
| -rw-r--r-- | lgc.c | 4 | ||||
| -rw-r--r-- | ltable.c | 46 | ||||
| -rw-r--r-- | ltable.h | 12 | ||||
| -rw-r--r-- | ltests.c | 6 |
4 files changed, 38 insertions, 30 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.212 2016/03/31 19:02:03 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.213 2016/10/19 12:31:42 roberto Exp roberto $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -467,7 +467,7 @@ static lu_mem traversetable (global_State *g, Table *h) { | |||
| 467 | else /* not weak */ | 467 | else /* not weak */ |
| 468 | traversestrongtable(g, h); | 468 | traversestrongtable(g, h); |
| 469 | return sizeof(Table) + sizeof(TValue) * h->sizearray + | 469 | return sizeof(Table) + sizeof(TValue) * h->sizearray + |
| 470 | sizeof(Node) * cast(size_t, sizenode(h)); | 470 | sizeof(Node) * cast(size_t, allocsizenode(h)); |
| 471 | } | 471 | } |
| 472 | 472 | ||
| 473 | 473 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 2.116 2015/11/03 18:35:21 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.117 2015/11/19 19:16:22 roberto Exp roberto $ |
| 3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -74,8 +74,6 @@ | |||
| 74 | 74 | ||
| 75 | #define dummynode (&dummynode_) | 75 | #define dummynode (&dummynode_) |
| 76 | 76 | ||
| 77 | #define isdummy(n) ((n) == dummynode) | ||
| 78 | |||
| 79 | static const Node dummynode_ = { | 77 | static const Node dummynode_ = { |
| 80 | {NILCONSTANT}, /* value */ | 78 | {NILCONSTANT}, /* value */ |
| 81 | {{NILCONSTANT, 0}} /* key */ | 79 | {{NILCONSTANT, 0}} /* key */ |
| @@ -308,14 +306,14 @@ static void setarrayvector (lua_State *L, Table *t, unsigned int size) { | |||
| 308 | 306 | ||
| 309 | 307 | ||
| 310 | static void setnodevector (lua_State *L, Table *t, unsigned int size) { | 308 | static void setnodevector (lua_State *L, Table *t, unsigned int size) { |
| 311 | int lsize; | ||
| 312 | if (size == 0) { /* no elements to hash part? */ | 309 | if (size == 0) { /* no elements to hash part? */ |
| 313 | t->node = cast(Node *, dummynode); /* use common 'dummynode' */ | 310 | t->node = cast(Node *, dummynode); /* use common 'dummynode' */ |
| 314 | lsize = 0; | 311 | t->lsizenode = 0; |
| 312 | t->lastfree = NULL; /* signal that it is using dummy node */ | ||
| 315 | } | 313 | } |
| 316 | else { | 314 | else { |
| 317 | int i; | 315 | int i; |
| 318 | lsize = luaO_ceillog2(size); | 316 | int lsize = luaO_ceillog2(size); |
| 319 | if (lsize > MAXHBITS) | 317 | if (lsize > MAXHBITS) |
| 320 | luaG_runerror(L, "table overflow"); | 318 | luaG_runerror(L, "table overflow"); |
| 321 | size = twoto(lsize); | 319 | size = twoto(lsize); |
| @@ -326,9 +324,9 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { | |||
| 326 | setnilvalue(wgkey(n)); | 324 | setnilvalue(wgkey(n)); |
| 327 | setnilvalue(gval(n)); | 325 | setnilvalue(gval(n)); |
| 328 | } | 326 | } |
| 327 | t->lsizenode = cast_byte(lsize); | ||
| 328 | t->lastfree = gnode(t, size); /* all positions are free */ | ||
| 329 | } | 329 | } |
| 330 | t->lsizenode = cast_byte(lsize); | ||
| 331 | t->lastfree = gnode(t, size); /* all positions are free */ | ||
| 332 | } | 330 | } |
| 333 | 331 | ||
| 334 | 332 | ||
| @@ -337,7 +335,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | |||
| 337 | unsigned int i; | 335 | unsigned int i; |
| 338 | int j; | 336 | int j; |
| 339 | unsigned int oldasize = t->sizearray; | 337 | unsigned int oldasize = t->sizearray; |
| 340 | int oldhsize = t->lsizenode; | 338 | int oldhsize = allocsizenode(t); |
| 341 | Node *nold = t->node; /* save old hash ... */ | 339 | Node *nold = t->node; /* save old hash ... */ |
| 342 | if (nasize > oldasize) /* array part must grow? */ | 340 | if (nasize > oldasize) /* array part must grow? */ |
| 343 | setarrayvector(L, t, nasize); | 341 | setarrayvector(L, t, nasize); |
| @@ -354,7 +352,7 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | |||
| 354 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); | 352 | luaM_reallocvector(L, t->array, oldasize, nasize, TValue); |
| 355 | } | 353 | } |
| 356 | /* re-insert elements from hash part */ | 354 | /* re-insert elements from hash part */ |
| 357 | for (j = twoto(oldhsize) - 1; j >= 0; j--) { | 355 | for (j = oldhsize - 1; j >= 0; j--) { |
| 358 | Node *old = nold + j; | 356 | Node *old = nold + j; |
| 359 | if (!ttisnil(gval(old))) { | 357 | if (!ttisnil(gval(old))) { |
| 360 | /* doesn't need barrier/invalidate cache, as entry was | 358 | /* doesn't need barrier/invalidate cache, as entry was |
| @@ -362,13 +360,13 @@ void luaH_resize (lua_State *L, Table *t, unsigned int nasize, | |||
| 362 | setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); | 360 | setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); |
| 363 | } | 361 | } |
| 364 | } | 362 | } |
| 365 | if (!isdummy(nold)) | 363 | if (oldhsize > 0) /* not the dummy node? */ |
| 366 | luaM_freearray(L, nold, cast(size_t, twoto(oldhsize))); /* free old hash */ | 364 | luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */ |
| 367 | } | 365 | } |
| 368 | 366 | ||
| 369 | 367 | ||
| 370 | void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { | 368 | void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { |
| 371 | int nsize = isdummy(t->node) ? 0 : sizenode(t); | 369 | int nsize = allocsizenode(t); |
| 372 | luaH_resize(L, t, nasize, nsize); | 370 | luaH_resize(L, t, nasize, nsize); |
| 373 | } | 371 | } |
| 374 | 372 | ||
| @@ -414,7 +412,7 @@ Table *luaH_new (lua_State *L) { | |||
| 414 | 412 | ||
| 415 | 413 | ||
| 416 | void luaH_free (lua_State *L, Table *t) { | 414 | void luaH_free (lua_State *L, Table *t) { |
| 417 | if (!isdummy(t->node)) | 415 | if (!isdummy(t)) |
| 418 | luaM_freearray(L, t->node, cast(size_t, sizenode(t))); | 416 | luaM_freearray(L, t->node, cast(size_t, sizenode(t))); |
| 419 | luaM_freearray(L, t->array, t->sizearray); | 417 | luaM_freearray(L, t->array, t->sizearray); |
| 420 | luaM_free(L, t); | 418 | luaM_free(L, t); |
| @@ -422,10 +420,12 @@ void luaH_free (lua_State *L, Table *t) { | |||
| 422 | 420 | ||
| 423 | 421 | ||
| 424 | static Node *getfreepos (Table *t) { | 422 | static Node *getfreepos (Table *t) { |
| 425 | while (t->lastfree > t->node) { | 423 | if (!isdummy(t)) { |
| 426 | t->lastfree--; | 424 | while (t->lastfree > t->node) { |
| 427 | if (ttisnil(gkey(t->lastfree))) | 425 | t->lastfree--; |
| 428 | return t->lastfree; | 426 | if (ttisnil(gkey(t->lastfree))) |
| 427 | return t->lastfree; | ||
| 428 | } | ||
| 429 | } | 429 | } |
| 430 | return NULL; /* could not find a free place */ | 430 | return NULL; /* could not find a free place */ |
| 431 | } | 431 | } |
| @@ -445,7 +445,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
| 445 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); | 445 | if (ttisnil(key)) luaG_runerror(L, "table index is nil"); |
| 446 | else if (ttisfloat(key)) { | 446 | else if (ttisfloat(key)) { |
| 447 | lua_Integer k; | 447 | lua_Integer k; |
| 448 | if (luaV_tointeger(key, &k, 0)) { /* index is int? */ | 448 | if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */ |
| 449 | setivalue(&aux, k); | 449 | setivalue(&aux, k); |
| 450 | key = &aux; /* insert it as an integer */ | 450 | key = &aux; /* insert it as an integer */ |
| 451 | } | 451 | } |
| @@ -453,7 +453,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
| 453 | luaG_runerror(L, "table index is NaN"); | 453 | luaG_runerror(L, "table index is NaN"); |
| 454 | } | 454 | } |
| 455 | mp = mainposition(t, key); | 455 | mp = mainposition(t, key); |
| 456 | if (!ttisnil(gval(mp)) || isdummy(mp)) { /* main position is taken? */ | 456 | if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ |
| 457 | Node *othern; | 457 | Node *othern; |
| 458 | Node *f = getfreepos(t); /* get a free place */ | 458 | Node *f = getfreepos(t); /* get a free place */ |
| 459 | if (f == NULL) { /* cannot find a free place? */ | 459 | if (f == NULL) { /* cannot find a free place? */ |
| @@ -461,7 +461,7 @@ TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { | |||
| 461 | /* whatever called 'newkey' takes care of TM cache */ | 461 | /* whatever called 'newkey' takes care of TM cache */ |
| 462 | return luaH_set(L, t, key); /* insert key into grown table */ | 462 | return luaH_set(L, t, key); /* insert key into grown table */ |
| 463 | } | 463 | } |
| 464 | lua_assert(!isdummy(f)); | 464 | lua_assert(!isdummy(t)); |
| 465 | othern = mainposition(t, gkey(mp)); | 465 | othern = mainposition(t, gkey(mp)); |
| 466 | if (othern != mp) { /* is colliding node out of its main position? */ | 466 | if (othern != mp) { /* is colliding node out of its main position? */ |
| 467 | /* yes; move colliding node into free position */ | 467 | /* yes; move colliding node into free position */ |
| @@ -651,7 +651,7 @@ int luaH_getn (Table *t) { | |||
| 651 | return i; | 651 | return i; |
| 652 | } | 652 | } |
| 653 | /* else must find a boundary in hash part */ | 653 | /* else must find a boundary in hash part */ |
| 654 | else if (isdummy(t->node)) /* hash part is empty? */ | 654 | else if (isdummy(t)) /* hash part is empty? */ |
| 655 | return j; /* that is easy... */ | 655 | return j; /* that is easy... */ |
| 656 | else return unbound_search(t, j); | 656 | else return unbound_search(t, j); |
| 657 | } | 657 | } |
| @@ -664,6 +664,6 @@ Node *luaH_mainposition (const Table *t, const TValue *key) { | |||
| 664 | return mainposition(t, key); | 664 | return mainposition(t, key); |
| 665 | } | 665 | } |
| 666 | 666 | ||
| 667 | int luaH_isdummy (Node *n) { return isdummy(n); } | 667 | int luaH_isdummy (const Table *t) { return isdummy(t); } |
| 668 | 668 | ||
| 669 | #endif | 669 | #endif |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.h,v 2.20 2014/09/04 18:15:29 roberto Exp roberto $ | 2 | ** $Id: ltable.h,v 2.21 2015/11/03 15:47:30 roberto Exp roberto $ |
| 3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -27,6 +27,14 @@ | |||
| 27 | #define invalidateTMcache(t) ((t)->flags = 0) | 27 | #define invalidateTMcache(t) ((t)->flags = 0) |
| 28 | 28 | ||
| 29 | 29 | ||
| 30 | /* true when 't' is using 'dummynode' as its hash part */ | ||
| 31 | #define isdummy(t) ((t)->lastfree == NULL) | ||
| 32 | |||
| 33 | |||
| 34 | /* allocated size for hash nodes */ | ||
| 35 | #define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) | ||
| 36 | |||
| 37 | |||
| 30 | /* returns the key, given the value of a table entry */ | 38 | /* returns the key, given the value of a table entry */ |
| 31 | #define keyfromval(v) \ | 39 | #define keyfromval(v) \ |
| 32 | (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) | 40 | (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) |
| @@ -51,7 +59,7 @@ LUAI_FUNC int luaH_getn (Table *t); | |||
| 51 | 59 | ||
| 52 | #if defined(LUA_DEBUG) | 60 | #if defined(LUA_DEBUG) |
| 53 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); | 61 | LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); |
| 54 | LUAI_FUNC int luaH_isdummy (Node *n); | 62 | LUAI_FUNC int luaH_isdummy (const Table *t); |
| 55 | #endif | 63 | #endif |
| 56 | 64 | ||
| 57 | 65 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 2.208 2015/09/08 16:55:43 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.209 2015/10/12 16:38:19 roberto Exp roberto $ |
| 3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -687,8 +687,8 @@ static int table_query (lua_State *L) { | |||
| 687 | t = hvalue(obj_at(L, 1)); | 687 | t = hvalue(obj_at(L, 1)); |
| 688 | if (i == -1) { | 688 | if (i == -1) { |
| 689 | lua_pushinteger(L, t->sizearray); | 689 | lua_pushinteger(L, t->sizearray); |
| 690 | lua_pushinteger(L, luaH_isdummy(t->node) ? 0 : sizenode(t)); | 690 | lua_pushinteger(L, allocsizenode(t)); |
| 691 | lua_pushinteger(L, t->lastfree - t->node); | 691 | lua_pushinteger(L, isdummy(t) ? 0 : t->lastfree - t->node); |
| 692 | } | 692 | } |
| 693 | else if ((unsigned int)i < t->sizearray) { | 693 | else if ((unsigned int)i < t->sizearray) { |
| 694 | lua_pushinteger(L, i); | 694 | lua_pushinteger(L, i); |
