OP_NEWTABLE keeps exact size of arrays

OP_NEWTABLE is followed by an OP_EXTRAARG, so that it can keep
the exact size of the array part of the table to be created.
(Functions 'luaO_int2fb'/'luaO_fb2int' were removed.)
diff --git a/lcode.c b/lcode.c
index 74ff47d..1ff32ed 100644
--- a/lcode.c
+++ b/lcode.c
@@ -430,7 +430,7 @@
 /*
 ** Emit an "extra argument" instruction (format 'iAx')
 */
-static int codeextraarg (FuncState *fs, int a) {
+int luaK_codeextraarg (FuncState *fs, int a) {
   lua_assert(a <= MAXARG_Ax);
   return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a));
 }
@@ -446,7 +446,7 @@
     return luaK_codeABx(fs, OP_LOADK, reg, k);
   else {
     int p = luaK_codeABx(fs, OP_LOADKX, reg, 0);
-    codeextraarg(fs, k);
+    luaK_codeextraarg(fs, k);
     return p;
   }
 }
@@ -1687,7 +1687,7 @@
     luaK_codeABC(fs, OP_SETLIST, base, b, c);
   else if (c <= MAXARG_Ax) {
     luaK_codeABC(fs, OP_SETLIST, base, b, 0);
-    codeextraarg(fs, c);
+    luaK_codeextraarg(fs, c);
   }
   else
     luaX_syntaxerror(fs->ls, "constructor too long");
diff --git a/lcode.h b/lcode.h
index a15b687..a924722 100644
--- a/lcode.h
+++ b/lcode.h
@@ -55,6 +55,7 @@
 LUAI_FUNC int luaK_codeAsBx (FuncState *fs, OpCode o, int A, int Bx);
 LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A,
                                             int B, int C, int k);
+LUAI_FUNC int luaK_codeextraarg (FuncState *fs, int a);
 LUAI_FUNC int luaK_isKint (expdesc *e);
 LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v);
 LUAI_FUNC void luaK_fixline (FuncState *fs, int line);
diff --git a/lobject.c b/lobject.c
index 2c265f9..b4efae4 100644
--- a/lobject.c
+++ b/lobject.c
@@ -30,32 +30,6 @@
 
 
 /*
-** converts an integer to a "floating point byte", represented as
-** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if
-** eeeee != 0 and (xxx) otherwise.
-*/
-int luaO_int2fb (unsigned int x) {
-  int e = 0;  /* exponent */
-  if (x < 8) return x;
-  while (x >= (8 << 4)) {  /* coarse steps */
-    x = (x + 0xf) >> 4;  /* x = ceil(x / 16) */
-    e += 4;
-  }
-  while (x >= (8 << 1)) {  /* fine steps */
-    x = (x + 1) >> 1;  /* x = ceil(x / 2) */
-    e++;
-  }
-  return ((e+1) << 3) | (cast_int(x) - 8);
-}
-
-
-/* converts back */
-int luaO_fb2int (int x) {
-  return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1);
-}
-
-
-/*
 ** Computes ceil(log2(x))
 */
 int luaO_ceillog2 (unsigned int x) {
diff --git a/lobject.h b/lobject.h
index 2f95bcb..95f8e18 100644
--- a/lobject.h
+++ b/lobject.h
@@ -734,8 +734,6 @@
 /* size of buffer for 'luaO_utf8esc' function */
 #define UTF8BUFFSZ	8
 
-LUAI_FUNC int luaO_int2fb (unsigned int x);
-LUAI_FUNC int luaO_fb2int (int x);
 LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x);
 LUAI_FUNC int luaO_ceillog2 (unsigned int x);
 LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1,
diff --git a/lopcodes.h b/lopcodes.h
index 7bbbb0e..0b23fa6 100644
--- a/lopcodes.h
+++ b/lopcodes.h
@@ -324,7 +324,8 @@
   (*) In OP_SETLIST, if (B == 0) then real B = 'top'; if (C == 0) then
   next 'instruction' is EXTRAARG(real C).
 
-  (*) In OP_LOADKX, the next 'instruction' is always EXTRAARG.
+  (*) In OP_LOADKX and OP_NEWTABLE, the next 'instruction' is always
+  EXTRAARG.
 
   (*) For comparisons, k specifies what condition the test should accept
   (true or false).
@@ -375,4 +376,11 @@
 #define LFIELDS_PER_FLUSH	50
 
 
+/*
+** In OP_NEWTABLE, array sizes smaller than LIMTABSZ are represented
+** directly in R(B). Otherwise, array size is given by
+**        (R(B) - LIMTABSZ) + EXTRAARG * LFIELDS_PER_FLUSH
+*/
+#define LIMTABSZ	(MAXARG_B - LFIELDS_PER_FLUSH)
+
 #endif
