Skip to content
Permalink
Browse files
Add shared, use age bits
  • Loading branch information
cloudwu committed Apr 17, 2020
1 parent 7b412bb commit 24ae266
Show file tree
Hide file tree
Showing 7 changed files with 36 additions and 16 deletions.
@@ -904,6 +904,8 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) {
}
switch (ttype(obj)) {
case LUA_TTABLE: {
if (isshared(hvalue(obj)))
luaG_runerror(L, "can't setmetatable to shared table");
hvalue(obj)->metatable = mt;
if (mt) {
luaC_objbarrier(L, gcvalue(obj), mt);
@@ -192,7 +192,7 @@ static int iscleared (global_State *g, const GCObject *o) {
*/
void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
global_State *g = G(L);
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o));
lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o) && !isshared(o));
if (keepinvariant(g)) { /* must keep invariant? */
reallymarkobject(g, v); /* restore invariant */
if (isold(o)) {
@@ -213,7 +213,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) {
*/
void luaC_barrierback_ (lua_State *L, GCObject *o) {
global_State *g = G(L);
lua_assert(isblack(o) && !isdead(g, o));
lua_assert(isblack(o) && !isdead(g, o) && !isshared(o));
lua_assert(g->gckind != KGC_GEN || (isold(o) && getage(o) != G_TOUCHED1));
if (getage(o) != G_TOUCHED2) /* not already in gray list? */
linkobjgclist(o, g->grayagain); /* link it in 'grayagain' */
@@ -226,7 +226,8 @@ void luaC_fix (lua_State *L, GCObject *o) {
global_State *g = G(L);
lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */
white2gray(o); /* they will be gray forever */
setage(o, G_OLD); /* and old forever */
if (!isshared(o))
setage(o, G_OLD); /* and old forever */
g->allgc = o->next; /* remove object from 'allgc' list */
o->next = g->fixedgc; /* link it to 'fixedgc' list */
g->fixedgc = o;
@@ -266,6 +267,8 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
** to avoid barriers, as their values will be revisited by the thread.)
*/
static void reallymarkobject (global_State *g, GCObject *o) {
if (isshared(o))
return;
white2gray(o);
switch (o->tt) {
case LUA_VSHRSTR:
@@ -976,7 +979,9 @@ static void setpause (global_State *g);
static void sweep2old (lua_State *L, GCObject **p) {
GCObject *curr;
while ((curr = *p) != NULL) {
if (iswhite(curr)) { /* is 'curr' dead? */
if (isshared(curr))
p = &curr->next; /* go to next element */
else if (iswhite(curr)) { /* is 'curr' dead? */
lua_assert(isdead(G(L), curr));
*p = curr->next; /* remove 'curr' from list */
freeobj(L, curr); /* erase 'curr' */
@@ -1010,7 +1015,9 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p,
int white = luaC_white(g);
GCObject *curr;
while ((curr = *p) != limit) {
if (iswhite(curr)) { /* is 'curr' dead? */
if (isshared(curr))
p = &curr->next; /* go to next element */
else if (iswhite(curr)) { /* is 'curr' dead? */
lua_assert(!isold(curr) && isdead(g, curr));
*p = curr->next; /* remove 'curr' from list */
freeobj(L, curr); /* erase 'curr' */
@@ -107,13 +107,17 @@
#define G_OLD 4 /* really old object (not to be visited) */
#define G_TOUCHED1 5 /* old object touched this cycle */
#define G_TOUCHED2 6 /* old object touched in previous cycle */
#define G_SHARED 7 /* object is shared */

#define AGEBITS 7 /* all age bits (111) */

#define getage(o) ((o)->marked & AGEBITS)
#define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a))
#define isold(o) (getage(o) > G_SURVIVAL)

#define isshared(x) (getage(x) == G_SHARED)
#define makeshared(x) setage(x, G_SHARED)

#define changeage(o,f,t) \
check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t)))

@@ -160,15 +164,15 @@


#define luaC_barrier(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v)) && !isshared(gcvalue(v))) ? \
luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0))

#define luaC_barrierback(L,p,v) ( \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \
(iscollectable(v) && isblack(p) && iswhite(gcvalue(v)) && !isshared(gcvalue(v))) ? \
luaC_barrierback_(L,p) : cast_void(0))

#define luaC_objbarrier(L,p,o) ( \
(isblack(p) && iswhite(o)) ? \
(isblack(p) && iswhite(o) && !isshared(o)) ? \
luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0))

LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o);
@@ -100,7 +100,7 @@ typedef struct TValue {
*/
#define checkliveness(L,obj) \
((void)L, lua_longassert(!iscollectable(obj) || \
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))))
(righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj)) || isshared(gcvalue(obj))))))


