aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-04-26 00:26:44 +0200
committerMike Pall <mike>2013-04-26 00:26:44 +0200
commiteeb204cd87a58f8a6e29022ea30aaba877acb2e0 (patch)
tree3fd7e85dcd77749ed13b2bdc77aa949b397e937f
parent7c2844873070f71e2e98765682326e6d98a6b55e (diff)
downloadluajit-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.c27
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;