diff options
author | Mike Pall <mike> | 2013-04-21 01:01:33 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2013-04-21 01:01:33 +0200 |
commit | 5f1781a1277508c2b7bec527f722da98d8556e26 (patch) | |
tree | e1bbc8b5b4af7c7b374a0139225a585aa0009fdf /src/lj_opt_fold.c | |
parent | 7b629b7bcf6bca3bd7733db601722c551098557e (diff) | |
download | luajit-5f1781a1277508c2b7bec527f722da98d8556e26.tar.gz luajit-5f1781a1277508c2b7bec527f722da98d8556e26.tar.bz2 luajit-5f1781a1277508c2b7bec527f722da98d8556e26.zip |
Compile string concatenations (BC_CAT).
Diffstat (limited to 'src/lj_opt_fold.c')
-rw-r--r-- | src/lj_opt_fold.c | 95 |
1 files changed, 93 insertions, 2 deletions
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index 75db47df..f35593f3 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #if LJ_HASJIT | 15 | #if LJ_HASJIT |
16 | 16 | ||
17 | #include "lj_buf.h" | ||
17 | #include "lj_str.h" | 18 | #include "lj_str.h" |
18 | #include "lj_tab.h" | 19 | #include "lj_tab.h" |
19 | #include "lj_ir.h" | 20 | #include "lj_ir.h" |
@@ -155,13 +156,14 @@ typedef IRRef (LJ_FASTCALL *FoldFunc)(jit_State *J); | |||
155 | 156 | ||
156 | /* Barrier to prevent folding across a GC step. | 157 | /* Barrier to prevent folding across a GC step. |
157 | ** GC steps can only happen at the head of a trace and at LOOP. | 158 | ** GC steps can only happen at the head of a trace and at LOOP. |
158 | ** And the GC is only driven forward if there is at least one allocation. | 159 | ** And the GC is only driven forward if there's at least one allocation. |
159 | */ | 160 | */ |
160 | #define gcstep_barrier(J, ref) \ | 161 | #define gcstep_barrier(J, ref) \ |
161 | ((ref) < J->chain[IR_LOOP] && \ | 162 | ((ref) < J->chain[IR_LOOP] && \ |
162 | (J->chain[IR_SNEW] || J->chain[IR_XSNEW] || \ | 163 | (J->chain[IR_SNEW] || J->chain[IR_XSNEW] || \ |
163 | J->chain[IR_TNEW] || J->chain[IR_TDUP] || \ | 164 | J->chain[IR_TNEW] || J->chain[IR_TDUP] || \ |
164 | J->chain[IR_CNEW] || J->chain[IR_CNEWI] || J->chain[IR_TOSTR])) | 165 | J->chain[IR_CNEW] || J->chain[IR_CNEWI] || \ |
166 | J->chain[IR_BUFSTR] || J->chain[IR_TOSTR])) | ||
165 | 167 | ||
166 | /* -- Constant folding for FP numbers ------------------------------------- */ | 168 | /* -- Constant folding for FP numbers ------------------------------------- */ |
167 | 169 | ||
@@ -515,6 +517,94 @@ LJFOLDF(kfold_strcmp) | |||
515 | return NEXTFOLD; | 517 | return NEXTFOLD; |
516 | } | 518 | } |
517 | 519 | ||
520 | /* -- Constant folding and forwarding for buffers ------------------------- */ | ||
521 | |||
522 | /* Note: buffer ops are not CSEd until the BUFSTR. It's ok to modify them. */ | ||
523 | |||
524 | /* BUFHDR is treated like a store, see below. */ | ||
525 | |||
526 | LJFOLD(BUFPUT BUFHDR BUFSTR) | ||
527 | LJFOLDF(bufput_append) | ||
528 | { | ||
529 | /* New buffer, no other buffer op inbetween and same buffer? */ | ||
530 | if ((J->flags & JIT_F_OPT_FWD) && | ||
531 | !(fleft->op2 & IRBUFHDR_APPEND) && | ||
532 | fleft->prev == fright->op1 && | ||
533 | fleft->op1 == IR(fright->op1)->op1) { | ||
534 | IRRef ref = fins->op1; | ||
535 | IR(ref)->op2 = (fleft->op2 | IRBUFHDR_APPEND); /* Modify BUFHDR. */ | ||
536 | return ref; | ||
537 | } | ||
538 | return EMITFOLD; /* This is a store and always emitted. */ | ||
539 | } | ||
540 | |||
541 | LJFOLD(BUFPUT any any) | ||
542 | LJFOLDF(bufput_kgc) | ||
543 | { | ||
544 | if (fright->o == IR_KGC) { | ||
545 | GCstr *s2 = ir_kstr(fright); | ||
546 | MSize len2 = s2->len; | ||
547 | if (len2 == 0) { /* Empty string? */ | ||
548 | return LEFTFOLD; | ||
549 | } else { | ||
550 | PHIBARRIER(fleft); | ||
551 | if (fleft->o == IR_BUFPUT && IR(fleft->op2)->o == IR_KGC) { | ||
552 | /* Join two constant string puts in a row. */ | ||
553 | GCstr *s1 = ir_kstr(IR(fleft->op2)); | ||
554 | MSize len1 = s1->len; | ||
555 | char *buf = lj_buf_tmp(J->L, len1 + len2); | ||
556 | IRRef kref; | ||
557 | memcpy(buf, strdata(s1), len1); | ||
558 | memcpy(buf+len1, strdata(s2), len2); | ||
559 | kref = lj_ir_kstr(J, lj_str_new(J->L, buf, len1 + len2)); | ||
560 | /* lj_ir_kstr() may realloc the IR and invalidates any IRIns *. */ | ||
561 | IR(fins->op1)->op2 = kref; /* Modify previous BUFPUT. */ | ||
562 | return fins->op1; | ||
563 | } | ||
564 | } | ||
565 | } | ||
566 | return EMITFOLD; /* This is a store and always emitted. */ | ||
567 | } | ||
568 | |||
569 | LJFOLD(BUFSTR any any) | ||
570 | LJFOLDF(bufstr_kfold_cse) | ||
571 | { | ||
572 | lua_assert(fright->o == IR_BUFHDR || fright->o == IR_BUFPUT); | ||
573 | if (fright->o == IR_BUFHDR) { /* No put operations? */ | ||
574 | if (!(fright->op2 & IRBUFHDR_APPEND)) /* Empty buffer? */ | ||
575 | return lj_ir_kstr(J, &J2G(J)->strempty); | ||
576 | fins->op2 = fright->prev; /* Relies on checks in bufput_append. */ | ||
577 | return CSEFOLD; | ||
578 | } else { | ||
579 | /* Shortcut for a single put operation. */ | ||
580 | IRIns *irb = IR(fright->op1); | ||
581 | if (irb->o == IR_BUFHDR && !(irb->op2 & IRBUFHDR_APPEND)) { | ||
582 | IRRef ref = fright->op2; | ||
583 | if (irt_isstr(IR(ref)->t)) | ||
584 | return ref; | ||
585 | lua_assert(irt_isinteger(IR(ref)->t) || irt_isnum(IR(ref)->t)); | ||
586 | return emitir(IRT(IR_TOSTR, IRT_STR), ref, 0); | ||
587 | } | ||
588 | } | ||
589 | /* Try to CSE the whole chain. */ | ||
590 | if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE) && !(fleft->op2 & IRBUFHDR_APPEND)) { | ||
591 | IRRef ref = J->chain[IR_BUFSTR]; | ||
592 | while (ref) { | ||
593 | IRIns *irs = IR(ref), *ira = fright, *irb = IR(irs->op2); | ||
594 | while (ira->o == irb->o && ira->op2 == irb->op2) { | ||
595 | if (ira->o == IR_BUFHDR) { | ||
596 | lj_ir_rollback(J, fins->op1); /* Eliminate the current chain. */ | ||
597 | return ref; /* CSE succeeded. */ | ||
598 | } | ||
599 | ira = IR(ira->op1); | ||
600 | irb = IR(irb->op1); | ||
601 | } | ||
602 | ref = irs->prev; | ||
603 | } | ||
604 | } | ||
605 | return EMITFOLD; /* No CSE possible. */ | ||
606 | } | ||
607 | |||
518 | /* -- Constant folding of pointer arithmetic ------------------------------ */ | 608 | /* -- Constant folding of pointer arithmetic ------------------------------ */ |
519 | 609 | ||
520 | LJFOLD(ADD KGC KINT) | 610 | LJFOLD(ADD KGC KINT) |
@@ -2128,6 +2218,7 @@ LJFOLD(TNEW any any) | |||
2128 | LJFOLD(TDUP any) | 2218 | LJFOLD(TDUP any) |
2129 | LJFOLD(CNEW any any) | 2219 | LJFOLD(CNEW any any) |
2130 | LJFOLD(XSNEW any any) | 2220 | LJFOLD(XSNEW any any) |
2221 | LJFOLD(BUFHDR any any) | ||
2131 | LJFOLDX(lj_ir_emit) | 2222 | LJFOLDX(lj_ir_emit) |
2132 | 2223 | ||
2133 | /* ------------------------------------------------------------------------ */ | 2224 | /* ------------------------------------------------------------------------ */ |