diff options
-rw-r--r-- | src/lib_string.c | 2 | ||||
-rw-r--r-- | src/lj_ffrecord.c | 108 | ||||
-rw-r--r-- | src/lj_ircall.h | 1 |
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 | ||
504 | LJLIB_CF(string_find) | 504 | LJLIB_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. */ | ||
650 | static 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). */ |
650 | static void LJ_FASTCALL recff_string_range(jit_State *J, RecordFFData *rd) | 676 | static 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 | ||
813 | static 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 | ||
807 | static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) | 873 | static 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) \ |