lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Shmuel Zeigerman wrote:
I'm not sure these were the reasons.
In my case, creating an extra table per a userdata, and doing an extra table lookup per access seem to be way more expensive.

Well there's definitely no technical reason, as to modify Lua such that the env can be a whole value would only be a few line modifications. So I'm guessing it's an intentional design decision ;). Either for space savings, or for consistency. (env is limited to a table for functions etc, for obvious reasons).

As for the weak table situation, I'm pretty sure they won't leak memory. They just won't shrink, so if it's greater than 100 mbytes of ram, that was merely it's peak usage. Not a leak, per se.

But in any case, given the savings for your particular application modifying lua may be worthwhile. On my (outdated) version of lua, it'd be something like (untested):

LUA_API void lua_getfenv (lua_State *L, int idx) {
-- sethvalue(L, L->top, uvalue(o)->env);
++ setobj2s(L, L->top, &uvalue(o)->env);

LUA_API int lua_setfenv (lua_State *L, int idx) {
-- api_check(L, ttistable(L->top - 1));
++ api_check(L, ttistable(L->top - 1) || ttisuserdata(o));
-- uvalue(o)->env = hvalue(L->top - 1);
++ setobj(L, &uvalue(o)->env, L->top-1);

static void reallymarkobject (global_State *g, GCObject *o) {
-- markobject(g, gco2u(o)->env);
++ markvalue(g, &gco2u(o)->env);

Udata *luaS_newudata (lua_State *L, size_t s, Table *e) {
--  u->uv.env = e;
++  sethvalue(L, &u->uv.env, e);

static int luaB_setfenv (lua_State *L) {
++ if (lua_type(L, 1) != LUA_TUSERDATA)
 luaL_checktype(L, 2, LUA_TTABLE);

- Alex