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