3 ** Copyright (C) 2005-2023 Mike Pall. See Copyright Notice in luajit.h
11 /* Garbage collector states. Order matters. */
13 GCSpause
, GCSpropagate
, GCSatomic
, GCSsweepstring
, GCSsweep
, GCSfinalize
16 /* Bitmasks for marked field of GCobj. */
17 #define LJ_GC_WHITE0 0x01
18 #define LJ_GC_WHITE1 0x02
19 #define LJ_GC_BLACK 0x04
20 #define LJ_GC_FINALIZED 0x08
21 #define LJ_GC_WEAKKEY 0x08
22 #define LJ_GC_WEAKVAL 0x10
23 #define LJ_GC_CDATA_FIN 0x10
24 #define LJ_GC_FIXED 0x20
25 #define LJ_GC_SFIXED 0x40
27 #define LJ_GC_WHITES (LJ_GC_WHITE0 | LJ_GC_WHITE1)
28 #define LJ_GC_COLORS (LJ_GC_WHITES | LJ_GC_BLACK)
29 #define LJ_GC_WEAK (LJ_GC_WEAKKEY | LJ_GC_WEAKVAL)
31 /* Macros to test and set GCobj colors. */
32 #define iswhite(x) ((x)->gch.marked & LJ_GC_WHITES)
33 #define isblack(x) ((x)->gch.marked & LJ_GC_BLACK)
34 #define isgray(x) (!((x)->gch.marked & (LJ_GC_BLACK|LJ_GC_WHITES)))
35 #define tviswhite(x) (tvisgcv(x) && iswhite(gcV(x)))
36 #define otherwhite(g) (g->gc.currentwhite ^ LJ_GC_WHITES)
37 #define isdead(g, v) ((v)->gch.marked & otherwhite(g) & LJ_GC_WHITES)
39 #define curwhite(g) ((g)->gc.currentwhite & LJ_GC_WHITES)
40 #define newwhite(g, x) (obj2gco(x)->gch.marked = (uint8_t)curwhite(g))
41 #define makewhite(g, x) \
42 ((x)->gch.marked = ((x)->gch.marked & (uint8_t)~LJ_GC_COLORS) | curwhite(g))
43 #define flipwhite(x) ((x)->gch.marked ^= LJ_GC_WHITES)
44 #define black2gray(x) ((x)->gch.marked &= (uint8_t)~LJ_GC_BLACK)
45 #define fixstring(s) ((s)->marked |= LJ_GC_FIXED)
46 #define markfinalized(x) ((x)->gch.marked |= LJ_GC_FINALIZED)
49 LJ_FUNC
size_t lj_gc_separateudata(global_State
*g
, int all
);
50 LJ_FUNC
void lj_gc_finalize_udata(lua_State
*L
);
52 LJ_FUNC
void lj_gc_finalize_cdata(lua_State
*L
);
54 #define lj_gc_finalize_cdata(L) UNUSED(L)
56 LJ_FUNC
void lj_gc_freeall(global_State
*g
);
57 LJ_FUNCA
int LJ_FASTCALL
lj_gc_step(lua_State
*L
);
58 LJ_FUNCA
void LJ_FASTCALL
lj_gc_step_fixtop(lua_State
*L
);
60 LJ_FUNC
int LJ_FASTCALL
lj_gc_step_jit(global_State
*g
, MSize steps
);
62 LJ_FUNC
void lj_gc_fullgc(lua_State
*L
);
64 /* GC check: drive collector forward if the GC threshold has been reached. */
65 #define lj_gc_check(L) \
66 { if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \
68 #define lj_gc_check_fixtop(L) \
69 { if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \
70 lj_gc_step_fixtop(L); }
73 LJ_FUNC
void lj_gc_barrierf(global_State
*g
, GCobj
*o
, GCobj
*v
);
74 LJ_FUNCA
void LJ_FASTCALL
lj_gc_barrieruv(global_State
*g
, TValue
*tv
);
75 LJ_FUNC
void lj_gc_closeuv(global_State
*g
, GCupval
*uv
);
77 LJ_FUNC
void lj_gc_barriertrace(global_State
*g
, uint32_t traceno
);
80 /* Move the GC propagation frontier back for tables (make it gray again). */
81 static LJ_AINLINE
void lj_gc_barrierback(global_State
*g
, GCtab
*t
)
83 GCobj
*o
= obj2gco(t
);
84 lj_assertG(isblack(o
) && !isdead(g
, o
),
85 "bad object states for backward barrier");
86 lj_assertG(g
->gc
.state
!= GCSfinalize
&& g
->gc
.state
!= GCSpause
,
89 setgcrefr(t
->gclist
, g
->gc
.grayagain
);
90 setgcref(g
->gc
.grayagain
, o
);
93 /* Barrier for stores to table objects. TValue and GCobj variant. */
94 #define lj_gc_anybarriert(L, t) \
95 { if (LJ_UNLIKELY(isblack(obj2gco(t)))) lj_gc_barrierback(G(L), (t)); }
96 #define lj_gc_barriert(L, t, tv) \
97 { if (tviswhite(tv) && isblack(obj2gco(t))) \
98 lj_gc_barrierback(G(L), (t)); }
99 #define lj_gc_objbarriert(L, t, o) \
100 { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) \
101 lj_gc_barrierback(G(L), (t)); }
103 /* Barrier for stores to any other object. TValue and GCobj variant. */
104 #define lj_gc_barrier(L, p, tv) \
105 { if (tviswhite(tv) && isblack(obj2gco(p))) \
106 lj_gc_barrierf(G(L), obj2gco(p), gcV(tv)); }
107 #define lj_gc_objbarrier(L, p, o) \
108 { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \
109 lj_gc_barrierf(G(L), obj2gco(p), obj2gco(o)); }
112 LJ_FUNC
void *lj_mem_realloc(lua_State
*L
, void *p
, GCSize osz
, GCSize nsz
);
113 LJ_FUNC
void * LJ_FASTCALL
lj_mem_newgco(lua_State
*L
, GCSize size
);
114 LJ_FUNC
void *lj_mem_grow(lua_State
*L
, void *p
,
115 MSize
*szp
, MSize lim
, MSize esz
);
117 #define lj_mem_new(L, s) lj_mem_realloc(L, NULL, 0, (s))
119 static LJ_AINLINE
void lj_mem_free(global_State
*g
, void *p
, size_t osize
)
121 g
->gc
.total
-= (GCSize
)osize
;
122 g
->allocf(g
->allocd
, p
, osize
, 0);
125 #define lj_mem_newvec(L, n, t) ((t *)lj_mem_new(L, (GCSize)((n)*sizeof(t))))
126 #define lj_mem_reallocvec(L, p, on, n, t) \
127 ((p) = (t *)lj_mem_realloc(L, p, (on)*sizeof(t), (GCSize)((n)*sizeof(t))))
128 #define lj_mem_growvec(L, p, n, m, t) \
129 ((p) = (t *)lj_mem_grow(L, (p), &(n), (m), (MSize)sizeof(t)))
130 #define lj_mem_freevec(g, p, n, t) lj_mem_free(g, (p), (n)*sizeof(t))
132 #define lj_mem_newobj(L, t) ((t *)lj_mem_newgco(L, sizeof(t)))
133 #define lj_mem_newt(L, s, t) ((t *)lj_mem_new(L, (s)))
134 #define lj_mem_freet(g, p) lj_mem_free(g, (p), sizeof(*(p)))