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 /src | |
| parent | 3b0b3afbb1357cbf206b56a46cd03955b201fa4b (diff) | |
| download | luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.tar.gz luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.tar.bz2 luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.zip | |
Optimize and refactor printing of numbers to buffers.
Diffstat (limited to 'src')
| -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); |
