Bläddra i källkod

new implementation for global variable values (separated from strings)

Roberto Ierusalimschy 26 år sedan
förälder
incheckning
cde179b369
12 ändrade filer med 166 tillägg och 145 borttagningar
  1. 28 39
      lapi.c
  2. 2 4
      lapi.h
  3. 35 26
      lbuiltin.c
  4. 2 3
      ldo.c
  5. 18 15
      lgc.c
  6. 16 11
      lobject.h
  7. 10 1
      lparser.c
  8. 2 2
      lstate.h
  9. 37 29
      lstring.c
  10. 3 2
      lstring.h
  11. 10 10
      lvm.c
  12. 3 3
      lvm.h

+ 28 - 39
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.53 1999/10/11 16:13:11 roberto Exp roberto $
+** $Id: lapi.c,v 1.54 1999/10/14 19:13:31 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -60,18 +60,6 @@ static const TObject *luaA_protovalue (const TObject *o) {
 }
 
 
-void luaA_packresults (void) {
-  luaV_pack(L->Cstack.lua2C, L->Cstack.num, L->stack.top);
-  incr_top;
-}
-
-
-int luaA_passresults (void) {
-  L->Cstack.base = L->Cstack.lua2C;  /* position of first result */
-  return L->Cstack.num;
-}
-
-
 static void checkCparams (int nParams) {
   if (L->stack.top-L->stack.stack < L->Cstack.base+nParams)
     lua_error("API error - wrong number of arguments in C2lua stack");
@@ -191,28 +179,28 @@ lua_Object lua_createtable (void) {
 
 lua_Object lua_getglobal (const char *name) {
   luaD_checkstack(2);  /* may need that to call T.M. */
-  luaV_getglobal(luaS_new(name));
+  luaV_getglobal(luaS_assertglobalbyname(name));
   return luaA_putObjectOnTop();
 }
 
 
 lua_Object lua_rawgetglobal (const char *name) {
-  TaggedString *ts = luaS_new(name);
-  return put_luaObject(&ts->u.s.globalval);
+  GlobalVar *gv = luaS_assertglobalbyname(name);
+  return put_luaObject(&gv->value);
 }
 
 
 void lua_setglobal (const char *name) {
   checkCparams(1);
   luaD_checkstack(2);  /* may need that to call T.M. */
-  luaV_setglobal(luaS_new(name));
+  luaV_setglobal(luaS_assertglobalbyname(name));
 }
 
 
 void lua_rawsetglobal (const char *name) {
-  TaggedString *ts = luaS_new(name);
+  GlobalVar *gv = luaS_assertglobalbyname(name);
   checkCparams(1);
-  luaS_rawsetglobal(ts, --L->stack.top);
+  gv->value = *(--L->stack.top);
 }
 
 
@@ -274,7 +262,7 @@ long lua_strlen (lua_Object object) {
 void *lua_getuserdata (lua_Object object) {
   if (object == LUA_NOOBJECT || ttype(Address(object)) != LUA_T_USERDATA)
     return NULL;
-  else return tsvalue(Address(object))->u.d.v;
+  else return tsvalue(Address(object))->u.d.value;
 }
 
 lua_CFunction lua_getcfunction (lua_Object object) {
@@ -388,31 +376,32 @@ void lua_settag (int tag) {
 }
 
 
-TaggedString *luaA_nextvar (TaggedString *g) {
-  if (g == NULL)
-    g = L->rootglobal;  /* first variable */
+GlobalVar *luaA_nextvar (TaggedString *ts) {
+  GlobalVar *gv;
+  if (ts == NULL)
+    gv = L->rootglobal;  /* first variable */
   else {
     /* check whether name is in global var list */
-    luaL_arg_check(g != g->nextglobal, 1, "variable name expected");
-    g = g->nextglobal;  /* get next */
+    luaL_arg_check(ts->u.s.gv, 1, "variable name expected");
+    gv = ts->u.s.gv->next;  /* get next */
   }
-  while (g && g->u.s.globalval.ttype == LUA_T_NIL)  /* skip globals with nil */
-    g = g->nextglobal;
-  if (g) {
-    ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = g;
+  while (gv && gv->value.ttype == LUA_T_NIL)  /* skip globals with nil */
+    gv = gv->next;
+  if (gv) {
+    ttype(L->stack.top) = LUA_T_STRING; tsvalue(L->stack.top) = gv->name;
     incr_top;
-    luaA_pushobject(&g->u.s.globalval);
+    luaA_pushobject(&gv->value);
   }
-  return g;
+  return gv;
 }
 
 
 const char *lua_nextvar (const char *varname) {
-  TaggedString *g = (varname == NULL) ? NULL : luaS_new(varname);
-  g = luaA_nextvar(g);
-  if (g) {
+  TaggedString *ts = (varname == NULL) ? NULL : luaS_new(varname);
+  GlobalVar *gv = luaA_nextvar(ts);
+  if (gv) {
     top2LC(2);
-    return g->str;
+    return gv->name->str;
   }
   else {
     top2LC(0);
@@ -577,11 +566,11 @@ static int checkfunc (TObject *o) {
 
 const char *lua_getobjname (lua_Object o, const char **name) {
   /* try to find a name for given function */
-  TaggedString *g;
+  GlobalVar *g;
   set_normalized(L->stack.top, Address(o)); /* to be accessed by "checkfunc" */
-  for (g=L->rootglobal; g; g=g->nextglobal) {
-    if (checkfunc(&g->u.s.globalval)) {
-      *name = g->str;
+  for (g=L->rootglobal; g; g=g->next) {
+    if (checkfunc(&g->value)) {
+      *name = g->name->str;
       return "global";
     }
   }

+ 2 - 4
lapi.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.h,v 1.6 1999/09/20 14:57:29 roberto Exp roberto $
+** $Id: lapi.h,v 1.7 1999/09/21 16:10:13 roberto Exp roberto $
 ** Auxiliary functions from Lua API
 ** See Copyright Notice in lua.h
 */
@@ -14,9 +14,7 @@
 
 TObject *luaA_Address (lua_Object o);
 void luaA_pushobject (const TObject *o);
-void luaA_packresults (void);
-int luaA_passresults (void);
-TaggedString *luaA_nextvar (TaggedString *g);
+GlobalVar *luaA_nextvar (TaggedString *g);
 int luaA_next (const Hash *t, int i);
 lua_Object luaA_putObjectOnTop (void);
 

+ 35 - 26
lbuiltin.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbuiltin.c,v 1.68 1999/10/19 13:33:22 roberto Exp roberto $
+** $Id: lbuiltin.c,v 1.69 1999/10/26 10:53:40 roberto Exp roberto $
 ** Built-in functions
 ** See Copyright Notice in lua.h
 */
@@ -35,10 +35,9 @@
 
 
 static void pushtagstring (TaggedString *s) {
-  TObject o;
-  o.ttype = LUA_T_STRING;
-  o.value.ts = s;
-  luaA_pushobject(&o);
+  ttype(L->stack.top) = LUA_T_STRING;
+  tsvalue(L->stack.top) = s;
+  incr_top;
 }
 
 
@@ -107,7 +106,7 @@ static void error_message (void) {
 
 
 /*
-** If your system does not support "stdout", just remove this function.
+** If your system does not support "stdout", you can just remove this function.
 ** If you need, you can define your own "print" function, following this
 ** model but changing "fputs" to put the strings at a proper place
 ** (a console window or a log file, for instance).
@@ -264,22 +263,29 @@ static void luaB_type (void) {
 ** =======================================================
 */
 
+
+static void passresults (void) {
+  L->Cstack.base = L->Cstack.lua2C;  /* position of first result */
+  if (L->Cstack.num == 0)
+    lua_pushuserdata(NULL);  /* at least one result to signal no errors */
+}
+
 static void luaB_dostring (void) {
   long l;
   const char *s = luaL_check_lstr(1, &l);
   if (*s == ID_CHUNK)
     lua_error("`dostring' cannot run pre-compiled code");
   if (lua_dobuffer(s, l, luaL_opt_string(2, s)) == 0)
-    if (luaA_passresults() == 0)
-      lua_pushuserdata(NULL);  /* at least one result to signal no errors */
+    passresults();
+  /* else return no value */
 }
 
 
 static void luaB_dofile (void) {
   const char *fname = luaL_opt_string(1, NULL);
   if (lua_dofile(fname) == 0)
-    if (luaA_passresults() == 0)
-      lua_pushuserdata(NULL);  /* at least one result to signal no errors */
+    passresults();
+  /* else return no value */
 }
 
 
@@ -312,10 +318,12 @@ static void luaB_call (void) {
       lua_error(NULL);
   }
   else {  /* no errors */
-    if (strchr(options, 'p'))
-      luaA_packresults();
+    if (strchr(options, 'p')) {  /* pack results? */
+      luaV_pack(L->Cstack.lua2C, L->Cstack.num, L->stack.top);
+      incr_top;
+    }
     else
-      luaA_passresults();
+      L->Cstack.base = L->Cstack.lua2C;  /* position of first result */
   }
 }
 
@@ -373,7 +381,7 @@ static void luaB_tostring (void) {
       sprintf(buff, "function: %p", (void *)o->value.f);
       break;
     case LUA_T_USERDATA:
-      sprintf(buff, "userdata: %p", o->value.ts->u.d.v);
+      sprintf(buff, "userdata: %p", o->value.ts->u.d.value);
       break;
     case LUA_T_NIL:
       lua_pushstring("nil");
@@ -449,23 +457,23 @@ static void luaB_foreach (void) {
 
 
 static void luaB_foreachvar (void) {
-  TaggedString *s;
+  GlobalVar *gv;
   TObject f;  /* see comment in 'foreachi' */
   f = *luaA_Address(luaL_functionarg(1));
   luaD_checkstack(4);  /* for extra var name, f, var name, and globalval */
-  for (s = L->rootglobal; s; s = s->nextglobal) {
-    if (s->u.s.globalval.ttype != LUA_T_NIL) {
-      pushtagstring(s);  /* keep (extra) s on stack to avoid GC */
+  for (gv = L->rootglobal; gv; gv = gv->next) {
+    if (gv->value.ttype != LUA_T_NIL) {
+      pushtagstring(gv->name);  /* keep (extra) name on stack to avoid GC */
       *(L->stack.top++) = f;
-      pushtagstring(s);
-      *(L->stack.top++) = s->u.s.globalval;
+      pushtagstring(gv->name);
+      *(L->stack.top++) = gv->value;
       luaD_calln(2, 1);
       if (ttype(L->stack.top-1) != LUA_T_NIL) {
         L->stack.top--;
-        *(L->stack.top-1) = *L->stack.top;  /* remove extra `s' */
+        *(L->stack.top-1) = *L->stack.top;  /* remove extra name */
         return;
       }
-      L->stack.top-=2;  /* remove result and extra `s' */
+      L->stack.top-=2;  /* remove result and extra name */
     }
   }
 }
@@ -507,7 +515,8 @@ static void luaB_tremove (void) {
 }
 
 
-/* {
+/*
+** {======================================================
 ** Quicksort
 */
 
@@ -593,11 +602,10 @@ static void luaB_sort (void) {
   lua_pushobject(t);
 }
 
-/* }}===================================================== */
+/* }====================================================== */
 
 
-/*
-** ====================================================== */
+/* }====================================================== */
 
 
 
@@ -605,6 +613,7 @@ static void luaB_sort (void) {
 /*
 ** {======================================================
 ** some DEBUG functions
+** (for internal debugging of the Lua implementation)
 ** =======================================================
 */
 

+ 2 - 3
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.49 1999/10/14 17:53:35 roberto Exp roberto $
+** $Id: ldo.c,v 1.50 1999/10/14 19:46:57 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -219,7 +219,7 @@ void luaD_calln (int nArgs, int nResults) {
 
 
 static void message (const char *s) {
-  const TObject *em = &(luaS_new("_ERRORMESSAGE")->u.s.globalval);
+  const TObject *em = &(luaS_assertglobalbyname("_ERRORMESSAGE")->value);
   if (ttype(em) == LUA_T_PROTO || ttype(em) == LUA_T_CPROTO ||
       ttype(em) == LUA_T_CLOSURE) {
     *L->stack.top = *em;
@@ -237,7 +237,6 @@ void lua_error (const char *s) {
   if (L->errorJmp)
     longjmp(L->errorJmp->b, 1);
   else {
-    LUA_INTERNALERROR("exit!!");
     message("exit(1). Unable to recover.\n");
     exit(1);
   }

+ 18 - 15
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.28 1999/10/11 16:13:11 roberto Exp roberto $
+** $Id: lgc.c,v 1.29 1999/10/14 19:13:31 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -62,13 +62,13 @@ static void hashmark (Hash *h) {
 }
 
 
-static void globalmark (void) {
-  TaggedString *g;
-  for (g=L->rootglobal; g; g=g->nextglobal) {
-    LUA_ASSERT(g->constindex >= 0, "userdata in global list");
-    if (g->u.s.globalval.ttype != LUA_T_NIL) {
-      markobject(&g->u.s.globalval);
-      strmark(g);  /* cannot collect non nil global variables */
+static void travglobal (void) {
+  GlobalVar *gv;
+  for (gv=L->rootglobal; gv; gv=gv->next) {
+    LUA_ASSERT(gv->name->u.s.gv == gv, "inconsistent global name");
+    if (gv->value.ttype != LUA_T_NIL) {
+      strmark(gv->name);  /* cannot collect non nil global variables */
+      markobject(&gv->value);
     }
   }
 }
@@ -157,12 +157,16 @@ static void collecttable (void) {
 }
 
 
+/*
+** remove from the global list globals whose names will be collected
+** (the global itself is freed when its name is freed)
+*/
 static void clear_global_list (int limit) {
-  TaggedString **p = &L->rootglobal;
-  TaggedString *next;
+  GlobalVar **p = &L->rootglobal;
+  GlobalVar *next;
   while ((next = *p) != NULL) {
-    if (next->marked >= limit) p = &next->nextglobal;
-    else *p = next->nextglobal;
+    if (next->name->marked >= limit) p = &next->next;
+    else *p = next->next;
   }
 }
 
@@ -226,7 +230,7 @@ static void tableTM (void) {
 
 static void markall (void) {
   travstack(); /* mark stack objects */
-  globalmark();  /* mark global variable values and names */
+  travglobal();  /* mark global variable values and names */
   travlock(); /* mark locked objects */
   luaT_travtagmethods(markobject);  /* mark tag methods */
 }
@@ -239,8 +243,6 @@ void luaC_collect (int all) {
   collectstring(all?MAX_INT:1);
   collectproto();
   collectclosure();
-  if (!all)
-    luaD_gcIM(&luaO_nilobject);  /* GC tag method for nil (signal end of GC) */
 }
 
 
@@ -249,6 +251,7 @@ long lua_collectgarbage (long limit) {
   markall();
   luaR_invalidaterefs();
   luaC_collect(0);
+  luaD_gcIM(&luaO_nilobject);  /* GC tag method for nil (signal end of GC) */
   recovered = recovered - L->nblocks;
   L->GCthreshold = (limit == 0) ? 2*L->nblocks : L->nblocks+limit;
   return recovered;

+ 16 - 11
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.33 1999/10/14 19:13:31 roberto Exp roberto $
+** $Id: lobject.h,v 1.34 1999/10/19 13:33:22 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -87,25 +87,30 @@ typedef struct TObject {
 
 
 
+typedef struct GlobalVar {
+  TObject value;
+  struct GlobalVar *next;
+  struct TaggedString *name;
+} GlobalVar;
+
+
 /*
 ** String headers for string table
 */
-
 typedef struct TaggedString {
-  struct TaggedString *nexthash;  /* chain hash table */
-  struct TaggedString *nextglobal;  /* chain global variables */
-  unsigned long hash;
-  int constindex;  /* hint to reuse constants (= -1 if this is a userdata) */
   union {
-    struct {
-      TObject globalval;
-      long len;  /* if this is a string, here is its length */
+    struct {  /* for strings */
+      GlobalVar *gv;  /* eventual global value with this name */
+      long len;
     } s;
-    struct {
+    struct {  /* for userdata */
       int tag;
-      void *v;  /* if this is a userdata, here is its value */
+      void *value;
     } d;
   } u;
+  struct TaggedString *nexthash;  /* chain for hash table */
+  unsigned long hash;
+  int constindex;  /* hint to reuse constants (= -1 if this is a userdata) */
   unsigned char marked;
   char str[1];   /* \0 byte already reserved */
 } TaggedString;

+ 10 - 1
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.40 1999/09/02 13:13:22 roberto Exp roberto $
+** $Id: lparser.c,v 1.41 1999/09/20 14:15:18 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -232,6 +232,13 @@ static void code_constant (LexState *ls, int c) {
 }
 
 
+static void assertglobal (LexState *ls, int index) {
+  TObject *o = &ls->fs->f->consts[index];
+  LUA_ASSERT(ttype(o) == LUA_T_STRING, "global name is not a string");
+  luaS_assertglobal(tsvalue(o));
+}
+
+
 static int next_constant (FuncState *fs) {
   TProtoFunc *f = fs->f;
   luaM_growvector(f->consts, f->nconsts, 1, TObject, constantEM, MAX_ARG);
@@ -478,6 +485,7 @@ static void lua_pushvar (LexState *ls, vardesc *var) {
       break;
     case VGLOBAL:
       code_oparg(ls, GETGLOBAL, var->info, 1);
+      assertglobal(ls, var->info);  /* make sure that there is a global */
       break;
     case VDOT:
       code_oparg(ls, GETDOTTED, var->info, 0);
@@ -501,6 +509,7 @@ static void storevar (LexState *ls, const vardesc *var) {
       break;
     case VGLOBAL:
       code_oparg(ls, SETGLOBAL, var->info, -1);
+      assertglobal(ls, var->info);  /* make sure that there is a global */
       break;
     case VINDEXED:
       code_opcode(ls, SETTABLEPOP, -3);

+ 2 - 2
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.19 1999/05/11 20:08:20 roberto Exp roberto $
+** $Id: lstate.h,v 1.20 1999/10/04 17:51:04 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -76,7 +76,7 @@ struct lua_State {
   TProtoFunc *rootproto;  /* list of all prototypes */
   Closure *rootcl;  /* list of all closures */
   Hash *roottable;  /* list of all tables */
-  TaggedString *rootglobal;  /* list of strings with global values */
+  GlobalVar *rootglobal;  /* list of global variables */
   stringtable *string_root;  /* array of hash tables for strings and udata */
   struct IM *IMtable;  /* table for tag methods */
   int last_tag;  /* last used tag in IMtable */

+ 37 - 29
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.24 1999/10/14 19:13:31 roberto Exp roberto $
+** $Id: lstring.c,v 1.25 1999/10/19 13:33:22 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -87,7 +87,6 @@ static TaggedString *newone (long l, unsigned long h) {
                                        sizeof(TaggedString)+l*sizeof(char));
   ts->marked = 0;
   ts->nexthash = NULL;
-  ts->nextglobal = ts;  /* signal it is not in global list */
   ts->hash = h;
   return ts;
 }
@@ -97,7 +96,7 @@ static TaggedString *newone_s (const char *str, long l, unsigned long h) {
   TaggedString *ts = newone(l, h);
   memcpy(ts->str, str, l);
   ts->str[l] = 0;  /* ending 0 */
-  ts->u.s.globalval.ttype = LUA_T_NIL;  /* initialize global value */
+  ts->u.s.gv = NULL;  /* no global value */
   ts->u.s.len = l;
   ts->constindex = 0;
   L->nblocks += gcsizestring(l);
@@ -107,7 +106,7 @@ static TaggedString *newone_s (const char *str, long l, unsigned long h) {
 
 static TaggedString *newone_u (void *buff, int tag, unsigned long h) {
   TaggedString *ts = newone(0, h);
-  ts->u.d.v = buff;
+  ts->u.d.value = buff;
   ts->u.d.tag = (tag == LUA_ANYTAG) ? 0 : tag;
   ts->constindex = -1;  /* tag -> this is a userdata */
   L->nblocks++;
@@ -131,13 +130,15 @@ static void newentry (stringtable *tb, TaggedString *ts, int h) {
 }
 
 
-static TaggedString *insert_s (const char *str, long l,
-                               stringtable *tb, unsigned long h) {
+TaggedString *luaS_newlstr (const char *str, long l) {
+  unsigned long h = hash_s(str, l);
+  stringtable *tb = &L->string_root[h%NUM_HASHSTR];
   int h1 = h%tb->size;
   TaggedString *ts;
-  for (ts = tb->hash[h1]; ts; ts = ts->nexthash)
+  for (ts = tb->hash[h1]; ts; ts = ts->nexthash) {
     if (ts->u.s.len == l && (memcmp(str, ts->str, l) == 0))
       return ts;
+  }
   /* not found */
   ts = newone_s(str, l, h);  /* create new entry */
   newentry(tb, ts, h1);  /* insert it on table */
@@ -145,30 +146,22 @@ static TaggedString *insert_s (const char *str, long l,
 }
 
 
-static TaggedString *insert_u (void *buff, int tag, stringtable *tb) {
-  unsigned long h = (IntPoint)buff;
+TaggedString *luaS_createudata (void *udata, int tag) {
+  unsigned long h = (IntPoint)udata;
+  stringtable *tb = &L->string_root[(h%NUM_HASHUDATA)+NUM_HASHSTR];
   int h1 = h%tb->size;
   TaggedString *ts;
-  for (ts = tb->hash[h1]; ts; ts = ts->nexthash)
-    if ((tag == ts->u.d.tag || tag == LUA_ANYTAG) && buff == ts->u.d.v)
+  for (ts = tb->hash[h1]; ts; ts = ts->nexthash) {
+    if (udata == ts->u.d.value && (tag == ts->u.d.tag || tag == LUA_ANYTAG))
       return ts;
+  }
   /* not found */
-  ts = newone_u(buff, tag, h);
+  ts = newone_u(udata, tag, h);
   newentry(tb, ts, h1);
   return ts;
 }
 
 
-TaggedString *luaS_createudata (void *udata, int tag) {
-  int t = ((IntPoint)udata%NUM_HASHUDATA)+NUM_HASHSTR;
-  return insert_u(udata, tag, &L->string_root[t]);
-}
-
-TaggedString *luaS_newlstr (const char *str, long l) {
-  unsigned long h = hash_s(str, l);
-  return insert_s(str, l, &L->string_root[h%NUM_HASHSTR], h);
-}
-
 TaggedString *luaS_new (const char *str) {
   return luaS_newlstr(str, strlen(str));
 }
@@ -181,23 +174,38 @@ TaggedString *luaS_newfixedstring (const char *str) {
 
 
 void luaS_free (TaggedString *t) {
-  L->nblocks -= (t->constindex == -1) ? 1 : gcsizestring(t->u.s.len);
+  if (t->constindex == -1)  /* is userdata? */
+    L->nblocks--;
+  else {  /* is string */
+    L->nblocks -= gcsizestring(t->u.s.len);
+    luaM_free(t->u.s.gv);
+  }
   luaM_free(t);
 }
 
 
-void luaS_rawsetglobal (TaggedString *ts, const TObject *newval) {
-  ts->u.s.globalval = *newval;
-  if (ts->nextglobal == ts) {  /* is not in list? */
-    ts->nextglobal = L->rootglobal;
-    L->rootglobal = ts;
+GlobalVar *luaS_assertglobal (TaggedString *ts) {
+  GlobalVar *gv = ts->u.s.gv;
+  if (!gv) {  /* no global value yet? */
+    gv = luaM_new(GlobalVar);
+    gv->value.ttype = LUA_T_NIL;  /* initial value */
+    gv->name = ts;
+    gv->next = L->rootglobal;  /* chain in global list */
+    L->rootglobal = gv; 
+    ts->u.s.gv = gv;
   }
+  return gv;
+}
+
+
+GlobalVar *luaS_assertglobalbyname (const char *name) {
+  return luaS_assertglobal(luaS_new(name));
 }
 
 
 int luaS_globaldefined (const char *name) {
   TaggedString *ts = luaS_new(name);
-  return ts->u.s.globalval.ttype != LUA_T_NIL;
+  return ts->u.s.gv && ts->u.s.gv->value.ttype != LUA_T_NIL;
 }
 
 

+ 3 - 2
lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.10 1999/10/11 16:13:11 roberto Exp roberto $
+** $Id: lstring.h,v 1.11 1999/10/14 19:13:31 roberto Exp roberto $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -33,7 +33,8 @@ void luaS_free (TaggedString *ts);
 TaggedString *luaS_newlstr (const char *str, long l);
 TaggedString *luaS_new (const char *str);
 TaggedString *luaS_newfixedstring (const char *str);
-void luaS_rawsetglobal (TaggedString *ts, const TObject *newval);
+GlobalVar *luaS_assertglobal (TaggedString *ts);
+GlobalVar *luaS_assertglobalbyname (const char *name);
 int luaS_globaldefined (const char *name);
 
 

+ 10 - 10
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.63 1999/10/14 19:13:31 roberto Exp roberto $
+** $Id: lvm.c,v 1.64 1999/10/14 19:46:57 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -167,9 +167,9 @@ void luaV_rawsettable (const TObject *t) {
 }
 
 
-void luaV_getglobal (TaggedString *ts) {
+void luaV_getglobal (GlobalVar *gv) {
   /* WARNING: caller must assure stack space */
-  const TObject *value = &ts->u.s.globalval;
+  const TObject *value = &gv->value;
   switch (ttype(value)) {
     /* only userdata, tables and nil can have getglobal tag methods */
     case LUA_T_USERDATA: case LUA_T_ARRAY: case LUA_T_NIL: {
@@ -177,7 +177,7 @@ void luaV_getglobal (TaggedString *ts) {
       if (ttype(im) != LUA_T_NIL) {  /* is there a tag method? */
         struct Stack *S = &L->stack;
         ttype(S->top) = LUA_T_STRING;
-        tsvalue(S->top) = ts;
+        tsvalue(S->top) = gv->name;  /* global name */
         S->top++;
         *S->top++ = *value;
         luaD_callTM(im, 2, 1);
@@ -190,18 +190,18 @@ void luaV_getglobal (TaggedString *ts) {
 }
 
 
-void luaV_setglobal (TaggedString *ts) {
-  const TObject *oldvalue = &ts->u.s.globalval;
+void luaV_setglobal (GlobalVar *gv) {
+  const TObject *oldvalue = &gv->value;
   const TObject *im = luaT_getimbyObj(oldvalue, IM_SETGLOBAL);
   if (ttype(im) == LUA_T_NIL)  /* is there a tag method? */
-    luaS_rawsetglobal(ts, --L->stack.top);
+    gv->value = *(--L->stack.top);
   else {
     /* WARNING: caller must assure stack space */
     struct Stack *S = &L->stack;
     TObject newvalue;
     newvalue = *(S->top-1);
     ttype(S->top-1) = LUA_T_STRING;
-    tsvalue(S->top-1) = ts;
+    tsvalue(S->top-1) = gv->name;
     *S->top++ = *oldvalue;
     *S->top++ = newvalue;
     luaD_callTM(im, 3, 0);
@@ -370,7 +370,7 @@ StkId luaV_execute (const Closure *cl, const TProtoFunc *tf, StkId base) {
 
       case GETGLOBALW: aux += highbyte(*pc++);
       case GETGLOBAL:  aux += *pc++;
-        luaV_getglobal(tsvalue(&consts[aux]));
+        luaV_getglobal(tsvalue(&consts[aux])->u.s.gv);
         break;
 
       case GETTABLE:
@@ -407,7 +407,7 @@ StkId luaV_execute (const Closure *cl, const TProtoFunc *tf, StkId base) {
 
       case SETGLOBALW: aux += highbyte(*pc++);
       case SETGLOBAL:  aux += *pc++;
-        luaV_setglobal(tsvalue(&consts[aux]));
+        luaV_setglobal(tsvalue(&consts[aux])->u.s.gv);
         break;
 
       case SETTABLEPOP:

+ 3 - 3
lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 1.9 1999/08/16 20:52:00 roberto Exp roberto $
+** $Id: lvm.h,v 1.10 1999/10/14 19:46:57 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -24,8 +24,8 @@ void luaV_setn (Hash *t, int val);
 void luaV_gettable (void);
 void luaV_settable (const TObject *t);
 void luaV_rawsettable (const TObject *t);
-void luaV_getglobal (TaggedString *ts);
-void luaV_setglobal (TaggedString *ts);
+void luaV_getglobal (GlobalVar *gv);
+void luaV_setglobal (GlobalVar *gv);
 StkId luaV_execute (const Closure *cl, const TProtoFunc *tf, StkId base);
 void luaV_closure (int nelems);
 void luaV_comparison (lua_Type ttype_less, lua_Type ttype_equal,