diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-07 11:21:44 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-08-07 11:21:44 -0300 |
commit | 7c3cb71fa48fbe84d9d9c664eb646446fb80898b (patch) | |
tree | 43d2b2282853b882877e42a0b8ec7467c9bb0e9e | |
parent | 68109afcdb59a7eeb75bacf055abce3e56a53645 (diff) | |
download | lua-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.h | 3 | ||||
-rw-r--r-- | lobject.h | 6 | ||||
-rw-r--r-- | ltable.c | 2 | ||||
-rw-r--r-- | ltable.h | 7 | ||||
-rw-r--r-- | ltm.h | 9 | ||||
-rw-r--r-- | testes/events.lua | 11 |
6 files changed, 31 insertions, 7 deletions
@@ -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) */ |
@@ -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 | ||
712 | typedef struct Table { | 712 | typedef struct Table { |
@@ -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); |
@@ -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 */ |
@@ -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 | |||
305 | assert(t[Set{1,3,5}] == undef) | 305 | assert(t[Set{1,3,5}] == undef) |
306 | 306 | ||
307 | 307 | ||
308 | do -- 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 | ||
316 | end | ||
317 | |||
318 | |||
308 | if not T then | 319 | if 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 |
310 | userdata <<<\n') | 321 | userdata <<<\n') |