aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2013-03-25 16:41:13 +0100
committerMike Pall <mike>2013-03-25 16:41:13 +0100
commit59329cfbbf1362bc17f5a13c10a1c3b9557321ef (patch)
tree2f9753b74eeddcc4850dc2c19f423623e0122198
parent3b0b3afbb1357cbf206b56a46cd03955b201fa4b (diff)
downloadluajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.tar.gz
luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.tar.bz2
luajit-59329cfbbf1362bc17f5a13c10a1c3b9557321ef.zip
Optimize and refactor printing of numbers to buffers.
-rw-r--r--src/lib_string.c17
-rw-r--r--src/lj_ctype.c14
-rw-r--r--src/lj_ffrecord.c5
-rw-r--r--src/lj_str.c92
-rw-r--r--src/lj_str.h5
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. */
569GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) 569GCstr *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. */
171MSize LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o) 171char * 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) \
189static 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. */
192char * 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. */
199MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v) 220char * 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)
237GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np) 257GCstr * 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)
245GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k) 265GCstr * 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
252GCstr * LJ_FASTCALL lj_str_fromnumber(lua_State *L, cTValue *o) 272GCstr * 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. */
23LJ_FUNC MSize LJ_FASTCALL lj_str_bufnum(char *s, cTValue *o); 23LJ_FUNC char * LJ_FASTCALL lj_str_bufint(char *buf, int32_t k);
24LJ_FUNC MSize LJ_FASTCALL lj_str_bufptr(char *p, const void *v); 24LJ_FUNC char * LJ_FASTCALL lj_str_bufnum(char *p, cTValue *o);
25LJ_FUNC char * LJ_FASTCALL lj_str_bufptr(char *p, const void *v);
25LJ_FUNC const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp); 26LJ_FUNC const char *lj_str_buftv(char *buf, cTValue *o, MSize *lenp);
26LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np); 27LJ_FUNCA GCstr * LJ_FASTCALL lj_str_fromnum(lua_State *L, const lua_Number *np);
27LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k); 28LJ_FUNC GCstr * LJ_FASTCALL lj_str_fromint(lua_State *L, int32_t k);