aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib_string.c2
-rw-r--r--src/lj_ffrecord.c108
-rw-r--r--src/lj_ircall.h1
3 files changed, 89 insertions, 22 deletions
diff --git a/src/lib_string.c b/src/lib_string.c
index ac21dda4..2c86daa4 100644
--- a/src/lib_string.c
+++ b/src/lib_string.c
@@ -501,7 +501,7 @@ static int str_find_aux(lua_State *L, int find)
501 return 1; 501 return 1;
502} 502}
503 503
504LJLIB_CF(string_find) 504LJLIB_CF(string_find) LJLIB_REC(.)
505{ 505{
506 return str_find_aux(L, 1); 506 return str_find_aux(L, 1);
507} 507}
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)
diff --git a/src/lj_ircall.h b/src/lj_ircall.h
index 8713e3f0..03563cd6 100644
--- a/src/lj_ircall.h
+++ b/src/lj_ircall.h
@@ -101,6 +101,7 @@ typedef struct CCallInfo {
101/* Function definitions for CALL* instructions. */ 101/* Function definitions for CALL* instructions. */
102#define IRCALLDEF(_) \ 102#define IRCALLDEF(_) \
103 _(ANY, lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \ 103 _(ANY, lj_str_cmp, 2, FN, INT, CCI_NOFPRCLOBBER) \
104 _(ANY, lj_str_find, 4, N, P32, 0) \
104 _(ANY, lj_str_new, 3, S, STR, CCI_L) \ 105 _(ANY, lj_str_new, 3, S, STR, CCI_L) \
105 _(ANY, lj_strscan_num, 2, FN, INT, 0) \ 106 _(ANY, lj_strscan_num, 2, FN, INT, 0) \
106 _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \ 107 _(ANY, lj_str_fromint, 2, FN, STR, CCI_L) \