diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-11-08 13:24:38 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2023-11-08 13:24:38 -0300 |
| commit | 7f4906f565ab9f8b1125107a3abae3d759f3ecf2 (patch) | |
| tree | f1c9c36ce0e96f1e89673bfe25175cbf83523bf6 | |
| parent | b8a9d14032b717f6e5c493a9ec20e3494c9f82a0 (diff) | |
| download | lua-7f4906f565ab9f8b1125107a3abae3d759f3ecf2.tar.gz lua-7f4906f565ab9f8b1125107a3abae3d759f3ecf2.tar.bz2 lua-7f4906f565ab9f8b1125107a3abae3d759f3ecf2.zip | |
Towards external strings
Long strings have a pointer to string contents.
| -rw-r--r-- | lgc.c | 4 | ||||
| -rw-r--r-- | lobject.h | 23 | ||||
| -rw-r--r-- | lstring.c | 19 | ||||
| -rw-r--r-- | lstring.h | 12 |
4 files changed, 36 insertions, 22 deletions
| @@ -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); |
| @@ -388,35 +388,38 @@ typedef struct GCObject { | |||
| 388 | typedef struct TString { | 388 | typedef 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 | /* }================================================================== */ |
| @@ -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 | */ |
| 143 | static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { | 143 | static 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 | ||
| 157 | TString *luaS_createlngstrobj (lua_State *L, size_t l) { | 155 | TString *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; |
| @@ -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)) |
