summaryrefslogtreecommitdiff
path: root/src/lj_ffrecord.c
diff options
context:
space:
mode:
authorMike Pall <mike>2013-05-08 10:37:52 +0200
committerMike Pall <mike>2013-05-08 10:40:22 +0200
commit87b560b3e18dc39934f7e49810f418a934036a61 (patch)
tree5d1fcfd736a277660e2e4b88929306befe38e761 /src/lj_ffrecord.c
parent43de451d7876c383a747c08f42424520ddcb74fa (diff)
downloadluajit-87b560b3e18dc39934f7e49810f418a934036a61.tar.gz
luajit-87b560b3e18dc39934f7e49810f418a934036a61.tar.bz2
luajit-87b560b3e18dc39934f7e49810f418a934036a61.zip
Compile string.find() for fixed string searches (no patterns).
Diffstat (limited to 'src/lj_ffrecord.c')
-rw-r--r--src/lj_ffrecord.c108
1 files changed, 87 insertions, 21 deletions
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c
index 5f69ea14..39e80842 100644
--- a/src/lj_ffrecord.c
+++ b/src/lj_ffrecord.c
@@ -646,6 +646,32 @@ static void LJ_FASTCALL recff_bit_shift(jit_State *J, RecordFFData *rd)
646 646
647/* -- String library fast functions --------------------------------------- */ 647/* -- String library fast functions --------------------------------------- */
648 648
649/* Specialize to relative starting position for string. */
650static TRef recff_string_start(jit_State *J, GCstr *s, int32_t *st, TRef tr,
651 TRef trlen, TRef tr0)
652{
653 int32_t start = *st;
654 if (start < 0) {
655 emitir(IRTGI(IR_LT), tr, tr0);
656 tr = emitir(IRTI(IR_ADD), trlen, tr);
657 start = start + (int32_t)s->len;
658 emitir(start < 0 ? IRTGI(IR_LT) : IRTGI(IR_GE), tr, tr0);
659 if (start < 0) {
660 tr = tr0;
661 start = 0;
662 }
663 } else if (start == 0) {
664 emitir(IRTGI(IR_EQ), tr, tr0);
665 tr = tr0;
666 } else {
667 tr = emitir(IRTI(IR_ADD), tr, lj_ir_kint(J, -1));
668 emitir(IRTGI(IR_GE), tr, tr0);
669 start--;
670 }
671 *st = start;
672 return tr;
673}
674
649/* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */ 675/* Handle string.byte (rd->data = 0) and string.sub (rd->data = 1). */
650static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd) 676static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
651{ 677{
@@ -691,29 +717,11 @@ static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
691 } else if ((MSize)end <= str->len) { 717 } else if ((MSize)end <= str->len) {
692 emitir(IRTGI(IR_ULE), trend, trlen); 718 emitir(IRTGI(IR_ULE), trend, trlen);
693 } else { 719 } else {
694 emitir(IRTGI(IR_GT), trend, trlen); 720 emitir(IRTGI(IR_UGT), trend, trlen);
695 end = (int32_t)str->len; 721 end = (int32_t)str->len;
696 trend = trlen; 722 trend = trlen;
697 } 723 }
698 if (start < 0) { 724 trstart = recff_string_start(J, str, &start, trstart, trlen, tr0);
699 emitir(IRTGI(IR_LT), trstart, tr0);
700 trstart = emitir(IRTI(IR_ADD), trlen, trstart);
701 start = start+(int32_t)str->len;
702 emitir(start < 0 ? IRTGI(IR_LT) : IRTGI(IR_GE), trstart, tr0);
703 if (start < 0) {
704 trstart = tr0;
705 start = 0;
706 }
707 } else {
708 if (start == 0) {
709 emitir(IRTGI(IR_EQ), trstart, tr0);
710 trstart = tr0;
711 } else {
712 trstart = emitir(IRTI(IR_ADD), trstart, lj_ir_kint(J, -1));
713 emitir(IRTGI(IR_GE), trstart, tr0);
714 start--;
715 }
716 }
717 if (rd->data) { /* Return string.sub result. */ 725 if (rd->data) { /* Return string.sub result. */
718 if (end - start >= 0) { 726 if (end - start >= 0) {
719 /* Also handle empty range here, to avoid extra traces. */ 727 /* Also handle empty range here, to avoid extra traces. */
@@ -723,7 +731,7 @@ static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd)
723 J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen); 731 J->base[0] = emitir(IRT(IR_SNEW, IRT_STR), trptr, trslen);
724 } else { /* Range underflow: return empty string. */ 732 } else { /* Range underflow: return empty string. */
725 emitir(IRTGI(IR_LT), trend, trstart); 733 emitir(IRTGI(IR_LT), trend, trstart);
726 J->base[0] = lj_ir_kstr(J, lj_str_new(J->L, strdata(str), 0)); 734 J->base[0] = lj_ir_kstr(J, &J2G(J)->strempty);
727 } 735 }
728 } else { /* Return string.byte result(s). */ 736 } else { /* Return string.byte result(s). */
729 ptrdiff_t i, len = end - start; 737 ptrdiff_t i, len = end - start;
@@ -802,6 +810,64 @@ static void LJ_FASTCALL recff_string_op(jit_State *J, RecordFFData *rd)
802 J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); 810 J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr);
803} 811}
804 812
813static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd)
814{
815 TRef trstr = lj_ir_tostr(J, J->base[0]);
816 TRef trpat = lj_ir_tostr(J, J->base[1]);
817 TRef trlen = emitir(IRTI(IR_FLOAD), trstr, IRFL_STR_LEN);
818 TRef tr0 = lj_ir_kint(J, 0);
819 TRef trstart;
820 GCstr *str = argv2str(J, &rd->argv[0]);
821 GCstr *pat = argv2str(J, &rd->argv[1]);
822 int32_t start;
823 J->needsnap = 1;
824 if (tref_isnil(J->base[2])) {
825 trstart = lj_ir_kint(J, 1);
826 start = 1;
827 } else {
828 trstart = lj_opt_narrow_toint(J, J->base[2]);
829 start = argv2int(J, &rd->argv[2]);
830 }
831 trstart = recff_string_start(J, str, &start, trstart, trlen, tr0);
832 if ((MSize)start <= str->len) {
833 emitir(IRTGI(IR_ULE), trstart, trlen);
834 } else {
835 emitir(IRTGI(IR_UGT), trstart, trlen);
836#if LJ_52
837 J->base[0] = TREF_NIL;
838 return;
839#else
840 trstart = trlen;
841 start = str->len;
842#endif
843 }
844 /* Fixed arg or no pattern matching chars? (Specialized to pattern string.) */
845 if ((J->base[2] && tref_istruecond(J->base[3])) ||
846 (emitir(IRTG(IR_EQ, IRT_STR), trpat, lj_ir_kstr(J, pat)),
847 !lj_str_haspattern(pat))) { /* Search for fixed string. */
848 TRef trsptr = emitir(IRT(IR_STRREF, IRT_P32), trstr, trstart);
849 TRef trpptr = emitir(IRT(IR_STRREF, IRT_P32), trpat, tr0);
850 TRef trslen = emitir(IRTI(IR_SUB), trlen, trstart);
851 TRef trplen = emitir(IRTI(IR_FLOAD), trpat, IRFL_STR_LEN);
852 TRef tr = lj_ir_call(J, IRCALL_lj_str_find, trsptr, trpptr, trslen, trplen);
853 TRef trp0 = lj_ir_kkptr(J, NULL);
854 if (lj_str_find(strdata(str)+(MSize)start, strdata(pat),
855 str->len-(MSize)start, pat->len)) {
856 TRef pos;
857 emitir(IRTG(IR_NE, IRT_P32), tr, trp0);
858 pos = emitir(IRTI(IR_SUB), tr, emitir(IRT(IR_STRREF, IRT_P32), trstr, tr0));
859 J->base[0] = emitir(IRTI(IR_ADD), pos, lj_ir_kint(J, 1));
860 J->base[1] = emitir(IRTI(IR_ADD), pos, trplen);
861 rd->nres = 2;
862 } else {
863 emitir(IRTG(IR_EQ, IRT_P32), tr, trp0);
864 J->base[0] = TREF_NIL;
865 }
866 } else { /* Search for pattern. */
867 recff_nyiu(J);
868 }
869}
870
805/* -- Table library fast functions ---------------------------------------- */ 871/* -- Table library fast functions ---------------------------------------- */
806 872
807static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) 873static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd)