Browse Source

Add table.new().

Mike Pall 12 years ago
parent
commit
c8cfca0557
11 changed files with 55 additions and 6 deletions
  1. 9 0
      doc/extensions.html
  2. 1 1
      src/Makefile.dep
  3. 20 0
      src/lib_table.c
  4. 1 3
      src/lj_api.c
  5. 3 0
      src/lj_asm.c
  6. 8 0
      src/lj_ffrecord.c
  7. 1 0
      src/lj_ir.h
  8. 2 0
      src/lj_ircall.h
  9. 3 2
      src/lj_opt_fold.c
  10. 6 0
      src/lj_tab.c
  11. 1 0
      src/lj_tab.h

+ 9 - 0
doc/extensions.html

@@ -208,6 +208,15 @@ minor releases (2.0 → 2.1) or between any beta release. Foreign
 bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
 bytecode (e.g. from Lua 5.1) is incompatible and cannot be loaded.
 </p>
 </p>
 
 
+<h3 id="table_new"><tt>table.new(narray, nhash)</tt> allocates a pre-sized table</h3>
+<p>
+An extra library function <tt>table.new()</tt> can be made available via
+<tt>require("table.new")</tt>. This creates a pre-sized table, just like
+the C API equivalent <tt>lua_createtable()</tt>. This is useful for big
+tables if the final table size is known and automatic table resizing is
+too expensive.
+</p>
+
 <h3 id="math_random">Enhanced PRNG for <tt>math.random()</tt></h3>
 <h3 id="math_random">Enhanced PRNG for <tt>math.random()</tt></h3>
 <p>
 <p>
 LuaJIT uses a Tausworthe PRNG with period 2^223 to implement
 LuaJIT uses a Tausworthe PRNG with period 2^223 to implement

+ 1 - 1
src/Makefile.dep

@@ -40,7 +40,7 @@ lib_string.o: lib_string.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
  lj_char.h lj_strfmt.h lj_lib.h lj_libdef.h
  lj_char.h lj_strfmt.h lj_lib.h lj_libdef.h
 lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
 lib_table.o: lib_table.c lua.h luaconf.h lauxlib.h lualib.h lj_obj.h \
  lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
  lj_def.h lj_arch.h lj_gc.h lj_err.h lj_errmsg.h lj_buf.h lj_str.h \
- lj_tab.h lj_lib.h lj_libdef.h
+ lj_tab.h lj_ff.h lj_ffdef.h lj_lib.h lj_libdef.h
 lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h
 lj_alloc.o: lj_alloc.c lj_def.h lua.h luaconf.h lj_arch.h lj_alloc.h
 lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
 lj_api.o: lj_api.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
  lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \
  lj_err.h lj_errmsg.h lj_debug.h lj_str.h lj_tab.h lj_func.h lj_udata.h \

+ 20 - 0
src/lib_table.c

@@ -18,6 +18,7 @@
 #include "lj_err.h"
 #include "lj_err.h"
 #include "lj_buf.h"
 #include "lj_buf.h"
 #include "lj_tab.h"
 #include "lj_tab.h"
+#include "lj_ff.h"
 #include "lj_lib.h"
 #include "lj_lib.h"
 
 
 /* ------------------------------------------------------------------------ */
 /* ------------------------------------------------------------------------ */
@@ -264,6 +265,24 @@ LJLIB_CF(table_pack)
 }
 }
 #endif
 #endif
 
 
+LJLIB_NOREG LJLIB_CF(table_new)		LJLIB_REC(.)
+{
+  int32_t a = lj_lib_checkint(L, 1);
+  int32_t h = lj_lib_checkint(L, 2);
+  lua_createtable(L, a, h);
+  return 1;
+}
+
+static int luaopen_table_new(lua_State *L)
+{
+  GCfunc *fn = lj_lib_pushcc(L, lj_cf_table_new, FF_table_new, 0);
+  GCtab *t = tabref(curr_func(L)->c.env);  /* Reference to "table". */
+  setfuncV(L, lj_tab_setstr(L, t, lj_str_newlit(L, "new")), fn);
+  lj_gc_anybarriert(L, t);
+  setfuncV(L, L->top++, fn);
+  return 1;
+}
+
 /* ------------------------------------------------------------------------ */
 /* ------------------------------------------------------------------------ */
 
 
 #include "lj_libdef.h"
 #include "lj_libdef.h"
