diff options
author | Mike Pall <mike> | 2013-03-25 16:41:13 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2013-03-25 16:41:13 +0100 |
commit | 59329cfbbf1362bc17f5a13c10a1c3b9557321ef (patch) | |
tree | 2f9753b74eeddcc4850dc2c19f423623e0122198 | |
parent | 3b0b3afbb1357cbf206b56a46cd03955b201fa4b (diff) | |
download | luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.tar.gz luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.tar.bz2 luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.zip |
Optimize and refactor printing of numbers to buffers.
-rw-r--r-- | src/lib_string.c | 17 | ||||
-rw-r--r-- | src/lj_ctype.c | 14 | ||||
-rw-r--r-- | src/lj_ffrecord.c | 5 | ||||
-rw-r--r-- | src/lj_str.c | 92 | ||||
-rw-r--r-- | src/lj_str.h | 5 |
5 files changed, 70 insertions, 63 deletions
diff --git a/src/lib_string.c b/src/lib_string.c index 09010b15..eb2ae226 100644 --- a/src/lib_string.c +++ b/src/lib_string.c | |||
@@ -881,14 +881,10 @@ LJLIB_CF(string_format) | |||
881 | tv.n = lj_lib_checknum(L, arg); | 881 | tv.n = lj_lib_checknum(L, arg); |
882 | if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) { | 882 | if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) { |
883 | /* Canonicalize output of non-finite values. */ | 883 | /* Canonicalize output of non-finite values. */ |
884 | char *p, nbuf[LJ_STR_NUMBUF]; | 884 | char nbuf[LJ_STR_NUMBUF]; |
885 | MSize n = lj_str_bufnum(nbuf, &tv); | 885 | char *p = lj_str_bufnum(nbuf, &tv); |
886 | if (fmt[-1] < 'a') { | 886 | if (fmt[-1] < 'a') { *(p-3) -= 0x20; *(p-2) -= 0x20; *(p-1) -= 0x20; } |
887 | nbuf[n-3] = nbuf[n-3] - 0x20; | 887 | *p = '\0'; |
888 | nbuf[n-2] = nbuf[n-2] - 0x20; | ||
889 | nbuf[n-1] = nbuf[n-1] - 0x20; | ||
890 | } | ||
891 | nbuf[n] = '\0'; | ||
892 | for (p = spec; *p < 'A' && *p != '.'; p++) ; | 888 | for (p = spec; *p < 'A' && *p != '.'; p++) ; |
893 | *p++ = 's'; *p = '\0'; | 889 | *p++ = 's'; *p = '\0'; |
894 | len = (MSize)sprintf(buf, spec, nbuf); | 890 | len = (MSize)sprintf(buf, spec, nbuf); |
@@ -901,8 +897,9 @@ LJLIB_CF(string_format) | |||
901 | string_fmt_quoted(sb, lj_lib_checkstr(L, arg)); | 897 | string_fmt_quoted(sb, lj_lib_checkstr(L, arg)); |
902 | continue; | 898 | continue; |
903 | case 'p': | 899 | case 'p': |
904 | len = lj_str_bufptr(buf, lua_topointer(L, arg)); | 900 | setsbufP(sb, lj_str_bufptr(lj_buf_more(sb, LJ_STR_PTRBUF), |
905 | break; | 901 | lua_topointer(L, arg))); |
902 | continue; | ||
906 | case 's': { | 903 | case 's': { |
907 | GCstr *str = string_fmt_tostring(L, arg); | 904 | GCstr *str = string_fmt_tostring(L, arg); |
908 | if (!strchr(spec, '.') && str->len >= 100) { /* Format overflow? */ | 905 | if (!strchr(spec, '.') && str->len >= 100) { /* Format overflow? */ |
diff --git a/src/lj_ctype.c b/src/lj_ctype.c index 69ba76d1..f9e75fd1 100644 --- a/src/lj_ctype.c +++ b/src/lj_ctype.c | |||
@@ -568,19 +568,19 @@ GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned) | |||
568 | /* Convert complex to string with 'i' or 'I' suffix. */ | 568 | /* Convert complex to string with 'i' or 'I' suffix. */ |
569 | GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) | 569 | GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) |
570 | { | 570 | { |
571 | char buf[2*LJ_STR_NUMBUF+2+1]; | 571 | char buf[2*LJ_STR_NUMBUF+2+1], *p = buf; |
572 | TValue re, im; | 572 | TValue re, im; |
573 | MSize len; | ||
574 | if (size == 2*sizeof(double)) { | 573 | if (size == 2*sizeof(double)) { |
575 | re.n = *(double *)sp; im.n = ((double *)sp)[1]; | 574 | re.n = *(double *)sp; im.n = ((double *)sp)[1]; |
576 | } else { | 575 | } else { |
577 | re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1]; | 576 | re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1]; |
578 | } | 577 | } |
579 | len = lj_str_bufnum(buf, &re); | 578 | p = lj_str_bufnum(p, &re); |
580 | if (!(im.u32.hi & 0x80000000u) || im.n != im.n) buf[len++] = '+'; | 579 | if (!(im.u32.hi & 0x80000000u) || im.n != im.n) *p++ = '+'; |
581 | len += lj_str_bufnum(buf+len, &im); | 580 | p = lj_str_bufnum(p, &im); |
582 | buf[len] = buf[len-1] >= 'a' ? 'I' : 'i'; | 581 | *p = *(p-1) >= 'a' ? 'I' : 'i'; |
583 | return lj_str_new(L, buf, len+1); | 582 | p++; |
583 | return lj_str_new(L, buf, p-buf); | ||
584 | } | 584 | } |
585 | 585 | ||
586 | /* -- C type state -------------------------------------------------------- */ | 586 | /* -- C type state -------------------------------------------------------- */ |
diff --git a/src/lj_ffrecord.c b/src/lj_ffrecord.c index 4f6aeb37..32346d22 100644 --- a/src/lj_ffrecord.c +++ b/src/lj_ffrecord.c | |||
@@ -79,10 +79,7 @@ static GCstr *argv2str(jit_State *J, TValue *o) | |||
79 | GCstr *s; | 79 | GCstr *s; |
80 | if (!tvisnumber(o)) | 80 | if (!tvisnumber(o)) |
81 | lj_trace_err(J, LJ_TRERR_BADTYPE); | 81 | lj_trace_err(J, LJ_TRERR_BADTYPE); |
82 | if (tvisint(o)) | 82 | s = lj_str_fromnumber(J->L, o); |
83 | s = lj_str_fromint(J->L, intV(o)); | ||
84 | else | ||
85 | s = lj_str_fromnum(J->L, &o->n); | ||
86 | setstrV(J->L, o, s); | 83 | setstrV(J->L, o, s); |
87 | return s; | 84 | return s; |
88 | } | 85 | } |
diff --git a/src/lj_str.c b/src/lj_str.c index 9eb04c57..a0080e31 100644 --- a/src/lj_str.c +++ b/src/lj_str.c | |||
@@ -168,41 +168,62 @@ void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s) | |||
168 | /* -- Type conversions ---------------------------------------------------- */ | 168 | /* -- Type conversions ---------------------------------------------------- */ |
169 | 169 | ||
170 | /* Print number to buffer. Canonicalizes non-finite values. */ | 170 | /* Print number to buffer. Canonicalizes non-finite values. */ |
171 | MSize LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) | 171 | char * LJ_FASTCALL lj_str_bufnum(char *p, cTValue *o) |
172 | { | 172 | { |
173 | if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */ | 173 | if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */ |
174 | lua_Number n = o->n; | ||
175 | #if __BIONIC__ | 174 | #if __BIONIC__ |
176 | if (tvismzero(o)) { s[0] = '-'; s[1] = '0'; return 2; } | 175 | if (tvismzero(o)) { *p++ = '-'; *p++ = '0'; return p; } |
177 | #endif | 176 | #endif |
178 | return (MSize)lua_number2str(s, n); | 177 | return p + lua_number2str(p, o->n); |
179 | } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) { | 178 | } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) { |
180 | s[0] = 'n'; s[1] = 'a'; s[2] = 'n'; return 3; | 179 | *p++ = 'n'; *p++ = 'a'; *p++ = 'n'; |
181 | } else if ((o->u32.hi & 0x80000000) == 0) { | 180 | } else if ((o->u32.hi & 0x80000000) == 0) { |
182 | s[0] = 'i'; s[1] = 'n'; s[2] = 'f'; return 3; | 181 | *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; |
183 | } else { | 182 | } else { |
184 | s[0] = '-'; s[1] = 'i'; s[2] = 'n'; s[3] = 'f'; return 4; | 183 | *p++ = '-'; *p++ = 'i'; *p++ = 'n'; *p++ = 'f'; |
185 | } | 184 | } |
185 | return p; | ||
186 | } | 186 | } |
187 | 187 | ||
188 | /* Print integer to buffer. Returns pointer to start (!= buffer start). */ | 188 | #define STR_BUFINT_R(x, sh, sc) \ |
189 | static char *str_bufint(char *p, int32_t k) | 189 | { uint32_t d = (x*(((1<<sh)+sc-1)/sc))>>sh; x -= d*sc; *p++ = (char)('0'+d); } |
190 | |||
191 | /* Print integer to buffer. */ | ||
192 | char * LJ_FASTCALL lj_str_bufint(char *p, int32_t k) | ||
190 | { | 193 | { |
191 | uint32_t u = (uint32_t)(k < 0 ? -k : k); | 194 | uint32_t u = (uint32_t)k; |
192 | p += LJ_STR_INTBUF; | 195 | if (k < 0) { u = (uint32_t)-k; *p++ = '-'; } |
193 | do { *--p = (char)('0' + u % 10); } while (u /= 10); | 196 | if (u < 10000) { |
194 | if (k < 0) *--p = '-'; | 197 | if (u < 10) goto dig1; if (u < 100) goto dig2; if (u < 1000) goto dig3; |
198 | } else { | ||
199 | uint32_t v = u / 10000; u -= v * 10000; | ||
200 | if (v < 10000) { | ||
201 | if (v < 10) goto dig5; if (v < 100) goto dig6; if (v < 1000) goto dig7; | ||
202 | } else { | ||
203 | uint32_t w = v / 10000; v -= w * 10000; | ||
204 | if (w >= 10) STR_BUFINT_R(w, 10, 10) | ||
205 | *p++ = (char)('0'+w); | ||
206 | } | ||
207 | STR_BUFINT_R(v, 23, 1000) | ||
208 | dig7: STR_BUFINT_R(v, 12, 100) | ||
209 | dig6: STR_BUFINT_R(v, 10, 10) | ||
210 | dig5: *p++ = (char)('0'+v); | ||
211 | } | ||
212 | STR_BUFINT_R(u, 23, 1000) | ||
213 | dig3: STR_BUFINT_R(u, 12, 100) | ||
214 | dig2: STR_BUFINT_R(u, 10, 10) | ||
215 | dig1: *p++ = (char)('0'+u); | ||
195 | return p; | 216 | return p; |
196 | } | 217 | } |
197 | 218 | ||
198 | /* Print pointer to buffer. */ | 219 | /* Print pointer to buffer. */ |
199 | MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v) | 220 | char * LJ_FASTCALL lj_str_bufptr(char *p, const void *v) |
200 | { | 221 | { |
201 | ptrdiff_t x = (ptrdiff_t)v; | 222 | ptrdiff_t x = (ptrdiff_t)v; |
202 | MSize i, n = LJ_STR_PTRBUF; | 223 | MSize i, n = LJ_STR_PTRBUF; |
203 | if (x == 0) { | 224 | if (x == 0) { |
204 | p[0] = 'N'; p[1] = 'U'; p[2] = 'L'; p[3] = 'L'; | 225 | *p++ = 'N'; *p++ = 'U'; *p++ = 'L'; *p++ = 'L'; |
205 | return 4; | 226 | return p; |
206 | } | 227 | } |
207 | #if LJ_64 | 228 | #if LJ_64 |
208 | /* Shorten output for 64 bit pointers. */ | 229 | /* Shorten output for 64 bit pointers. */ |
@@ -212,7 +233,7 @@ MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v) | |||
212 | p[1] = 'x'; | 233 | p[1] = 'x'; |
213 | for (i = n-1; i >= 2; i--, x >>= 4) | 234 | for (i = n-1; i >= 2; i--, x >>= 4) |
214 | p[i] = "0123456789abcdef"[(x & 15)]; | 235 | p[i] = "0123456789abcdef"[(x & 15)]; |
215 | return n; | 236 | return p+n; |
216 | } | 237 | } |
217 | 238 | ||
218 | /* Print TValue to buffer (only for numbers) and return pointer to start. */ | 239 | /* Print TValue to buffer (only for numbers) and return pointer to start. */ |
@@ -222,11 +243,10 @@ const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp) | |||
222 | *lenp = strV(o)->len; | 243 | *lenp = strV(o)->len; |
223 | return strVdata(o); | 244 | return strVdata(o); |
224 | } else if (tvisint(o)) { | 245 | } else if (tvisint(o)) { |
225 | char *p = str_bufint(buf, intV(o)); | 246 | *lenp = (MSize)(lj_str_bufint(buf, intV(o)) - buf); |
226 | *lenp = (MSize)(buf+LJ_STR_INTBUF-p); | 247 | return buf; |
227 | return p; | ||
228 | } else if (tvisnum(o)) { | 248 | } else if (tvisnum(o)) { |
229 | *lenp = lj_str_bufnum(buf, o); | 249 | *lenp = (MSize)(lj_str_bufnum(buf, o) - buf); |
230 | return buf; | 250 | return buf; |
231 | } else { | 251 | } else { |
232 | return NULL; | 252 | return NULL; |
@@ -237,7 +257,7 @@ const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp) | |||
237 | GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) | 257 | GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) |
238 | { | 258 | { |
239 | char buf[LJ_STR_NUMBUF]; | 259 | char buf[LJ_STR_NUMBUF]; |
240 | MSize len = lj_str_bufnum(buf, (TValue *)np); | 260 | MSize len = (MSize)(lj_str_bufnum(buf, (TValue *)np) - buf); |
241 | return lj_str_new(L, buf, len); | 261 | return lj_str_new(L, buf, len); |
242 | } | 262 | } |
243 | 263 | ||
@@ -245,8 +265,8 @@ GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) | |||
245 | GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) | 265 | GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) |
246 | { | 266 | { |
247 | char buf[LJ_STR_INTBUF]; | 267 | char buf[LJ_STR_INTBUF]; |
248 | char *p = str_bufint(buf, k); | 268 | MSize len = (MSize)(lj_str_bufint(buf, k) - buf); |
249 | return lj_str_new(L, p, (size_t)(buf+sizeof(buf)-p)); | 269 | return lj_str_new(L, buf, len); |
250 | } | 270 | } |
251 | 271 | ||
252 | GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o) | 272 | GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o) |
@@ -278,28 +298,20 @@ const char *lj_str_pushvf(lua_State *L, const char *fmt, va_list argp) | |||
278 | case 'c': | 298 | case 'c': |
279 | lj_buf_putb(sb, va_arg(argp, int)); | 299 | lj_buf_putb(sb, va_arg(argp, int)); |
280 | break; | 300 | break; |
281 | case 'd': { | 301 | case 'd': |
282 | char buf[LJ_STR_INTBUF]; | 302 | setsbufP(sb, lj_str_bufint(lj_buf_more(sb, LJ_STR_INTBUF), |
283 | char *p = str_bufint(buf, va_arg(argp, int32_t)); | 303 | va_arg(argp, int32_t))); |
284 | lj_buf_putmem(sb, p, (MSize)(buf+LJ_STR_INTBUF-p)); | ||
285 | break; | 304 | break; |
286 | } | ||
287 | case 'f': { | 305 | case 'f': { |
288 | char buf[LJ_STR_NUMBUF]; | ||
289 | TValue tv; | 306 | TValue tv; |
290 | MSize len; | 307 | tv.n = va_arg(argp, lua_Number); |
291 | tv.n = (lua_Number)(va_arg(argp, LUAI_UACNUMBER)); | 308 | setsbufP(sb, lj_str_bufnum(lj_buf_more(sb, LJ_STR_NUMBUF), &tv)); |
292 | len = (MSize)lj_str_bufnum(buf, &tv); | ||
293 | lj_buf_putmem(sb, buf, len); | ||
294 | break; | 309 | break; |
295 | } | 310 | } |
296 | case 'p': { | 311 | case 'p': |
297 | #define FMTP_CHARS (2*sizeof(ptrdiff_t)) | 312 | setsbufP(sb, lj_str_bufptr(lj_buf_more(sb, LJ_STR_PTRBUF), |
298 | char buf[LJ_STR_PTRBUF]; | 313 | va_arg(argp, void *))); |
299 | MSize len = lj_str_bufptr(buf, va_arg(argp, void *)); | ||
300 | lj_buf_putmem(sb, buf, len); | ||
301 | break; | 314 | break; |
302 | } | ||
303 | case '%': | 315 | case '%': |
304 | lj_buf_putb(sb, '%'); | 316 | lj_buf_putb(sb, '%'); |
305 | break; | 317 | break; |
diff --git a/src/lj_str.h b/src/lj_str.h index 6317e794..61666a2a 100644 --- a/src/lj_str.h +++ b/src/lj_str.h | |||
@@ -20,8 +20,9 @@ LJ_FUNC void LJ_FASTCALL lj_str_free(global_State *g, GCstr *s); | |||
20 | #define lj_str_newlit(L, s) (lj_str_new(L, "" s, sizeof(s)-1)) | 20 | #define lj_str_newlit(L, s) (lj_str_new(L, "" s, sizeof(s)-1)) |
21 | 21 | ||
22 | /* Type conversions. */ | 22 | /* Type conversions. */ |
23 | LJ_FUNC MSize LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o); | 23 | LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *buf, int32_t k); |
24 | LJ_FUNC MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v); | 24 | LJ_FUNC char * LJ_FASTCALL lj_str_bufnum(char *p, cTValue *o); |
25 | LJ_FUNC char * LJ_FASTCALL lj_str_bufptr(char *p, const void *v); | ||
25 | LJ_FUNC const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp); | 26 | LJ_FUNC const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp); |
26 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); | 27 | LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); |
27 | LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); | 28 | LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); |