diff options
| author | Mike Pall <mike> | 2013-11-25 15:18:31 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-11-25 15:19:17 +0100 |
| commit | 4593fb5e29adc09cd53beaba8777f5656434c08d (patch) | |
| tree | 104b63db5384ad540451645294879e2cdc91ad28 | |
| parent | c378f7dbb882068d1ae06edc8e7049fb1907db2d (diff) | |
| download | luajit-4593fb5e29adc09cd53beaba8777f5656434c08d.tar.gz luajit-4593fb5e29adc09cd53beaba8777f5656434c08d.tar.bz2 luajit-4593fb5e29adc09cd53beaba8777f5656434c08d.zip | |
Add table.clear().
| -rw-r--r-- | doc/extensions.html | 16 | ||||
| -rw-r--r-- | src/Makefile.dep | 2 | ||||
| -rw-r--r-- | src/lib_table.c | 12 | ||||
| -rw-r--r-- | src/lj_ffrecord.c | 10 | ||||
| -rw-r--r-- | src/lj_ircall.h | 1 | ||||
| -rw-r--r-- | src/lj_opt_mem.c | 11 | ||||
| -rw-r--r-- | src/lj_tab.c | 11 | ||||
| -rw-r--r-- | 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 | |||
| 217 | too expensive. | 217 | too expensive. |
| 218 | </p> | 218 | </p> |
| 219 | 219 | ||
| 220 | <h3 id="table_clear"><tt>table.clear(tab)</tt> clears a table</h3> | ||
| 221 | <p> | ||
| 222 | An extra library function <tt>table.clear()</tt> can be made available | ||
| 223 | via <tt>require("table.clear")</tt>. This clears all keys and values | ||
| 224 | from a table, but preserves the allocated array/hash sizes. This is | ||
| 225 | useful when a table, which is linked from multiple places, needs to be | ||
| 226 | cleared and/or when recycling a table for use by the same context. This | ||
| 227 | avoids managing backlinks, saves an allocation and the overhead of | ||
| 228 | incremental array/hash part growth. | ||
| 229 | </p> | ||
| 230 | <p> | ||
| 231 | Please note this function is meant for very specific situations. In most | ||
| 232 | cases it's better to replace the (usually single) link with a new table | ||
| 233 | and let the GC do its work. | ||
| 234 | </p> | ||
| 235 | |||
| 220 | <h3 id="math_random">Enhanced PRNG for <tt>math.random()</tt></h3> | 236 | <h3 id="math_random">Enhanced PRNG for <tt>math.random()</tt></h3> |
| 221 | <p> | 237 | <p> |
| 222 | LuaJIT uses a Tausworthe PRNG with period 2^223 to implement | 238 | 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 \ | |||
| 155 | lj_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \ | 155 | lj_iropt.h lj_trace.h lj_dispatch.h lj_bc.h lj_traceerr.h lj_snap.h \ |
| 156 | lj_vm.h | 156 | lj_vm.h |
| 157 | lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ | 157 | lj_opt_mem.o: lj_opt_mem.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ |
| 158 | lj_tab.h lj_ir.h lj_jit.h lj_iropt.h | 158 | lj_tab.h lj_ir.h lj_jit.h lj_iropt.h lj_ircall.h |
| 159 | lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \ | 159 | lj_opt_narrow.o: lj_opt_narrow.c lj_obj.h lua.h luaconf.h lj_def.h \ |
| 160 | lj_arch.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \ | 160 | lj_arch.h lj_bc.h lj_ir.h lj_jit.h lj_iropt.h lj_trace.h lj_dispatch.h \ |
| 161 | lj_traceerr.h lj_vm.h lj_strscan.h | 161 | 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(.) | |||
| 273 | return 1; | 273 | return 1; |
| 274 | } | 274 | } |
| 275 | 275 | ||
| 276 | LJLIB_NOREG LJLIB_CF(table_clear) LJLIB_REC(.) | ||
| 277 | { | ||
| 278 | lj_tab_clear(lj_lib_checktab(L, 1)); | ||
| 279 | return 0; | ||
| 280 | } | ||
| 281 | |||
| 276 | static int luaopen_table_new(lua_State *L) | 282 | static int luaopen_table_new(lua_State *L) |
| 277 | { | 283 | { |
| 278 | return lj_lib_postreg(L, lj_cf_table_new, FF_table_new, "new"); | 284 | return lj_lib_postreg(L, lj_cf_table_new, FF_table_new, "new"); |
| 279 | } | 285 | } |
| 280 | 286 | ||
| 287 | static int luaopen_table_clear(lua_State *L) | ||
| 288 | { | ||
| 289 | return lj_lib_postreg(L, lj_cf_table_clear, FF_table_clear, "clear"); | ||
| 290 | } | ||
| 291 | |||
| 281 | /* ------------------------------------------------------------------------ */ | 292 | /* ------------------------------------------------------------------------ */ |
| 282 | 293 | ||
| 283 | #include "lj_libdef.h" | 294 | #include "lj_libdef.h" |
| @@ -290,6 +301,7 @@ LUALIB_API int luaopen_table(lua_State *L) | |||
| 290 | lua_setfield(L, -2, "unpack"); | 301 | lua_setfield(L, -2, "unpack"); |
| 291 | #endif | 302 | #endif |
| 292 | lj_lib_prereg(L, LUA_TABLIBNAME ".new", luaopen_table_new, tabV(L->top-1)); | 303 | lj_lib_prereg(L, LUA_TABLIBNAME ".new", luaopen_table_new, tabV(L->top-1)); |
| 304 | lj_lib_prereg(L, LUA_TABLIBNAME ".clear", luaopen_table_clear, tabV(L->top-1)); | ||
| 293 | return 1; | 305 | return 1; |
| 294 | } | 306 | } |
| 295 | 307 | ||
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) | |||
| 1024 | UNUSED(rd); | 1024 | UNUSED(rd); |
| 1025 | } | 1025 | } |
| 1026 | 1026 | ||
| 1027 | static void LJ_FASTCALL recff_table_clear(jit_State *J, RecordFFData *rd) | ||
| 1028 | { | ||
| 1029 | TRef tr = J->base[0]; | ||
| 1030 | if (tref_istab(tr)) { | ||
| 1031 | rd->nres = 0; | ||
| 1032 | lj_ir_call(J, IRCALL_lj_tab_clear, tr); | ||
| 1033 | J->needsnap = 1; | ||
| 1034 | } /* else: Interpreter will throw. */ | ||
| 1035 | } | ||
| 1036 | |||
| 1027 | /* -- I/O library fast functions ------------------------------------------ */ | 1037 | /* -- I/O library fast functions ------------------------------------------ */ |
| 1028 | 1038 | ||
| 1029 | /* Get FILE* for I/O function. Any I/O error aborts recording, so there's | 1039 | /* 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 { | |||
| 144 | _(ANY, lj_tab_new_ah, 3, A, TAB, CCI_L) \ | 144 | _(ANY, lj_tab_new_ah, 3, A, TAB, CCI_L) \ |
| 145 | _(ANY, lj_tab_new1, 2, FS, TAB, CCI_L) \ | 145 | _(ANY, lj_tab_new1, 2, FS, TAB, CCI_L) \ |
| 146 | _(ANY, lj_tab_dup, 2, FS, TAB, CCI_L) \ | 146 | _(ANY, lj_tab_dup, 2, FS, TAB, CCI_L) \ |
| 147 | _(ANY, lj_tab_clear, 1, FS, NIL, 0) \ | ||
| 147 | _(ANY, lj_tab_newkey, 3, S, P32, CCI_L) \ | 148 | _(ANY, lj_tab_newkey, 3, S, P32, CCI_L) \ |
| 148 | _(ANY, lj_tab_len, 1, FL, INT, 0) \ | 149 | _(ANY, lj_tab_len, 1, FL, INT, 0) \ |
| 149 | _(ANY, lj_gc_step_jit, 2, FS, NIL, CCI_L) \ | 150 | _(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 @@ | |||
| 17 | #include "lj_ir.h" | 17 | #include "lj_ir.h" |
| 18 | #include "lj_jit.h" | 18 | #include "lj_jit.h" |
| 19 | #include "lj_iropt.h" | 19 | #include "lj_iropt.h" |
| 20 | #include "lj_ircall.h" | ||
| 20 | 21 | ||
| 21 | /* Some local macros to save typing. Undef'd at the end. */ | 22 | /* Some local macros to save typing. Undef'd at the end. */ |
| 22 | #define IR(ref) (&J->cur.ir[(ref)]) | 23 | #define IR(ref) (&J->cur.ir[(ref)]) |
| @@ -308,7 +309,7 @@ int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J) | |||
| 308 | return 1; /* No conflict. Can fold to niltv. */ | 309 | return 1; /* No conflict. Can fold to niltv. */ |
| 309 | } | 310 | } |
| 310 | 311 | ||
| 311 | /* Check whether there's no aliasing NEWREF for the left operand. */ | 312 | /* Check whether there's no aliasing NEWREF/table.clear for the left operand. */ |
| 312 | int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) | 313 | int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) |
| 313 | { | 314 | { |
| 314 | IRRef ta = fins->op1; | 315 | IRRef ta = fins->op1; |
| @@ -319,6 +320,14 @@ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) | |||
| 319 | return 0; /* Conflict. */ | 320 | return 0; /* Conflict. */ |
| 320 | ref = newref->prev; | 321 | ref = newref->prev; |
| 321 | } | 322 | } |
| 323 | ref = J->chain[IR_CALLS]; | ||
| 324 | while (ref > lim) { | ||
| 325 | IRIns *calls = IR(ref); | ||
| 326 | if (calls->op2 == IRCALL_lj_tab_clear && | ||
| 327 | (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO)) | ||
| 328 | return 0; /* Conflict. */ | ||
| 329 | ref = calls->prev; | ||
| 330 | } | ||
| 322 | return 1; /* No conflict. Can safely FOLD/CSE. */ | 331 | return 1; /* No conflict. Can safely FOLD/CSE. */ |
| 323 | } | 332 | } |
| 324 | 333 | ||
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) | |||
| 204 | return t; | 204 | return t; |
| 205 | } | 205 | } |
| 206 | 206 | ||
| 207 | /* Clear a table. */ | ||
| 208 | void LJ_FASTCALL lj_tab_clear(GCtab *t) | ||
| 209 | { | ||
| 210 | clearapart(t); | ||
| 211 | if (t->hmask > 0) { | ||
| 212 | Node *node = noderef(t->node); | ||
| 213 | setmref(node->freetop, &node[t->hmask+1]); | ||
| 214 | clearhpart(t); | ||
| 215 | } | ||
| 216 | } | ||
| 217 | |||
| 207 | /* Free a table. */ | 218 | /* Free a table. */ |
| 208 | void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t) | 219 | void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t) |
| 209 | { | 220 | { |
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); | |||
| 39 | LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize); | 39 | LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize); |
| 40 | #endif | 40 | #endif |
| 41 | LJ_FUNCA GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt); | 41 | LJ_FUNCA GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt); |
| 42 | LJ_FUNC void LJ_FASTCALL lj_tab_clear(GCtab *t); | ||
| 42 | LJ_FUNC void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t); | 43 | LJ_FUNC void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t); |
| 43 | #if LJ_HASFFI | 44 | #if LJ_HASFFI |
| 44 | LJ_FUNC void lj_tab_rehash(lua_State *L, GCtab *t); | 45 | LJ_FUNC void lj_tab_rehash(lua_State *L, GCtab *t); |
