commit 9b4f39ab14fb2e55345c3d23537d129dac23b091
parent f4211a5ea4e235ccfa8b8dfa46031c23e9e839e2
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Thu, 17 Aug 2023 15:59:01 -0300
More disciplined use of 'getstr' and 'tsslen'
We may want to add other string variants in the future; this change
documents better where the code may need to handle those variants.
Diffstat:
9 files changed, 37 insertions(+), 33 deletions(-)
diff --git a/lapi.c b/lapi.c
@@ -417,9 +417,9 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) {
o = index2value(L, idx); /* previous call may reallocate the stack */
}
if (len != NULL)
- *len = vslen(o);
+ *len = tsslen(tsvalue(o));
lua_unlock(L);
- return svalue(o);
+ return getstr(tsvalue(o));
}
diff --git a/ldebug.c b/ldebug.c
@@ -426,7 +426,7 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
*/
static void kname (const Proto *p, int c, const char **name) {
TValue *kvalue = &p->k[c];
- *name = (ttisstring(kvalue)) ? svalue(kvalue) : "?";
+ *name = (ttisstring(kvalue)) ? getstr(tsvalue(kvalue)) : "?";
}
@@ -569,7 +569,7 @@ static const char *getobjname (const Proto *p, int lastpc, int reg,
int b = (op == OP_LOADK) ? GETARG_Bx(i)
: GETARG_Ax(p->code[pc + 1]);
if (ttisstring(&p->k[b])) {
- *name = svalue(&p->k[b]);
+ *name = getstr(tsvalue(&p->k[b]));
return "constant";
}
break;
@@ -627,7 +627,7 @@ static const char *funcnamefromcode (lua_State *L, const Proto *p,
default:
return NULL; /* cannot find a reasonable name */
}
- *name = getstr(G(L)->tmname[tm]) + 2;
+ *name = getshrstr(G(L)->tmname[tm]) + 2;
return "metamethod";
}
diff --git a/lgc.c b/lgc.c
@@ -542,10 +542,12 @@ static void traversestrongtable (global_State *g, Table *h) {
static lu_mem traversetable (global_State *g, Table *h) {
const char *weakkey, *weakvalue;
const TValue *mode = gfasttm(g, h->metatable, TM_MODE);
+ TString *smode;
markobjectN(g, h->metatable);
- if (mode && ttisstring(mode) && /* is there a weak mode? */
- (cast_void(weakkey = strchr(svalue(mode), 'k')),
- cast_void(weakvalue = strchr(svalue(mode), 'v')),
+ if (mode && ttisshrstring(mode) && /* is there a weak mode? */
+ (cast_void(smode = tsvalue(mode)),
+ cast_void(weakkey = strchr(getshrstr(smode), 'k')),
+ cast_void(weakvalue = strchr(getshrstr(smode), 'v')),
(weakkey || weakvalue))) { /* is really weak? */
if (!weakkey) /* strong keys? */
traverseweakvalue(g, h);
diff --git a/lobject.c b/lobject.c
@@ -542,7 +542,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) {
addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */
clearbuff(&buff); /* empty buffer into the stack */
lua_assert(buff.pushed == 1);
- return svalue(s2v(L->top.p - 1));
+ return getstr(tsvalue(s2v(L->top.p - 1)));
}
diff --git a/lobject.h b/lobject.h
@@ -386,7 +386,7 @@ 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 */
+ lu_byte shrlen; /* length for short strings, 0xFF for long strings */
unsigned int hash;
union {
size_t lnglen; /* length for long strings */
@@ -398,19 +398,17 @@ typedef struct TString {
/*
-** Get the actual string (array of bytes) from a 'TString'.
+** Get the actual string (array of bytes) from a 'TString'. (Generic
+** version and specialized versions for long and short strings.)
*/
-#define getstr(ts) ((ts)->contents)
+#define getstr(ts) ((ts)->contents)
+#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents)
+#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents)
-/* 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_VSHRSTR ? (s)->shrlen : (s)->u.lnglen)
-
-/* get string length from 'TValue *o' */
-#define vslen(o) tsslen(tsvalue(o))
+#define tsslen(s) \
+ ((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen)
/* }================================================================== */
diff --git a/lstate.c b/lstate.c
@@ -433,7 +433,7 @@ void luaE_warning (lua_State *L, const char *msg, int tocont) {
void luaE_warnerror (lua_State *L, const char *where) {
TValue *errobj = s2v(L->top.p - 1); /* error object */
const char *msg = (ttisstring(errobj))
- ? svalue(errobj)
+ ? getstr(tsvalue(errobj))
: "error object is not a string";
/* produce warning "error in %s (%s)" (where, msg) */
luaE_warning(L, "error in ", 1);
diff --git a/lstring.c b/lstring.c
@@ -36,7 +36,7 @@ int luaS_eqlngstr (TString *a, TString *b) {
lua_assert(a->tt == LUA_VLNGSTR && b->tt == LUA_VLNGSTR);
return (a == b) || /* same instance or... */
((len == b->u.lnglen) && /* equal length and ... */
- (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
+ (memcmp(getlngstr(a), getlngstr(b), len) == 0)); /* equal contents */
}
@@ -52,7 +52,7 @@ unsigned int luaS_hashlongstr (TString *ts) {
lua_assert(ts->tt == LUA_VLNGSTR);
if (ts->extra == 0) { /* no hash? */
size_t len = ts->u.lnglen;
- ts->hash = luaS_hash(getstr(ts), len, ts->hash);
+ ts->hash = luaS_hash(getlngstr(ts), len, ts->hash);
ts->extra = 1; /* now it has its hash */
}
return ts->hash;
@@ -157,6 +157,7 @@ static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed);
ts->u.lnglen = l;
+ ts->shrlen = 0xFF; /* signals that it is a long string */
return ts;
}
@@ -193,7 +194,7 @@ 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, getstr(ts), l * sizeof(char)) == 0)) {
+ if (l == 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,7 +207,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */
}
ts = createstrobj(L, l, LUA_VSHRSTR, h);
- memcpy(getstr(ts), str, l * sizeof(char));
+ memcpy(getshrstr(ts), str, l * sizeof(char));
ts->shrlen = cast_byte(l);
ts->u.hnext = *list;
*list = ts;
@@ -226,7 +227,7 @@ TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
if (l_unlikely(l >= (MAX_SIZE - sizeof(TString))/sizeof(char)))
luaM_toobig(L);
ts = luaS_createlngstrobj(L, l);
- memcpy(getstr(ts), str, l * sizeof(char));
+ memcpy(getlngstr(ts), str, l * sizeof(char));
return ts;
}
}
diff --git a/lundump.c b/lundump.c
@@ -122,7 +122,7 @@ static TString *loadStringN (LoadState *S, Proto *p) {
ts = luaS_createlngstrobj(L, size); /* create string */
setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */
luaD_inctop(L);
- loadVector(S, getstr(ts), size); /* load directly in final place */
+ loadVector(S, getlngstr(ts), size); /* load directly in final place */
L->top.p--; /* pop string */
}
luaC_objbarrier(L, p, ts);
diff --git a/lvm.c b/lvm.c
@@ -91,8 +91,10 @@ static int l_strton (const TValue *obj, TValue *result) {
lua_assert(obj != result);
if (!cvt2num(obj)) /* is object not a string? */
return 0;
- else
- return (luaO_str2num(svalue(obj), result) == vslen(obj) + 1);
+ else {
+ TString *st = tsvalue(obj);
+ return (luaO_str2num(getstr(st), result) == tsslen(st) + 1);
+ }
}
@@ -626,8 +628,9 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) {
static void copy2buff (StkId top, int n, char *buff) {
size_t tl = 0; /* size already copied */
do {
- size_t l = vslen(s2v(top - n)); /* length of string being copied */
- memcpy(buff + tl, svalue(s2v(top - n)), l * sizeof(char));
+ TString *st = tsvalue(s2v(top - n));
+ size_t l = tsslen(st); /* length of string being copied */
+ memcpy(buff + tl, getstr(st), l * sizeof(char));
tl += l;
} while (--n > 0);
}
@@ -653,11 +656,11 @@ void luaV_concat (lua_State *L, int total) {
}
else {
/* at least two non-empty string values; get as many as possible */
- size_t tl = vslen(s2v(top - 1));
+ size_t tl = tsslen(tsvalue(s2v(top - 1)));
TString *ts;
/* collect total length and number of strings */
for (n = 1; n < total && tostring(L, s2v(top - n - 1)); n++) {
- size_t l = vslen(s2v(top - n - 1));
+ size_t l = tsslen(tsvalue(s2v(top - n - 1)));
if (l_unlikely(l >= (MAX_SIZE/sizeof(char)) - tl)) {
L->top.p = top - total; /* pop strings to avoid wasting stack */
luaG_runerror(L, "string length overflow");
@@ -671,7 +674,7 @@ void luaV_concat (lua_State *L, int total) {
}
else { /* long string; copy strings directly to final result */
ts = luaS_createlngstrobj(L, tl);
- copy2buff(top, n, getstr(ts));
+ copy2buff(top, n, getlngstr(ts));
}
setsvalue2s(L, top - n, ts); /* create result */
}