Ver Fonte

size of short strings stored in a single byte, to reduce the size
of struct 'TString'

Roberto Ierusalimschy há 10 anos atrás
pai
commit
7e2015a46d
9 ficheiros alterados com 69 adições e 45 exclusões
  1. 6 4
      lapi.c
  2. 2 2
      ldump.c
  3. 10 5
      lgc.c
  4. 12 3
      lobject.h
  5. 15 12
      lstring.c
  6. 1 2
      lstring.h
  7. 2 2
      ltable.c
  8. 2 2
      ltests.c
  9. 19 13
      lvm.c

+ 6 - 4
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;

+ 2 - 2
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 {

+ 10 - 5
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);

+ 12 - 3
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

+ 15 - 12
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;
   }
 }
 

+ 1 - 2
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)

+ 2 - 2
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));

+ 2 - 2
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++;

+ 19 - 13
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 */