Skip to content

Commit 28d8bda

Browse files
committed
Phase 122: Refactor luaS_* functions to TString static methods
Converted the following luaS_* functions to TString static methods: - luaS_hash → TString::hashString() (renamed to avoid conflict with member var) - luaS_sizelngstr → TString::longStringSize() - luaS_createlngstrobj → TString::createLongString() - luaS_newlstr → TString::create() (with explicit length) - luaS_new → TString::create() (null-terminated C string) - luaS_newextlstr → TString::createExternal() Added backward compatibility inline wrappers for all converted functions to maintain compatibility with existing code. The wrappers simply call the new TString static methods. This improves encapsulation by making string creation part of the TString class interface rather than scattered free functions. Performance: 4.25s avg (1.2% regression, well within 4.33s target) ✅ Tests: All passing ✅
1 parent 8fa3882 commit 28d8bda

File tree

2 files changed

+78
-49
lines changed

2 files changed

+78
-49
lines changed

src/objects/lstring.cpp

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,6 @@ int luaS_eqstr (TString *a, TString *b) {
5353
}
5454

5555

56-
// Phase 115.1: Pointer-based implementation for performance
57-
unsigned luaS_hash (const char *str, size_t l, unsigned seed) {
58-
unsigned int h = seed ^ cast_uint(l);
59-
for (; l > 0; l--)
60-
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
61-
return h;
62-
}
63-
64-
6556
unsigned luaS_hashlongstr (TString *ts) {
6657
return ts->hashLongStr();
6758
}
@@ -137,15 +128,31 @@ void luaS_init (lua_State *L) {
137128
tablerehash(tb->getHash(), 0, MINSTRTABSIZE); /* clear array */
138129
tb->setSize(MINSTRTABSIZE);
139130
/* pre-create memory-error message */
140-
g->setMemErrMsg(luaS_newliteral(L, MEMERRMSG));
131+
g->setMemErrMsg(TString::create(L, MEMERRMSG, sizeof(MEMERRMSG) - 1));
141132
obj2gco(g->getMemErrMsg())->fix(L); /* Phase 25c: it should never be collected */
142133
for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */
143134
for (j = 0; j < STRCACHE_M; j++)
144135
g->setStrCache(i, j, g->getMemErrMsg());
145136
}
146137

147138

