aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-11-08 13:24:38 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2023-11-08 13:24:38 -0300
commit7f4906f565ab9f8b1125107a3abae3d759f3ecf2 (patch)
treef1c9c36ce0e96f1e89673bfe25175cbf83523bf6
parentb8a9d14032b717f6e5c493a9ec20e3494c9f82a0 (diff)
downloadlua-7f4906f565ab9f8b1125107a3abae3d759f3ecf2.tar.gz
lua-7f4906f565ab9f8b1125107a3abae3d759f3ecf2.tar.bz2
lua-7f4906f565ab9f8b1125107a3abae3d759f3ecf2.zip
Towards external strings
Long strings have a pointer to string contents.
Diffstat (limited to '')
-rw-r--r--lgc.c4
-rw-r--r--lobject.h23
-rw-r--r--lstring.c19
-rw-r--r--lstring.h12
4 files changed, 36 insertions, 22 deletions
diff --git a/lgc.c b/lgc.c
index e4f8e396..e3fcaa3e 100644
--- a/lgc.c
+++ b/lgc.c
@@ -808,12 +808,12 @@ static void freeobj (lua_State *L, GCObject *o) {
808 case LUA_VSHRSTR: { 808 case LUA_VSHRSTR: {
809 TString *ts = gco2ts(o); 809 TString *ts = gco2ts(o);
810 luaS_remove(L, ts); /* remove it from hash table */ 810 luaS_remove(L, ts); /* remove it from hash table */
811 luaM_freemem(L, ts, sizelstring(ts->shrlen)); 811 luaM_freemem(L, ts, sizestrshr(ts->shrlen));
812 break; 812 break;
813 } 813 }
814 case LUA_VLNGSTR: { 814 case LUA_VLNGSTR: {
815 TString *ts = gco2ts(o); 815 TString *ts = gco2ts(o);
816 luaM_freemem(L, ts, sizelstring(ts->u.lnglen)); 816 luaM_freemem(L, ts, sizestrlng(ts->u.lnglen));
817 break; 817 break;
818 } 818 }
819 default: lua_assert(0); 819 default: lua_assert(0);
diff --git a/lobject.h b/lobject.h
index c6c43647..f76d26a6 100644
--- a/lobject.h
+++ b/lobject.h
@@ -388,35 +388,38 @@ typedef struct GCObject {
388typedef struct TString { 388typedef struct TString {
389 CommonHeader; 389 CommonHeader;
390 lu_byte extra; /* reserved words for short strings; "has hash" for longs */ 390 lu_byte extra; /* reserved words for short strings; "has hash" for longs */
391 lu_byte shrlen; /* length for short strings, 0xFF for long strings */ 391 ls_byte shrlen; /* length for short strings, negative for long strings */
392 unsigned int hash; 392 unsigned int hash;
393 union { 393 union {
394 size_t lnglen; /* length for long strings */ 394 size_t lnglen; /* length for long strings */
395 struct TString *hnext; /* linked list for hash table */ 395 struct TString *hnext; /* linked list for hash table */
396 } u; 396 } u;
397 char contents[1]; /* string body starts here */ 397 char *contents; /* pointer to content in long strings */
398} TString; 398} TString;
399 399
400 400
401#define strisshr(ts) ((ts)->shrlen >= 0)
402
401 403
402/* 404/*
403** Get the actual string (array of bytes) from a 'TString'. (Generic 405** Get the actual string (array of bytes) from a 'TString'. (Generic
404** version and specialized versions for long and short strings.) 406** version and specialized versions for long and short strings.)
405*/ 407*/
406#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents) 408#define rawgetshrstr(ts) (cast_charp(&(ts)->contents))
407#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents) 409#define getshrstr(ts) check_exp(strisshr(ts), rawgetshrstr(ts))
408#define getstr(ts) ((ts)->contents) 410#define getlngstr(ts) check_exp(!strisshr(ts), (ts)->contents)
411#define getstr(ts) (strisshr(ts) ? rawgetshrstr(ts) : (ts)->contents)
409 412
410 413
411/* get string length from 'TString *s' */ 414/* get string length from 'TString *ts' */
412#define tsslen(s) \ 415#define tsslen(ts) \
413 ((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen) 416 (strisshr(ts) ? cast_uint((ts)->shrlen) : (ts)->u.lnglen)
414 417
415/* 418/*
416** Get string and length */ 419** Get string and length */
417#define getlstr(ts, len) \ 420#define getlstr(ts, len) \
418 ((ts)->shrlen != 0xFF \ 421 (strisshr(ts) \
419 ? (cast_void(len = (ts)->shrlen), (ts)->contents) \ 422 ? (cast_void(len = (ts)->shrlen), rawgetshrstr(ts)) \
420 : (cast_void(len = (ts)->u.lnglen), (ts)->contents)) 423 : (cast_void(len = (ts)->u.lnglen), (ts)->contents))
421 424
422/* }================================================================== */ 425/* }================================================================== */
diff --git a/lstring.c b/lstring.c
index e921dd0f..c4b3c7ba 100644
--- a/lstring.c
+++ b/lstring.c
@@ -140,24 +140,25 @@ void luaS_init (lua_State *L) {
140/* 140/*
141** creates a new string object 141** creates a new string object
142*/ 142*/
143static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { 143static TString *createstrobj (lua_State *L, size_t totalsize, int tag,
144 unsigned int h) {
144 TString *ts; 145 TString *ts;
145 GCObject *o; 146 GCObject *o;
146 size_t totalsize; /* total size of TString object */
147 totalsize = sizelstring(l);
148 o = luaC_newobj(L, tag, totalsize); 147 o = luaC_newobj(L, tag, totalsize);
149 ts = gco2ts(o); 148 ts = gco2ts(o);
150 ts->hash = h; 149 ts->hash = h;
151 ts->extra = 0; 150 ts->extra = 0;
152 getstr(ts)[l] = '\0'; /* ending 0 */
153 return ts; 151 return ts;
154} 152}
155 153
156 154
157TString *luaS_createlngstrobj (lua_State *L, size_t l) { 155TString *luaS_createlngstrobj (lua_State *L, size_t l) {
158 TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed); 156 size_t totalsize = sizestrlng(l);
157 TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed);
159 ts->u.lnglen = l; 158 ts->u.lnglen = l;
160 ts->shrlen = 0xFF; /* signals that it is a long string */ 159 ts->shrlen = -1; /* signals that it is a long string */
160 ts->contents = cast_charp(ts) + sizeof(TString);
161 ts->contents[l] = '\0'; /* ending 0 */
161 return ts; 162 return ts;
162} 163}
163 164
@@ -194,7 +195,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
194 TString **list = &tb->hash[lmod(h, tb->size)]; 195 TString **list = &tb->hash[lmod(h, tb->size)];
195 lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ 196 lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */
196 for (ts = *list; ts != NULL; ts = ts->u.hnext) { 197 for (ts = *list; ts != NULL; ts = ts->u.hnext) {
197 if (l == ts->shrlen && (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) { 198 if (l == cast_uint(ts->shrlen) &&
199 (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) {
198 /* found! */ 200 /* found! */
199 if (isdead(g, ts)) /* dead (but not collected yet)? */ 201 if (isdead(g, ts)) /* dead (but not collected yet)? */
200 changewhite(ts); /* resurrect it */ 202 changewhite(ts); /* resurrect it */
@@ -206,8 +208,9 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
206 growstrtab(L, tb); 208 growstrtab(L, tb);
207 list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */ 209 list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
208 } 210 }
209 ts = createstrobj(L, l, LUA_VSHRSTR, h); 211 ts = createstrobj(L, sizestrshr(l), LUA_VSHRSTR, h);
210 ts->shrlen = cast_byte(l); 212 ts->shrlen = cast_byte(l);
213 getshrstr(ts)[l] = '\0'; /* ending 0 */
211 memcpy(getshrstr(ts), str, l * sizeof(char)); 214 memcpy(getshrstr(ts), str, l * sizeof(char));
212 ts->u.hnext = *list; 215 ts->u.hnext = *list;
213 *list = ts; 216 *list = ts;
diff --git a/lstring.h b/lstring.h
index 450c2390..069e64b7 100644
--- a/lstring.h
+++ b/lstring.h
@@ -20,10 +20,18 @@
20 20
21 21
22/* 22/*
23** Size of a TString: Size of the header plus space for the string 23** Size of a short TString: Size of the header plus space for the string
24** itself (including final '\0'). 24** itself (including final '\0').
25*/ 25*/
26#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char)) 26#define sizestrshr(l) \
27 (offsetof(TString, contents) + ((l) + 1) * sizeof(char))
28
29/*
30** Size of a long TString: Size of the header plus space for the string
31** itself (including final '\0').
32*/
33#define sizestrlng(l) (sizeof(TString) + ((l) + 1) * sizeof(char))
34
27 35
28#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ 36#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \
29 (sizeof(s)/sizeof(char))-1)) 37 (sizeof(s)/sizeof(char))-1))