Просмотр исходного кода

Towards external strings

Long strings have a pointer to string contents.
Roberto Ierusalimschy 1 год назад
Родитель
Сommit
7f4906f565
4 измененных файлов с 36 добавлено и 22 удалено
  1. 2 2
      lgc.c
  2. 13 10
      lobject.h
  3. 11 8
      lstring.c
  4. 10 2
      lstring.h

+ 2 - 2
lgc.c

@@ -808,12 +808,12 @@ static void freeobj (lua_State *L, GCObject *o) {
     case LUA_VSHRSTR: {
       TString *ts = gco2ts(o);
       luaS_remove(L, ts);  /* remove it from hash table */
-      luaM_freemem(L, ts, sizelstring(ts->shrlen));
+      luaM_freemem(L, ts, sizestrshr(ts->shrlen));
       break;
     }
     case LUA_VLNGSTR: {
       TString *ts = gco2ts(o);
-      luaM_freemem(L, ts, sizelstring(ts->u.lnglen));
+      luaM_freemem(L, ts, sizestrlng(ts->u.lnglen));
       break;
     }
     default: lua_assert(0);

+ 13 - 10
lobject.h

@@ -388,35 +388,38 @@ typedef struct GCObject {
 typedef struct TString {
   CommonHeader;
   lu_byte extra;  /* reserved words for short strings; "has hash" for longs */
-  lu_byte shrlen;  /* length for short strings, 0xFF for long strings */
+  ls_byte shrlen;  /* length for short strings, negative for long strings */
   unsigned int hash;
   union {
     size_t lnglen;  /* length for long strings */
     struct TString *hnext;  /* linked list for hash table */
   } u;
-  char contents[1];  /* string body starts here */
+  char *contents;  /* pointer to content in long strings */
 } TString;
 
 
+#define strisshr(ts)	((ts)->shrlen >= 0)
+
 
 /*
 ** Get the actual string (array of bytes) from a 'TString'. (Generic
 ** version and specialized versions for long and short strings.)
 */
-#define getlngstr(ts)	check_exp((ts)->shrlen == 0xFF, (ts)->contents)
-#define getshrstr(ts)	check_exp((ts)->shrlen != 0xFF, (ts)->contents)
-#define getstr(ts) 	((ts)->contents)
+#define rawgetshrstr(ts)  (cast_charp(&(ts)->contents))
+#define getshrstr(ts)	check_exp(strisshr(ts), rawgetshrstr(ts))
+#define getlngstr(ts)	check_exp(!strisshr(ts), (ts)->contents)
+#define getstr(ts) 	(strisshr(ts) ? rawgetshrstr(ts) : (ts)->contents)
 
 
-/* get string length from 'TString *s' */
-#define tsslen(s)  \
-	((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen)
+/* get string length from 'TString *ts' */
+#define tsslen(ts)  \
+	(strisshr(ts) ? cast_uint((ts)->shrlen) : (ts)->u.lnglen)
 
 /*
 ** Get string and length */
 #define getlstr(ts, len)  \
-	((ts)->shrlen != 0xFF \
-	? (cast_void(len = (ts)->shrlen), (ts)->contents) \
+	(strisshr(ts) \
+	? (cast_void(len = (ts)->shrlen), rawgetshrstr(ts)) \
 	: (cast_void(len = (ts)->u.lnglen), (ts)->contents))
 
 /* }================================================================== */

+ 11 - 8
lstring.c

@@ -140,24 +140,25 @@ void luaS_init (lua_State *L) {
 /*
 ** creates a new string object
 */
-static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
+static TString *createstrobj (lua_State *L, size_t totalsize, int tag,
+                              unsigned int h) {
   TString *ts;
   GCObject *o;
-  size_t totalsize;  /* total size of TString object */
-  totalsize = sizelstring(l);
   o = luaC_newobj(L, tag, totalsize);
   ts = gco2ts(o);
   ts->hash = h;
   ts->extra = 0;
-  getstr(ts)[l] = '\0';  /* ending 0 */
   return ts;
 }
 
 
 TString *luaS_createlngstrobj (lua_State *L, size_t l) {
-  TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
+  size_t totalsize = sizestrlng(l);
+  TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed);
   ts->u.lnglen = l;
-  ts->shrlen = 0xFF;  /* signals that it is a long string */
+  ts->shrlen = -1;  /* signals that it is a long string */
+  ts->contents = cast_charp(ts) + sizeof(TString);
+  ts->contents[l] = '\0';  /* ending 0 */
   return ts;
 }
 
@@ -194,7 +195,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
   TString **list = &tb->hash[lmod(h, tb->size)];
   lua_assert(str != NULL);  /* otherwise 'memcmp'/'memcpy' are undefined */
   for (ts = *list; ts != NULL; ts = ts->u.hnext) {
-    if (l == ts->shrlen && (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
+    if (l == cast_uint(ts->shrlen) &&
+        (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
       /* found! */
       if (isdead(g, ts))  /* dead (but not collected yet)? */
         changewhite(ts);  /* resurrect it */
@@ -206,8 +208,9 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
     growstrtab(L, tb);
     list = &tb->hash[lmod(h, tb->size)];  /* rehash with new size */
   }
-  ts = createstrobj(L, l, LUA_VSHRSTR, h);
+  ts = createstrobj(L, sizestrshr(l), LUA_VSHRSTR, h);
   ts->shrlen = cast_byte(l);
+  getshrstr(ts)[l] = '\0';  /* ending 0 */
   memcpy(getshrstr(ts), str, l * sizeof(char));
   ts->u.hnext = *list;
   *list = ts;

+ 10 - 2
lstring.h

@@ -20,10 +20,18 @@
 
 
 /*
-** Size of a TString: Size of the header plus space for the string
+** Size of a short TString: Size of the header plus space for the string
 ** itself (including final '\0').
 */
-#define sizelstring(l)  (offsetof(TString, contents) + ((l) + 1) * sizeof(char))
+#define sizestrshr(l)  \
+	(offsetof(TString, contents) + ((l) + 1) * sizeof(char))
+
+/*
+** Size of a long TString: Size of the header plus space for the string
+** itself (including final '\0').
+*/
+#define sizestrlng(l)	(sizeof(TString) + ((l) + 1) * sizeof(char))
+
 
 #define luaS_newliteral(L, s)	(luaS_newlstr(L, "" s, \
                                  (sizeof(s)/sizeof(char))-1))