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/lj_str.c | |
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/lj_str.c')
-rw-r--r-- | src/lj_str.c | 92 |
1 files changed, 52 insertions, 40 deletions
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; |