lua

A copy of the Lua development repository
Log | Files | Refs | README

commit 7f4906f565ab9f8b1125107a3abae3d759f3ecf2
parent b8a9d14032b717f6e5c493a9ec20e3494c9f82a0
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date:   Wed,  8 Nov 2023 13:24:11 -0300

Towards external strings

Long strings have a pointer to string contents.

Diffstat:
Mlgc.c | 4++--
Mlobject.h | 23+++++++++++++----------
Mlstring.c | 19+++++++++++--------
Mlstring.h | 12++++++++++--
4 files changed, 36 insertions(+), 22 deletions(-)

diff --git a/lgc.c b/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); diff --git a/lobject.h b/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)) /* }================================================================== */ diff --git a/lstring.c b/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; diff --git a/lstring.h b/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))