From 3941af53adee868e2cccfb9b85783aba9ac311c1 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 20 Jun 2002 17:41:46 -0300 Subject: [PATCH] first implementation of independent global table per function --- lapi.c | 62 +++++++++++++++++++++++++++++++++++++++++--------- lbaselib.c | 66 ++++++++++++++++++++++++++++++++---------------------- ldo.c | 6 ++--- lfunc.c | 5 +++-- lfunc.h | 4 ++-- lgc.c | 19 ++++++++-------- lobject.h | 5 +++-- lua.h | 8 +++---- lvm.c | 12 +++++----- 9 files changed, 121 insertions(+), 66 deletions(-) diff --git a/lapi.c b/lapi.c index 0d27a7e8..f4f56602 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.199 2002/06/13 13:44:50 roberto Exp roberto $ +** $Id: lapi.c,v 1.200 2002/06/18 15:19:27 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -487,6 +487,29 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex) { } +static LClosure *getfunc (lua_State *L, int level) { + CallInfo *ci; + TObject *f; + if (L->ci - L->base_ci < level) ci = L->base_ci; + else ci = L->ci - level; + f = ci->base - 1; + if (isLfunction(f)) + return &clvalue(f)->l; + else + return NULL; +} + + +LUA_API void lua_getglobals (lua_State *L, int level) { + LClosure *f; + lua_lock(L); + f = getfunc(L, level); + setobj(L->top, (f ? &f->g : gt(L))); + api_incr_top(L); + lua_unlock(L); +} + + /* ** set functions (stack -> Lua) */ @@ -527,27 +550,44 @@ LUA_API void lua_rawseti (lua_State *L, int index, int n) { } -LUA_API void lua_setmetatable (lua_State *L, int objindex) { - StkId obj, mt; +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TObject *obj, *mt; + int res = 1; lua_lock(L); api_checknelems(L, 1); obj = luaA_index(L, objindex); - mt = --L->top; - if (ttype(mt) == LUA_TNIL) - mt = defaultmeta(L); + mt = (ttype(L->top - 1) != LUA_TNIL) ? L->top - 1 : defaultmeta(L); api_check(L, ttype(mt) == LUA_TTABLE); switch (ttype(obj)) { - case LUA_TTABLE: + case LUA_TTABLE: { hvalue(obj)->metatable = hvalue(mt); break; - case LUA_TUSERDATA: + } + case LUA_TUSERDATA: { uvalue(obj)->uv.metatable = hvalue(mt); break; - default: - luaG_runerror(L, "cannot change the meta table of a %s", - luaT_typenames[ttype(obj)]); + } + default: { + res = 0; /* cannot set */ + break; + } } + L->top--; lua_unlock(L); + return res; +} + + +LUA_API int lua_setglobals (lua_State *L, int level) { + LClosure *f; + lua_lock(L); + api_checknelems(L, 1); + f = getfunc(L, level); + L->top--; + api_check(L, ttype(L->top) == LUA_TTABLE); + if (f) f->g = *(L->top); + lua_unlock(L); + return (f != NULL); } diff --git a/lbaselib.c b/lbaselib.c index 14843ace..67d95f8e 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.81 2002/06/13 13:44:50 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.82 2002/06/18 15:19:27 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -81,41 +81,51 @@ static int luaB_error (lua_State *L) { } -static int luaB_metatable (lua_State *L) { +static int luaB_getmetatable (lua_State *L) { luaL_check_any(L, 1); - if (lua_isnone(L, 2)) { - if (!lua_getmetatable(L, 1)) - return 0; /* no metatable */ - else { - lua_pushliteral(L, "__metatable"); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) - lua_pop(L, 1); - } - } + if (!lua_getmetatable(L, 1)) + return 0; /* no metatable */ else { - int t = lua_type(L, 2); - luaL_check_type(L, 1, LUA_TTABLE); - luaL_arg_check(L, t == LUA_TNIL || t == LUA_TTABLE, 2, - "nil or table expected"); - lua_settop(L, 2); - lua_setmetatable(L, 1); + lua_pushliteral(L, "__metatable"); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) + lua_pop(L, 1); + /* otherwise returns metatable.__metatable */ } return 1; } -static int luaB_globals (lua_State *L) { - lua_getglobals(L); /* value to be returned */ - if (!lua_isnoneornil(L, 1)) { - luaL_check_type(L, 1, LUA_TTABLE); - lua_pushvalue(L, 1); /* new table of globals */ - lua_setglobals(L); - } +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_check_type(L, 1, LUA_TTABLE); + luaL_arg_check(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_setmetatable(L, 1); return 1; } +static int luaB_getglobals (lua_State *L) { + int level = luaL_opt_int(L, 1, 1); + luaL_arg_check(L, level >= 1, 2, "level must be positive"); + lua_getglobals(L, level); /* value to be returned */ + return 1; +} + + +static int luaB_setglobals (lua_State *L) { + int level = luaL_opt_int(L, 2, 1); + luaL_arg_check(L, level >= 1, 2, "level must be positive"); + luaL_check_type(L, 1, LUA_TTABLE); + lua_settop(L, 1); + if (lua_setglobals(L, level) == 0) + luaL_error(L, "cannot change global table at level %d", level); + return 0; +} + + static int luaB_rawequal (lua_State *L) { luaL_check_any(L, 1); luaL_check_any(L, 2); @@ -385,8 +395,10 @@ static int luaB_require (lua_State *L) { static const luaL_reg base_funcs[] = { {"error", luaB_error}, - {"metatable", luaB_metatable}, - {"globals", luaB_globals}, + {"getmetatable", luaB_getmetatable}, + {"setmetatable", luaB_setmetatable}, + {"getglobals", luaB_getglobals}, + {"setglobals", luaB_setglobals}, {"next", luaB_next}, {"nexti", luaB_nexti}, {"print", luaB_print}, diff --git a/ldo.c b/ldo.c index be9b3d4d..616a8e75 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.181 2002/06/18 17:10:43 roberto Exp roberto $ +** $Id: ldo.c,v 1.182 2002/06/18 17:42:52 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -407,7 +407,7 @@ struct SParser { /* data to `f_parser' */ static void f_parser (lua_State *L, void *ud) { struct SParser *p = cast(struct SParser *, ud); Proto *tf = p->bin ? luaU_undump(L, p->z) : luaY_parser(L, p->z); - Closure *cl = luaF_newLclosure(L, 0); + Closure *cl = luaF_newLclosure(L, 0, gt(L)); cl->l.p = tf; setclvalue(L->top, cl); incr_top(L); @@ -467,8 +467,8 @@ static void seterrorobj (lua_State *L, int errcode, TObject *m) { void luaD_throw (lua_State *L, int errcode) { - seterrorobj(L, errcode, L->errorJmp->err); if (L->errorJmp) { + seterrorobj(L, errcode, L->errorJmp->err); L->errorJmp->status = errcode; longjmp(L->errorJmp->b, 1); } diff --git a/lfunc.c b/lfunc.c index 720fb6e4..e973d850 100644 --- a/lfunc.c +++ b/lfunc.c @@ -1,5 +1,5 @@ /* -** $Id: lfunc.c,v 1.55 2002/03/25 17:47:14 roberto Exp roberto $ +** $Id: lfunc.c,v 1.56 2002/05/02 13:06:20 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -34,12 +34,13 @@ Closure *luaF_newCclosure (lua_State *L, int nelems) { } -Closure *luaF_newLclosure (lua_State *L, int nelems) { +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt) { Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); c->l.isC = 0; c->c.next = G(L)->rootcl; G(L)->rootcl = c; c->l.marked = 0; + c->l.g = *gt; c->l.nupvalues = cast(lu_byte, nelems); return c; } diff --git a/lfunc.h b/lfunc.h index f57df4c2..9daf115c 100644 --- a/lfunc.h +++ b/lfunc.h @@ -1,5 +1,5 @@ /* -** $Id: lfunc.h,v 1.17 2001/10/02 16:45:03 roberto Exp $ +** $Id: lfunc.h,v 1.19 2001/11/29 20:22:22 roberto Exp roberto $ ** Auxiliary functions to manipulate prototypes and closures ** See Copyright Notice in lua.h */ @@ -13,7 +13,7 @@ Proto *luaF_newproto (lua_State *L); Closure *luaF_newCclosure (lua_State *L, int nelems); -Closure *luaF_newLclosure (lua_State *L, int nelems); +Closure *luaF_newLclosure (lua_State *L, int nelems, TObject *gt); UpVal *luaF_findupval (lua_State *L, StkId level); void luaF_close (lua_State *L, StkId level); void luaF_freeproto (lua_State *L, Proto *f); diff --git a/lgc.c b/lgc.c index 3ca610e6..3f9bcf86 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.135 2002/04/23 15:04:39 roberto Exp roberto $ +** $Id: lgc.c,v 1.136 2002/05/08 17:34:23 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -72,6 +72,14 @@ static void protomark (Proto *f) { } +static void marktable (GCState *st, Table *h) { + if (!ismarked(h)) { + h->mark = st->tmark; /* chain it for later traversal */ + st->tmark = h; + } +} + + static void markclosure (GCState *st, Closure *cl) { if (!cl->c.marked) { cl->c.marked = 1; @@ -83,6 +91,7 @@ static void markclosure (GCState *st, Closure *cl) { else { int i; lua_assert(cl->l.nupvalues == cl->l.p->nupvalues); + marktable(st, hvalue(&cl->l.g)); protomark(cl->l.p); for (i=0; il.nupvalues; i++) { /* mark its upvalues */ UpVal *u = cl->l.upvals[i]; @@ -96,14 +105,6 @@ static void markclosure (GCState *st, Closure *cl) { } -static void marktable (GCState *st, Table *h) { - if (!ismarked(h)) { - h->mark = st->tmark; /* chain it for later traversal */ - st->tmark = h; - } -} - - static void markudata (GCState *st, Udata *u) { markud(u); marktable(st, u->uv.metatable); diff --git a/lobject.h b/lobject.h index 8438881f..75610c99 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 1.134 2002/06/12 14:56:22 roberto Exp roberto $ +** $Id: lobject.h,v 1.135 2002/06/13 13:39:55 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -178,6 +178,7 @@ typedef struct LClosure { lu_byte marked; union Closure *next; /* first four fields must be equal to CClosure!! */ struct Proto *p; + TObject g; /* global table for this closure */ UpVal *upvals[1]; } LClosure; @@ -189,7 +190,7 @@ typedef union Closure { #define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) - +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) /* diff --git a/lua.h b/lua.h index fd2856e8..a14d00d7 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.140 2002/06/13 13:44:50 roberto Exp roberto $ +** $Id: lua.h,v 1.141 2002/06/18 15:19:27 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil ** http://www.lua.org mailto:info@lua.org @@ -169,6 +169,7 @@ LUA_API void lua_rawget (lua_State *L, int index); LUA_API void lua_rawgeti (lua_State *L, int index, int n); LUA_API void lua_newtable (lua_State *L); LUA_API int lua_getmetatable (lua_State *L, int objindex); +LUA_API void lua_getglobals (lua_State *L, int level); /* @@ -177,7 +178,8 @@ LUA_API int lua_getmetatable (lua_State *L, int objindex); LUA_API void lua_settable (lua_State *L, int index); LUA_API void lua_rawset (lua_State *L, int index); LUA_API void lua_rawseti (lua_State *L, int index, int n); -LUA_API void lua_setmetatable (lua_State *L, int objindex); +LUA_API int lua_setmetatable (lua_State *L, int objindex); +LUA_API int lua_setglobals (lua_State *L, int level); /* @@ -259,8 +261,6 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size); LUA_API int lua_pushupvalues (lua_State *L); #define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) -#define lua_getglobals(L) lua_pushvalue(L, LUA_GLOBALSINDEX) -#define lua_setglobals(L) lua_replace(L, LUA_GLOBALSINDEX) #define lua_setglobal(L,s) \ (lua_pushstring(L, s), lua_insert(L, -2), lua_settable(L, LUA_GLOBALSINDEX)) diff --git a/lvm.c b/lvm.c index 501c22be..9aeab5b4 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 1.238 2002/06/13 13:39:55 roberto Exp roberto $ +** $Id: lvm.c,v 1.239 2002/06/14 17:21:32 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -401,8 +401,8 @@ StkId luaV_execute (lua_State *L) { break; } case OP_GETGLOBAL: { - lua_assert(ttype(KBx(i)) == LUA_TSTRING); - luaV_gettable(L, gt(L), KBx(i), ra); + lua_assert(ttype(KBx(i)) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE); + luaV_gettable(L, &cl->g, KBx(i), ra); break; } case OP_GETTABLE: { @@ -410,8 +410,8 @@ StkId luaV_execute (lua_State *L) { break; } case OP_SETGLOBAL: { - lua_assert(ttype(KBx(i)) == LUA_TSTRING); - luaV_settable(L, gt(L), KBx(i), ra); + lua_assert(ttype(KBx(i)) == LUA_TSTRING && ttype(&cl->g) == LUA_TTABLE); + luaV_settable(L, &cl->g, KBx(i), ra); break; } case OP_SETUPVAL: { @@ -642,7 +642,7 @@ StkId luaV_execute (lua_State *L) { int nup, j; p = cl->p->p[GETARG_Bx(i)]; nup = p->nupvalues; - ncl = luaF_newLclosure(L, nup); + ncl = luaF_newLclosure(L, nup, &cl->g); ncl->l.p = p; for (j=0; j