aboutsummaryrefslogtreecommitdiff
path: root/src/lj_gc.c
diff options
context:
space:
mode:
authorMike Pall <mike>2010-04-25 03:32:29 +0200
committerMike Pall <mike>2010-04-25 03:32:29 +0200
commit721b73fecbbeda5b5cb76628511c5b3fac41eb4d (patch)
treece72efaa313ab16eda652e4d277413c31a8d2af3 /src/lj_gc.c
parent3a32bbc7cb5c2287e8d4e24e362281c165f50976 (diff)
downloadluajit-721b73fecbbeda5b5cb76628511c5b3fac41eb4d.tar.gz
luajit-721b73fecbbeda5b5cb76628511c5b3fac41eb4d.tar.bz2
luajit-721b73fecbbeda5b5cb76628511c5b3fac41eb4d.zip
Turn traces into true GC objects (GCtrace).
Diffstat (limited to 'src/lj_gc.c')
-rw-r--r--src/lj_gc.c68
1 files changed, 45 insertions, 23 deletions
diff --git a/src/lj_gc.c b/src/lj_gc.c
index b457c424..7c224759 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -214,8 +214,21 @@ static void gc_traverse_func(global_State *g, GCfunc *fn)
214} 214}
215 215
216#if LJ_HASJIT 216#if LJ_HASJIT
217/* Mark a trace. */
218static void gc_marktrace(global_State *g, TraceNo traceno)
219{
220 if (traceno && traceno != G2J(g)->curtrace) {
221 GCobj *o = obj2gco(traceref(G2J(g), traceno));
222 if (iswhite(o)) {
223 white2gray(o);
224 setgcrefr(o->gch.gclist, g->gc.gray);
225 setgcref(g->gc.gray, o);
226 }
227 }
228}
229
217/* Traverse a trace. */ 230/* Traverse a trace. */
218static void gc_traverse_trace(global_State *g, Trace *T) 231static void gc_traverse_trace(global_State *g, GCtrace *T)
219{ 232{
220 IRRef ref; 233 IRRef ref;
221 for (ref = T->nk; ref < REF_TRUE; ref++) { 234 for (ref = T->nk; ref < REF_TRUE; ref++) {
@@ -223,31 +236,23 @@ static void gc_traverse_trace(global_State *g, Trace *T)
223 if (ir->o == IR_KGC) 236 if (ir->o == IR_KGC)
224 gc_markobj(g, ir_kgc(ir)); 237 gc_markobj(g, ir_kgc(ir));
225 } 238 }
239 gc_marktrace(g, T->link);
240 gc_marktrace(g, T->nextroot);
241 gc_marktrace(g, T->nextside);
242 gc_markobj(g, gcref(T->startpt));
226} 243}
227 244
228/* The current trace is a GC root while not anchored in the prototype (yet). */ 245/* The current trace is a GC root while not anchored in the prototype (yet). */
229#define gc_mark_curtrace(g) \ 246#define gc_traverse_curtrace(g) \
230 { if (G2J(g)->curtrace != 0) gc_traverse_trace(g, &G2J(g)->cur); } 247 { if (G2J(g)->curtrace != 0) gc_traverse_trace(g, &G2J(g)->cur); }
231#else 248#else
232#define gc_mark_curtrace(g) UNUSED(g) 249#define gc_traverse_curtrace(g) UNUSED(g)
233#endif 250#endif
234 251
235/* Traverse a prototype. */ 252/* Traverse a prototype. */
236static void gc_traverse_proto(global_State *g, GCproto *pt) 253static void gc_traverse_proto(global_State *g, GCproto *pt)
237{ 254{
238 ptrdiff_t i; 255 ptrdiff_t i;
239#if LJ_HASJIT
240 jit_State *J = G2J(g);
241 TraceNo root, side;
242 /* Mark all root traces and attached side traces. */
243 for (root = pt->trace; root != 0; root = J->trace[root]->nextroot) {
244 for (side = J->trace[root]->nextside; side != 0;
245 side = J->trace[side]->nextside)
246 gc_traverse_trace(g, J->trace[side]);
247 gc_traverse_trace(g, J->trace[root]);
248 }
249#endif
250 /* GC during prototype creation could cause NULL fields. */
251 gc_mark_str(proto_chunkname(pt)); 256 gc_mark_str(proto_chunkname(pt));
252 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */ 257 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */
253 gc_markobj(g, proto_kgc(pt, i)); 258 gc_markobj(g, proto_kgc(pt, i));
@@ -255,6 +260,9 @@ static void gc_traverse_proto(global_State *g, GCproto *pt)
255 gc_mark_str(proto_uvname(pt, i)); 260 gc_mark_str(proto_uvname(pt, i));
256 for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */ 261 for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */
257 gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name))); 262 gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name)));
263#if LJ_HASJIT
264 gc_marktrace(g, pt->trace);
265#endif
258} 266}
259 267
260/* Traverse the frame structure of a stack. */ 268/* Traverse the frame structure of a stack. */
@@ -311,13 +319,23 @@ static size_t propagatemark(global_State *g)
311 GCproto *pt = gco2pt(o); 319 GCproto *pt = gco2pt(o);
312 gc_traverse_proto(g, pt); 320 gc_traverse_proto(g, pt);
313 return pt->sizept; 321 return pt->sizept;
314 } else { 322 } else if (LJ_LIKELY(o->gch.gct == ~LJ_TTHREAD)) {
315 lua_State *th = gco2th(o); 323 lua_State *th = gco2th(o);
316 setgcrefr(th->gclist, g->gc.grayagain); 324 setgcrefr(th->gclist, g->gc.grayagain);
317 setgcref(g->gc.grayagain, o); 325 setgcref(g->gc.grayagain, o);
318 black2gray(o); /* Threads are never black. */ 326 black2gray(o); /* Threads are never black. */
319 gc_traverse_thread(g, th); 327 gc_traverse_thread(g, th);
320 return sizeof(lua_State) + sizeof(TValue) * th->stacksize; 328 return sizeof(lua_State) + sizeof(TValue) * th->stacksize;
329 } else {
330#if LJ_HASJIT
331 GCtrace *T = gco2trace(o);
332 gc_traverse_trace(g, T);
333 return ((sizeof(GCtrace)+7)&~7) + (T->nins-T->nk)*sizeof(IRIns) +
334 T->nsnap*sizeof(SnapShot) + T->nsnapmap*sizeof(SnapEntry);
335#else
336 lua_assert(0);
337 return 0;
338#endif
321 } 339 }
322} 340}
323 341
@@ -351,7 +369,11 @@ static const GCFreeFunc gc_freefunc[] = {
351 (GCFreeFunc)lj_state_free, 369 (GCFreeFunc)lj_state_free,
352 (GCFreeFunc)lj_func_freeproto, 370 (GCFreeFunc)lj_func_freeproto,
353 (GCFreeFunc)lj_func_free, 371 (GCFreeFunc)lj_func_free,
372#if LJ_HASJIT
373 (GCFreeFunc)lj_trace_free,
374#else
354 (GCFreeFunc)0, 375 (GCFreeFunc)0,
376#endif
355 (GCFreeFunc)lj_tab_free, 377 (GCFreeFunc)lj_tab_free,
356 (GCFreeFunc)lj_udata_free 378 (GCFreeFunc)lj_udata_free
357}; 379};
@@ -502,7 +524,7 @@ static void atomic(global_State *g, lua_State *L)
502 setgcrefnull(g->gc.weak); 524 setgcrefnull(g->gc.weak);
503 lua_assert(!iswhite(obj2gco(mainthread(g)))); 525 lua_assert(!iswhite(obj2gco(mainthread(g))));
504 gc_markobj(g, L); /* Mark running thread. */ 526 gc_markobj(g, L); /* Mark running thread. */
505 gc_mark_curtrace(g); /* Mark current trace. */ 527 gc_traverse_curtrace(g); /* Traverse current trace. */
506 gc_mark_gcroot(g); /* Mark GC roots (again). */ 528 gc_mark_gcroot(g); /* Mark GC roots (again). */
507 gc_propagate_gray(g); /* Propagate all of the above. */ 529 gc_propagate_gray(g); /* Propagate all of the above. */
508 530
@@ -681,7 +703,7 @@ void lj_gc_barrierf(global_State *g, GCobj *o, GCobj *v)
681 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause); 703 lua_assert(g->gc.state != GCSfinalize && g->gc.state != GCSpause);
682 lua_assert(o->gch.gct != ~LJ_TTAB); 704 lua_assert(o->gch.gct != ~LJ_TTAB);
683 /* Preserve invariant during propagation. Otherwise it doesn't matter. */ 705 /* Preserve invariant during propagation. Otherwise it doesn't matter. */
684 if (g->gc.state == GCSpropagate) 706 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
685 gc_mark(g, v); /* Move frontier forward. */ 707 gc_mark(g, v); /* Move frontier forward. */
686 else 708 else
687 makewhite(g, o); /* Make it white to avoid the following barrier. */ 709 makewhite(g, o); /* Make it white to avoid the following barrier. */
@@ -692,7 +714,7 @@ void LJ_FASTCALL lj_gc_barrieruv(global_State *g, TValue *tv)
692{ 714{
693#define TV2MARKED(x) \ 715#define TV2MARKED(x) \
694 (*((uint8_t *)(x) - offsetof(GCupval, tv) + offsetof(GCupval, marked))) 716 (*((uint8_t *)(x) - offsetof(GCupval, tv) + offsetof(GCupval, marked)))
695 if (g->gc.state == GCSpropagate) 717 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
696 gc_mark(g, gcV(tv)); 718 gc_mark(g, gcV(tv));
697 else 719 else
698 TV2MARKED(tv) = (TV2MARKED(tv) & cast_byte(~LJ_GC_COLORS)) | curwhite(g); 720 TV2MARKED(tv) = (TV2MARKED(tv) & cast_byte(~LJ_GC_COLORS)) | curwhite(g);
@@ -710,7 +732,7 @@ void lj_gc_closeuv(global_State *g, GCupval *uv)
710 setgcrefr(o->gch.nextgc, g->gc.root); 732 setgcrefr(o->gch.nextgc, g->gc.root);
711 setgcref(g->gc.root, o); 733 setgcref(g->gc.root, o);
712 if (isgray(o)) { /* A closed upvalue is never gray, so fix this. */ 734 if (isgray(o)) { /* A closed upvalue is never gray, so fix this. */
713 if (g->gc.state == GCSpropagate) { 735 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic) {
714 gray2black(o); /* Make it black and preserve invariant. */ 736 gray2black(o); /* Make it black and preserve invariant. */
715 if (tviswhite(&uv->tv)) 737 if (tviswhite(&uv->tv))
716 lj_gc_barrierf(g, o, gcV(&uv->tv)); 738 lj_gc_barrierf(g, o, gcV(&uv->tv));
@@ -723,10 +745,10 @@ void lj_gc_closeuv(global_State *g, GCupval *uv)
723 745
724#if LJ_HASJIT 746#if LJ_HASJIT
725/* Mark a trace if it's saved during the propagation phase. */ 747/* Mark a trace if it's saved during the propagation phase. */
726void lj_gc_barriertrace(global_State *g, void *T) 748void lj_gc_barriertrace(global_State *g, uint32_t traceno)
727{ 749{
728 if (g->gc.state == GCSpropagate) 750 if (g->gc.state == GCSpropagate || g->gc.state == GCSatomic)
729 gc_traverse_trace(g, (Trace *)T); 751 gc_marktrace(g, traceno);
730} 752}
731#endif 753#endif
732 754