aboutsummaryrefslogtreecommitdiff
path: root/src/lj_gc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_gc.c')
-rw-r--r--src/lj_gc.c57
1 files changed, 27 insertions, 30 deletions
diff --git a/src/lj_gc.c b/src/lj_gc.c
index d38238dd..18c07533 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -442,6 +442,7 @@ static void gc_finalize(lua_State *L)
442 GCobj *o = gcnext(gcref(g->gc.mmudata)); 442 GCobj *o = gcnext(gcref(g->gc.mmudata));
443 GCudata *ud = gco2ud(o); 443 GCudata *ud = gco2ud(o);
444 cTValue *mo; 444 cTValue *mo;
445 lua_assert(gcref(g->jit_L) == NULL); /* Must not be called on trace. */
445 /* Unchain from list of userdata to be finalized. */ 446 /* Unchain from list of userdata to be finalized. */
446 if (o == gcref(g->gc.mmudata)) 447 if (o == gcref(g->gc.mmudata))
447 setgcrefnull(g->gc.mmudata); 448 setgcrefnull(g->gc.mmudata);
@@ -457,16 +458,8 @@ static void gc_finalize(lua_State *L)
457 /* Save and restore lots of state around the __gc callback. */ 458 /* Save and restore lots of state around the __gc callback. */
458 uint8_t oldh = hook_save(g); 459 uint8_t oldh = hook_save(g);
459 MSize oldt = g->gc.threshold; 460 MSize oldt = g->gc.threshold;
460 GCobj *oldjl = gcref(g->jit_L);
461 MSize oldjs = 0;
462 ptrdiff_t oldjb = 0;
463 int errcode; 461 int errcode;
464 TValue *top; 462 TValue *top;
465 if (oldjl) {
466 oldjs = gco2th(oldjl)->stacksize;
467 oldjb = savestack(gco2th(oldjl), mref(g->jit_base, TValue ));
468 setgcrefnull(g->jit_L);
469 }
470 lj_trace_abort(g); 463 lj_trace_abort(g);
471 top = L->top; 464 top = L->top;
472 L->top = top+2; 465 L->top = top+2;
@@ -477,12 +470,6 @@ static void gc_finalize(lua_State *L)
477 errcode = lj_vm_pcall(L, top+1, 1+0, -1); /* Stack: |mo|ud| -> | */ 470 errcode = lj_vm_pcall(L, top+1, 1+0, -1); /* Stack: |mo|ud| -> | */
478 hook_restore(g, oldh); 471 hook_restore(g, oldh);
479 g->gc.threshold = oldt; /* Restore GC threshold. */ 472 g->gc.threshold = oldt; /* Restore GC threshold. */
480 if (oldjl) {
481 if (gco2th(oldjl)->stacksize < oldjs)
482 lj_state_growstack(gco2th(oldjl), oldjs - gco2th(oldjl)->stacksize);
483 setgcref(g->jit_L, oldjl);
484 setmref(g->jit_base, restorestack(gco2th(oldjl), oldjb));
485 }
486 if (errcode) 473 if (errcode)
487 lj_err_throw(L, errcode); /* Propagate errors. */ 474 lj_err_throw(L, errcode); /* Propagate errors. */
488 } 475 }
@@ -514,7 +501,6 @@ static void atomic(global_State *g, lua_State *L)
514{ 501{
515 size_t udsize; 502 size_t udsize;
516 503
517 g->gc.state = GCSatomic;
518 gc_mark_uv(g); /* Need to remark open upvalues (the thread may be dead). */ 504 gc_mark_uv(g); /* Need to remark open upvalues (the thread may be dead). */
519 gc_propagate_gray(g); /* Propagate any left-overs. */ 505 gc_propagate_gray(g); /* Propagate any left-overs. */
520 506
@@ -539,9 +525,7 @@ static void atomic(global_State *g, lua_State *L)
539 525
540 /* Prepare for sweep phase. */ 526 /* Prepare for sweep phase. */
541 g->gc.currentwhite = cast_byte(otherwhite(g)); /* Flip current white. */ 527 g->gc.currentwhite = cast_byte(otherwhite(g)); /* Flip current white. */
542 g->gc.sweepstr = 0;
543 setmref(g->gc.sweep, &g->gc.root); 528 setmref(g->gc.sweep, &g->gc.root);
544 g->gc.state = GCSsweepstring;
545 g->gc.estimate = g->gc.total - (MSize)udsize; /* Initial estimate. */ 529 g->gc.estimate = g->gc.total - (MSize)udsize; /* Initial estimate. */
546} 530}
547 531
@@ -556,7 +540,14 @@ static size_t gc_onestep(lua_State *L)
556 case GCSpropagate: 540 case GCSpropagate:
557 if (gcref(g->gc.gray) != NULL) 541 if (gcref(g->gc.gray) != NULL)
558 return propagatemark(g); /* Propagate one gray object. */ 542 return propagatemark(g); /* Propagate one gray object. */
559 atomic(g, L); /* End of mark phase. */ 543 g->gc.state = GCSatomic; /* End of mark phase. */
544 return 0;
545 case GCSatomic:
546 if (gcref(g->jit_L)) /* Don't run atomic phase on trace. */
547 return LJ_MAX_MEM;
548 atomic(g, L);
549 g->gc.state = GCSsweepstring; /* Start of sweep phase. */
550 g->gc.sweepstr = 0;
560 return 0; 551 return 0;
561 case GCSsweepstring: { 552 case GCSsweepstring: {
562 MSize old = g->gc.total; 553 MSize old = g->gc.total;
@@ -572,7 +563,12 @@ static size_t gc_onestep(lua_State *L)
572 setmref(g->gc.sweep, gc_sweep(g, mref(g->gc.sweep, GCRef), GCSWEEPMAX)); 563 setmref(g->gc.sweep, gc_sweep(g, mref(g->gc.sweep, GCRef), GCSWEEPMAX));
573 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) { 564 if (gcref(*mref(g->gc.sweep, GCRef)) == NULL) {
574 gc_shrink(g, L); 565 gc_shrink(g, L);
575 g->gc.state = GCSfinalize; /* End of sweep phase. */ 566 if (gcref(g->gc.mmudata)) { /* Need any finalizations? */
567 g->gc.state = GCSfinalize;
568 } else { /* Otherwise skip this phase to help the JIT. */
569 g->gc.state = GCSpause; /* End of GC cycle. */
570 g->gc.debt = 0;
571 }
576 } 572 }
577 lua_assert(old >= g->gc.total); 573 lua_assert(old >= g->gc.total);
578 g->gc.estimate -= old - g->gc.total; 574 g->gc.estimate -= old - g->gc.total;
@@ -580,6 +576,8 @@ static size_t gc_onestep(lua_State *L)
580 } 576 }
581 case GCSfinalize: 577 case GCSfinalize:
582 if (gcref(g->gc.mmudata) != NULL) { 578 if (gcref(g->gc.mmudata) != NULL) {
579 if (gcref(g->jit_L)) /* Don't call finalizers on trace. */
580 return LJ_MAX_MEM;
583 gc_finalize(L); /* Finalize one userdata object. */ 581 gc_finalize(L); /* Finalize one userdata object. */
584 if (g->gc.estimate > GCFINALIZECOST) 582 if (g->gc.estimate > GCFINALIZECOST)
585 g->gc.estimate -= GCFINALIZECOST; 583 g->gc.estimate -= GCFINALIZECOST;
@@ -633,11 +631,13 @@ void LJ_FASTCALL lj_gc_step_fixtop(lua_State *L)
633 631
634#if LJ_HASJIT 632#if LJ_HASJIT
635/* Perform multiple GC steps. Called from JIT-compiled code. */ 633/* Perform multiple GC steps. Called from JIT-compiled code. */
636void LJ_FASTCALL lj_gc_step_jit(lua_State *L, MSize steps) 634int LJ_FASTCALL lj_gc_step_jit(lua_State *L, MSize steps)
637{ 635{
638 L->top = curr_topL(L); 636 L->top = curr_topL(L);
639 while (steps-- > 0 && lj_gc_step(L) == 0) 637 while (steps-- > 0 && lj_gc_step(L) == 0)
640 ; 638 ;
639 /* Return 1 to force a trace exit. */
640 return (G(L)->gc.state == GCSatomic || G(L)->gc.state == GCSfinalize);
641} 641}
642#endif 642#endif
643 643
@@ -647,23 +647,20 @@ void lj_gc_fullgc(lua_State *L)
647 global_State *g = G(L); 647 global_State *g = G(L);
648 int32_t ostate = g->vmstate; 648 int32_t ostate = g->vmstate;
649 setvmstate(g, GC); 649 setvmstate(g, GC);
650 if (g->gc.state <= GCSpropagate) { /* Caught somewhere in the middle. */ 650 if (g->gc.state <= GCSatomic) { /* Caught somewhere in the middle. */
651 g->gc.sweepstr = 0;
652 setmref(g->gc.sweep, &g->gc.root); /* Sweep everything (preserving it). */ 651 setmref(g->gc.sweep, &g->gc.root); /* Sweep everything (preserving it). */
653 setgcrefnull(g->gc.gray); /* Reset lists from partial propagation. */ 652 setgcrefnull(g->gc.gray); /* Reset lists from partial propagation. */
654 setgcrefnull(g->gc.grayagain); 653 setgcrefnull(g->gc.grayagain);
655 setgcrefnull(g->gc.weak); 654 setgcrefnull(g->gc.weak);
656 g->gc.state = GCSsweepstring; /* Fast forward to the sweep phase. */ 655 g->gc.state = GCSsweepstring; /* Fast forward to the sweep phase. */
656 g->gc.sweepstr = 0;
657 } 657 }
658 lua_assert(g->gc.state != GCSpause && g->gc.state != GCSpropagate); 658 while (g->gc.state == GCSsweepstring || g->gc.state == GCSsweep)
659 while (g->gc.state != GCSfinalize) { /* Finish sweep. */ 659 gc_onestep(L); /* Finish sweep. */
660 lua_assert(g->gc.state == GCSsweepstring || g->gc.state == GCSsweep); 660 lua_assert(g->gc.state == GCSfinalize || g->gc.state == GCSpause);
661 gc_onestep(L);
662 }
663 /* Now perform a full GC. */ 661 /* Now perform a full GC. */
664 gc_mark_start(g); 662 g->gc.state = GCSpause;
665 while (g->gc.state != GCSpause) 663 do { gc_onestep(L); } while (g->gc.state != GCSpause);
666 gc_onestep(L);
667 g->gc.threshold = (g->gc.estimate/100) * g->gc.pause; 664 g->gc.threshold = (g->gc.estimate/100) * g->gc.pause;
668 g->vmstate = ostate; 665 g->vmstate = ostate;
669} 666}