/* Macros to set values */
@@ -760,7 +760,10 @@ const TValue *luaH_get (Table *t, const TValue *key) {
** barrier and invalidate the TM cache.
*/
TValue *luaH_set (lua_State *L, Table *t, const TValue *key) {
const TValue *p = luaH_get(t, key);
const TValue *p;
if(isshared(t))
luaG_runerror(L,"attempt to change a shared table");
p = luaH_get(t, key);
if (!isabstkey(p))
return cast(TValue *, p);
else return luaH_newkey(L, t, key);
@@ -334,6 +334,8 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
const TValue *tm; /* '__newindex' metamethod */
if (slot != NULL) { /* is 't' a table? */
Table *h = hvalue(t); /* save 't' table */
if (isshared(h))
luaG_typeerror(L, t, "change");
lua_assert(isempty(slot)); /* slot must be empty */
tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */
if (tm == NULL) { /* no metamethod? */
@@ -358,7 +360,7 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key,
return;
}
t = tm; /* else repeat assignment over 'tm' */
if (luaV_fastget(L, t, key, slot, luaH_get)) {
if (luaV_fastset(L, t, key, slot, luaH_get)) {
luaV_finishfastset(L, t, slot, val);
return; /* done */
}
@@ -1270,7 +1272,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
TValue *rb = KB(i);
TValue *rc = RKC(i);
TString *key = tsvalue(rb); /* key must be a string */
if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) {
if (luaV_fastset(L, upval, key, slot, luaH_getshortstr)) {
luaV_finishfastset(L, upval, slot, rc);
}
else
@@ -1283,8 +1285,8 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
TValue *rc = RKC(i); /* value */
lua_Unsigned n;
if (ttisinteger(rb) /* fast track for integers? */
? (cast_void(n = ivalue(rb)), luaV_fastgeti(L, s2v(ra), n, slot))
: luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) {
? (cast_void(n = ivalue(rb)), luaV_fastseti(L, s2v(ra), n, slot))
: luaV_fastset(L, s2v(ra), rb, slot, luaH_get)) {
luaV_finishfastset(L, s2v(ra), slot, rc);
}
else
@@ -1295,7 +1297,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
const TValue *slot;
int c = GETARG_B(i);
TValue *rc = RKC(i);
if (luaV_fastgeti(L, s2v(ra), c, slot)) {
if (luaV_fastseti(L, s2v(ra), c, slot)) {
luaV_finishfastset(L, s2v(ra), slot, rc);
}
else {
@@ -1310,7 +1312,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) {
TValue *rb = KB(i);
TValue *rc = RKC(i);
TString *key = tsvalue(rb); /* key must be a string */
if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) {
if (luaV_fastset(L, s2v(ra), key, slot, luaH_getshortstr)) {
luaV_finishfastset(L, s2v(ra), slot, rc);
}
else
@@ -86,6 +86,7 @@ typedef enum {
: (slot = f(hvalue(t), k), /* else, do raw access */ \
!isempty(slot))) /* result not empty? */

#define luaV_fastset(L,t,k,slot,f) (luaV_fastget(L,t,k,slot,f)) && !isshared(hvalue(t))

/*
** Special case of 'luaV_fastget' for integers, inlining the fast case
@@ -98,6 +99,7 @@ typedef enum {
? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \
!isempty(slot))) /* result not empty? */

#define luaV_fastseti(L,t,k,slot) (luaV_fastgeti(L,t,k,slot)) && !isshared(hvalue(t))

/*
** Finish a fast set operation (when fast get succeeds). In that case,

0 comments on commit 24ae266

Please sign in to comment.