diff options
| author | Mike Pall <mike> | 2013-04-26 00:26:44 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-04-26 00:26:44 +0200 |
| commit | eeb204cd87a58f8a6e29022ea30aaba877acb2e0 (patch) | |
| tree | 3fd7e85dcd77749ed13b2bdc77aa949b397e937f | |
| parent | 7c2844873070f71e2e98765682326e6d98a6b55e (diff) | |
| download | luajit-eeb204cd87a58f8a6e29022ea30aaba877acb2e0.tar.gz luajit-eeb204cd87a58f8a6e29022ea30aaba877acb2e0.tar.bz2 luajit-eeb204cd87a58f8a6e29022ea30aaba877acb2e0.zip | |
Fix FOLD rules for appending to string buffers.
| -rw-r--r-- | src/lj_opt_fold.c | 27 |
1 files changed, 21 insertions, 6 deletions
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 75b8e174..2ed0bc93 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
| @@ -533,6 +533,7 @@ LJFOLDF(bufput_append) | |||
| 533 | fleft->op1 == IR(fright->op1)->op1) { | 533 | fleft->op1 == IR(fright->op1)->op1) { |
| 534 | IRRef ref = fins->op1; | 534 | IRRef ref = fins->op1; |
| 535 | IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */ | 535 | IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */ |
| 536 | IR(ref)->op1 = fright->op2; | ||
| 536 | return ref; | 537 | return ref; |
| 537 | } | 538 | } |
| 538 | return EMITFOLD; /* This is a store and always emitted. */ | 539 | return EMITFOLD; /* This is a store and always emitted. */ |
| @@ -572,27 +573,41 @@ LJFOLDF(bufstr_kfold_cse) | |||
| 572 | lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT); | 573 | lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT); |
| 573 | if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) { | 574 | if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) { |
| 574 | if (fright->o == IR_BUFHDR) { /* No put operations? */ | 575 | if (fright->o == IR_BUFHDR) { /* No put operations? */ |
| 575 | if (!(fright->op2 & IRBUFHDR_APPEND)) /* Empty buffer? */ | 576 | if (!(fright->op2 & IRBUFHDR_APPEND)) { /* Empty buffer? */ |
| 577 | lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ | ||
| 576 | return lj_ir_kstr(J, &J2G(J)->strempty); | 578 | return lj_ir_kstr(J, &J2G(J)->strempty); |
| 579 | } | ||
| 577 | fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ | 580 | fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ |
| 578 | return CSEFOLD; | 581 | return CSEFOLD; |
| 579 | } else { | 582 | } else { |
| 580 | IRIns *irb = IR(fright->op1); | 583 | IRIns *irb = IR(fright->op1); |
| 581 | if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) | 584 | if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) { |
| 585 | lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ | ||
| 582 | return fright->op2; /* Shortcut for a single put operation. */ | 586 | return fright->op2; /* Shortcut for a single put operation. */ |
| 587 | } | ||
| 583 | } | 588 | } |
| 584 | } | 589 | } |
| 585 | /* Try to CSE the whole chain. */ | 590 | /* Try to CSE the whole chain. */ |
| 586 | if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE) && !(fleft->op2 & IRBUFHDR_APPEND)) { | 591 | if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) { |
| 587 | IRRef ref = J->chain[IR_BUFSTR]; | 592 | IRRef ref = J->chain[IR_BUFSTR]; |
| 588 | while (ref) { | 593 | while (ref) { |
| 594 | IRRef last = fins->op2; | ||
| 589 | IRIns *irs = IR(ref), *ira = fright, *irb = IR(irs->op2); | 595 | IRIns *irs = IR(ref), *ira = fright, *irb = IR(irs->op2); |
| 590 | while (ira->o == irb->o && ira->op2 == irb->op2) { | 596 | while (ira->o == irb->o && ira->op2 == irb->op2) { |
| 591 | if (ira->o == IR_BUFHDR) { | 597 | if (ira->o == IR_BUFHDR && !(ira->op2 & IRBUFHDR_APPEND)) { |
| 592 | lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ | 598 | IRIns *irh; |
| 599 | for (irh = IR(ira->prev); irh != irb; irh = IR(irh->prev)) | ||
| 600 | if (irh->op1 == irs->op2) | ||
| 601 | return ref; /* Do CSE, but avoid rollback if append follows. */ | ||
| 602 | lj_ir_rollback(J, last); /* Eliminate the current chain. */ | ||
| 593 | return ref; /* CSE succeeded. */ | 603 | return ref; /* CSE succeeded. */ |
| 604 | } else if (ira->o == IR_CALLS) { | ||
| 605 | ira = IR(ira->op1); irb = IR(irb->op1); | ||
| 606 | lua_assert(ira->o == IR_CARG && irb->o == IR_CARG); | ||
| 607 | if (ira->op2 != irb->op2) break; | ||
| 594 | } | 608 | } |
| 595 | ira = IR(ira->op1); | 609 | last = ira->op1; |
| 610 | ira = IR(last); | ||
| 596 | irb = IR(irb->op1); | 611 | irb = IR(irb->op1); |
| 597 | } | 612 | } |
| 598 | ref = irs->prev; | 613 | ref = irs->prev; |
