Roberto Ierusalimschy 10 лет назад
Родитель
Сommit
3b795541c4
3 измененных файлов с 67 добавлено и 39 удалено
  1. 31 21
      lapi.c
  2. 18 15
      lvm.c
  3. 18 3
      lvm.h

+ 31 - 21
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.250 2015/06/18 14:19:52 roberto Exp roberto $
+** $Id: lapi.c,v 2.251 2015/07/20 18:24:50 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -731,18 +731,28 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
 ** set functions (stack -> Lua)
 */
 
+static void auxsetstr (lua_State *L, const TValue *t, const char *k) {
+  const TValue *aux;
+  TString *str = luaS_new(L, k);
+  api_checknelems(L, 1);
+  if (luaV_fastset(L, t, str, aux, luaH_getstr, L->top)) {
+    setobj2t(L, cast(TValue *, aux), L->top - 1);
+    L->top--;  /* pop value */
+  }
+  else {
+    setsvalue2s(L, L->top, str);
+    api_incr_top(L);
+    luaV_finishset(L, t, L->top - 1, L->top - 2, aux);
+    L->top -= 2;  /* pop value and key */
+  }
+  lua_unlock(L);
+}
+
 
 LUA_API void lua_setglobal (lua_State *L, const char *name) {
   Table *reg = hvalue(&G(L)->l_registry);
-  const TValue *gt;  /* global table */
   lua_lock(L);
-  api_checknelems(L, 1);
-  gt = luaH_getint(reg, LUA_RIDX_GLOBALS);
-  setsvalue2s(L, L->top, luaS_new(L, name));
-  api_incr_top(L);
-  luaV_settable(L, gt, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
-  lua_unlock(L);
+  auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name);
 }
 
 
@@ -758,27 +768,27 @@ LUA_API void lua_settable (lua_State *L, int idx) {
 
 
 LUA_API void lua_setfield (lua_State *L, int idx, const char *k) {
-  StkId t;
   lua_lock(L);
-  api_checknelems(L, 1);
-  t = index2addr(L, idx);
-  setsvalue2s(L, L->top, luaS_new(L, k));
-  api_incr_top(L);
-  luaV_settable(L, t, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
-  lua_unlock(L);
+  auxsetstr(L, index2addr(L, idx), k);
 }
 
 
 LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) {
   StkId t;
+  const TValue *aux;
   lua_lock(L);
   api_checknelems(L, 1);
   t = index2addr(L, idx);
-  setivalue(L->top, n);
-  api_incr_top(L);
-  luaV_settable(L, t, L->top - 1, L->top - 2);
-  L->top -= 2;  /* pop value and key */
+  if (luaV_fastset(L, t, n, aux, luaH_getint, L->top - 1)) {
+    setobj2t(L, cast(TValue *, aux), L->top - 1);
+    L->top--;  /* pop value */
+  }
+  else {
+    setivalue(L->top, n);
+    api_incr_top(L);
+    luaV_finishset(L, t, L->top - 1, L->top - 2, aux);
+    L->top -= 2;  /* pop value and key */
+  }
   lua_unlock(L);
 }
 

+ 18 - 15
lvm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.c,v 2.247 2015/07/04 16:31:03 roberto Exp roberto $
+** $Id: lvm.c,v 2.248 2015/07/20 18:24:50 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -184,40 +184,43 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val,
 ** Main function for table assignment (invoking metamethods if needed).
 ** Compute 't[key] = val'
 */
-void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) {
+void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
+                     StkId val, const TValue *oldval) {
   int loop;  /* counter to avoid infinite loops */
   for (loop = 0; loop < MAXTAGLOOP; loop++) {
     const TValue *tm;
-    if (ttistable(t)) {  /* 't' is a table? */
-      Table *h = hvalue(t);
-      TValue *oldval = cast(TValue *, luaH_get(h, key));
-      /* if previous value is not nil, there must be a previous entry
-         in the table; a metamethod has no relevance */
-      if (!ttisnil(oldval) ||
-         /* previous value is nil; must check the metamethod */
-         ((tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL &&
+    if (oldval != NULL) {
+      lua_assert(ttistable(t) && ttisnil(oldval));
+      /* must check the metamethod */
+      if ((tm = fasttm(L, hvalue(t)->metatable, TM_NEWINDEX)) == NULL &&
          /* no metamethod; is there a previous entry in the table? */
          (oldval != luaO_nilobject ||
          /* no previous entry; must create one. (The next test is
             always true; we only need the assignment.) */
-         (oldval = luaH_newkey(L, h, key), 1)))) {
+         (oldval = luaH_newkey(L, hvalue(t), key), 1))) {
         /* no metamethod and (now) there is an entry with given key */
-        setobj2t(L, oldval, val);  /* assign new value to that entry */
-        invalidateTMcache(h);
-        luaC_barrierback(L, h, val);
+        setobj2t(L, cast(TValue *, oldval), val);
+        invalidateTMcache(hvalue(t));
+        luaC_barrierback(L, hvalue(t), val);
         return;
       }
       /* else will try the metamethod */
     }
-    else  /* not a table; check metamethod */
+    else {  /* not a table; check metamethod */
       if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX)))
         luaG_typeerror(L, t, "index");
+    }
     /* try the metamethod */
     if (ttisfunction(tm)) {
       luaT_callTM(L, tm, t, key, val, 0);
       return;
     }
     t = tm;  /* else repeat assignment over 'tm' */
+    if (luaV_fastset(L, t, key, oldval, luaH_get, val)) {
+      setobj2t(L, cast(TValue *, oldval), val);
+      return;
+    }
+    /* else loop */
   }
   luaG_runerror(L, "settable chain too long; possible loop");
 }

+ 18 - 3
lvm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lvm.h,v 2.35 2015/02/20 14:27:53 roberto Exp roberto $
+** $Id: lvm.h,v 2.36 2015/07/20 18:24:50 roberto Exp roberto $
 ** Lua virtual machine
 ** See Copyright Notice in lua.h
 */
@@ -70,6 +70,21 @@
   else luaV_finishget(L,t,k,v,aux); }
 
 
+#define luaV_fastset(L,t,k,aux,f,v) \
+  (!ttistable(t) \
+   ? (aux = NULL, 0) \
+   : (aux = f(hvalue(t), k), \
+     ttisnil(aux) ? 0 \
+     : (invalidateTMcache(hvalue(t)), \
+        luaC_barrierback(L, hvalue(t), v), 1)))
+
+#define luaV_settable(L,t,k,v) { const TValue *aux; \
+  if (luaV_fastset(L,t,k,aux,luaH_get,v)) \
+  { setobj2t(L, cast(TValue *,aux), v); } \
+  else luaV_finishset(L,t,k,v,aux); }
+  
+
+
 LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2);
 LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r);
 LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r);
@@ -77,8 +92,8 @@ LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n);
 LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode);
 LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key,
                                StkId val, const TValue *tm);
-LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key,
-                                            StkId val);
+LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
+                               StkId val, const TValue *oldval);
 LUAI_FUNC void luaV_finishOp (lua_State *L);
 LUAI_FUNC void luaV_execute (lua_State *L);
 LUAI_FUNC void luaV_concat (lua_State *L, int total);