aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-04-26 19:57:25 +0200
committerMike Pall <mike>2013-04-26 19:57:25 +0200
commit9b8db403f28bc8b290f275ea3967d29ebccedde1 (patch)
treebbadb5346afbadd6b306685b6efe505f71803fa8
parenta98e6a70c1692cf4e5686d0acee2ede54728af6f (diff)
downloadluajit-9b8db403f28bc8b290f275ea3967d29ebccedde1.tar.gz
luajit-9b8db403f28bc8b290f275ea3967d29ebccedde1.tar.bz2
luajit-9b8db403f28bc8b290f275ea3967d29ebccedde1.zip
Refactor string.rep().
-rw-r--r--src/lib_string.c56
-rw-r--r--src/lj_buf.c24
-rw-r--r--src/lj_buf.h1
-rw-r--r--src/lj_dispatch.h2
-rw-r--r--src/vm_arm.dasc27
-rw-r--r--src/vm_mips.dasc35
-rw-r--r--src/vm_ppc.dasc43
-rw-r--r--src/vm_x86.dasc35
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
88LJLIB_ASM(string_rep) 88LJLIB_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
137LJLIB_ASM(string_reverse) LJLIB_REC(string_op IRCALL_lj_buf_putstr_reverse) 107LJLIB_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
147SBuf *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
147GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb) 171GCstr * 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);
35LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s); 35LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_reverse(SBuf *sb, GCstr *s);
36LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s); 36LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_lower(SBuf *sb, GCstr *s);
37LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s); 37LJ_FUNCA SBuf * LJ_FASTCALL lj_buf_putstr_upper(SBuf *sb, GCstr *s);
38LJ_FUNC SBuf *lj_buf_putstr_rep(SBuf *sb, GCstr *s, int32_t rep);
38LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb); 39LJ_FUNCA GCstr * LJ_FASTCALL lj_buf_tostr(SBuf *sb);
39LJ_FUNC GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2); 40LJ_FUNC GCstr *lj_buf_cat2str(lua_State *L, GCstr *s1, GCstr *s2);
40LJ_FUNC uint32_t LJ_FASTCALL lj_buf_ruleb128(const char **pp); 41LJ_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