diff --git a/lparser.c b/lparser.c
index 79df021..193e50f 100644
--- a/lparser.c
+++ b/lparser.c
@@ -811,16 +811,16 @@
 */
 
 
-struct ConsControl {
+typedef struct ConsControl {
   expdesc v;  /* last list item read */
   expdesc *t;  /* table descriptor */
   int nh;  /* total number of 'record' elements */
   int na;  /* total number of array elements */
   int tostore;  /* number of array elements pending to be stored */
-};
+} ConsControl;
 
 
-static void recfield (LexState *ls, struct ConsControl *cc) {
+static void recfield (LexState *ls, ConsControl *cc) {
   /* recfield -> (NAME | '['exp']') = exp */
   FuncState *fs = ls->fs;
   int reg = ls->fs->freereg;
@@ -841,7 +841,7 @@
 }
 
 
-static void closelistfield (FuncState *fs, struct ConsControl *cc) {
+static void closelistfield (FuncState *fs, ConsControl *cc) {
   if (cc->v.k == VVOID) return;  /* there is no list item */
   luaK_exp2nextreg(fs, &cc->v);
   cc->v.k = VVOID;
@@ -852,7 +852,7 @@
 }
 
 
-static void lastlistfield (FuncState *fs, struct ConsControl *cc) {
+static void lastlistfield (FuncState *fs, ConsControl *cc) {
   if (cc->tostore == 0) return;
   if (hasmultret(cc->v.k)) {
     luaK_setmultret(fs, &cc->v);
@@ -867,16 +867,15 @@
 }
 
 
-static void listfield (LexState *ls, struct ConsControl *cc) {
+static void listfield (LexState *ls, ConsControl *cc) {
   /* listfield -> exp */
   expr(ls, &cc->v);
-  checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor");
   cc->na++;
   cc->tostore++;
 }
 
 
-static void field (LexState *ls, struct ConsControl *cc) {
+static void field (LexState *ls, ConsControl *cc) {
   /* field -> listfield | recfield */
   switch(ls->t.token) {
     case TK_NAME: {  /* may be 'listfield' or 'recfield' */
@@ -898,13 +897,30 @@
 }
 
 
+static void settablesize (FuncState *fs, ConsControl *cc, int pc) {
+  Instruction *inst = &fs->f->code[pc];
+  int rc = (cc->nh == 0) ? 0 : luaO_ceillog2(cc->nh) + 1;
+  int rb = cc->na;
+  int extra = 0;
+  if (rb >= LIMTABSZ) {
+    extra = rb / LFIELDS_PER_FLUSH;
+    rb = rb % LFIELDS_PER_FLUSH + LIMTABSZ;
+    checklimit(fs, extra, MAXARG_Ax, "items in a constructor");
+  }
+  SETARG_C(*inst, rc);  /* set initial table size */
+  SETARG_B(*inst, rb); /* set initial array size */
+  SETARG_Ax(*(inst + 1), extra);
+}
+
+
 static void constructor (LexState *ls, expdesc *t) {
   /* constructor -> '{' [ field { sep field } [sep] ] '}'
      sep -> ',' | ';' */
   FuncState *fs = ls->fs;
   int line = ls->linenumber;
   int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0);
-  struct ConsControl cc;
+  ConsControl cc;
+  luaK_codeextraarg(fs, 0);
   cc.na = cc.nh = cc.tostore = 0;
   cc.t = t;
   init_exp(t, VRELOC, pc);
@@ -919,8 +935,7 @@
   } while (testnext(ls, ',') || testnext(ls, ';'));
   check_match(ls, '}', '{', line);
   lastlistfield(fs, &cc);
-  SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */
-  SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh));  /* set initial table size */
+  settablesize(fs, &cc, pc);
 }
 
 /* }====================================================================== */
diff --git a/ltests.c b/ltests.c
index dc83065..cb8c422 100644
--- a/ltests.c
+++ b/ltests.c
@@ -1103,14 +1103,6 @@
 }
 
 
-static int int2fb_aux (lua_State *L) {
-  int b = luaO_int2fb((unsigned int)luaL_checkinteger(L, 1));
-  lua_pushinteger(L, b);
-  lua_pushinteger(L, (unsigned int)luaO_fb2int(b));
-  return 2;
-}
-
-
 static int log2_aux (lua_State *L) {
   unsigned int x = (unsigned int)luaL_checkinteger(L, 1);
   lua_pushinteger(L, luaO_ceillog2(x));
@@ -1780,7 +1772,6 @@
   {"pobj", gc_printobj},
   {"getref", getref},
   {"hash", hash_query},
-  {"int2fb", int2fb_aux},
   {"log2", log2_aux},
   {"limits", get_limits},
   {"listcode", listcode},
diff --git a/lvm.c b/lvm.c
index a52f186..4011819 100644
--- a/lvm.c
+++ b/lvm.c
@@ -1250,11 +1250,15 @@
         int b = GETARG_B(i);
         int c = GETARG_C(i);
         Table *t;
+        c = (c == 0) ? 0 : 1 << (c - 1);  /* size is 2^c */
+        if (b >= LIMTABSZ)
+          b += LFIELDS_PER_FLUSH * GETARG_Ax(*pc) - LIMTABSZ;
+        pc++;  /* skip extra argument */
         L->top = ci->top;  /* correct top in case of GC */
         t = luaH_new(L);  /* memory allocation */
         sethvalue2s(L, ra, t);
         if (b != 0 || c != 0)
-          luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c));  /* idem */
+          luaH_resize(L, t, b, c);  /* idem */
         checkGC(L, ra + 1);
         vmbreak;
       }
diff --git a/testes/code.lua b/testes/code.lua
index 49d682f..b2702c6 100644
--- a/testes/code.lua
+++ b/testes/code.lua
@@ -93,11 +93,13 @@
 -- some basic instructions
 check(function ()   -- function does not create upvalues
   (function () end){f()}
-end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN0')
+end, 'CLOSURE', 'NEWTABLE', 'EXTRAARG', 'GETTABUP', 'CALL',
+     'SETLIST', 'CALL', 'RETURN0')
 
 check(function (x)   -- function creates upvalues
   (function () return x end){f()}
-end, 'CLOSURE', 'NEWTABLE', 'GETTABUP', 'CALL', 'SETLIST', 'CALL', 'RETURN')
+end, 'CLOSURE', 'NEWTABLE', 'EXTRAARG', 'GETTABUP', 'CALL',
+     'SETLIST', 'CALL', 'RETURN')
 
 
 -- sequence of LOADNILs
