diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-03 12:00:32 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-12-03 12:00:32 -0300 |
commit | c36ced53c92088748c278764acb68dfb66f353c9 (patch) | |
tree | 320af9030539f4ebad929b7f91a5768f43625341 /lauxlib.c | |
parent | d41c36bf67d6628bccd91697e7f88e55d40d3970 (diff) | |
download | lua-c36ced53c92088748c278764acb68dfb66f353c9.tar.gz lua-c36ced53c92088748c278764acb68dfb66f353c9.tar.bz2 lua-c36ced53c92088748c278764acb68dfb66f353c9.zip |
Avoid "bad programming habits" in the reference system
References were using both 0 indices and nils as values in arrays.
Both do not fit in the concept of a sequence, which is the kind
of use that guides all Lua optimizations.
Diffstat (limited to 'lauxlib.c')
-rw-r--r-- | lauxlib.c | 24 |
1 files changed, 18 insertions, 6 deletions
@@ -639,10 +639,14 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { | |||
639 | ** ======================================================= | 639 | ** ======================================================= |
640 | */ | 640 | */ |
641 | 641 | ||
642 | /* index of free-list header */ | 642 | /* index of free-list header (after the predefined values) */ |
643 | #define freelist 0 | 643 | #define freelist (LUA_RIDX_LAST + 1) |
644 | |||
645 | 644 | ||
645 | /* | ||
646 | ** The previously freed references form a linked list: | ||
647 | ** t[freelist] is the index of a first free index, or zero if list is | ||
648 | ** empty; t[t[freelist]] is the index of the second element; etc. | ||
649 | */ | ||
646 | LUALIB_API int luaL_ref (lua_State *L, int t) { | 650 | LUALIB_API int luaL_ref (lua_State *L, int t) { |
647 | int ref; | 651 | int ref; |
648 | if (lua_isnil(L, -1)) { | 652 | if (lua_isnil(L, -1)) { |
@@ -650,9 +654,16 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { | |||
650 | return LUA_REFNIL; /* 'nil' has a unique fixed reference */ | 654 | return LUA_REFNIL; /* 'nil' has a unique fixed reference */ |
651 | } | 655 | } |
652 | t = lua_absindex(L, t); | 656 | t = lua_absindex(L, t); |
653 | lua_rawgeti(L, t, freelist); /* get first free element */ | 657 | if (lua_rawgeti(L, t, freelist) == LUA_TNIL) { /* first access? */ |
654 | ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ | 658 | ref = 0; /* list is empty */ |
655 | lua_pop(L, 1); /* remove it from stack */ | 659 | lua_pushinteger(L, 0); /* initialize as an empty list */ |
660 | lua_rawseti(L, t, freelist); /* ref = t[freelist] = 0 */ | ||
661 | } | ||
662 | else { /* already initialized */ | ||
663 | lua_assert(lua_isinteger(L, -1)); | ||
664 | ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ | ||
665 | } | ||
666 | lua_pop(L, 1); /* remove element from stack */ | ||
656 | if (ref != 0) { /* any free element? */ | 667 | if (ref != 0) { /* any free element? */ |
657 | lua_rawgeti(L, t, ref); /* remove it from list */ | 668 | lua_rawgeti(L, t, ref); /* remove it from list */ |
658 | lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ | 669 | lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ |
@@ -668,6 +679,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { | |||
668 | if (ref >= 0) { | 679 | if (ref >= 0) { |
669 | t = lua_absindex(L, t); | 680 | t = lua_absindex(L, t); |
670 | lua_rawgeti(L, t, freelist); | 681 | lua_rawgeti(L, t, freelist); |
682 | lua_assert(lua_isinteger(L, -1)); | ||
671 | lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ | 683 | lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ |
672 | lua_pushinteger(L, ref); | 684 | lua_pushinteger(L, ref); |
673 | lua_rawseti(L, t, freelist); /* t[freelist] = ref */ | 685 | lua_rawseti(L, t, freelist); /* t[freelist] = ref */ |