diff options
| author | Mike Pall <mike> | 2013-05-08 10:37:52 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-05-08 10:40:22 +0200 |
| commit | 87b560b3e18dc39934f7e49810f418a934036a61 (patch) | |
| tree | 5d1fcfd736a277660e2e4b88929306befe38e761 /src | |
| parent | 43de451d7876c383a747c08f42424520ddcb74fa (diff) | |
| download | luajit-87b560b3e18dc39934f7e49810f418a934036a61.tar.gz luajit-87b560b3e18dc39934f7e49810f418a934036a61.tar.bz2 luajit-87b560b3e18dc39934f7e49810f418a934036a61.zip | |
Compile string.find() for fixed string searches (no patterns).
Diffstat (limited to 'src')
| -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) \ |