diff --git a/testes/nextvar.lua b/testes/nextvar.lua
index 87a6bfa..bdc9fc2 100644
--- a/testes/nextvar.lua
+++ b/testes/nextvar.lua
@@ -49,33 +49,13 @@
 else --[
 -- testing table sizes
 
-local function log2 (x) return math.log(x, 2) end
 
 local function mp2 (n)   -- minimum power of 2 >= n
-  local mp = 2^math.ceil(log2(n))
+  local mp = 2^math.ceil(math.log(n, 2))
   assert(n == 0 or (mp/2 < n and n <= mp))
   return mp
 end
 
-local function fb (n)
-  local r, nn = T.int2fb(n)
-  assert(r < 256)
-  return nn
-end
-
--- test fb function
-for a = 1, 10000 do   -- all numbers up to 10^4
-  local n = fb(a)
-  assert(a <= n and n <= a*1.125)
-end
-local a = 1024   -- plus a few up to 2 ^30
-local lim = 2^30
-while a < lim do
-  local n = fb(a)
-  assert(a <= n and n <= a*1.125)
-  a = math.ceil(a*1.3)
-end
-
 
 local function check (t, na, nh)
   local a, h = T.querytab(t)
@@ -95,24 +75,30 @@
 
 
 -- testing constructor sizes
-local lim = 40
-local s = 'return {'
-for i=1,lim do
-  s = s..i..','
-  local s = s
-  for k=0,lim do
-    local t = load(s..'}', '')()
-    assert(#t == i)
-    check(t, fb(i), mp2(k))
-    s = string.format('%sa%d=%d,', s, k, k)
+local sizes = {0, 1, 2, 3, 4, 5, 7, 8, 9, 15, 16, 17,
+  30, 31, 32, 33, 34, 500, 1000}
+
+for _, sa in ipairs(sizes) do    -- 'sa' is size of the array part
+  local arr = {"return {"}
+  -- array part
+  for i = 1, sa do arr[1 + i] = "1," end
+  for _, sh in ipairs(sizes) do    -- 'sh' is size of the hash part
+    for j = 1, sh do   -- hash part
+      arr[1 + sa + j] = string.format('k%x=%d,', j, j)
+    end
+    arr[1 + sa + sh + 1] = "}"
+    local prog = table.concat(arr)
+    local t = assert(load(prog))()
+    assert(#t == sa)
+    check(t, sa, mp2(sh))
   end
 end
 
 
 -- tests with unknown number of elements
 local a = {}
-for i=1,lim do a[i] = i end   -- build auxiliary table
-for k=0,lim do
+for i=1,sizes[#sizes] do a[i] = i end   -- build auxiliary table
+for k in ipairs(sizes) do
   local a = {table.unpack(a,1,k)}
   assert(#a == k)
   check(a, k, 0)