@@ -275,6 +294,7 @@ LUALIB_API int luaopen_table(lua_State *L)
   lua_getglobal(L, "unpack");
   lua_getglobal(L, "unpack");
   lua_setfield(L, -2, "unpack");
   lua_setfield(L, -2, "unpack");
 #endif
 #endif
+  lj_lib_prereg(L, LUA_TABLIBNAME ".new", luaopen_table_new, tabV(L->top-1));
   return 1;
   return 1;
 }
 }
 
 

+ 1 - 3
src/lj_api.c

@@ -640,10 +640,8 @@ LUA_API void lua_pushlightuserdata(lua_State *L, void *p)
 
 
 LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
 LUA_API void lua_createtable(lua_State *L, int narray, int nrec)
 {
 {
-  GCtab *t;
   lj_gc_check(L);
   lj_gc_check(L);
-  t = lj_tab_new(L, (uint32_t)(narray > 0 ? narray+1 : 0), hsize2hbits(nrec));
-  settabV(L, L->top, t);
+  settabV(L, L->top, lj_tab_new_ah(L, narray, nrec));
   incr_top(L);
   incr_top(L);
 }
 }
 
 

+ 3 - 0
src/lj_asm.c

@@ -1659,6 +1659,9 @@ static void asm_ir(ASMState *as, IRIns *ir)
   case IR_STRTO: asm_strto(as, ir); break;
   case IR_STRTO: asm_strto(as, ir); break;
 
 
   /* Calls. */
   /* Calls. */
+  case IR_CALLA:
+    as->gcsteps++;
+    /* fallthrough */
   case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break;
   case IR_CALLN: case IR_CALLL: case IR_CALLS: asm_call(as, ir); break;
   case IR_CALLXS: asm_callx(as, ir); break;
   case IR_CALLXS: asm_callx(as, ir); break;
   case IR_CARG: break;
   case IR_CARG: break;

+ 8 - 0
src/lj_ffrecord.c

@@ -1003,6 +1003,14 @@ static void LJ_FASTCALL recff_table_concat(jit_State *J, RecordFFData *rd)
   UNUSED(rd);
   UNUSED(rd);
 }
 }
 
 
+static void LJ_FASTCALL recff_table_new(jit_State *J, RecordFFData *rd)
+{
+  TRef tra = lj_opt_narrow_toint(J, J->base[0]);
+  TRef trh = lj_opt_narrow_toint(J, J->base[1]);
+  J->base[0] = lj_ir_call(J, IRCALL_lj_tab_new_ah, tra, trh);
+  UNUSED(rd);
+}
+
 /* -- I/O library fast functions ------------------------------------------ */
 /* -- I/O library fast functions ------------------------------------------ */
 
 
 /* Get FILE* for I/O function. Any I/O error aborts recording, so there's
 /* Get FILE* for I/O function. Any I/O error aborts recording, so there's

+ 1 - 0
src/lj_ir.h

@@ -139,6 +139,7 @@
   \
   \
   /* Calls. */ \
   /* Calls. */ \
   _(CALLN,	N , ref, lit) \
   _(CALLN,	N , ref, lit) \
+  _(CALLA,	A , ref, lit) \
   _(CALLL,	L , ref, lit) \
   _(CALLL,	L , ref, lit) \
   _(CALLS,	S , ref, lit) \
   _(CALLS,	S , ref, lit) \
   _(CALLXS,	S , ref, ref) \
   _(CALLXS,	S , ref, ref) \

+ 2 - 0
src/lj_ircall.h

