浏览代码

specialized versions for luaH_set (numbers and strings)

Roberto Ierusalimschy 24 年之前
父节点
当前提交
dabb19fc17
共有 5 个文件被更改,包括 92 次插入87 次删除
  1. 3 3
      lapi.c
  2. 2 2
      ldo.c
  3. 71 57
      ltable.c
  4. 4 6
      ltable.h
  5. 12 19
      lvm.c

+ 3 - 3
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.114 2000/12/28 12:55:41 roberto Exp roberto $
+** $Id: lapi.c,v 1.115 2001/01/10 17:41:50 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -267,7 +267,7 @@ LUA_API void lua_gettable (lua_State *L, int index) {
 LUA_API void lua_rawget (lua_State *L, int index) {
   StkId t = Index(L, index);
   LUA_ASSERT(ttype(t) == LUA_TTABLE, "table expected");
-  *(L->top - 1) = *luaH_get(L, hvalue(t), L->top - 1);
+  *(L->top - 1) = *luaH_get(hvalue(t), L->top - 1);
 }
 
 
@@ -338,7 +338,7 @@ LUA_API void lua_rawset (lua_State *L, int index) {
 LUA_API void lua_rawseti (lua_State *L, int index, int n) {
   StkId o = Index(L, index);
   LUA_ASSERT(ttype(o) == LUA_TTABLE, "table expected");
-  *luaH_setint(L, hvalue(o), n) = *(L->top-1);
+  *luaH_setnum(L, hvalue(o), n) = *(L->top-1);
   L->top--;
 }
 

+ 2 - 2
ldo.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldo.c,v 1.111 2000/12/28 12:55:41 roberto Exp roberto $
+** $Id: ldo.c,v 1.112 2001/01/10 16:58:11 roberto Exp roberto $
 ** Stack and Call structure of Lua
 ** See Copyright Notice in lua.h
 */
@@ -332,7 +332,7 @@ struct lua_longjmp {
 
 
 static void message (lua_State *L, const char *s) {
-  const TObject *em = luaH_getglobal(L, LUA_ERRORMESSAGE);
+  const TObject *em = luaH_getstr(L->gt, luaS_newliteral(L, LUA_ERRORMESSAGE));
   if (ttype(em) == LUA_TFUNCTION) {
     *L->top = *em;
     incr_top;

+ 71 - 57
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.61 2000/12/22 16:57:46 roberto Exp roberto $
+** $Id: ltable.c,v 1.62 2000/12/28 12:55:41 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -23,7 +23,6 @@
 #include "lmem.h"
 #include "lobject.h"
 #include "lstate.h"
-#include "lstring.h"
 #include "ltable.h"
 
 
@@ -31,6 +30,9 @@
 #define TagDefault LUA_TTABLE
 
 
+#define hashnum(t,n)	(&t->node[(luint32)(lint32)(n)&(t->size-1)])
+#define hashstr(t,str)	(&t->node[(str)->u.s.hash&(t->size-1)])
+
 
 /*
 ** returns the `main' position of an element in a table (that is, the index
@@ -40,11 +42,9 @@ Node *luaH_mainposition (const Hash *t, const TObject *key) {
   luint32 h;
   switch (ttype(key)) {
     case LUA_TNUMBER:
-      h = (luint32)(lint32)nvalue(key);
-      break;
+      return hashnum(t, nvalue(key));
     case LUA_TSTRING:
-      h = tsvalue(key)->u.s.hash;
-      break;
+      return hashstr(t, tsvalue(key));
     case LUA_TUSERDATA:
       h = IntPoint(tsvalue(key));
       break;
@@ -57,31 +57,26 @@ Node *luaH_mainposition (const Hash *t, const TObject *key) {
     default:
       return NULL;  /* invalid key */
   }
-  LUA_ASSERT(h%(unsigned int)t->size == (h&((unsigned int)t->size-1)),
-            "a&(x-1) == a%x, for x power of 2");
   return &t->node[h&(t->size-1)];
 }
 
 
-static const TObject *luaH_getany (lua_State *L, const Hash *t,
-                                   const TObject *key) {
+static const TObject *luaH_getany (const Hash *t, const TObject *key) {
   Node *n = luaH_mainposition(t, key);
-  if (!n)
-    lua_error(L, "table index is nil");
-  else do {
+  while (n) {
     if (luaO_equalObj(key, &n->key))
       return &n->val;
     n = n->next;
-  } while (n);
+  }
   return &luaO_nilobject;  /* key not found */
 }
 
 
 /* specialized version for numbers */
 const TObject *luaH_getnum (const Hash *t, lua_Number key) {
-  Node *n = &t->node[(luint32)(lint32)key&(t->size-1)];
+  Node *n = hashnum(t, key);
   do {
-    if (ttype(&n->key) == LUA_TNUMBER && nvalue(&n->key) == key)
+    if (nvalue(&n->key) == key && ttype(&n->key) == LUA_TNUMBER)
       return &n->val;
     n = n->next;
   } while (n);
@@ -91,9 +86,9 @@ const TObject *luaH_getnum (const Hash *t, lua_Number key) {
 
 /* specialized version for strings */
 const TObject *luaH_getstr (const Hash *t, TString *key) {
-  Node *n = &t->node[key->u.s.hash&(t->size-1)];
+  Node *n = hashstr(t, key);
   do {
-    if (ttype(&n->key) == LUA_TSTRING && tsvalue(&n->key) == key)
+    if (tsvalue(&n->key) == key && ttype(&n->key) == LUA_TSTRING)
       return &n->val;
     n = n->next;
   } while (n);
@@ -101,11 +96,11 @@ const TObject *luaH_getstr (const Hash *t, TString *key) {
 }
 
 
-const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key) {
+const TObject *luaH_get (const Hash *t, const TObject *key) {
   switch (ttype(key)) {
     case LUA_TNUMBER: return luaH_getnum(t, nvalue(key));
     case LUA_TSTRING: return luaH_getstr(t, tsvalue(key));
-    default:         return luaH_getany(L, t, key);
+    default:         return luaH_getany(t, key);
   }
 }
 
@@ -115,7 +110,7 @@ Node *luaH_next (lua_State *L, const Hash *t, const TObject *key) {
   if (ttype(key) == LUA_TNIL)
     i = 0;  /* first iteration */
   else {
-    const TObject *v = luaH_get(L, t, key);
+    const TObject *v = luaH_get(t, key);
     if (v == &luaO_nilobject)
       lua_error(L, "invalid key for `next'");
     i = (int)(((const char *)v -
@@ -224,30 +219,17 @@ static void rehash (lua_State *L, Hash *t) {
 
 
 /*
-** inserts a key into a hash table; first, check whether key is
-** already present; if not, check whether key's main position is free;
-** if not, check whether colliding node is in its main position or not;
-** if it is not, move colliding node to an empty place and put new key
-** in its main position; otherwise (colliding node is in its main position),
-** new key goes to an empty position.
+** inserts a new key into a hash table; first, check whether key's main 
+** position is free; if not, check whether colliding node is in its main 
+** position or not; if it is not, move colliding node to an empty place and 
+** put new key in its main position; otherwise (colliding node is in its main 
+** position), new key goes to an empty position. 
 */
-TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
-  Node *mp = luaH_mainposition(t, key);
-  Node *n = mp;
-  if (!mp)
-    lua_error(L, "table index is nil");
-  do {  /* check whether `key' is somewhere in the chain */
-    if (luaO_equalObj(key, &n->key))
-      return &n->val;  /* that's all */
-    else n = n->next;
-  } while (n);
-  /* `key' not found; must insert it */
+static TObject *newkey (lua_State *L, Hash *t, Node *mp, const TObject *key) {
   if (ttype(&mp->key) != LUA_TNIL) {  /* main position is not free? */
-    Node *othern;  /* main position of colliding node */
-    n = t->firstfree;  /* get a free place */
-    /* is colliding node out of its main position? (can only happens if
-       its position is after "firstfree") */
-    if (mp > n && (othern=luaH_mainposition(t, &mp->key)) != mp) {
+    Node *othern = luaH_mainposition(t, &mp->key);  /* `mp' of colliding node */
+    Node *n = t->firstfree;  /* get a free place */
+    if (othern != mp) {  /* is colliding node out of its main position? */
       /* yes; move colliding node into free position */
       while (othern->next != mp) othern = othern->next;  /* find previous */
       othern->next = n;  /* redo the chain with `n' in place of `mp' */
@@ -273,25 +255,57 @@ TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
 }
 
 
-TObject *luaH_setint (lua_State *L, Hash *t, int key) {
-  TObject index;
-  ttype(&index) = LUA_TNUMBER;
-  nvalue(&index) = key;
-  return luaH_set(L, t, &index);
+static TObject *luaH_setany (lua_State *L, Hash *t, const TObject *key) {
+  Node *mp = luaH_mainposition(t, key);
+  Node *n = mp;
+  if (!mp)
+    lua_error(L, "table index is nil");
+  do {  /* check whether `key' is somewhere in the chain */
+    if (luaO_equalObj(key, &n->key))
+      return &n->val;  /* that's all */
+    else n = n->next;
+  } while (n);
+  return newkey(L, t, mp, key);  /* `key' not found; must insert it */
+}
+
+
+TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key) {
+  TObject kobj;
+  Node *mp = hashnum(t, key);
+  Node *n = mp;
+  do {  /* check whether `key' is somewhere in the chain */
+    if (nvalue(&n->key) == key && ttype(&n->key) == LUA_TNUMBER)
+      return &n->val;  /* that's all */
+    else n = n->next;
+  } while (n);
+  /* `key' not found; must insert it */
+  ttype(&kobj) = LUA_TNUMBER;
+  nvalue(&kobj) = key;
+  return newkey(L, t, mp, &kobj);
 }
 
 
-void luaH_setstrnum (lua_State *L, Hash *t, TString *key, lua_Number val) {
-  TObject *value, index;
-  ttype(&index) = LUA_TSTRING;
-  tsvalue(&index) = key;
-  value = luaH_set(L, t, &index);
-  ttype(value) = LUA_TNUMBER;
-  nvalue(value) = val;
+TObject *luaH_setstr (lua_State *L, Hash *t, TString *key) {
+  TObject kobj;
+  Node *mp = hashstr(t, key);
+  Node *n = mp;
+  do {  /* check whether `key' is somewhere in the chain */
+    if (tsvalue(&n->key) == key && ttype(&n->key) == LUA_TSTRING)
+      return &n->val;  /* that's all */
+    else n = n->next;
+  } while (n);
+  /* `key' not found; must insert it */
+  ttype(&kobj) = LUA_TSTRING;
+  tsvalue(&kobj) = key;
+  return newkey(L, t, mp, &kobj);
 }
 
 
-const TObject *luaH_getglobal (lua_State *L, const char *name) {
-  return luaH_getstr(L->gt, luaS_new(L, name));
+TObject *luaH_set (lua_State *L, Hash *t, const TObject *key) {
+  switch (ttype(key)) {
+    case LUA_TNUMBER: return luaH_setnum(L, t, nvalue(key));
+    case LUA_TSTRING: return luaH_setstr(L, t, tsvalue(key));
+    default:         return luaH_setany(L, t, key);
+  }
 }
 

+ 4 - 6
ltable.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.h,v 1.25 2000/11/24 17:39:56 roberto Exp roberto $
+** $Id: ltable.h,v 1.26 2000/12/04 18:33:40 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -16,16 +16,14 @@
 
 Hash *luaH_new (lua_State *L, int nhash);
 void luaH_free (lua_State *L, Hash *t);
-const TObject *luaH_get (lua_State *L, const Hash *t, const TObject *key);
+const TObject *luaH_get (const Hash *t, const TObject *key);
 const TObject *luaH_getnum (const Hash *t, lua_Number key);
 const TObject *luaH_getstr (const Hash *t, TString *key);
 void luaH_remove (Hash *t, TObject *key);
 TObject *luaH_set (lua_State *L, Hash *t, const TObject *key);
 Node * luaH_next (lua_State *L, const Hash *t, const TObject *r);
-TObject *luaH_setint (lua_State *L, Hash *t, int key);
-void luaH_setstrnum (lua_State *L, Hash *t, TString *key, lua_Number val);
-luint32 luaH_hash (lua_State *L, const TObject *key);
-const TObject *luaH_getglobal (lua_State *L, const char *name);
+TObject *luaH_setnum (lua_State *L, Hash *t, lua_Number key);
+TObject *luaH_setstr (lua_State *L, Hash *t, TString *key);
 
 /* exported only for debugging */
 Node *luaH_mainposition (const Hash *t, const TObject *key);

+ 12 - 19
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 1.149 2000/12/28 12:55:41 roberto Exp roberto $
+** $Id: lvm.c,v 1.150 2001/01/10 17:41:50 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -122,7 +122,7 @@ const TObject *luaV_gettable (lua_State *L, StkId t) {
       ((tg = hvalue(t)->htag) == LUA_TTABLE ||  /* with default tag? */
         luaT_gettm(L, tg, TM_GETTABLE) == NULL)) { /* or no TM? */
     /* do a primitive get */
-    const TObject *h = luaH_get(L, hvalue(t), L->top-1);
+    const TObject *h = luaH_get(hvalue(t), L->top-1);
     /* result is no nil or there is no `index' tag method? */
     if (ttype(h) != LUA_TNIL || ((tm=luaT_gettm(L, tg, TM_INDEX)) == NULL))
       return h;  /* return result */
@@ -195,21 +195,11 @@ const TObject *luaV_getglobal (lua_State *L, TString *s) {
 
 
 void luaV_setglobal (lua_State *L, TString *s) {
-  const TObject *oldvalue = luaH_getstr(L->gt, s);
+  TObject *oldvalue = luaH_setstr(L, L->gt, s);
   Closure *tm = luaT_gettmbyObj(L, oldvalue, TM_SETGLOBAL);
-  if (tm == NULL) {  /* is there a tag method? */
-    if (oldvalue != &luaO_nilobject) {
-      /* cast to remove `const' is OK, because `oldvalue' != luaO_nilobject */
-      *(TObject *)oldvalue = *(L->top - 1);
-    }
-    else {
-      TObject key;
-      ttype(&key) = LUA_TSTRING;
-      tsvalue(&key) = s;
-      *luaH_set(L, L->gt, &key) = *(L->top - 1);
-    }
-  }
-  else {
+  if (tm == NULL)  /* no tag methods? */
+    *oldvalue = *(L->top - 1);  /* raw set */
+  else {  /* call tag method */
     luaD_checkstack(L, 3);
     *(L->top+2) = *(L->top-1);  /* new value */
     *(L->top+1) = *oldvalue;
@@ -320,12 +310,15 @@ void luaV_strconc (lua_State *L, int total, StkId top) {
 
 
 static void luaV_pack (lua_State *L, StkId firstelem) {
+  TObject *nf;
   int i;
   Hash *htab = luaH_new(L, 0);
   for (i=0; firstelem+i<L->top; i++)
-    *luaH_setint(L, htab, i+1) = *(firstelem+i);
+    *luaH_setnum(L, htab, i+1) = *(firstelem+i);
   /* store counter in field `n' */
-  luaH_setstrnum(L, htab, luaS_newliteral(L, "n"), i);
+  nf = luaH_setstr(L, htab, luaS_newliteral(L, "n"));
+  ttype(nf) = LUA_TNUMBER;
+  nvalue(nf) = i;
   L->top = firstelem;  /* remove elements from the stack */
   ttype(L->top) = LUA_TTABLE;
   hvalue(L->top) = htab;
@@ -498,7 +491,7 @@ StkId luaV_execute (lua_State *L, const Closure *cl, StkId base) {
         Hash *arr = hvalue(top-n-1);
         L->top = top-n;  /* final value of `top' (in case of errors) */
         for (; n; n--)
-          *luaH_setint(L, arr, n+aux) = *(--top);
+          *luaH_setnum(L, arr, n+aux) = *(--top);
         break;
       }
       case OP_SETMAP: {