From 4593fb5e29adc09cd53beaba8777f5656434c08d Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 25 Nov 2013 15:18:31 +0100 Subject: [PATCH] Add table.clear(). --- doc/extensions.html | 16 ++++++++++++++++ src/Makefile.dep | 2 +- src/lib_table.c | 12 ++++++++++++ src/lj_ffrecord.c | 10 ++++++++++ src/lj_ircall.h | 1 + src/lj_opt_mem.c | 11 ++++++++++- src/lj_tab.c | 11 +++++++++++ src/lj_tab.h | 1 + 8 files changed, 62 insertions(+), 2 deletions(-) diff --git a/doc/extensions.html b/doc/extensions.html index 48f4220c..3443f201 100644 --- a/doc/extensions.html +++ b/doc/extensions.html @@ -217,6 +217,22 @@ tables if the final table size is known and automatic table resizing is too expensive.

+

table.clear(tab) clears a table

+

+An extra library function table.clear() can be made available +via require("table.clear"). This clears all keys and values +from a table, but preserves the allocated array/hash sizes. This is +useful when a table, which is linked from multiple places, needs to be +cleared and/or when recycling a table for use by the same context. This +avoids managing backlinks, saves an allocation and the overhead of +incremental array/hash part growth. +

+

+Please note this function is meant for very specific situations. In most +cases it's better to replace the (usually single) link with a new table +and let the GC do its work. +

+

Enhanced PRNG for math.random()

LuaJIT uses a Tausworthe PRNG with period 2^223 to implement diff --git a/src/Makefile.dep b/src/Makefile.dep index 97f8125a..9aefb236 100644 --- a/src/Makefile.dep +++ b/src/Makefile.dep @@ -155,7 +155,7 @@ lj_opt_loop.o: lj_opt_loop.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ lj_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \ lj_vm.h lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ - lj_tab.h lj_ir.h lj_jit.h lj_iropt.h + lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_ircall.h lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \ lj_arch.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \ lj_traceerr.h lj_vm.h lj_strscan.h diff --git a/src/lib_table.c b/src/lib_table.c index 91c022bb..4436ebd7 100644 --- a/src/lib_table.c +++ b/src/lib_table.c @@ -273,11 +273,22 @@ LJLIB_NOREG LJLIB_CF(table_new) LJLIB_REC(.) return 1; } +LJLIB_NOREG LJLIB_CF(table_clear) LJLIB_REC(.) +{ + lj_tab_clear(lj_lib_checktab(L, 1)); + return 0; +} + static int luaopen_table_new(lua_State *L) { return lj_lib_postreg(L, lj_cf_table_new, FF_table_new, "new"); } +static int luaopen_table_clear(lua_State *L) +{ + return lj_lib_postreg(L, lj_cf_table_clear, FF_table_clear, "clear"); +} + /* ------------------------------------------------------------------------ */ #include "lj_libdef.h" @@ -290,6 +301,7 @@ LUALIB_API int luaopen_table(lua_State *L) lua_setfield(L, -2, "unpack"); #endif lj_lib_prereg(L, LUA_TABLIBNAME ".new", luaopen_table_new, tabV(L->top-1)); + lj_lib_prereg(L, LUA_TABLIBNAME ".clear", luaopen_table_clear, tabV(L->top-1)); return 1; } diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index de74a3ec..69614d92 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c @@ -1024,6 +1024,16 @@ static void LJ_FASTCALL recff_table_new(jit_State *J, RecordFFData *rd) UNUSED(rd); } +static void LJ_FASTCALL recff_table_clear(jit_State *J, RecordFFData *rd) +{ + TRef tr = J->base[0]; + if (tref_istab(tr)) { + rd->nres = 0; + lj_ir_call(J, IRCALL_lj_tab_clear, tr); + J->needsnap = 1; + } /* else: Interpreter will throw. */ +} + /* -- I/O library fast functions ------------------------------------------ */ /* Get FILE* for I/O function. Any I/O error aborts recording, so there's diff --git a/src/lj_ircall.h b/src/lj_ircall.h index 53eb4638..db5ed5ab 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h @@ -144,6 +144,7 @@ typedef struct CCallInfo { _(ANY, lj_tab_new_ah, 3, A, TAB, CCI_L) \ _(ANY, lj_tab_new1, 2, FS, TAB, CCI_L) \ _(ANY, lj_tab_dup, 2, FS, TAB, CCI_L) \ + _(ANY, lj_tab_clear, 1, FS, NIL, 0) \ _(ANY, lj_tab_newkey, 3, S, P32, CCI_L) \ _(ANY, lj_tab_len, 1, FL, INT, 0) \ _(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \ diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index 7177ce2c..d705bf3d 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c @@ -17,6 +17,7 @@ #include "lj_ir.h" #include "lj_jit.h" #include "lj_iropt.h" +#include "lj_ircall.h" /* Some local macros to save typing. Undef'd at the end. */ #define IR(ref) (&J->cur.ir[(ref)]) @@ -308,7 +309,7 @@ int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J) return 1; /* No conflict. Can fold to niltv. */ } -/* Check whether there's no aliasing NEWREF for the left operand. */ +/* Check whether there's no aliasing NEWREF/table.clear for the left operand. */ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) { IRRef ta = fins->op1; @@ -319,6 +320,14 @@ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) return 0; /* Conflict. */ ref = newref->prev; } + ref = J->chain[IR_CALLS]; + while (ref > lim) { + IRIns *calls = IR(ref); + if (calls->op2 == IRCALL_lj_tab_clear && + (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO)) + return 0; /* Conflict. */ + ref = calls->prev; + } return 1; /* No conflict. Can safely FOLD/CSE. */ } diff --git a/src/lj_tab.c b/src/lj_tab.c index 37a3c32c..643d0819 100644 --- a/src/lj_tab.c +++ b/src/lj_tab.c @@ -204,6 +204,17 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt) return t; } +/* Clear a table. */ +void LJ_FASTCALL lj_tab_clear(GCtab *t) +{ + clearapart(t); + if (t->hmask > 0) { + Node *node = noderef(t->node); + setmref(node->freetop, &node[t->hmask+1]); + clearhpart(t); + } +} + /* Free a table. */ void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t) { diff --git a/src/lj_tab.h b/src/lj_tab.h index 5ec73286..b6e85579 100644 --- a/src/lj_tab.h +++ b/src/lj_tab.h @@ -39,6 +39,7 @@ LJ_FUNC GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h); LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize); #endif LJ_FUNCA GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt); +LJ_FUNC void LJ_FASTCALL lj_tab_clear(GCtab *t); LJ_FUNC void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t); #if LJ_HASFFI LJ_FUNC void lj_tab_rehash(lua_State *L, GCtab *t);