@@ -25,6 +25,7 @@ typedef struct CCallInfo {
 #define CCI_OP(ci)		((ci)->flags >> CCI_OPSHIFT)  /* Get op. */
 #define CCI_OP(ci)		((ci)->flags >> CCI_OPSHIFT)  /* Get op. */
 
 
 #define CCI_CALL_N		(IR_CALLN << CCI_OPSHIFT)
 #define CCI_CALL_N		(IR_CALLN << CCI_OPSHIFT)
+#define CCI_CALL_A		(IR_CALLA << CCI_OPSHIFT)
 #define CCI_CALL_L		(IR_CALLL << CCI_OPSHIFT)
 #define CCI_CALL_L		(IR_CALLL << CCI_OPSHIFT)
 #define CCI_CALL_S		(IR_CALLS << CCI_OPSHIFT)
 #define CCI_CALL_S		(IR_CALLS << CCI_OPSHIFT)
 #define CCI_CALL_FN		(CCI_CALL_N|CCI_CC_FASTCALL)
 #define CCI_CALL_FN		(CCI_CALL_N|CCI_CC_FASTCALL)
@@ -140,6 +141,7 @@ typedef struct CCallInfo {
   _(ANY,	lj_buf_putstr_rep,	3,   L, P32, 0) \
   _(ANY,	lj_buf_putstr_rep,	3,   L, P32, 0) \
   _(ANY,	lj_buf_puttab,		5,   L, P32, 0) \
   _(ANY,	lj_buf_puttab,		5,   L, P32, 0) \
   _(ANY,	lj_buf_tostr,		1,  FL, STR, 0) \
   _(ANY,	lj_buf_tostr,		1,  FL, STR, 0) \
+  _(ANY,	lj_tab_new_ah,		3,   A, TAB, CCI_L) \
   _(ANY,	lj_tab_new1,		2,  FS, TAB, CCI_L) \
   _(ANY,	lj_tab_new1,		2,  FS, TAB, CCI_L) \
   _(ANY,	lj_tab_dup,		2,  FS, TAB, CCI_L) \
   _(ANY,	lj_tab_dup,		2,  FS, TAB, CCI_L) \
   _(ANY,	lj_tab_newkey,		3,   S, P32, CCI_L) \
   _(ANY,	lj_tab_newkey,		3,   S, P32, CCI_L) \

+ 3 - 2
src/lj_opt_fold.c

@@ -165,7 +165,7 @@ typedef IRRef (LJ_FASTCALL *FoldFunc)(jit_State *J);
    (J->chain[IR_SNEW] || J->chain[IR_XSNEW] || \
    (J->chain[IR_SNEW] || J->chain[IR_XSNEW] || \
     J->chain[IR_TNEW] || J->chain[IR_TDUP] || \
     J->chain[IR_TNEW] || J->chain[IR_TDUP] || \
     J->chain[IR_CNEW] || J->chain[IR_CNEWI] || \
     J->chain[IR_CNEW] || J->chain[IR_CNEWI] || \
-    J->chain[IR_BUFSTR] || J->chain[IR_TOSTR]))
+    J->chain[IR_BUFSTR] || J->chain[IR_TOSTR] || J->chain[IR_CALLA]))
 
 
 /* -- Constant folding for FP numbers ------------------------------------- */
 /* -- Constant folding for FP numbers ------------------------------------- */
 
 
@@ -2319,8 +2319,9 @@ LJFOLD(XSTORE any any)
 LJFOLDX(lj_opt_dse_xstore)
 LJFOLDX(lj_opt_dse_xstore)
 
 
 LJFOLD(NEWREF any any)  /* Treated like a store. */
 LJFOLD(NEWREF any any)  /* Treated like a store. */
-LJFOLD(CALLS any any)
+LJFOLD(CALLA any any)
 LJFOLD(CALLL any any)  /* Safeguard fallback. */
 LJFOLD(CALLL any any)  /* Safeguard fallback. */
+LJFOLD(CALLS any any)
 LJFOLD(CALLXS any any)
 LJFOLD(CALLXS any any)
 LJFOLD(XBAR)
 LJFOLD(XBAR)
 LJFOLD(RETF any any)  /* Modifies BASE. */
 LJFOLD(RETF any any)  /* Modifies BASE. */

+ 6 - 0
src/lj_tab.c

@@ -149,6 +149,12 @@ GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits)
   return t;
   return t;
 }
 }
 
 
+/* The API of this function conforms to lua_createtable(). */
+GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h)
+{
+  return lj_tab_new(L, (uint32_t)(a > 0 ? a+1 : 0), hsize2hbits(h));
+}
+
 #if LJ_HASJIT
 #if LJ_HASJIT
 GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize)
 GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize)
 {
 {

+ 1 - 0
src/lj_tab.h

@@ -34,6 +34,7 @@ static LJ_AINLINE uint32_t hashrot(uint32_t lo, uint32_t hi)
 #define hsize2hbits(s)	((s) ? ((s)==1 ? 1 : 1+lj_fls((uint32_t)((s)-1))) : 0)
 #define hsize2hbits(s)	((s) ? ((s)==1 ? 1 : 1+lj_fls((uint32_t)((s)-1))) : 0)
 
 
 LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits);
 LJ_FUNCA GCtab *lj_tab_new(lua_State *L, uint32_t asize, uint32_t hbits);
+LJ_FUNC GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h);
 #if LJ_HASJIT
 #if LJ_HASJIT
 LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize);
 LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize);
 #endif
 #endif