diff options
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 */ |