diff options
| author | Mike Pall <mike> | 2013-04-26 19:57:25 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-04-26 19:57:25 +0200 |
| commit | 9b8db403f28bc8b290f275ea3967d29ebccedde1 (patch) | |
| tree | bbadb5346afbadd6b306685b6efe505f71803fa8 | |
| parent | a98e6a70c1692cf4e5686d0acee2ede54728af6f (diff) | |
| download | luajit-9b8db403f28bc8b290f275ea3967d29ebccedde1.tar.gz luajit-9b8db403f28bc8b290f275ea3967d29ebccedde1.tar.bz2 luajit-9b8db403f28bc8b290f275ea3967d29ebccedde1.zip | |
Refactor string.rep().
| -rw-r--r-- | src/lib_string.c | 56 | ||||
| -rw-r--r-- | src/lj_buf.c | 24 | ||||
| -rw-r--r-- | src/lj_buf.h | 1 | ||||
| -rw-r--r-- | src/lj_dispatch.h | 2 | ||||
| -rw-r--r-- | src/vm_arm.dasc | 27 | ||||
| -rw-r--r-- | src/vm_mips.dasc | 35 | ||||
| -rw-r--r-- | src/vm_ppc.dasc | 43 | ||||
| -rw-r--r-- | src/vm_x86.dasc | 35 |
8 files changed, 39 insertions, 184 deletions
diff --git a/src/lib_string.c b/src/lib_string.c index cd673478..598cd93e 100644 --- a/src/lib_string.c +++ b/src/lib_string.c | |||
| @@ -85,53 +85,23 @@ LJLIB_ASM(string_sub) LJLIB_REC(string_range 1) | |||
| 85 | return FFH_RETRY; | 85 | return FFH_RETRY; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | LJLIB_ASM(string_rep) | 88 | LJLIB_CF(string_rep) |
| 89 | { | 89 | { |
| 90 | GCstr *s = lj_lib_checkstr(L, 1); | 90 | GCstr *s = lj_lib_checkstr(L, 1); |
| 91 | int32_t k = lj_lib_checkint(L, 2); | 91 | int32_t rep = lj_lib_checkint(L, 2); |
| 92 | GCstr *sep = lj_lib_optstr(L, 3); | 92 | GCstr *sep = lj_lib_optstr(L, 3); |
| 93 | int32_t len = (int32_t)s->len; | 93 | SBuf *sb = lj_buf_tmp_(L); |
| 94 | global_State *g = G(L); | 94 | if (sep && rep > 1) { |
| 95 | int64_t tlen; | 95 | GCstr *s2 = lj_buf_cat2str(L, sep, s); |
| 96 | if (k <= 0) { | 96 | lj_buf_reset(sb); |
| 97 | empty: | 97 | lj_buf_putstr(sb, s); |
| 98 | setstrV(L, L->base-1, &g->strempty); | 98 | s = s2; |
| 99 | return FFH_RES(1); | 99 | rep--; |
| 100 | } | ||
| 101 | if (sep) { | ||
| 102 | tlen = (int64_t)len + sep->len; | ||
| 103 | if (tlen > LJ_MAX_STR) | ||
| 104 | lj_err_caller(L, LJ_ERR_STROV); | ||
| 105 | tlen *= k; | ||
| 106 | if (tlen > LJ_MAX_STR) | ||
| 107 | lj_err_caller(L, LJ_ERR_STROV); | ||
| 108 | } else { | ||
| 109 | tlen = (int64_t)k * len; | ||
| 110 | if (tlen > LJ_MAX_STR) | ||
| 111 | lj_err_caller(L, LJ_ERR_STROV); | ||
| 112 | } | ||
| 113 | if (tlen == 0) { | ||
| 114 | goto empty; | ||
| 115 | } else { | ||
| 116 | char *buf = lj_buf_tmp(L, (MSize)tlen), *p = buf; | ||
| 117 | const char *src = strdata(s); | ||
| 118 | if (sep) { | ||
| 119 | tlen -= sep->len; /* Ignore trailing separator. */ | ||
| 120 | if (k > 1) { /* Paste one string and one separator. */ | ||
| 121 | int32_t i; | ||
| 122 | i = 0; while (i < len) *p++ = src[i++]; | ||
| 123 | src = strdata(sep); len = sep->len; | ||
| 124 | i = 0; while (i < len) *p++ = src[i++]; | ||
| 125 | src = buf; len += s->len; k--; /* Now copy that k-1 times. */ | ||
| 126 | } | ||
| 127 | } | ||
| 128 | do { | ||
| 129 | int32_t i = 0; | ||
| 130 | do { *p++ = src[i++]; } while (i < len); | ||
| 131 | } while (--k > 0); | ||
| 132 | setstrV(L, L->base-1, lj_str_new(L, buf, (size_t)tlen)); | ||
| 133 | } | 100 | } |
| 134 | return FFH_RES(1); | 101 | sb = lj_buf_putstr_rep(sb, s, rep); |
| 102 | setstrV(L, L->top-1, lj_buf_str(L, sb)); | ||
| 103 | lj_gc_check(L); | ||
| 104 | return 1; | ||
| 135 | } | 105 | } |
| 136 | 106 | ||
| 137 | LJLIB_ASM(string_reverse) LJLIB_REC(string_op IRCALL_lj_buf_putstr_reverse) | 107 | LJLIB_ASM(string_reverse) LJLIB_REC(string_op IRCALL_lj_buf_putstr_reverse) |
diff --git a/src/lj_buf.c b/src/lj_buf.c index 3526a6e5..55a885a9 100644 --- a/src/lj_buf.c +++ b/src/lj_buf.c | |||
| @@ -144,6 +144,30 @@ SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s) | |||
| 144 | return sb; | 144 | return sb; |
| 145 | } | 145 | } |
| 146 | 146 | ||
| 147 | SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep) | ||
| 148 | { | ||
| 149 | MSize len = s->len; | ||
| 150 | if (rep > 0 && len) { | ||
| 151 | uint64_t tlen = (uint64_t)rep * len; | ||
| 152 | char *p; | ||
| 153 | if (LJ_UNLIKELY(tlen > LJ_MAX_STR)) | ||
| 154 | lj_err_mem(sbufL(sb)); | ||
| 155 | p = lj_buf_more(sb, (MSize)tlen); | ||
| 156 | if (len == 1) { /* Optimize a common case. */ | ||
| 157 | uint32_t c = strdata(s)[0]; | ||
| 158 | do { *p++ = c; } while (--rep > 0); | ||
| 159 | } else { | ||
| 160 | const char *e = strdata(s) + len; | ||
| 161 | do { | ||
| 162 | const char *q = strdata(s); | ||
| 163 | do { *p++ = *q++; } while (q < e); | ||
| 164 | } while (--rep > 0); | ||
| 165 | } | ||
| 166 | setsbufP(sb, p); | ||
| 167 | } | ||
| 168 | return sb; | ||
| 169 | } | ||
| 170 | |||
| 147 | GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb) | 171 | GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb) |
| 148 | { | 172 | { |
| 149 | return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb)); | 173 | return lj_str_new(sbufL(sb), sbufB(sb), sbuflen(sb)); |
diff --git a/src/lj_buf.h b/src/lj_buf.h index 92a6055a..4d764938 100644 --- a/src/lj_buf.h +++ b/src/lj_buf.h | |||
| @@ -35,6 +35,7 @@ LJ_FUNC SBuf * LJ_FASTCALL lj_buf_putnum(SBuf *sb, cTValue *o); | |||
| 35 | LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s); | 35 | LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s); |
| 36 | LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s); | 36 | LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s); |
| 37 | LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s); | 37 | LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s); |
| 38 | LJ_FUNC SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep); | ||
| 38 | LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb); | 39 | LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb); |
| 39 | LJ_FUNC GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2); | 40 | LJ_FUNC GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2); |
| 40 | LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp); | 41 | LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp); |
diff --git a/src/lj_dispatch.h b/src/lj_dispatch.h index e744e3f8..1ca29329 100644 --- a/src/lj_dispatch.h +++ b/src/lj_dispatch.h | |||
| @@ -61,7 +61,7 @@ typedef uint16_t HotCount; | |||
| 61 | #define HOTCOUNT_CALL 1 | 61 | #define HOTCOUNT_CALL 1 |
| 62 | 62 | ||
| 63 | /* This solves a circular dependency problem -- bump as needed. Sigh. */ | 63 | /* This solves a circular dependency problem -- bump as needed. Sigh. */ |
| 64 | #define GG_NUM_ASMFF 58 | 64 | #define GG_NUM_ASMFF 57 |
| 65 | 65 | ||
| 66 | #define GG_LEN_DDISP (BC__MAX + GG_NUM_ASMFF) | 66 | #define GG_LEN_DDISP (BC__MAX + GG_NUM_ASMFF) |
| 67 | #define GG_LEN_SDISP BC_FUNCF | 67 | #define GG_LEN_SDISP BC_FUNCF |
diff --git a/src/vm_arm.dasc b/src/vm_arm.dasc index 5c149bc4..0c542e1e 100644 --- a/src/vm_arm.dasc +++ b/src/vm_arm.dasc | |||
| @@ -1782,33 +1782,6 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 1782 | | mvn CARG2, #~LJ_TSTR | 1782 | | mvn CARG2, #~LJ_TSTR |
| 1783 | | b ->fff_restv | 1783 | | b ->fff_restv |
| 1784 | | | 1784 | | |
| 1785 | |.ffunc string_rep // Only handle the 1-char case inline. | ||
| 1786 | | ffgccheck | ||
| 1787 | | ldrd CARG12, [BASE] | ||
| 1788 | | ldrd CARG34, [BASE, #8] | ||
| 1789 | | cmp NARGS8:RC, #16 | ||
| 1790 | | bne ->fff_fallback // Exactly 2 arguments | ||
| 1791 | | checktp CARG2, LJ_TSTR | ||
| 1792 | | checktpeq CARG4, LJ_TISNUM | ||
| 1793 | | bne ->fff_fallback | ||
| 1794 | | subs CARG4, CARG3, #1 | ||
| 1795 | | ldr CARG2, STR:CARG1->len | ||
| 1796 | | blt ->fff_emptystr // Count <= 0? | ||
| 1797 | | cmp CARG2, #1 | ||
| 1798 | | blo ->fff_emptystr // Zero-length string? | ||
| 1799 | | bne ->fff_fallback // Fallback for > 1-char strings. | ||
| 1800 | | ldr CARG2, [DISPATCH, #DISPATCH_GL(tmpbuf.b)] | ||
| 1801 | | ldr RB, [DISPATCH, #DISPATCH_GL(tmpbuf.e)] | ||
| 1802 | | ldr CARG1, STR:CARG1[1] | ||
| 1803 | | add INS, CARG2, CARG3 | ||
| 1804 | | cmp RB, INS | ||
| 1805 | | blo ->fff_fallback | ||
| 1806 | |1: // Fill buffer with char. | ||
| 1807 | | strb CARG1, [CARG2, CARG4] | ||
| 1808 | | subs CARG4, CARG4, #1 | ||
| 1809 | | bge <1 | ||
| 1810 | | b ->fff_newstr | ||
| 1811 | | | ||
| 1812 | |.macro ffstring_op, name | 1785 | |.macro ffstring_op, name |
| 1813 | | .ffunc string_ .. name | 1786 | | .ffunc string_ .. name |
| 1814 | | ffgccheck | 1787 | | ffgccheck |
diff --git a/src/vm_mips.dasc b/src/vm_mips.dasc index 962e9290..9ab68981 100644 --- a/src/vm_mips.dasc +++ b/src/vm_mips.dasc | |||
| @@ -1716,41 +1716,6 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 1716 | | b ->fff_restv | 1716 | | b ->fff_restv |
| 1717 | |. li CARG3, LJ_TSTR | 1717 | |. li CARG3, LJ_TSTR |
| 1718 | | | 1718 | | |
| 1719 | |.ffunc string_rep // Only handle the 1-char case inline. | ||
| 1720 | | ffgccheck | ||
| 1721 | | lw TMP0, HI(BASE) | ||
| 1722 | | addiu AT, NARGS8:RC, -16 // Exactly 2 arguments. | ||
| 1723 | | lw CARG4, 8+HI(BASE) | ||
| 1724 | | lw STR:CARG1, LO(BASE) | ||
| 1725 | | addiu TMP0, TMP0, -LJ_TSTR | ||
| 1726 | | ldc1 f0, 8(BASE) | ||
| 1727 | | or AT, AT, TMP0 | ||
| 1728 | | bnez AT, ->fff_fallback | ||
| 1729 | |. sltiu AT, CARG4, LJ_TISNUM | ||
| 1730 | | trunc.w.d f0, f0 | ||
| 1731 | | beqz AT, ->fff_fallback | ||
| 1732 | |. lw TMP0, STR:CARG1->len | ||
| 1733 | | mfc1 CARG3, f0 | ||
| 1734 | | lw CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH) | ||
| 1735 | | lw TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH) | ||
| 1736 | | li AT, 1 | ||
| 1737 | | blez CARG3, ->fff_emptystr // Count <= 0? | ||
| 1738 | |. sltu AT, AT, TMP0 | ||
| 1739 | | beqz TMP0, ->fff_emptystr // Zero length string? | ||
| 1740 | |. addu TMP3, CARG2, CARG3 | ||
| 1741 | | sltu TMP0, TMP1, TMP3 | ||
| 1742 | | or AT, AT, TMP0 | ||
| 1743 | | bnez AT, ->fff_fallback // Fallback for > 1-char strings. | ||
| 1744 | |. lbu TMP0, STR:CARG1[1] | ||
| 1745 | | addu TMP2, CARG2, CARG3 | ||
| 1746 | |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). | ||
| 1747 | | addiu TMP2, TMP2, -1 | ||
| 1748 | | sltu AT, CARG2, TMP2 | ||
| 1749 | | bnez AT, <1 | ||
| 1750 | |. sb TMP0, 0(TMP2) | ||
| 1751 | | b ->fff_newstr | ||
| 1752 | |. nop | ||
| 1753 | | | ||
| 1754 | |.macro ffstring_op, name | 1719 | |.macro ffstring_op, name |
| 1755 | | .ffunc string_ .. name | 1720 | | .ffunc string_ .. name |
| 1756 | | ffgccheck | 1721 | | ffgccheck |
diff --git a/src/vm_ppc.dasc b/src/vm_ppc.dasc index 19211825..733eeb8f 100644 --- a/src/vm_ppc.dasc +++ b/src/vm_ppc.dasc | |||
| @@ -2177,49 +2177,6 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2177 | | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0) | 2177 | | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0) |
| 2178 | | b <3 | 2178 | | b <3 |
| 2179 | | | 2179 | | |
| 2180 | |.ffunc string_rep // Only handle the 1-char case inline. | ||
| 2181 | | ffgccheck | ||
| 2182 | | cmplwi NARGS8:RC, 16 | ||
| 2183 | | lwz TMP0, 0(BASE) | ||
| 2184 | | lwz STR:CARG1, 4(BASE) | ||
| 2185 | | lwz CARG4, 8(BASE) | ||
| 2186 | |.if DUALNUM | ||
| 2187 | | lwz CARG3, 12(BASE) | ||
| 2188 | |.else | ||
| 2189 | | lfd FARG2, 8(BASE) | ||
| 2190 | |.endif | ||
| 2191 | | bne ->fff_fallback // Exactly 2 arguments. | ||
| 2192 | | checkstr TMP0; bne ->fff_fallback | ||
| 2193 | |.if DUALNUM | ||
| 2194 | | checknum CARG4; bne ->fff_fallback | ||
| 2195 | |.else | ||
| 2196 | | checknum CARG4; bge ->fff_fallback | ||
| 2197 | | toint CARG3, FARG2 | ||
| 2198 | |.endif | ||
| 2199 | | lwz TMP0, STR:CARG1->len | ||
| 2200 | | cmpwi CARG3, 0 | ||
| 2201 | | lwz TMP1, DISPATCH_GL(tmpbuf.e)(DISPATCH) | ||
| 2202 | | lwz CARG2, DISPATCH_GL(tmpbuf.b)(DISPATCH) | ||
| 2203 | | ble >2 // Count <= 0? (or non-int) | ||
| 2204 | | cmplwi TMP0, 1 | ||
| 2205 | | add TMP3, CARG2, CARG3 | ||
| 2206 | | subi TMP2, CARG3, 1 | ||
| 2207 | | blt >2 // Zero length string? | ||
| 2208 | | cmplw cr1, TMP1, TMP3 | ||
| 2209 | | bne ->fff_fallback // Fallback for > 1-char strings. | ||
| 2210 | | lbz TMP0, STR:CARG1[1] | ||
| 2211 | | blt cr1, ->fff_fallback | ||
| 2212 | |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?). | ||
| 2213 | | cmplwi TMP2, 0 | ||
| 2214 | | stbx TMP0, CARG2, TMP2 | ||
| 2215 | | subi TMP2, TMP2, 1 | ||
| 2216 | | bne <1 | ||
| 2217 | | b ->fff_newstr | ||
| 2218 | |2: // Return empty string. | ||
| 2219 | | la STR:CARG1, DISPATCH_GL(strempty)(DISPATCH) | ||
| 2220 | | li CARG3, LJ_TSTR | ||
| 2221 | | b ->fff_restv | ||
| 2222 | | | ||
| 2223 | |.macro ffstring_op, name | 2180 | |.macro ffstring_op, name |
| 2224 | | .ffunc string_ .. name | 2181 | | .ffunc string_ .. name |
| 2225 | | ffgccheck | 2182 | | ffgccheck |
diff --git a/src/vm_x86.dasc b/src/vm_x86.dasc index 3f2959be..b7c5393f 100644 --- a/src/vm_x86.dasc +++ b/src/vm_x86.dasc | |||
| @@ -2331,41 +2331,6 @@ static void build_subroutines(BuildCtx *ctx) | |||
| 2331 | | xor RC, RC // Zero length. Any ptr in RB is ok. | 2331 | | xor RC, RC // Zero length. Any ptr in RB is ok. |
| 2332 | | jmp <4 | 2332 | | jmp <4 |
| 2333 | | | 2333 | | |
| 2334 | |.ffunc string_rep // Only handle the 1-char case inline. | ||
| 2335 | | ffgccheck | ||
| 2336 | | cmp NARGS:RD, 2+1; jne ->fff_fallback // Exactly 2 arguments. | ||
| 2337 | | cmp dword [BASE+4], LJ_TSTR; jne ->fff_fallback | ||
| 2338 | | cmp dword [BASE+12], LJ_TISNUM | ||
| 2339 | | mov STR:RB, [BASE] | ||
| 2340 | |.if DUALNUM | ||
| 2341 | | jne ->fff_fallback | ||
| 2342 | | mov RC, dword [BASE+8] | ||
| 2343 | |.else | ||
| 2344 | | jae ->fff_fallback | ||
| 2345 | | cvttsd2si RC, qword [BASE+8] | ||
| 2346 | |.endif | ||
| 2347 | | test RC, RC | ||
| 2348 | | jle ->fff_emptystr // Count <= 0? (or non-int) | ||
| 2349 | | cmp dword STR:RB->len, 1 | ||
| 2350 | | jb ->fff_emptystr // Zero length string? | ||
| 2351 | | jne ->fff_fallback_2 // Fallback for > 1-char strings. | ||
| 2352 | | movzx RA, byte STR:RB[1] | ||
| 2353 | | mov RB, [DISPATCH+DISPATCH_GL(tmpbuf.b)] | ||
| 2354 | | add RB, RC | ||
| 2355 | | cmp [DISPATCH+DISPATCH_GL(tmpbuf.e)], RB; jb ->fff_fallback_2 | ||
| 2356 | |.if X64 | ||
| 2357 | | mov TMP3, RC | ||
| 2358 | |.else | ||
| 2359 | | mov ARG3, RC | ||
| 2360 | |.endif | ||
| 2361 | |1: // Fill buffer with char. | ||
| 2362 | | sub RB, 1 | ||
| 2363 | | sub RC, 1 | ||
| 2364 | | mov [RB], RAL | ||
| 2365 | | jnz <1 | ||
| 2366 | | mov RD, [DISPATCH+DISPATCH_GL(tmpbuf.b)] | ||
| 2367 | | jmp ->fff_newstr | ||
| 2368 | | | ||
| 2369 | |.macro ffstring_op, name | 2334 | |.macro ffstring_op, name |
| 2370 | | .ffunc_1 string_ .. name | 2335 | | .ffunc_1 string_ .. name |
| 2371 | | ffgccheck | 2336 | | ffgccheck |
