diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-01-16 14:54:37 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2015-01-16 14:54:37 -0200 |
| commit | 7e2015a46df7976bddee313b994742e49e420714 (patch) | |
| tree | 0b2db30f1214a478ccb3664d165c8a431f0d5850 | |
| parent | 5b01cb39b5ec36c544152351c35c43149d9bbfec (diff) | |
| download | lua-7e2015a46df7976bddee313b994742e49e420714.tar.gz lua-7e2015a46df7976bddee313b994742e49e420714.tar.bz2 lua-7e2015a46df7976bddee313b994742e49e420714.zip | |
size of short strings stored in a single byte, to reduce the size
of struct 'TString'
| -rw-r--r-- | lapi.c | 10 | ||||
| -rw-r--r-- | ldump.c | 4 | ||||
| -rw-r--r-- | lgc.c | 15 | ||||
| -rw-r--r-- | lobject.h | 15 | ||||
| -rw-r--r-- | lstring.c | 27 | ||||
| -rw-r--r-- | lstring.h | 3 | ||||
| -rw-r--r-- | ltable.c | 4 | ||||
| -rw-r--r-- | ltests.c | 4 | ||||
| -rw-r--r-- | lvm.c | 32 |
9 files changed, 69 insertions, 45 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lapi.c,v 2.243 2014/11/12 13:28:54 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp roberto $ |
| 3 | ** Lua API | 3 | ** Lua API |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -382,15 +382,17 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { | |||
| 382 | luaO_tostring(L, o); | 382 | luaO_tostring(L, o); |
| 383 | lua_unlock(L); | 383 | lua_unlock(L); |
| 384 | } | 384 | } |
| 385 | if (len != NULL) *len = tsvalue(o)->len; | 385 | if (len != NULL) |
| 386 | *len = vslen(o); | ||
| 386 | return svalue(o); | 387 | return svalue(o); |
| 387 | } | 388 | } |
| 388 | 389 | ||
| 389 | 390 | ||
| 390 | LUA_API size_t lua_rawlen (lua_State *L, int idx) { | 391 | LUA_API size_t lua_rawlen (lua_State *L, int idx) { |
| 391 | StkId o = index2addr(L, idx); | 392 | StkId o = index2addr(L, idx); |
| 392 | switch (ttnov(o)) { | 393 | switch (ttype(o)) { |
| 393 | case LUA_TSTRING: return tsvalue(o)->len; | 394 | case LUA_TSHRSTR: return tsvalue(o)->shrlen; |
| 395 | case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; | ||
| 394 | case LUA_TUSERDATA: return uvalue(o)->len; | 396 | case LUA_TUSERDATA: return uvalue(o)->len; |
| 395 | case LUA_TTABLE: return luaH_getn(hvalue(o)); | 397 | case LUA_TTABLE: return luaH_getn(hvalue(o)); |
| 396 | default: return 0; | 398 | default: return 0; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ldump.c,v 2.33 2014/07/18 13:36:14 roberto Exp roberto $ | 2 | ** $Id: ldump.c,v 2.34 2014/11/02 19:19:04 roberto Exp roberto $ |
| 3 | ** save precompiled Lua chunks | 3 | ** save precompiled Lua chunks |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -74,7 +74,7 @@ static void DumpString (const TString *s, DumpState *D) { | |||
| 74 | if (s == NULL) | 74 | if (s == NULL) |
| 75 | DumpByte(0, D); | 75 | DumpByte(0, D); |
| 76 | else { | 76 | else { |
| 77 | size_t size = s->len + 1; /* include trailing '\0' */ | 77 | size_t size = tsslen(s) + 1; /* include trailing '\0' */ |
| 78 | if (size < 0xFF) | 78 | if (size < 0xFF) |
| 79 | DumpByte(cast_int(size), D); | 79 | DumpByte(cast_int(size), D); |
| 80 | else { | 80 | else { |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.200 2014/11/02 19:19:04 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp roberto $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -226,10 +226,14 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 226 | reentry: | 226 | reentry: |
| 227 | white2gray(o); | 227 | white2gray(o); |
| 228 | switch (o->tt) { | 228 | switch (o->tt) { |
| 229 | case LUA_TSHRSTR: | 229 | case LUA_TSHRSTR: { |
| 230 | gray2black(o); | ||
| 231 | g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); | ||
| 232 | break; | ||
| 233 | } | ||
| 230 | case LUA_TLNGSTR: { | 234 | case LUA_TLNGSTR: { |
| 231 | gray2black(o); | 235 | gray2black(o); |
| 232 | g->GCmemtrav += sizestring(gco2ts(o)); | 236 | g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); |
| 233 | break; | 237 | break; |
| 234 | } | 238 | } |
| 235 | case LUA_TUSERDATA: { | 239 | case LUA_TUSERDATA: { |
| @@ -689,9 +693,10 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
| 689 | case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; | 693 | case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; |
| 690 | case LUA_TSHRSTR: | 694 | case LUA_TSHRSTR: |
| 691 | luaS_remove(L, gco2ts(o)); /* remove it from hash table */ | 695 | luaS_remove(L, gco2ts(o)); /* remove it from hash table */ |
| 692 | /* go through */ | 696 | luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); |
| 697 | break; | ||
| 693 | case LUA_TLNGSTR: { | 698 | case LUA_TLNGSTR: { |
| 694 | luaM_freemem(L, o, sizestring(gco2ts(o))); | 699 | luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); |
| 695 | break; | 700 | break; |
| 696 | } | 701 | } |
| 697 | default: lua_assert(0); | 702 | default: lua_assert(0); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.105 2014/12/19 13:36:32 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -303,9 +303,12 @@ typedef TValue *StkId; /* index to stack elements */ | |||
| 303 | typedef struct TString { | 303 | typedef struct TString { |
| 304 | CommonHeader; | 304 | CommonHeader; |
| 305 | lu_byte extra; /* reserved words for short strings; "has hash" for longs */ | 305 | lu_byte extra; /* reserved words for short strings; "has hash" for longs */ |
| 306 | lu_byte shrlen; /* length for short strings */ | ||
| 306 | unsigned int hash; | 307 | unsigned int hash; |
| 307 | size_t len; /* number of characters in string */ | 308 | union { |
| 308 | struct TString *hnext; /* linked list for hash table */ | 309 | size_t lnglen; /* length for long strings */ |
| 310 | struct TString *hnext; /* linked list for hash table */ | ||
| 311 | } u; | ||
| 309 | } TString; | 312 | } TString; |
| 310 | 313 | ||
| 311 | 314 | ||
| @@ -329,6 +332,12 @@ typedef union UTString { | |||
| 329 | /* get the actual string (array of bytes) from a Lua value */ | 332 | /* get the actual string (array of bytes) from a Lua value */ |
| 330 | #define svalue(o) getstr(tsvalue(o)) | 333 | #define svalue(o) getstr(tsvalue(o)) |
| 331 | 334 | ||
| 335 | /* get string length from 'TString *s' */ | ||
| 336 | #define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen) | ||
| 337 | |||
| 338 | /* get string length from 'TValue *o' */ | ||
| 339 | #define vslen(o) tsslen(tsvalue(o)) | ||
| 340 | |||
| 332 | 341 | ||
| 333 | /* | 342 | /* |
| 334 | ** Header for userdata; memory area follows the end of this structure | 343 | ** Header for userdata; memory area follows the end of this structure |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.c,v 2.44 2014/07/21 16:02:10 roberto Exp roberto $ | 2 | ** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp roberto $ |
| 3 | ** String table (keeps all strings handled by Lua) | 3 | ** String table (keeps all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -36,10 +36,10 @@ | |||
| 36 | ** equality for long strings | 36 | ** equality for long strings |
| 37 | */ | 37 | */ |
| 38 | int luaS_eqlngstr (TString *a, TString *b) { | 38 | int luaS_eqlngstr (TString *a, TString *b) { |
| 39 | size_t len = a->len; | 39 | size_t len = a->u.lnglen; |
| 40 | lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); | 40 | lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); |
| 41 | return (a == b) || /* same instance or... */ | 41 | return (a == b) || /* same instance or... */ |
| 42 | ((len == b->len) && /* equal length and ... */ | 42 | ((len == b->u.lnglen) && /* equal length and ... */ |
| 43 | (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ | 43 | (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ |
| 44 | } | 44 | } |
| 45 | 45 | ||
| @@ -69,9 +69,9 @@ void luaS_resize (lua_State *L, int newsize) { | |||
| 69 | TString *p = tb->hash[i]; | 69 | TString *p = tb->hash[i]; |
| 70 | tb->hash[i] = NULL; | 70 | tb->hash[i] = NULL; |
| 71 | while (p) { /* for each node in the list */ | 71 | while (p) { /* for each node in the list */ |
| 72 | TString *hnext = p->hnext; /* save next */ | 72 | TString *hnext = p->u.hnext; /* save next */ |
| 73 | unsigned int h = lmod(p->hash, newsize); /* new position */ | 73 | unsigned int h = lmod(p->hash, newsize); /* new position */ |
| 74 | p->hnext = tb->hash[h]; /* chain it */ | 74 | p->u.hnext = tb->hash[h]; /* chain it */ |
| 75 | tb->hash[h] = p; | 75 | tb->hash[h] = p; |
| 76 | p = hnext; | 76 | p = hnext; |
| 77 | } | 77 | } |
| @@ -97,7 +97,6 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, | |||
| 97 | totalsize = sizelstring(l); | 97 | totalsize = sizelstring(l); |
| 98 | o = luaC_newobj(L, tag, totalsize); | 98 | o = luaC_newobj(L, tag, totalsize); |
| 99 | ts = gco2ts(o); | 99 | ts = gco2ts(o); |
| 100 | ts->len = l; | ||
| 101 | ts->hash = h; | 100 | ts->hash = h; |
| 102 | ts->extra = 0; | 101 | ts->extra = 0; |
| 103 | memcpy(getaddrstr(ts), str, l * sizeof(char)); | 102 | memcpy(getaddrstr(ts), str, l * sizeof(char)); |
| @@ -110,8 +109,8 @@ void luaS_remove (lua_State *L, TString *ts) { | |||
| 110 | stringtable *tb = &G(L)->strt; | 109 | stringtable *tb = &G(L)->strt; |
| 111 | TString **p = &tb->hash[lmod(ts->hash, tb->size)]; | 110 | TString **p = &tb->hash[lmod(ts->hash, tb->size)]; |
| 112 | while (*p != ts) /* find previous element */ | 111 | while (*p != ts) /* find previous element */ |
| 113 | p = &(*p)->hnext; | 112 | p = &(*p)->u.hnext; |
| 114 | *p = (*p)->hnext; /* remove element from its list */ | 113 | *p = (*p)->u.hnext; /* remove element from its list */ |
| 115 | tb->nuse--; | 114 | tb->nuse--; |
| 116 | } | 115 | } |
| 117 | 116 | ||
| @@ -124,8 +123,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { | |||
| 124 | global_State *g = G(L); | 123 | global_State *g = G(L); |
| 125 | unsigned int h = luaS_hash(str, l, g->seed); | 124 | unsigned int h = luaS_hash(str, l, g->seed); |
| 126 | TString **list = &g->strt.hash[lmod(h, g->strt.size)]; | 125 | TString **list = &g->strt.hash[lmod(h, g->strt.size)]; |
| 127 | for (ts = *list; ts != NULL; ts = ts->hnext) { | 126 | for (ts = *list; ts != NULL; ts = ts->u.hnext) { |
| 128 | if (l == ts->len && | 127 | if (l == ts->shrlen && |
| 129 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { | 128 | (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { |
| 130 | /* found! */ | 129 | /* found! */ |
| 131 | if (isdead(g, ts)) /* dead (but not collected yet)? */ | 130 | if (isdead(g, ts)) /* dead (but not collected yet)? */ |
| @@ -138,7 +137,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { | |||
| 138 | list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ | 137 | list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ |
| 139 | } | 138 | } |
| 140 | ts = createstrobj(L, str, l, LUA_TSHRSTR, h); | 139 | ts = createstrobj(L, str, l, LUA_TSHRSTR, h); |
| 141 | ts->hnext = *list; | 140 | ts->shrlen = cast_byte(l); |
| 141 | ts->u.hnext = *list; | ||
| 142 | *list = ts; | 142 | *list = ts; |
| 143 | g->strt.nuse++; | 143 | g->strt.nuse++; |
| 144 | return ts; | 144 | return ts; |
| @@ -152,9 +152,12 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { | |||
| 152 | if (l <= LUAI_MAXSHORTLEN) /* short string? */ | 152 | if (l <= LUAI_MAXSHORTLEN) /* short string? */ |
| 153 | return internshrstr(L, str, l); | 153 | return internshrstr(L, str, l); |
| 154 | else { | 154 | else { |
| 155 | TString *ts; | ||
| 155 | if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) | 156 | if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) |
| 156 | luaM_toobig(L); | 157 | luaM_toobig(L); |
| 157 | return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); | 158 | ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); |
| 159 | ts->u.lnglen = l; | ||
| 160 | return ts; | ||
| 158 | } | 161 | } |
| 159 | } | 162 | } |
| 160 | 163 | ||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstring.h,v 1.54 2014/03/19 18:51:42 roberto Exp roberto $ | 2 | ** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp roberto $ |
| 3 | ** String table (keep all strings handled by Lua) | 3 | ** String table (keep all strings handled by Lua) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -13,7 +13,6 @@ | |||
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) | 15 | #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) |
| 16 | #define sizestring(s) sizelstring((s)->len) | ||
| 17 | 16 | ||
| 18 | #define sizeludata(l) (sizeof(union UUdata) + (l)) | 17 | #define sizeludata(l) (sizeof(union UUdata) + (l)) |
| 19 | #define sizeudata(u) sizeludata((u)->len) | 18 | #define sizeudata(u) sizeludata((u)->len) |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltable.c,v 2.99 2014/11/02 19:19:04 roberto Exp roberto $ | 2 | ** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp roberto $ |
| 3 | ** Lua tables (hash) | 3 | ** Lua tables (hash) |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -127,7 +127,7 @@ static Node *mainposition (const Table *t, const TValue *key) { | |||
| 127 | case LUA_TLNGSTR: { | 127 | case LUA_TLNGSTR: { |
| 128 | TString *s = tsvalue(key); | 128 | TString *s = tsvalue(key); |
| 129 | if (s->extra == 0) { /* no hash? */ | 129 | if (s->extra == 0) { /* no hash? */ |
| 130 | s->hash = luaS_hash(getstr(s), s->len, s->hash); | 130 | s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash); |
| 131 | s->extra = 1; /* now it has its hash */ | 131 | s->extra = 1; /* now it has its hash */ |
| 132 | } | 132 | } |
| 133 | return hashstr(t, tsvalue(key)); | 133 | return hashstr(t, tsvalue(key)); |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: ltests.c,v 2.200 2014/12/10 11:30:51 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.201 2014/12/18 12:13:42 roberto Exp roberto $ |
| 3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -724,7 +724,7 @@ static int string_query (lua_State *L) { | |||
| 724 | else if (s < tb->size) { | 724 | else if (s < tb->size) { |
| 725 | TString *ts; | 725 | TString *ts; |
| 726 | int n = 0; | 726 | int n = 0; |
| 727 | for (ts = tb->hash[s]; ts != NULL; ts = ts->hnext) { | 727 | for (ts = tb->hash[s]; ts != NULL; ts = ts->u.hnext) { |
| 728 | setsvalue2s(L, L->top, ts); | 728 | setsvalue2s(L, L->top, ts); |
| 729 | api_incr_top(L); | 729 | api_incr_top(L); |
| 730 | n++; | 730 | n++; |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lvm.c,v 2.231 2014/12/19 13:36:32 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.232 2014/12/27 20:30:38 roberto Exp roberto $ |
| 3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -73,7 +73,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { | |||
| 73 | return 1; | 73 | return 1; |
| 74 | } | 74 | } |
| 75 | else if (cvt2num(obj) && /* string convertible to number? */ | 75 | else if (cvt2num(obj) && /* string convertible to number? */ |
| 76 | luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { | 76 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { |
| 77 | *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ | 77 | *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ |
| 78 | return 1; | 78 | return 1; |
| 79 | } | 79 | } |
| @@ -106,7 +106,7 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) { | |||
| 106 | return 1; | 106 | return 1; |
| 107 | } | 107 | } |
| 108 | else if (cvt2num(obj) && | 108 | else if (cvt2num(obj) && |
| 109 | luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { | 109 | luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { |
| 110 | obj = &v; | 110 | obj = &v; |
| 111 | goto again; /* convert result from 'luaO_str2num' to an integer */ | 111 | goto again; /* convert result from 'luaO_str2num' to an integer */ |
| 112 | } | 112 | } |
| @@ -239,9 +239,9 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { | |||
| 239 | */ | 239 | */ |
| 240 | static int l_strcmp (const TString *ls, const TString *rs) { | 240 | static int l_strcmp (const TString *ls, const TString *rs) { |
| 241 | const char *l = getstr(ls); | 241 | const char *l = getstr(ls); |
| 242 | size_t ll = ls->len; | 242 | size_t ll = tsslen(ls); |
| 243 | const char *r = getstr(rs); | 243 | const char *r = getstr(rs); |
| 244 | size_t lr = rs->len; | 244 | size_t lr = tsslen(rs); |
| 245 | for (;;) { /* for each segment */ | 245 | for (;;) { /* for each segment */ |
| 246 | int temp = strcoll(l, r); | 246 | int temp = strcoll(l, r); |
| 247 | if (temp != 0) /* not equal? */ | 247 | if (temp != 0) /* not equal? */ |
| @@ -354,6 +354,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { | |||
| 354 | #define tostring(L,o) \ | 354 | #define tostring(L,o) \ |
| 355 | (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) | 355 | (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) |
| 356 | 356 | ||
| 357 | #define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) | ||
| 358 | |||
| 357 | /* | 359 | /* |
| 358 | ** Main operation for concatenation: concat 'total' values in the stack, | 360 | ** Main operation for concatenation: concat 'total' values in the stack, |
| 359 | ** from 'L->top - total' up to 'L->top - 1'. | 361 | ** from 'L->top - total' up to 'L->top - 1'. |
| @@ -365,19 +367,19 @@ void luaV_concat (lua_State *L, int total) { | |||
| 365 | int n = 2; /* number of elements handled in this pass (at least 2) */ | 367 | int n = 2; /* number of elements handled in this pass (at least 2) */ |
| 366 | if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) | 368 | if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) |
| 367 | luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); | 369 | luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); |
| 368 | else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ | 370 | else if (isemptystr(top - 1)) /* second operand is empty? */ |
| 369 | cast_void(tostring(L, top - 2)); /* result is first operand */ | 371 | cast_void(tostring(L, top - 2)); /* result is first operand */ |
| 370 | else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { | 372 | else if (isemptystr(top - 2)) { /* first operand is an empty string? */ |
| 371 | setobjs2s(L, top - 2, top - 1); /* result is second op. */ | 373 | setobjs2s(L, top - 2, top - 1); /* result is second op. */ |
| 372 | } | 374 | } |
| 373 | else { | 375 | else { |
| 374 | /* at least two non-empty string values; get as many as possible */ | 376 | /* at least two non-empty string values; get as many as possible */ |
| 375 | size_t tl = tsvalue(top-1)->len; | 377 | size_t tl = vslen(top - 1); |
| 376 | char *buffer; | 378 | char *buffer; |
| 377 | int i; | 379 | int i; |
| 378 | /* collect total length */ | 380 | /* collect total length */ |
| 379 | for (i = 1; i < total && tostring(L, top-i-1); i++) { | 381 | for (i = 1; i < total && tostring(L, top-i-1); i++) { |
| 380 | size_t l = tsvalue(top-i-1)->len; | 382 | size_t l = vslen(top - i - 1); |
| 381 | if (l >= (MAX_SIZE/sizeof(char)) - tl) | 383 | if (l >= (MAX_SIZE/sizeof(char)) - tl) |
| 382 | luaG_runerror(L, "string length overflow"); | 384 | luaG_runerror(L, "string length overflow"); |
| 383 | tl += l; | 385 | tl += l; |
| @@ -386,7 +388,7 @@ void luaV_concat (lua_State *L, int total) { | |||
| 386 | tl = 0; | 388 | tl = 0; |
| 387 | n = i; | 389 | n = i; |
| 388 | do { /* copy all strings to buffer */ | 390 | do { /* copy all strings to buffer */ |
| 389 | size_t l = tsvalue(top-i)->len; | 391 | size_t l = vslen(top - i); |
| 390 | memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); | 392 | memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); |
| 391 | tl += l; | 393 | tl += l; |
| 392 | } while (--i > 0); | 394 | } while (--i > 0); |
| @@ -403,7 +405,7 @@ void luaV_concat (lua_State *L, int total) { | |||
| 403 | */ | 405 | */ |
| 404 | void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | 406 | void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { |
| 405 | const TValue *tm; | 407 | const TValue *tm; |
| 406 | switch (ttnov(rb)) { | 408 | switch (ttype(rb)) { |
| 407 | case LUA_TTABLE: { | 409 | case LUA_TTABLE: { |
| 408 | Table *h = hvalue(rb); | 410 | Table *h = hvalue(rb); |
| 409 | tm = fasttm(L, h->metatable, TM_LEN); | 411 | tm = fasttm(L, h->metatable, TM_LEN); |
| @@ -411,8 +413,12 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { | |||
| 411 | setivalue(ra, luaH_getn(h)); /* else primitive len */ | 413 | setivalue(ra, luaH_getn(h)); /* else primitive len */ |
| 412 | return; | 414 | return; |
| 413 | } | 415 | } |
| 414 | case LUA_TSTRING: { | 416 | case LUA_TSHRSTR: { |
| 415 | setivalue(ra, tsvalue(rb)->len); | 417 | setivalue(ra, tsvalue(rb)->shrlen); |
| 418 | return; | ||
| 419 | } | ||
| 420 | case LUA_TLNGSTR: { | ||
| 421 | setivalue(ra, tsvalue(rb)->u.lnglen); | ||
| 416 | return; | 422 | return; |
| 417 | } | 423 | } |
| 418 | default: { /* try metamethod */ | 424 | default: { /* try metamethod */ |
