=== modified file 'src/lapi.c'
--- src/lapi.c	2009-12-27 04:10:06 +0000
+++ src/lapi.c	2010-01-18 04:29:53 +0000
@@ -675,6 +675,7 @@
   t = index2adr(L, idx);
   api_check(L, ttistable(t));
   setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1);
+  luaH_updatelenkey(hvalue(t), L->top-2, ttisnil(L->top-1));
   luaC_barriert(L, hvalue(t), L->top-1);
   L->top -= 2;
   lua_unlock(L);
@@ -688,6 +689,7 @@
   o = index2adr(L, idx);
   api_check(L, ttistable(o));
   setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1);
+  luaH_updatelen(hvalue(o), n, ttisnil(L->top-1));
   luaC_barriert(L, hvalue(o), L->top-1);
   L->top--;
   lua_unlock(L);

=== modified file 'src/lcode.c'
--- src/lcode.c	2009-12-27 04:10:06 +0000
+++ src/lcode.c	2010-01-18 04:29:13 +0000
@@ -236,7 +236,8 @@
     return cast_int(nvalue(idx));
   }
   else {  /* constant not found; create a new entry */
-    setnvalue(idx, cast_num(fs->nk));
+    setnvalue(idx, cast_num(fs->nk)); /* SMARTLEN -- that is a table set */
+    luaH_updatelenkey(fs->h, k, 0);
     luaM_growvector(L, f->k, fs->nk, f->sizek, TValue,
                     MAXARG_Bx, "constant table overflow");
     while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]);

=== modified file 'src/ldebug.c'
--- src/ldebug.c	2009-12-27 04:10:06 +0000
+++ src/ldebug.c	2010-01-18 04:29:53 +0000
@@ -182,8 +182,10 @@
     Table *t = luaH_new(L, 0, 0);
     int *lineinfo = f->l.p->lineinfo;
     int i;
-    for (i=0; i<f->l.p->sizelineinfo; i++)
+    for (i=0; i<f->l.p->sizelineinfo; i++) {
       setbvalue(luaH_setnum(L, t, lineinfo[i]), 1);
+      luaH_updatelen(t, lineinfo[i], 0);
+    }
     sethvalue(L, L->top, t); 
   }
   incr_top(L);

=== modified file 'src/ldo.c'
--- src/ldo.c	2009-12-27 04:10:06 +0000
+++ src/ldo.c	2010-01-18 04:29:53 +0000
@@ -218,8 +218,10 @@
     lua_assert(p->is_vararg & VARARG_HASARG);
     luaC_checkGC(L);
     htab = luaH_new(L, nvar, 1);  /* create `arg' table */
-    for (i=0; i<nvar; i++)  /* put extra arguments into `arg' table */
+    for (i=0; i<nvar; i++) { /* put extra arguments into `arg' table */
       setobj2n(L, luaH_setnum(L, htab, i+1), L->top - nvar + i);
+      luaH_updatelen(htab, i+1, ttisnil(L->top - nvar + i));
+    }
     /* store counter in field `n' */
     setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar));
   }

=== modified file 'src/lobject.h'
--- src/lobject.h	2009-12-27 04:10:06 +0000
+++ src/lobject.h	2010-01-15 12:04:02 +0000
@@ -345,6 +345,9 @@
   Node *lastfree;  /* any free position is before this position */
   GCObject *gclist;
   int sizearray;  /* size of `array' array */
+#ifdef LUA_SMARTLEN
+  int lastint;
+#endif
 } Table;
 
 

=== modified file 'src/ltable.c'
--- src/ltable.c	2009-12-27 04:10:06 +0000
+++ src/ltable.c	2010-01-18 04:29:53 +0000
@@ -130,6 +130,34 @@
 
 
 /*
+** updates t->lastint
+*/
+
+#ifdef LUA_SMARTLEN
+
+#ifndef luaH_updatelen
+void luaH_updatelen(Table *t, int index, int nilvalue) {
+  if (nilvalue) {
+    const int ci = index - 1; /* C index */
+    if (t->lastint > ci) {
+      t->lastint = ci;
+    }
+  }
+}
+#endif
+
+#ifndef luaH_updatelenkey
+void luaH_updatelenkey(Table *t, const TValue* k, int nilvalue) {
+  int i = arrayindex(k);
+  if (i <= 0) { return; }
+  luaH_updatelen(t, i, nilvalue);
+}
+#endif
+
+#endif /* LUA_SMARTLEN */
+
+
+/*
 ** returns the index of a `key' for table traversals. First goes all
 ** elements in the array part, then elements in the hash part. The
 ** beginning of a traversal is signalled by -1.
@@ -307,8 +335,9 @@
     t->sizearray = nasize;
     /* re-insert elements from vanishing slice */
     for (i=nasize; i<oldasize; i++) {
-      if (!ttisnil(&t->array[i]))
+      if (!ttisnil(&t->array[i])) {
         setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]);
+      }
     }
     /* shrink array */
     luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
@@ -316,8 +345,9 @@
   /* re-insert elements from hash part */
   for (i = twoto(oldhsize) - 1; i >= 0; i--) {
     Node *old = nold+i;
-    if (!ttisnil(gval(old)))
+    if (!ttisnil(gval(old))) {
       setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old));
