lj_gc.h (5202B)
1 /* 2 ** Garbage collector. 3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h 4 */ 5 6 #ifndef _LJ_GC_H 7 #define _LJ_GC_H 8 9 #include "lj_obj.h" 10 11 /* Garbage collector states. Order matters. */ 12 enum { 13 GCSpause, GCSpropagate, GCSatomic, GCSsweepstring, GCSsweep, GCSfinalize 14 }; 15 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_WEAKKEY 0x08 21 #define LJ_GC_WEAKVAL 0x10 22 #define LJ_GC_CDATAV 0x10 23 #define LJ_GC_FIXED 0x20 24 #define LJ_GC_SFIXED 0x40 25 #define LJ_GC_FINALIZED 0x80 /* CAVEAT: For udata, it means fin has been called. 26 * For CDATA and tables, it means finalizer is 27 * yet to be called (and one is in place). */ 28 29 #define LJ_GC_WHITES (LJ_GC_WHITE0 | LJ_GC_WHITE1) 30 #define LJ_GC_COLORS (LJ_GC_WHITES | LJ_GC_BLACK) 31 #define LJ_GC_WEAK (LJ_GC_WEAKKEY | LJ_GC_WEAKVAL) 32 33 /* Macros to test and set GCobj colors. */ 34 #define iswhite(x) ((x)->gch.marked & LJ_GC_WHITES) 35 #define isblack(x) ((x)->gch.marked & LJ_GC_BLACK) 36 #define isgray(x) (!((x)->gch.marked & (LJ_GC_BLACK|LJ_GC_WHITES))) 37 #define tviswhite(x) (tvisgcv(x) && iswhite(gcV(x))) 38 #define otherwhite(g) (g->gc.currentwhite ^ LJ_GC_WHITES) 39 #define isdead(g, v) ((v)->gch.marked & otherwhite(g) & LJ_GC_WHITES) 40 41 #define curwhite(g) ((g)->gc.currentwhite & LJ_GC_WHITES) 42 #define newwhite(g, x) (obj2gco(x)->gch.marked = (uint8_t)curwhite(g)) 43 #define makewhite(g, x) \ 44 ((x)->gch.marked = ((x)->gch.marked & (uint8_t)~LJ_GC_COLORS) | curwhite(g)) 45 #define flipwhite(x) ((x)->gch.marked ^= LJ_GC_WHITES) 46 #define black2gray(x) ((x)->gch.marked &= (uint8_t)~LJ_GC_BLACK) 47 #define fixstring(s) ((s)->marked |= LJ_GC_FIXED) 48 #define markfinalized(x) ((x)->gch.marked |= LJ_GC_FINALIZED) 49 #define clearfinalized(x) ((x)->gch.marked &= ~LJ_GC_FINALIZED) 50 51 /* Collector. */ 52 LJ_FUNC size_t lj_gc_separateudata(global_State *g, int all); 53 LJ_FUNC void lj_gc_finalize_udata(lua_State *L); 54 LJ_FUNC void lj_gc_tab_finalized(lua_State *L, GCobj *o); 55 #if LJ_HASFFI 56 LJ_FUNC void lj_gc_finalize_cdata(lua_State *L); 57 #else 58 #define lj_gc_finalize_cdata(L) UNUSED(L) 59 #endif 60 LJ_FUNC void lj_gc_freeall(global_State *g); 61 LJ_FUNCA int LJ_FASTCALL lj_gc_step(lua_State *L); 62 LJ_FUNCA void LJ_FASTCALL lj_gc_step_fixtop(lua_State *L); 63 #if LJ_HASJIT 64 LJ_FUNC int LJ_FASTCALL lj_gc_step_jit(global_State *g, MSize steps); 65 #endif 66 LJ_FUNC void lj_gc_fullgc(lua_State *L); 67 68 /* GC check: drive collector forward if the GC threshold has been reached. */ 69 #define lj_gc_check(L) \ 70 { if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \ 71 lj_gc_step(L); } 72 #define lj_gc_check_fixtop(L) \ 73 { if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) \ 74 lj_gc_step_fixtop(L); } 75 76 /* Write barriers. */ 77 LJ_FUNC void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v); 78 LJ_FUNCA void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv); 79 LJ_FUNC void lj_gc_closeuv(global_State *g, GCupval *uv); 80 #if LJ_HASJIT 81 LJ_FUNC void lj_gc_barriertrace(global_State *g, uint32_t traceno); 82 #endif 83 84 /* Move the GC propagation frontier back for tables (make it gray again). */ 85 static LJ_AINLINE void lj_gc_barrierback(global_State *g, GCtab *t) 86 { 87 GCobj *o = obj2gco(t); 88 lua_assert(isblack(o) && !isdead(g, o)); 89 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause); 90 black2gray(o); 91 setgcrefr(t->gclist, g->gc.grayagain); 92 setgcref(g->gc.grayagain, o); 93 } 94 95 /* Barrier for stores to table objects. TValue and GCobj variant. */ 96 #define lj_gc_anybarriert(L, t) \ 97 { if (LJ_UNLIKELY(isblack(obj2gco(t)))) lj_gc_barrierback(G(L), (t)); } 98 #define lj_gc_barriert(L, t, tv) \ 99 { if (tviswhite(tv) && isblack(obj2gco(t))) \ 100 lj_gc_barrierback(G(L), (t)); } 101 #define lj_gc_objbarriert(L, t, o) \ 102 { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) \ 103 lj_gc_barrierback(G(L), (t)); } 104 105 /* Barrier for stores to any other object. TValue and GCobj variant. */ 106 #define lj_gc_barrier(L, p, tv) \ 107 { if (tviswhite(tv) && isblack(obj2gco(p))) \ 108 lj_gc_barrierf(G(L), obj2gco(p), gcV(tv)); } 109 #define lj_gc_objbarrier(L, p, o) \ 110 { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ 111 lj_gc_barrierf(G(L), obj2gco(p), obj2gco(o)); } 112 113 /* Allocator. */ 114 LJ_FUNC void *lj_mem_realloc(lua_State *L, void *p, GCSize osz, GCSize nsz); 115 LJ_FUNC void * LJ_FASTCALL lj_mem_newgco(lua_State *L, GCSize size); 116 LJ_FUNC void *lj_mem_grow(lua_State *L, void *p, 117 MSize *szp, MSize lim, MSize esz); 118 119 #define lj_mem_new(L, s) lj_mem_realloc(L, NULL, 0, (s)) 120 121 static LJ_AINLINE void lj_mem_free(global_State *g, void *p, size_t osize) 122 { 123 g->gc.total -= (GCSize)osize; 124 g->allocf(g->allocd, p, osize, 0); 125 } 126 127 #define lj_mem_newvec(L, n, t) ((t *)lj_mem_new(L, (GCSize)((n)*sizeof(t)))) 128 #define lj_mem_reallocvec(L, p, on, n, t) \ 129 ((p) = (t *)lj_mem_realloc(L, p, (on)*sizeof(t), (GCSize)((n)*sizeof(t)))) 130 #define lj_mem_growvec(L, p, n, m, t) \ 131 ((p) = (t *)lj_mem_grow(L, (p), &(n), (m), (MSize)sizeof(t))) 132 #define lj_mem_freevec(g, p, n, t) lj_mem_free(g, (p), (n)*sizeof(t)) 133 134 #define lj_mem_newobj(L, t) ((t *)lj_mem_newgco(L, sizeof(t))) 135 #define lj_mem_newt(L, s, t) ((t *)lj_mem_new(L, (s))) 136 #define lj_mem_freet(g, p) lj_mem_free(g, (p), sizeof(*(p))) 137 138 #endif