diff options
Diffstat (limited to 'src/lj_gc.c')
-rw-r--r-- | src/lj_gc.c | 57 |
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. */ |
636 | void LJ_FASTCALL lj_gc_step_jit(lua_State *L, MSize steps) | 634 | int 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 | } |