+    }
   }
   if (nold != dummynode)
     luaM_freearray(L, nold, twoto(oldhsize), Node);  /* free old array */
@@ -362,6 +392,9 @@
   t->flags = cast_byte(~0);
   /* temporary values (kept only if some malloc fails) */
   t->array = NULL;
+#ifdef LUA_SMARTLEN
+  t->lastint = 0;
+#endif
   t->sizearray = 0;
   t->lsizenode = 0;
   t->node = cast(Node *, dummynode);
@@ -529,6 +562,7 @@
 }
 
 
+#ifndef LUA_SMARTLEN
 static int unbound_search (Table *t, unsigned int j) {
   unsigned int i = j;  /* i is zero or a present index */
   j++;
@@ -551,6 +585,7 @@
   }
   return i;
 }
+#endif
 
 
 /*
@@ -558,6 +593,16 @@
 ** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
 */
 int luaH_getn (Table *t) {
+#ifdef LUA_SMARTLEN
+  while (1) {
+    const int nextint = t->lastint + 1;
+    if (ttisnil(luaH_getnum(t, nextint))) {
+      break;
+    }
+    t->lastint = nextint;
+  }
+  return t->lastint;
+#else
   unsigned int j = t->sizearray;
   if (j > 0 && ttisnil(&t->array[j - 1])) {
     /* there is a boundary in the array part: (binary) search for it */
@@ -573,6 +618,7 @@
   else if (t->node == dummynode)  /* hash part is empty? */
     return j;  /* that is easy... */
   else return unbound_search(t, j);
+#endif /* LUA_SMARTLEN */
 }
 
 

=== modified file 'src/ltable.h'
--- src/ltable.h	2009-12-27 04:10:06 +0000
+++ src/ltable.h	2010-01-18 04:29:53 +0000
@@ -18,12 +18,12 @@
 #define key2tval(n)	(&(n)->i_key.tvk)
 
 
+LUAI_FUNC const TValue *luaH_get    (Table *t, const TValue *key);
 LUAI_FUNC const TValue *luaH_getnum (Table *t, int key);
+LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
+LUAI_FUNC TValue *luaH_set    (lua_State *L, Table *t, const TValue *key);
 LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key);
-LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key);
 LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key);
-LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key);
-LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key);
 LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash);
 LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize);
 LUAI_FUNC void luaH_free (lua_State *L, Table *t);
@@ -31,6 +31,35 @@
 LUAI_FUNC int luaH_getn (Table *t);
 
 
+#ifdef LUA_SMARTLEN
+LUAI_FUNC void luaH_updatelen(Table *t, int index, int nilvalue);
+LUAI_FUNC void luaH_updatelenkey(Table *t, const TValue* k, int nilvalue);
+#define luaH_updatelen(t, index, nilvalue) \
+  if (nilvalue) { \
+    const int ci = index - 1; /* C index */ \
+    if ((t)->lastint > (ci) && (ci) >= 0) { \
+      (t)->lastint = (ci); \
+    } \
+  }
+#define luaH_updatelenkey(t, k, nilvalue) \
+  if ((nilvalue) && ttisnumber(k)) { \
+    lua_Number n = nvalue(k); \
+    int ci; \
+    lua_number2int(ci, n); \
+    if (luai_numeq(cast_num(ci), n)) { \
+      ci--; /* C index */ \
+      if ((t)->lastint > (ci) && (ci) >= 0) { \
+        (t)->lastint = (ci); \
+      } \
+    } \
+  }
+#else
+#define luaH_updatelen(t, index, nilvalue)    ((void) 0)
+#define luaH_updatelenkey(t, index, nilvalue) ((void) 0)
+#endif
+
+
+
 #if defined(LUA_DEBUG)
 LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key);
 LUAI_FUNC int luaH_isdummy (Node *n);

=== modified file 'src/luaconf.h'
--- src/luaconf.h	2009-12-27 04:10:06 +0000
+++ src/luaconf.h	2010-01-15 12:04:02 +0000
@@ -11,6 +11,7 @@
 #include <limits.h>
 #include <stddef.h>
 
+#define LUA_SMARTLEN
 
 /*
 ** ==================================================================

=== modified file 'src/lvm.c'
--- src/lvm.c	2009-12-27 04:10:06 +0000
+++ src/lvm.c	2010-01-18 04:29:54 +0000
@@ -141,6 +141,7 @@
       if (!ttisnil(oldval) ||  /* result is no nil? */
           (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */
         setobj2t(L, oldval, val);
+        luaH_updatelenkey(h, key, ttisnil(oldval));
         luaC_barriert(L, h, val);
         return;
       }
@@ -707,8 +708,10 @@
           luaH_resizearray(L, h, last);  /* pre-alloc it at once */
         for (; n > 0; n--) {
           TValue *val = ra+n;
-          setobj2t(L, luaH_setnum(L, h, last--), val);
+          setobj2t(L, luaH_setnum(L, h, last), val);
+          luaH_updatelen(h, last, ttisnil(val));
           luaC_barriert(L, h, val);
+          last--;
         }
         continue;
       }

