diff options
| author | Mike Pall <mike> | 2013-05-13 21:18:22 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-05-13 21:18:22 +0200 |
| commit | 4c39e9ffc89cf5ddb691f1cbed0d6e23571a3288 (patch) | |
| tree | 9744dc4a3e86a521a16decba6ce2deb581db0ada /src | |
| parent | 09ef8d10773f604452510c9fb3c32b3cdc424ae4 (diff) | |
| download | luajit-4c39e9ffc89cf5ddb691f1cbed0d6e23571a3288.tar.gz luajit-4c39e9ffc89cf5ddb691f1cbed0d6e23571a3288.tar.bz2 luajit-4c39e9ffc89cf5ddb691f1cbed0d6e23571a3288.zip | |
Compile string.format().
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib_string.c | 10 | ||||
| -rw-r--r-- | src/lj_ffrecord.c | 78 | ||||
| -rw-r--r-- | src/lj_ircall.h | 7 | ||||
| -rw-r--r-- | src/lj_opt_fold.c | 43 |
4 files changed, 133 insertions, 5 deletions
diff --git a/src/lib_string.c b/src/lib_string.c index cc1affbd..204f6975 100644 --- a/src/lib_string.c +++ b/src/lib_string.c | |||
| @@ -658,10 +658,10 @@ static GCstr *string_fmt_tostring(lua_State *L, int arg, int retry) | |||
| 658 | return lj_strfmt_obj(L, o); | 658 | return lj_strfmt_obj(L, o); |
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | LJLIB_CF(string_format) | 661 | LJLIB_CF(string_format) LJLIB_REC(.) |
| 662 | { | 662 | { |
| 663 | int arg, top = (int)(L->top - L->base); | 663 | int arg, top = (int)(L->top - L->base); |
| 664 | GCstr *sfmt; | 664 | GCstr *fmt; |
| 665 | SBuf *sb; | 665 | SBuf *sb; |
| 666 | FormatState fs; | 666 | FormatState fs; |
| 667 | SFormat sf; | 667 | SFormat sf; |
| @@ -669,8 +669,8 @@ LJLIB_CF(string_format) | |||
| 669 | again: | 669 | again: |
| 670 | arg = 1; | 670 | arg = 1; |
| 671 | sb = lj_buf_tmp_(L); | 671 | sb = lj_buf_tmp_(L); |
| 672 | sfmt = lj_lib_checkstr(L, arg); | 672 | fmt = lj_lib_checkstr(L, arg); |
| 673 | lj_strfmt_init(&fs, strdata(sfmt), sfmt->len); | 673 | lj_strfmt_init(&fs, strdata(fmt), fmt->len); |
| 674 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { | 674 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { |
| 675 | if (sf == STRFMT_LIT) { | 675 | if (sf == STRFMT_LIT) { |
| 676 | lj_buf_putmem(sb, fs.str, fs.len); | 676 | lj_buf_putmem(sb, fs.str, fs.len); |
| @@ -705,7 +705,7 @@ again: | |||
| 705 | if (str == NULL) | 705 | if (str == NULL) |
| 706 | retry = 1; | 706 | retry = 1; |
| 707 | else if ((sf & STRFMT_T_QUOTED)) | 707 | else if ((sf & STRFMT_T_QUOTED)) |
| 708 | lj_strfmt_putquoted(sb, str); | 708 | lj_strfmt_putquoted(sb, str); /* No formatting. */ |
| 709 | else | 709 | else |
| 710 | lj_strfmt_putfstr(sb, sf, str); | 710 | lj_strfmt_putfstr(sb, sf, str); |
| 711 | break; | 711 | break; |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 97c24836..31f9b390 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
| @@ -871,6 +871,84 @@ static void LJ_FASTCALL recff_string_find(jit_State *J, RecordFFData *rd) | |||
| 871 | } | 871 | } |
| 872 | } | 872 | } |
| 873 | 873 | ||
| 874 | static void LJ_FASTCALL recff_string_format(jit_State *J, RecordFFData *rd) | ||
| 875 | { | ||
| 876 | TRef trfmt = lj_ir_tostr(J, J->base[0]); | ||
| 877 | GCstr *fmt = argv2str(J, &rd->argv[0]); | ||
| 878 | int arg = 1; | ||
| 879 | TRef hdr, tr; | ||
| 880 | FormatState fs; | ||
| 881 | SFormat sf; | ||
| 882 | /* Specialize to the format string. */ | ||
| 883 | emitir(IRTG(IR_EQ, IRT_STR), trfmt, lj_ir_kstr(J, fmt)); | ||
| 884 | tr = hdr = recff_bufhdr(J); | ||
| 885 | lj_strfmt_init(&fs, strdata(fmt), fmt->len); | ||
| 886 | while ((sf = lj_strfmt_parse(&fs)) != STRFMT_EOF) { /* Parse format. */ | ||
| 887 | TRef tra = sf == STRFMT_LIT ? 0 : J->base[arg++]; | ||
| 888 | TRef trsf = lj_ir_kint(J, (int32_t)sf); | ||
| 889 | IRCallID id; | ||
| 890 | switch (STRFMT_TYPE(sf)) { | ||
| 891 | case STRFMT_LIT: | ||
| 892 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, | ||
| 893 | lj_ir_kstr(J, lj_str_new(J->L, fs.str, fs.len))); | ||
| 894 | break; | ||
| 895 | case STRFMT_INT: | ||
| 896 | id = IRCALL_lj_strfmt_putfnum_int; | ||
| 897 | handle_int: | ||
| 898 | if (!tref_isinteger(tra)) | ||
| 899 | goto handle_num; | ||
| 900 | if (sf == STRFMT_INT) { /* Shortcut for plain %d. */ | ||
| 901 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, | ||
| 902 | emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_INT)); | ||
| 903 | } else { | ||
| 904 | #if LJ_HASFFI | ||
| 905 | tra = emitir(IRT(IR_CONV, IRT_U64), tra, | ||
| 906 | (IRT_INT|(IRT_U64<<5)|IRCONV_SEXT)); | ||
| 907 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfxint, tr, trsf, tra); | ||
| 908 | lj_needsplit(J); | ||
| 909 | #else | ||
| 910 | recff_nyiu(J); /* Don't bother working around this NYI. */ | ||
| 911 | #endif | ||
| 912 | } | ||
| 913 | break; | ||
| 914 | case STRFMT_UINT: | ||
| 915 | id = IRCALL_lj_strfmt_putfnum_uint; | ||
| 916 | goto handle_int; | ||
| 917 | case STRFMT_NUM: | ||
| 918 | id = IRCALL_lj_strfmt_putfnum; | ||
| 919 | handle_num: | ||
| 920 | tra = lj_ir_tonum(J, tra); | ||
| 921 | tr = lj_ir_call(J, id, tr, trsf, tra); | ||
| 922 | if (LJ_SOFTFP) lj_needsplit(J); | ||
| 923 | break; | ||
| 924 | case STRFMT_STR: | ||
| 925 | if (!tref_isstr(tra)) | ||
| 926 | recff_nyiu(J); /* NYI: __tostring and non-string types for %s. */ | ||
| 927 | if (sf == STRFMT_STR) /* Shortcut for plain %s. */ | ||
| 928 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, tra); | ||
| 929 | else if ((sf & STRFMT_T_QUOTED)) | ||
| 930 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putquoted, tr, tra); | ||
| 931 | else | ||
| 932 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfstr, tr, trsf, tra); | ||
| 933 | break; | ||
| 934 | case STRFMT_CHAR: | ||
| 935 | tra = lj_opt_narrow_toint(J, tra); | ||
| 936 | if (sf == STRFMT_CHAR) /* Shortcut for plain %c. */ | ||
| 937 | tr = emitir(IRT(IR_BUFPUT, IRT_P32), tr, | ||
| 938 | emitir(IRT(IR_TOSTR, IRT_STR), tra, IRTOSTR_CHAR)); | ||
| 939 | else | ||
| 940 | tr = lj_ir_call(J, IRCALL_lj_strfmt_putfchar, tr, trsf, tra); | ||
| 941 | break; | ||
| 942 | case STRFMT_PTR: /* NYI */ | ||
| 943 | case STRFMT_ERR: | ||
| 944 | default: | ||
| 945 | recff_nyiu(J); | ||
| 946 | break; | ||
| 947 | } | ||
| 948 | } | ||
| 949 | J->base[0] = emitir(IRT(IR_BUFSTR, IRT_STR), tr, hdr); | ||
| 950 | } | ||
| 951 | |||
| 874 | /* -- Table library fast functions ---------------------------------------- */ | 952 | /* -- Table library fast functions ---------------------------------------- */ |
| 875 | 953 | ||
| 876 | static void LJ_FASTCALL recff_table_insert(jit_State *J, RecordFFData *rd) | 954 | 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 43bd25d9..7271ceca 100644 --- a/src/lj_ircall.h +++ b/src/lj_ircall.h | |||
| @@ -124,6 +124,13 @@ typedef struct CCallInfo { | |||
| 124 | _(ANY, lj_strfmt_char, 2, FN, STR, CCI_L) \ | 124 | _(ANY, lj_strfmt_char, 2, FN, STR, CCI_L) \ |
| 125 | _(ANY, lj_strfmt_putint, 2, FL, P32, 0) \ | 125 | _(ANY, lj_strfmt_putint, 2, FL, P32, 0) \ |
| 126 | _(ANY, lj_strfmt_putnum, 2, FL, P32, 0) \ | 126 | _(ANY, lj_strfmt_putnum, 2, FL, P32, 0) \ |
| 127 | _(ANY, lj_strfmt_putquoted, 2, FL, P32, 0) \ | ||
| 128 | _(ANY, lj_strfmt_putfxint, 3, L, P32, XA_64) \ | ||
| 129 | _(ANY, lj_strfmt_putfnum_int, 3, L, P32, XA_FP) \ | ||
| 130 | _(ANY, lj_strfmt_putfnum_uint, 3, L, P32, XA_FP) \ | ||
| 131 | _(ANY, lj_strfmt_putfnum, 3, L, P32, XA_FP) \ | ||
| 132 | _(ANY, lj_strfmt_putfstr, 3, L, P32, 0) \ | ||
| 133 | _(ANY, lj_strfmt_putfchar, 3, L, P32, 0) \ | ||
| 127 | _(ANY, lj_buf_putmem, 3, S, P32, 0) \ | 134 | _(ANY, lj_buf_putmem, 3, S, P32, 0) \ |
| 128 | _(ANY, lj_buf_putstr, 2, FL, P32, 0) \ | 135 | _(ANY, lj_buf_putstr, 2, FL, P32, 0) \ |
| 129 | _(ANY, lj_buf_putchar, 2, FL, P32, 0) \ | 136 | _(ANY, lj_buf_putchar, 2, FL, P32, 0) \ |
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c index e2ac28f2..f3abe8ea 100644 --- a/src/lj_opt_fold.c +++ b/src/lj_opt_fold.c | |||
| @@ -617,6 +617,7 @@ LJFOLDF(bufstr_kfold_cse) | |||
| 617 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_reverse) | 617 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_reverse) |
| 618 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_upper) | 618 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_upper) |
| 619 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_lower) | 619 | LJFOLD(CALLL CARG IRCALL_lj_buf_putstr_lower) |
| 620 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putquoted) | ||
| 620 | LJFOLDF(bufput_kfold_op) | 621 | LJFOLDF(bufput_kfold_op) |
| 621 | { | 622 | { |
| 622 | if (irref_isk(fleft->op2)) { | 623 | if (irref_isk(fleft->op2)) { |
| @@ -649,6 +650,48 @@ LJFOLDF(bufput_kfold_rep) | |||
| 649 | return EMITFOLD; /* Always emit, CSE later. */ | 650 | return EMITFOLD; /* Always emit, CSE later. */ |
| 650 | } | 651 | } |
| 651 | 652 | ||
| 653 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfxint) | ||
| 654 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfnum_int) | ||
| 655 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfnum_uint) | ||
| 656 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfnum) | ||
| 657 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfstr) | ||
| 658 | LJFOLD(CALLL CARG IRCALL_lj_strfmt_putfchar) | ||
| 659 | LJFOLDF(bufput_kfold_fmt) | ||
| 660 | { | ||
| 661 | IRIns *irc = IR(fleft->op1); | ||
| 662 | lua_assert(irref_isk(irc->op2)); /* SFormat must be const. */ | ||
| 663 | if (irref_isk(fleft->op2)) { | ||
| 664 | SFormat sf = (SFormat)IR(irc->op2)->i; | ||
| 665 | IRIns *ira = IR(fleft->op2); | ||
| 666 | SBuf *sb = lj_buf_tmp_(J->L); | ||
| 667 | switch (fins->op2) { | ||
| 668 | case IRCALL_lj_strfmt_putfxint: | ||
| 669 | sb = lj_strfmt_putfxint(sb, sf, ir_k64(ira)->u64); | ||
| 670 | break; | ||
| 671 | case IRCALL_lj_strfmt_putfstr: | ||
| 672 | sb = lj_strfmt_putfstr(sb, sf, ir_kstr(ira)); | ||
| 673 | break; | ||
| 674 | case IRCALL_lj_strfmt_putfchar: | ||
| 675 | sb = lj_strfmt_putfchar(sb, sf, ira->i); | ||
| 676 | break; | ||
| 677 | case IRCALL_lj_strfmt_putfnum_int: | ||
| 678 | case IRCALL_lj_strfmt_putfnum_uint: | ||
| 679 | case IRCALL_lj_strfmt_putfnum: | ||
| 680 | default: { | ||
| 681 | const CCallInfo *ci = &lj_ir_callinfo[fins->op2]; | ||
| 682 | sb = ((SBuf * (*)(SBuf *, SFormat, lua_Number))ci->func)(sb, sf, | ||
| 683 | ir_knum(ira)->n); | ||
| 684 | break; | ||
| 685 | } | ||
| 686 | } | ||
| 687 | fins->o = IR_BUFPUT; | ||
| 688 | fins->op1 = irc->op1; | ||
| 689 | fins->op2 = lj_ir_kstr(J, lj_buf_tostr(sb)); | ||
| 690 | return RETRYFOLD; | ||
| 691 | } | ||
| 692 | return EMITFOLD; /* Always emit, CSE later. */ | ||
| 693 | } | ||
| 694 | |||
| 652 | /* -- Constant folding of pointer arithmetic ------------------------------ */ | 695 | /* -- Constant folding of pointer arithmetic ------------------------------ */ |
| 653 | 696 | ||
| 654 | LJFOLD(ADD KGC KINT) | 697 | LJFOLD(ADD KGC KINT) |
