diff options
author | Mike Pall <mike> | 2010-04-25 03:32:29 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2010-04-25 03:32:29 +0200 |
commit | 721b73fecbbeda5b5cb76628511c5b3fac41eb4d (patch) | |
tree | ce72efaa313ab16eda652e4d277413c31a8d2af3 /src/lj_gc.c | |
parent | 3a32bbc7cb5c2287e8d4e24e362281c165f50976 (diff) | |
download | luajit-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.c | 68 |
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. */ | ||
218 | static 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. */ |
218 | static void gc_traverse_trace(global_State *g, Trace *T) | 231 | static 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. */ |
236 | static void gc_traverse_proto(global_State *g, GCproto *pt) | 253 | static 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. */ |
726 | void lj_gc_barriertrace(global_State *g, void *T) | 748 | void 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 | ||