diff options
| author | Mike Pall <mike> | 2013-03-25 16:44:19 +0100 |
|---|---|---|
| committer | Mike Pall <mike> | 2013-03-25 17:13:08 +0100 |
| commit | df94b81b2d9244b9c88486bfd15a001fd899b46b (patch) | |
| tree | 1b558ac097dafc86d1885209aff1266ff124cce8 | |
| parent | 59329cfbbf1362bc17f5a13c10a1c3b9557321ef (diff) | |
| download | luajit-df94b81b2d9244b9c88486bfd15a001fd899b46b.tar.gz luajit-df94b81b2d9244b9c88486bfd15a001fd899b46b.tar.bz2 luajit-df94b81b2d9244b9c88486bfd15a001fd899b46b.zip | |
Tune string concatenation.
| -rw-r--r-- | src/lj_meta.c | 58 |
1 files changed, 22 insertions, 36 deletions
diff --git a/src/lj_meta.c b/src/lj_meta.c index db1ce928..2601af94 100644 --- a/src/lj_meta.c +++ b/src/lj_meta.c | |||
| @@ -227,27 +227,14 @@ TValue *lj_meta_arith(lua_State *L, TValue *ra, cTValue *rb, cTValue *rc, | |||
| 227 | } | 227 | } |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | /* In-place coercion of a number to a string. */ | ||
| 231 | static LJ_AINLINE int tostring(lua_State *L, TValue *o) | ||
| 232 | { | ||
| 233 | if (tvisstr(o)) { | ||
| 234 | return 1; | ||
| 235 | } else if (tvisnumber(o)) { | ||
| 236 | setstrV(L, o, lj_str_fromnumber(L, o)); | ||
| 237 | return 1; | ||
| 238 | } else { | ||
| 239 | return 0; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | |||
| 243 | /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */ | 230 | /* Helper for CAT. Coercion, iterative concat, __concat metamethod. */ |
| 244 | TValue *lj_meta_cat(lua_State *L, TValue *top, int left) | 231 | TValue *lj_meta_cat(lua_State *L, TValue *top, int left) |
| 245 | { | 232 | { |
| 246 | int fromc = 0; | 233 | int fromc = 0; |
| 247 | if (left < 0) { left = -left; fromc = 1; } | 234 | if (left < 0) { left = -left; fromc = 1; } |
| 248 | do { | 235 | do { |
| 249 | int n = 1; | 236 | if (!(tvisstr(top) || tvisnumber(top)) || |
| 250 | if (!(tvisstr(top-1) || tvisnumber(top-1)) || !tostring(L, top)) { | 237 | !(tvisstr(top-1) || tvisnumber(top-1))) { |
| 251 | cTValue *mo = lj_meta_lookup(L, top-1, MM_concat); | 238 | cTValue *mo = lj_meta_lookup(L, top-1, MM_concat); |
| 252 | if (tvisnil(mo)) { | 239 | if (tvisnil(mo)) { |
| 253 | mo = lj_meta_lookup(L, top, MM_concat); | 240 | mo = lj_meta_lookup(L, top, MM_concat); |
| @@ -273,8 +260,6 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) | |||
| 273 | copyTV(L, top, mo); | 260 | copyTV(L, top, mo); |
| 274 | setcont(top-1, lj_cont_cat); | 261 | setcont(top-1, lj_cont_cat); |
| 275 | return top+1; /* Trigger metamethod call. */ | 262 | return top+1; /* Trigger metamethod call. */ |
| 276 | } else if (strV(top)->len == 0) { /* Shortcut. */ | ||
| 277 | (void)tostring(L, top-1); | ||
| 278 | } else { | 263 | } else { |
| 279 | /* Pick as many strings as possible from the top and concatenate them: | 264 | /* Pick as many strings as possible from the top and concatenate them: |
| 280 | ** | 265 | ** |
| @@ -283,27 +268,28 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left) | |||
| 283 | ** concat: [...][CAT stack ...] [result] | 268 | ** concat: [...][CAT stack ...] [result] |
| 284 | ** next step: [...][CAT stack ............] | 269 | ** next step: [...][CAT stack ............] |
| 285 | */ | 270 | */ |
| 286 | MSize tlen = strV(top)->len; | 271 | TValue *e, *o = top; |
| 287 | char *buf; | 272 | uint64_t tlen = tvisstr(o) ? strV(o)->len : LJ_STR_NUMBERBUF; |
| 288 | int i; | 273 | char *p, *buf; |
| 289 | for (n = 1; n <= left && tostring(L, top-n); n++) { | 274 | do { |
| 290 | MSize len = strV(top-n)->len; | 275 | o--; tlen += tvisstr(o) ? strV(o)->len : LJ_STR_NUMBERBUF; |
| 291 | if (len >= LJ_MAX_STR - tlen) | 276 | } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1))); |
| 292 | lj_err_msg(L, LJ_ERR_STROV); | 277 | if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV); |
| 293 | tlen += len; | 278 | p = buf = lj_buf_tmp(L, (MSize)tlen); |
| 294 | } | 279 | for (e = top, top = o; o <= e; o++) { |
| 295 | buf = lj_buf_tmp(L, tlen); | 280 | if (tvisstr(o)) { |
| 296 | n--; | 281 | GCstr *s = strV(o); |
| 297 | tlen = 0; | 282 | MSize len = s->len; |
| 298 | for (i = n; i >= 0; i--) { | 283 | p = lj_buf_wmem(p, strdata(s), len); |
| 299 | MSize len = strV(top-i)->len; | 284 | } else if (tvisint(o)) { |
| 300 | memcpy(buf + tlen, strVdata(top-i), len); | 285 | p = lj_str_bufint(p, intV(o)); |
| 301 | tlen += len; | 286 | } else { |
| 287 | lua_assert(tvisnum(o)); | ||
| 288 | p = lj_str_bufnum(p, o); | ||
| 289 | } | ||
| 302 | } | 290 | } |
| 303 | setstrV(L, top-n, lj_str_new(L, buf, tlen)); | 291 | setstrV(L, top, lj_str_new(L, buf, (size_t)(p-buf))); |
| 304 | } | 292 | } |
| 305 | left -= n; | ||
| 306 | top -= n; | ||
| 307 | } while (left >= 1); | 293 | } while (left >= 1); |
| 308 | if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) { | 294 | if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) { |
| 309 | if (!fromc) L->top = curr_topL(L); | 295 | if (!fromc) L->top = curr_topL(L); |
