Skip to content

Commit ee1d7b7

Browse files
committed
luajit: implement read-only tables
1 parent f341f0c commit ee1d7b7

6 files changed

Lines changed: 80 additions & 3 deletions

File tree

LuaJIT-2.1/src/lib_table.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,24 @@ LJLIB_CF(table_pack)
286286
}
287287
#endif
288288

289+
LJLIB_CF(table_setreadonly)
290+
{
291+
GCtab *t = lj_lib_checktab(L, 1);
292+
int readOnly = lj_lib_checkint(L, 2) != 0;
293+
294+
lj_tab_setreadonly(t, readOnly);
295+
return 0;
296+
}
297+
298+
LJLIB_CF(table_isreadonly)
299+
{
300+
GCtab *t = lj_lib_checktab(L, 1);
301+
int readOnly = lj_lib_checkint(L, 2) != 0;
302+
303+
lua_pushboolean(L, lj_tab_isreadonly(t));
304+
return 1;
305+
}
306+
289307
LJLIB_NOREG LJLIB_CF(table_new) LJLIB_REC(.)
290308
{
291309
int32_t a = lj_lib_checkint(L, 1);
@@ -296,7 +314,7 @@ LJLIB_NOREG LJLIB_CF(table_new) LJLIB_REC(.)
296314

297315
LJLIB_NOREG LJLIB_CF(table_clear) LJLIB_REC(.)
298316
{
299-
lj_tab_clear(lj_lib_checktab(L, 1));
317+
lj_tab_clear(L, lj_lib_checktab(L, 1));
300318
return 0;
301319
}
302320

LuaJIT-2.1/src/lj_errmsg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ ERRDEF(TABOV, "table overflow")
2121
ERRDEF(NANIDX, "table index is NaN")
2222
ERRDEF(NILIDX, "table index is nil")
2323
ERRDEF(NEXTIDX, "invalid key to " LUA_QL("next"))
24+
ERRDEF(READONLY, "table is in read only")
2425

2526
/* Metamethod resolving. */
2627
ERRDEF(BADCALL, "attempt to call a %s value")

LuaJIT-2.1/src/lj_gc.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ enum {
2323
#define LJ_GC_CDATA_FIN 0x10
2424
#define LJ_GC_FIXED 0x20
2525
#define LJ_GC_SFIXED 0x40
26+
#define LJ_GC_READONLY 0x80
2627

2728
#define LJ_GC_WHITES (LJ_GC_WHITE0 | LJ_GC_WHITE1)
2829
#define LJ_GC_COLORS (LJ_GC_WHITES | LJ_GC_BLACK)
@@ -45,6 +46,10 @@ enum {
4546
#define fixstring(s) ((s)->marked |= LJ_GC_FIXED)
4647
#define markfinalized(x) ((x)->gch.marked |= LJ_GC_FINALIZED)
4748

49+
#define isreadonly(x) ((x)->marked & LJ_GC_READONLY)
50+
#define markreadonly(x) ((x)->marked |= LJ_GC_READONLY)
51+
#define unmarkreadonly(x) ((x)->marked &= ~LJ_GC_READONLY)
52+
4853
/* Collector. */
4954
LJ_FUNC size_t lj_gc_separateudata(global_State *g, int all);
5055
LJ_FUNC void lj_gc_finalize_udata(lua_State *L);

LuaJIT-2.1/src/lj_meta.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ TValue *lj_meta_tset(lua_State *L, cTValue *o, cTValue *k)
166166
cTValue *mo;
167167
if (LJ_LIKELY(tvistab(o))) {
168168
GCtab *t = tabV(o);
169+
if (isreadonly(t))
170+
{
171+
lj_err_msg(L, LJ_ERR_READONLY);
172+
return NULL;
173+
}
174+
169175
cTValue *tv = lj_tab_get(L, t, k);
170176
if (LJ_LIKELY(!tvisnil(tv))) {
171177
t->nomm = 0; /* Invalidate negative metamethod cache. */

LuaJIT-2.1/src/lj_tab.c

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "lj_gc.h"
1414
#include "lj_err.h"
1515
#include "lj_tab.h"
16+
#include "lj_lib.h"
1617

1718
/* -- Object hashing ------------------------------------------------------ */
1819

@@ -201,8 +202,13 @@ GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt)
201202
}
202203

203204
/* Clear a table. */
204-
void LJ_FASTCALL lj_tab_clear(GCtab *t)
205+
void LJ_FASTCALL lj_tab_clear(lua_State* L, GCtab *t)
205206
{
207+
if (isreadonly(t))
208+
{
209+
lj_err_msg(L, LJ_ERR_READONLY);
210+
}
211+
206212
clearapart(t);
207213
if (t->hmask > 0) {
208214
Node *node = noderef(t->node);
@@ -229,6 +235,11 @@ void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t)
229235
/* Resize a table to fit the new array/hash part sizes. */
230236
void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits)
231237
{
238+
if (isreadonly(t))
239+
{
240+
lj_err_msg(L, LJ_ERR_READONLY);
241+
}
242+
232243
Node *oldnode = noderef(t->node);
233244
uint32_t oldasize = t->asize;
234245
uint32_t oldhmask = t->hmask;
@@ -434,6 +445,11 @@ cTValue *lj_tab_get(lua_State *L, GCtab *t, cTValue *key)
434445
/* Insert new key. Use Brent's variation to optimize the chain length. */
435446
TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
436447
{
448+
if (isreadonly(t))
449+
{
450+
lj_err_msg(L, LJ_ERR_READONLY);
451+
}
452+
437453
Node *n = hashkey(t, key);
438454
if (!tvisnil(&n->val) || t->hmask == 0) {
439455
Node *nodebase = noderef(t->node);
@@ -509,6 +525,11 @@ TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key)
509525

510526
TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key)
511527
{
528+
if (isreadonly(t))
529+
{
530+
lj_err_msg(L, LJ_ERR_READONLY);
531+
}
532+
512533
TValue k;
513534
Node *n;
514535
k.n = (lua_Number)key;
@@ -522,6 +543,11 @@ TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key)
522543

523544
TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key)
524545
{
546+
if (isreadonly(t))
547+
{
548+
lj_err_msg(L, LJ_ERR_READONLY);
549+
}
550+
525551
TValue k;
526552
Node *n = hashstr(t, key);
527553
do {
@@ -534,6 +560,11 @@ TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key)
534560

535561
TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key)
536562
{
563+
if (isreadonly(t))
564+
{
565+
lj_err_msg(L, LJ_ERR_READONLY);
566+
}
567+
537568
Node *n;
538569
t->nomm = 0; /* Invalidate negative metamethod cache. */
539570
if (tvisstr(key)) {
@@ -684,3 +715,17 @@ MSize LJ_FASTCALL lj_tab_len_hint(GCtab *t, size_t hint)
684715
}
685716
#endif
686717

718+
void LJ_FASTCALL lj_tab_setreadonly(GCtab *t, int readOnly)
719+
{
720+
if (readOnly != 0)
721+
{
722+
markreadonly(t);
723+
} else {
724+
unmarkreadonly(t);
725+
}
726+
}
727+
728+
int LJ_FASTCALL lj_tab_isreadonly(GCtab *t)
729+
{
730+
return isreadonly(t);
731+
}

LuaJIT-2.1/src/lj_tab.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ LJ_FUNC GCtab *lj_tab_new_ah(lua_State *L, int32_t a, int32_t h);
5858
LJ_FUNC GCtab * LJ_FASTCALL lj_tab_new1(lua_State *L, uint32_t ahsize);
5959
#endif
6060
LJ_FUNCA GCtab * LJ_FASTCALL lj_tab_dup(lua_State *L, const GCtab *kt);
61-
LJ_FUNC void LJ_FASTCALL lj_tab_clear(GCtab *t);
61+
LJ_FUNC void LJ_FASTCALL lj_tab_clear(lua_State* L, GCtab *t);
6262
LJ_FUNC void LJ_FASTCALL lj_tab_free(global_State *g, GCtab *t);
6363
LJ_FUNC void lj_tab_resize(lua_State *L, GCtab *t, uint32_t asize, uint32_t hbits);
6464
LJ_FUNCA void lj_tab_reasize(lua_State *L, GCtab *t, uint32_t nasize);
@@ -75,6 +75,8 @@ LJ_FUNCA TValue *lj_tab_newkey(lua_State *L, GCtab *t, cTValue *key);
7575
LJ_FUNCA TValue *lj_tab_setinth(lua_State *L, GCtab *t, int32_t key);
7676
LJ_FUNC TValue *lj_tab_setstr(lua_State *L, GCtab *t, const GCstr *key);
7777
LJ_FUNC TValue *lj_tab_set(lua_State *L, GCtab *t, cTValue *key);
78+
LJ_FUNC void LJ_FASTCALL lj_tab_setreadonly(GCtab *t, int readOnly);
79+
LJ_FUNC int LJ_FASTCALL lj_tab_isreadonly(GCtab *t);
7880

7981
#define inarray(t, key) ((MSize)(key) < (MSize)(t)->asize)
8082
#define arrayslot(t, i) (&tvref((t)->array)[(i)])

0 commit comments

Comments
 (0)