Browse Source

first implementation of independent global table per function

Roberto Ierusalimschy 23 năm trước cách đây
mục cha
commit
3941af53ad
9 tập tin đã thay đổi với 121 bổ sung66 xóa
  1. 51 11
      lapi.c
  2. 39 27
      lbaselib.c
  3. 3 3
      ldo.c
  4. 3 2
      lfunc.c
  5. 2 2
      lfunc.h
  6. 10 9
      lgc.c
  7. 3 2
      lobject.h
  8. 4 4
      lua.h
  9. 6 6
      lvm.c

+ 51 - 11
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);
 }
 
 

+ 39 - 27
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},

+ 3 - 3
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);
   }

+ 3 - 2
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;
 }

+ 2 - 2
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);

+ 10 - 9
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; i<cl->l.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);

+ 3 - 2
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)
 
 
 /*

+ 4 - 4
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:[email protected]
@@ -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))
 

+ 6 - 6
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<nup; j++, pc++) {
           if (GET_OPCODE(*pc) == OP_GETUPVAL)