aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-07 11:21:44 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2020-08-07 11:21:44 -0300
commit7c3cb71fa48fbe84d9d9c664eb646446fb80898b (patch)
tree43d2b2282853b882877e42a0b8ec7467c9bb0e9e
parent68109afcdb59a7eeb75bacf055abce3e56a53645 (diff)
downloadlua-7c3cb71fa48fbe84d9d9c664eb646446fb80898b.tar.gz
lua-7c3cb71fa48fbe84d9d9c664eb646446fb80898b.tar.bz2
lua-7c3cb71fa48fbe84d9d9c664eb646446fb80898b.zip
Free bit 7 of GC 'marked' field
Tables were using this bit to indicate their array sizes were real ('isrealasize'), but this bit can be useful for tests. Instead, they can use bit 7 of their 'flag' field for that purpose. (There are only six fast-access metamethods.) This 'flag' field only exists in tables, so this use does not affect other types.
-rw-r--r--lgc.h3
-rw-r--r--lobject.h6
-rw-r--r--ltable.c2
-rw-r--r--ltable.h7
-rw-r--r--ltm.h9
-rw-r--r--testes/events.lua11
6 files changed, 31 insertions, 7 deletions
diff --git a/lgc.h b/lgc.h
index b972472f..f571fd2b 100644
--- a/lgc.h
+++ b/lgc.h
@@ -69,8 +69,7 @@
69 69
70/* 70/*
71** Layout for bit use in 'marked' field. First three bits are 71** Layout for bit use in 'marked' field. First three bits are
72** used for object "age" in generational mode. Last bit is free 72** used for object "age" in generational mode.
73** to be used by respective objects.
74*/ 73*/
75#define WHITE0BIT 3 /* object is white (type 0) */ 74#define WHITE0BIT 3 /* object is white (type 0) */
76#define WHITE1BIT 4 /* object is white (type 1) */ 75#define WHITE1BIT 4 /* object is white (type 1) */
diff --git a/lobject.h b/lobject.h
index 16202230..a9d45785 100644
--- a/lobject.h
+++ b/lobject.h
@@ -704,9 +704,9 @@ typedef union Node {
704*/ 704*/
705 705
706#define BITRAS (1 << 7) 706#define BITRAS (1 << 7)
707#define isrealasize(t) (!((t)->marked & BITRAS)) 707#define isrealasize(t) (!((t)->flags & BITRAS))
708#define setrealasize(t) ((t)->marked &= cast_byte(~BITRAS)) 708#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS))
709#define setnorealasize(t) ((t)->marked |= BITRAS) 709#define setnorealasize(t) ((t)->flags |= BITRAS)
710 710
711 711
712typedef struct Table { 712typedef struct Table {
diff --git a/ltable.c b/ltable.c
index d7eb69a2..5a0d066f 100644
--- a/ltable.c
+++ b/ltable.c
@@ -583,7 +583,7 @@ Table *luaH_new (lua_State *L) {
583 GCObject *o = luaC_newobj(L, LUA_VTABLE, sizeof(Table)); 583 GCObject *o = luaC_newobj(L, LUA_VTABLE, sizeof(Table));
584 Table *t = gco2t(o); 584 Table *t = gco2t(o);
585 t->metatable = NULL; 585 t->metatable = NULL;
586 t->flags = cast_byte(~0); 586 t->flags = cast_byte(maskflags); /* table has no metamethod fields */
587 t->array = NULL; 587 t->array = NULL;
588 t->alimit = 0; 588 t->alimit = 0;
589 setnodevector(L, t, 0); 589 setnodevector(L, t, 0);
diff --git a/ltable.h b/ltable.h
index ebd7f8ec..c0060f4b 100644
--- a/ltable.h
+++ b/ltable.h
@@ -15,7 +15,12 @@
15#define gnext(n) ((n)->u.next) 15#define gnext(n) ((n)->u.next)
16 16
17 17
18#define invalidateTMcache(t) ((t)->flags = 0) 18/*
19** Clear all bits of fast-access metamethods, which means that the table
20** may have any of these metamethods. (First access that fails after the
21** clearing will set the bit again.)
22*/
23#define invalidateTMcache(t) ((t)->flags &= ~maskflags)
19 24
20 25
21/* true when 't' is using 'dummynode' as its hash part */ 26/* true when 't' is using 'dummynode' as its hash part */
diff --git a/ltm.h b/ltm.h
index 99b545e7..73b833c6 100644
--- a/ltm.h
+++ b/ltm.h
@@ -46,6 +46,15 @@ typedef enum {
46 46
47 47
48/* 48/*
49** Mask with 1 in all fast-access methods. A 1 in any of these bits
50** in the flag of a (meta)table means the metatable does not have the
51** corresponding metamethod field. (Bit 7 of the flag is used for
52** 'isrealasize'.)
53*/
54#define maskflags (~(~0u << (TM_EQ + 1)))
55
56
57/*
49** Test whether there is no tagmethod. 58** Test whether there is no tagmethod.
50** (Because tagmethods use raw accesses, the result may be an "empty" nil.) 59** (Because tagmethods use raw accesses, the result may be an "empty" nil.)
51*/ 60*/
diff --git a/testes/events.lua b/testes/events.lua
index 8a01330e..17a73664 100644
--- a/testes/events.lua
+++ b/testes/events.lua
@@ -305,6 +305,17 @@ t[Set{1,3,5}] = 1
305assert(t[Set{1,3,5}] == undef) 305assert(t[Set{1,3,5}] == undef)
306 306
307 307
308do -- test invalidating flags
309 local mt = {__eq = true}
310 local a = setmetatable({10}, mt)
311 local b = setmetatable({10}, mt)
312 mt.__eq = nil
313 assert(a ~= b) -- no metamethod
314 mt.__eq = function (x,y) return x[1] == y[1] end
315 assert(a == b) -- must use metamethod now
316end
317
318
308if not T then 319if not T then
309 (Message or print)('\n >>> testC not active: skipping tests for \z 320 (Message or print)('\n >>> testC not active: skipping tests for \z
310userdata <<<\n') 321userdata <<<\n')