148-
size_t luaS_sizelngstr (size_t len, int kind) {
139+
// Phase 122: TString static method implementations
140+
141+
// Static helper: hash a string
142+
unsigned TString::hashString(const char* str, size_t l, unsigned seed) {
143+
unsigned int h = seed ^ cast_uint(l);
144+
for (; l > 0; l--)
145+
h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1]));
146+
return h;
147+
}
148+
149+
// Static helper: hash a string (std::span overload)
150+
unsigned TString::hashString(std::span<const char> str, unsigned seed) {
151+
return hashString(str.data(), str.size(), seed);
152+
}
153+
154+
// Static helper: calculate size of long string
155+
size_t TString::longStringSize(size_t len, int kind) {
149156
switch (kind) {
150157
case LSTRREG: /* regular long string */
151158
/* don't need 'falloc'/'ud', but need space for content */
@@ -222,8 +229,9 @@ static TString *createstrobj (lua_State *L, size_t totalsize, lu_byte tag,
222229
}
223230

224231

225-
TString *luaS_createlngstrobj (lua_State *L, size_t l) {
226-
size_t totalsize = luaS_sizelngstr(l, LSTRREG);
232+
// Static factory: create long string object
233+
TString* TString::createLongString(lua_State* L, size_t l) {
234+
size_t totalsize = longStringSize(l, LSTRREG);
227235
TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->getSeed());
228236
ts->setLnglen(l);
229237
ts->setShrlen(LSTRREG); /* signals that it is a regular long string */
@@ -254,7 +262,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
254262
TString *ts;
255263
global_State *g = G(L);
256264
stringtable *tb = g->getStringTable();
257-
unsigned int h = luaS_hash(str, l, g->getSeed());
265+
unsigned int h = TString::hashString(str, l, g->getSeed());
258266
TString **list = &tb->getHash()[lmod(h, tb->getSize())];
259267
lua_assert(str != nullptr); /* otherwise 'memcmp'/'memcpy' are undefined */
260268
for (ts = *list; ts != nullptr; ts = ts->getNext()) {
@@ -283,30 +291,28 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
283291
}
284292

285293

286-
/*
287-
** new string (with explicit length)
288-
*/
289-
TString *luaS_newlstr (lua_State *L, const char *str, size_t l) {
294+
// Static factory: create string with explicit length
295+
TString* TString::create(lua_State* L, const char* str, size_t l) {
290296
if (l <= LUAI_MAXSHORTLEN) /* short string? */
291297
return internshrstr(L, str, l);
292298
else {
293299
TString *ts;
294300
if (l_unlikely(l * sizeof(char) >= (MAX_SIZE - sizeof(TString))))
295301
luaM_toobig(L);
296-
ts = luaS_createlngstrobj(L, l);
302+
ts = createLongString(L, l);
297303
std::copy_n(str, l, getlngstr(ts));
298304
return ts;
299305
}
300306
}
301307

308+
// Static factory: create string from std::span
309+
TString* TString::create(lua_State* L, std::span<const char> str) {
310+
return create(L, str.data(), str.size());
311+
}
302312

303-
/*
304-
** Create or reuse a zero-terminated string, first checking in the
305-
** cache (using the string address as a key). The cache can contain
306-
** only zero-terminated strings, so it is safe to use 'strcmp' to
307-
** check hits.
308-
*/
309-
TString *luaS_new (lua_State *L, const char *str) {
313+
314+
// Static factory: create string from null-terminated C string
315+
TString* TString::create(lua_State* L, const char* str) {
310316
unsigned int i = point2uint(str) % STRCACHE_N; /* hash */
311317
unsigned int j;
312318
global_State *g = G(L);
@@ -318,7 +324,7 @@ TString *luaS_new (lua_State *L, const char *str) {
318324
for (j = STRCACHE_M - 1; j > 0; j--)
319325
g->setStrCache(i, j, g->getStrCache(i, j - 1)); /* move out last element */
320326
/* new element is first in the list */
321-
TString *newstr = luaS_newlstr(L, str, strlen(str));
327+
TString *newstr = create(L, str, strlen(str));
322328
g->setStrCache(i, 0, newstr);
323329
return newstr;
324330
}
@@ -365,13 +371,14 @@ struct NewExt {
365371

366372
static void f_newext (lua_State *L, void *ud) {
367373
NewExt *ne = static_cast<NewExt*>(ud);
368-
size_t size = luaS_sizelngstr(0, ne->kind);
374+
size_t size = TString::longStringSize(0, ne->kind);
369375
ne->ts = createstrobj(L, size, LUA_VLNGSTR, G(L)->getSeed());
370376
}
371377

372378

373-
TString *luaS_newextlstr (lua_State *L,
374-
const char *s, size_t len, lua_Alloc falloc, void *ud) {
379+
// Static factory: create external long string
380+
TString* TString::createExternal(lua_State* L, const char* s, size_t len,
381+
lua_Alloc falloc, void* ud) {
375382
struct NewExt ne;
376383
if (!falloc) {
377384
ne.kind = LSTRFIX;
@@ -401,7 +408,7 @@ unsigned TString::hashLongStr() {
401408
lua_assert(getType() == LUA_VLNGSTR);
402409
if (getExtra() == 0) { /* no hash? */
403410
size_t len = getLnglen();
404-
setHash(luaS_hash(getlngstr(this), len, getHash()));
411+
setHash(hashString(getlngstr(this), len, getHash()));
405412
setExtra(1); /* now it has its hash */
406413
}
407414
return getHash();

src/objects/lstring.h

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,16 @@ class TString : public GCBase<TString> {
180180
void remove(lua_State* L); // Phase 25a: from luaS_remove
181181
TString* normalize(lua_State* L); // Phase 25a: from luaS_normstr
182182

183-
// Static factory-like functions (still use luaS_* for now)
184-
// static TString* create(lua_State* L, const char* str, size_t len);
183+
// Phase 122: Static factory methods and helpers (from luaS_*)
184+
static unsigned hashString(const char* str, size_t l, unsigned seed);
185+
static unsigned hashString(std::span<const char> str, unsigned seed);
186+
static size_t longStringSize(size_t len, int kind);
187+
static TString* createLongString(lua_State* L, size_t l);
188+
static TString* create(lua_State* L, const char* str, size_t l);
189+
static TString* create(lua_State* L, std::span<const char> str);
190+
static TString* create(lua_State* L, const char* str); // null-terminated
191+
static TString* createExternal(lua_State* L, const char* s, size_t len,
192+
lua_Alloc falloc, void* ud);
185193

186194
// Comparison operator overloads (defined after l_strcmp declaration)
187195
friend bool operator<(const TString& l, const TString& r) noexcept;
@@ -296,31 +304,45 @@ inline bool eqshrstr(const TString* a, const TString* b) noexcept {
296304
}
297305

298306

299-
// Phase 115.1: Primary implementations use pointer+size for performance
300-
LUAI_FUNC unsigned luaS_hash (const char *str, size_t l, unsigned seed);
301-
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
302-
303-
// std::span overloads (inline wrappers for convenience)
304-
inline unsigned luaS_hash (std::span<const char> str, unsigned seed) {
305-
return luaS_hash(str.data(), str.size(), seed);
307+
// Phase 122: Backward compatibility wrappers (call TString static methods)
308+
inline unsigned luaS_hash(const char* str, size_t l, unsigned seed) {
309+
return TString::hashString(str, l, seed);
310+
}
311+
inline unsigned luaS_hash(std::span<const char> str, unsigned seed) {
312+
return TString::hashString(str, seed);
313+
}
314+
inline TString* luaS_newlstr(lua_State* L, const char* str, size_t l) {
315+
return TString::create(L, str, l);
316+
}
317+
inline TString* luaS_newlstr(lua_State* L, std::span<const char> str) {
318+
return TString::create(L, str);
319+
}
320+
inline TString* luaS_new(lua_State* L, const char* str) {
321+
return TString::create(L, str);
306322
}
307-
inline TString *luaS_newlstr (lua_State *L, std::span<const char> str) {
308-
return luaS_newlstr(L, str.data(), str.size());
323+
inline TString* luaS_createlngstrobj(lua_State* L, size_t l) {
324+
return TString::createLongString(L, l);
325+
}
326+
inline TString* luaS_newextlstr(lua_State* L, const char* s, size_t len,
327+
lua_Alloc falloc, void* ud) {
328+
return TString::createExternal(L, s, len, falloc, ud);
329+
}
330+
inline size_t luaS_sizelngstr(size_t len, int kind) {
331+
return TString::longStringSize(len, kind);
309332
}
310333

334+
// Functions that operate on individual TString instances (wrappers to methods)
311335
LUAI_FUNC unsigned luaS_hashlongstr (TString *ts);
312336
LUAI_FUNC int luaS_eqstr (TString *a, TString *b);
337+
338+
// Functions that operate on global state (remain as free functions)
313339
LUAI_FUNC void luaS_resize (lua_State *L, unsigned int newsize);
314340
LUAI_FUNC void luaS_clearcache (global_State *g);
315341
LUAI_FUNC void luaS_init (lua_State *L);
342+
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, unsigned short nuvalue);
343+
316344
/* Phase 26: Removed luaS_remove - now TString::remove() method */
317-
LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s,
318-
unsigned short nuvalue);
319-
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
320-
LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);
321-
LUAI_FUNC TString *luaS_newextlstr (lua_State *L,
322-
const char *s, size_t len, lua_Alloc falloc, void *ud);
323-
LUAI_FUNC size_t luaS_sizelngstr (size_t len, int kind);
324345
/* Phase 26: Removed luaS_normstr - now TString::normalize() method */
346+
/* Phase 122: luaS_hash, luaS_new*, luaS_sizelngstr now call TString:: methods */
325347

326348
#endif

0 commit comments

Comments
 (0)