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 |