diff --git a/lapi.c b/lapi.c index c2ef6019..9d6123ce 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.243 2014/11/12 13:28:54 roberto Exp roberto $ +** $Id: lapi.c,v 2.244 2014/12/26 14:43:45 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -382,15 +382,17 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { luaO_tostring(L, o); lua_unlock(L); } - if (len != NULL) *len = tsvalue(o)->len; + if (len != NULL) + *len = vslen(o); return svalue(o); } LUA_API size_t lua_rawlen (lua_State *L, int idx) { StkId o = index2addr(L, idx); - switch (ttnov(o)) { - case LUA_TSTRING: return tsvalue(o)->len; + switch (ttype(o)) { + case LUA_TSHRSTR: return tsvalue(o)->shrlen; + case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; case LUA_TUSERDATA: return uvalue(o)->len; case LUA_TTABLE: return luaH_getn(hvalue(o)); default: return 0; diff --git a/ldump.c b/ldump.c index a3da9a9f..ec35031e 100644 --- a/ldump.c +++ b/ldump.c @@ -1,5 +1,5 @@ /* -** $Id: ldump.c,v 2.33 2014/07/18 13:36:14 roberto Exp roberto $ +** $Id: ldump.c,v 2.34 2014/11/02 19:19:04 roberto Exp roberto $ ** save precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -74,7 +74,7 @@ static void DumpString (const TString *s, DumpState *D) { if (s == NULL) DumpByte(0, D); else { - size_t size = s->len + 1; /* include trailing '\0' */ + size_t size = tsslen(s) + 1; /* include trailing '\0' */ if (size < 0xFF) DumpByte(cast_int(size), D); else { diff --git a/lgc.c b/lgc.c index 185c1d8c..1695ea74 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.200 2014/11/02 19:19:04 roberto Exp roberto $ +** $Id: lgc.c,v 2.201 2014/12/20 13:58:15 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -226,10 +226,14 @@ static void reallymarkobject (global_State *g, GCObject *o) { reentry: white2gray(o); switch (o->tt) { - case LUA_TSHRSTR: + case LUA_TSHRSTR: { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); + break; + } case LUA_TLNGSTR: { gray2black(o); - g->GCmemtrav += sizestring(gco2ts(o)); + g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); break; } case LUA_TUSERDATA: { @@ -689,9 +693,10 @@ static void freeobj (lua_State *L, GCObject *o) { case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; case LUA_TSHRSTR: luaS_remove(L, gco2ts(o)); /* remove it from hash table */ - /* go through */ + luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + break; case LUA_TLNGSTR: { - luaM_freemem(L, o, sizestring(gco2ts(o))); + luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); break; } default: lua_assert(0); diff --git a/lobject.h b/lobject.h index f98eb812..cb194105 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.105 2014/12/19 13:36:32 roberto Exp roberto $ +** $Id: lobject.h,v 2.106 2015/01/05 13:52:37 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -303,9 +303,12 @@ typedef TValue *StkId; /* index to stack elements */ typedef struct TString { CommonHeader; lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + lu_byte shrlen; /* length for short strings */ unsigned int hash; - size_t len; /* number of characters in string */ - struct TString *hnext; /* linked list for hash table */ + union { + size_t lnglen; /* length for long strings */ + struct TString *hnext; /* linked list for hash table */ + } u; } TString; @@ -329,6 +332,12 @@ typedef union UTString { /* get the actual string (array of bytes) from a Lua value */ #define svalue(o) getstr(tsvalue(o)) +/* get string length from 'TString *s' */ +#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen) + +/* get string length from 'TValue *o' */ +#define vslen(o) tsslen(tsvalue(o)) + /* ** Header for userdata; memory area follows the end of this structure diff --git a/lstring.c b/lstring.c index 27b06dd3..29e4630c 100644 --- a/lstring.c +++ b/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.44 2014/07/21 16:02:10 roberto Exp roberto $ +** $Id: lstring.c,v 2.45 2014/11/02 19:19:04 roberto Exp roberto $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -36,10 +36,10 @@ ** equality for long strings */ int luaS_eqlngstr (TString *a, TString *b) { - size_t len = a->len; + size_t len = a->u.lnglen; lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); return (a == b) || /* same instance or... */ - ((len == b->len) && /* equal length and ... */ + ((len == b->u.lnglen) && /* equal length and ... */ (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ } @@ -69,9 +69,9 @@ void luaS_resize (lua_State *L, int newsize) { TString *p = tb->hash[i]; tb->hash[i] = NULL; while (p) { /* for each node in the list */ - TString *hnext = p->hnext; /* save next */ + TString *hnext = p->u.hnext; /* save next */ unsigned int h = lmod(p->hash, newsize); /* new position */ - p->hnext = tb->hash[h]; /* chain it */ + p->u.hnext = tb->hash[h]; /* chain it */ tb->hash[h] = p; p = hnext; } @@ -97,7 +97,6 @@ static TString *createstrobj (lua_State *L, const char *str, size_t l, totalsize = sizelstring(l); o = luaC_newobj(L, tag, totalsize); ts = gco2ts(o); - ts->len = l; ts->hash = h; ts->extra = 0; memcpy(getaddrstr(ts), str, l * sizeof(char)); @@ -110,8 +109,8 @@ void luaS_remove (lua_State *L, TString *ts) { stringtable *tb = &G(L)->strt; TString **p = &tb->hash[lmod(ts->hash, tb->size)]; while (*p != ts) /* find previous element */ - p = &(*p)->hnext; - *p = (*p)->hnext; /* remove element from its list */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ tb->nuse--; } @@ -124,8 +123,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { global_State *g = G(L); unsigned int h = luaS_hash(str, l, g->seed); TString **list = &g->strt.hash[lmod(h, g->strt.size)]; - for (ts = *list; ts != NULL; ts = ts->hnext) { - if (l == ts->len && + for (ts = *list; ts != NULL; ts = ts->u.hnext) { + if (l == ts->shrlen && (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { /* found! */ 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) { list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ } ts = createstrobj(L, str, l, LUA_TSHRSTR, h); - ts->hnext = *list; + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; *list = ts; g->strt.nuse++; return ts; @@ -152,9 +152,12 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { if (l <= LUAI_MAXSHORTLEN) /* short string? */ return internshrstr(L, str, l); else { + TString *ts; if (l + 1 > (MAX_SIZE - sizeof(TString))/sizeof(char)) luaM_toobig(L); - return createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); + ts = createstrobj(L, str, l, LUA_TLNGSTR, G(L)->seed); + ts->u.lnglen = l; + return ts; } } diff --git a/lstring.h b/lstring.h index e515bf30..573daf9a 100644 --- a/lstring.h +++ b/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.54 2014/03/19 18:51:42 roberto Exp roberto $ +** $Id: lstring.h,v 1.56 2014/07/18 14:46:47 roberto Exp roberto $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -13,7 +13,6 @@ #define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) -#define sizestring(s) sizelstring((s)->len) #define sizeludata(l) (sizeof(union UUdata) + (l)) #define sizeudata(u) sizeludata((u)->len) diff --git a/ltable.c b/ltable.c index 563ae6de..26b1f773 100644 --- a/ltable.c +++ b/ltable.c @@ -1,5 +1,5 @@ /* -** $Id: ltable.c,v 2.99 2014/11/02 19:19:04 roberto Exp roberto $ +** $Id: ltable.c,v 2.100 2015/01/05 13:52:37 roberto Exp roberto $ ** Lua tables (hash) ** See Copyright Notice in lua.h */ @@ -127,7 +127,7 @@ static Node *mainposition (const Table *t, const TValue *key) { case LUA_TLNGSTR: { TString *s = tsvalue(key); if (s->extra == 0) { /* no hash? */ - s->hash = luaS_hash(getstr(s), s->len, s->hash); + s->hash = luaS_hash(getstr(s), s->u.lnglen, s->hash); s->extra = 1; /* now it has its hash */ } return hashstr(t, tsvalue(key)); diff --git a/ltests.c b/ltests.c index 85a7c742..dadcad8d 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.200 2014/12/10 11:30:51 roberto Exp roberto $ +** $Id: ltests.c,v 2.201 2014/12/18 12:13:42 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -724,7 +724,7 @@ static int string_query (lua_State *L) { else if (s < tb->size) { TString *ts; int n = 0; - for (ts = tb->hash[s]; ts != NULL; ts = ts->hnext) { + for (ts = tb->hash[s]; ts != NULL; ts = ts->u.hnext) { setsvalue2s(L, L->top, ts); api_incr_top(L); n++; diff --git a/lvm.c b/lvm.c index 1b4357fd..06fc60a4 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.231 2014/12/19 13:36:32 roberto Exp roberto $ +** $Id: lvm.c,v 2.232 2014/12/27 20:30:38 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -73,7 +73,7 @@ int luaV_tonumber_ (const TValue *obj, lua_Number *n) { return 1; } else if (cvt2num(obj) && /* string convertible to number? */ - luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ return 1; } @@ -106,7 +106,7 @@ static int tointeger_aux (const TValue *obj, lua_Integer *p, int mode) { return 1; } else if (cvt2num(obj) && - luaO_str2num(svalue(obj), &v) == tsvalue(obj)->len + 1) { + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { obj = &v; goto again; /* convert result from 'luaO_str2num' to an integer */ } @@ -239,9 +239,9 @@ void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { */ static int l_strcmp (const TString *ls, const TString *rs) { const char *l = getstr(ls); - size_t ll = ls->len; + size_t ll = tsslen(ls); const char *r = getstr(rs); - size_t lr = rs->len; + size_t lr = tsslen(rs); for (;;) { /* for each segment */ int temp = strcoll(l, r); if (temp != 0) /* not equal? */ @@ -354,6 +354,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { #define tostring(L,o) \ (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) +#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) + /* ** Main operation for concatenation: concat 'total' values in the stack, ** from 'L->top - total' up to 'L->top - 1'. @@ -365,19 +367,19 @@ void luaV_concat (lua_State *L, int total) { int n = 2; /* number of elements handled in this pass (at least 2) */ if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); - else if (tsvalue(top-1)->len == 0) /* second operand is empty? */ + else if (isemptystr(top - 1)) /* second operand is empty? */ cast_void(tostring(L, top - 2)); /* result is first operand */ - else if (ttisstring(top-2) && tsvalue(top-2)->len == 0) { + else if (isemptystr(top - 2)) { /* first operand is an empty string? */ setobjs2s(L, top - 2, top - 1); /* result is second op. */ } else { /* at least two non-empty string values; get as many as possible */ - size_t tl = tsvalue(top-1)->len; + size_t tl = vslen(top - 1); char *buffer; int i; /* collect total length */ for (i = 1; i < total && tostring(L, top-i-1); i++) { - size_t l = tsvalue(top-i-1)->len; + size_t l = vslen(top - i - 1); if (l >= (MAX_SIZE/sizeof(char)) - tl) luaG_runerror(L, "string length overflow"); tl += l; @@ -386,7 +388,7 @@ void luaV_concat (lua_State *L, int total) { tl = 0; n = i; do { /* copy all strings to buffer */ - size_t l = tsvalue(top-i)->len; + size_t l = vslen(top - i); memcpy(buffer+tl, svalue(top-i), l * sizeof(char)); tl += l; } while (--i > 0); @@ -403,7 +405,7 @@ void luaV_concat (lua_State *L, int total) { */ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { const TValue *tm; - switch (ttnov(rb)) { + switch (ttype(rb)) { case LUA_TTABLE: { Table *h = hvalue(rb); tm = fasttm(L, h->metatable, TM_LEN); @@ -411,8 +413,12 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { setivalue(ra, luaH_getn(h)); /* else primitive len */ return; } - case LUA_TSTRING: { - setivalue(ra, tsvalue(rb)->len); + case LUA_TSHRSTR: { + setivalue(ra, tsvalue(rb)->shrlen); + return; + } + case LUA_TLNGSTR: { + setivalue(ra, tsvalue(rb)->u.lnglen); return; } default: { /* try metamethod */