Skip to content

Commit

Permalink
add id for short string
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudwu committed Apr 17, 2020
1 parent f64ce23 commit fa95776
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 9 deletions.
1 change: 1 addition & 0 deletions src/lobject.h
Expand Up @@ -364,6 +364,7 @@ typedef struct TString {
lu_byte extra; /* reserved words for short strings; "has hash" for longs */
lu_byte shrlen; /* length for short strings */
unsigned int hash;
size_t id; /* id for short strings */
union {
size_t lnglen; /* length for long strings */
struct TString *hnext; /* linked list for hash table */
Expand Down
3 changes: 1 addition & 2 deletions src/lstate.c
Expand Up @@ -55,7 +55,7 @@ typedef struct LG {
** A macro to create a "random" seed when a state is created;
** the seed is used to randomize string hashes.
*/
#if !defined(luai_makeseed)
#if 0 && !defined(luai_makeseed)

#include <time.h>

Expand Down Expand Up @@ -394,7 +394,6 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) {
g->warnf = NULL;
g->ud_warn = NULL;
g->mainthread = L;
g->seed = luai_makeseed(L);
g->gcrunning = 0; /* no GC while building state */
g->strt.size = g->strt.nuse = 0;
g->strt.hash = NULL;
Expand Down
1 change: 0 additions & 1 deletion src/lstate.h
Expand Up @@ -234,7 +234,6 @@ typedef struct global_State {
stringtable strt; /* hash table for strings */
TValue l_registry;
TValue nilvalue; /* a nil value */
unsigned int seed; /* randomized seed for hashes */
lu_byte currentwhite;
lu_byte gcstate; /* state of garbage collector */
lu_byte gckind; /* kind of GC running */
Expand Down
46 changes: 44 additions & 2 deletions src/lstring.c
Expand Up @@ -20,7 +20,10 @@
#include "lobject.h"
#include "lstate.h"
#include "lstring.h"
#include "atomic.h"

static unsigned int STRSEED;
static size_t STRID = 0;

/*
** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a long string to
Expand Down Expand Up @@ -49,6 +52,26 @@ int luaS_eqlngstr (TString *a, TString *b) {
(memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */
}

int luaS_eqshrstr (TString *a, TString *b) {
lu_byte len = a->shrlen;
lua_assert(b->tt == LUA_TSHRSTR);
int r = len == b->shrlen && (memcmp(getstr(a), getstr(b), len) == 0);
if (r) {
if (a->id < b->id) {
a->id = b->id;
} else {
b->id = a->id;
}
}
return r;
}

void luaS_share (TString *ts) {
if (ts == NULL)
return;
makeshared(ts);
ts->id = ATOM_DEC(&STRID);
}

unsigned int luaS_hash (const char *str, size_t l, unsigned int seed,
size_t step) {
Expand Down Expand Up @@ -128,13 +151,31 @@ void luaS_clearcache (global_State *g) {
}
}

#if !defined(luai_makeseed)

#include <time.h>

static unsigned int luai_makeseed(lua_State *L) {
size_t buff[4];
unsigned int h = time(NULL);
buff[0] = cast(size_t, h);
buff[1] = cast(size_t, &STRSEED);
buff[2] = cast(size_t, &luai_makeseed);
buff[3] = cast(size_t, L);
return luaS_hash((const char*)buff, sizeof(buff), h, 1);
}

#endif

/*
** Initialize the string table and the string cache
*/
void luaS_init (lua_State *L) {
global_State *g = G(L);
int i, j;
if (STRSEED == 0) {
STRSEED = luai_makeseed(L);
}
stringtable *tb = &G(L)->strt;
tb->hash = luaM_newvector(L, MINSTRTABSIZE, TString*);
tablerehash(tb->hash, 0, MINSTRTABSIZE); /* clear array */
Expand All @@ -161,13 +202,14 @@ static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) {
ts = gco2ts(o);
ts->hash = h;
ts->extra = 0;
ts->id = 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);
TString *ts = createstrobj(L, l, LUA_VLNGSTR, STRSEED);
ts->u.lnglen = l;
return ts;
}
Expand Down Expand Up @@ -201,7 +243,7 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) {
TString *ts;
global_State *g = G(L);
stringtable *tb = &g->strt;
unsigned int h = luaS_hash(str, l, g->seed, 1);
unsigned int h = luaS_hash(str, l, STRSEED, 1);
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) {
Expand Down
9 changes: 5 additions & 4 deletions src/lstring.h
Expand Up @@ -32,15 +32,16 @@


/*
** equality for short strings, which are always internalized
** equality for short strings, compare id first
*/
#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b))

#define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b) || \
( ((a)->id == (b)->id) ? ((a)->id != 0) : ((a)->hash == (b)->hash && luaS_eqshrstr(a,b)) ) )

LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l,
unsigned int seed, size_t step);
LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts);
LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b);
LUAI_FUNC int luaS_eqshrstr (TString *a, TString *b);
LUAI_FUNC void luaS_resize (lua_State *L, int newsize);
LUAI_FUNC void luaS_clearcache (global_State *g);
LUAI_FUNC void luaS_init (lua_State *L);
Expand All @@ -49,6 +50,6 @@ LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue);
LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l);
LUAI_FUNC TString *luaS_new (lua_State *L, const char *str);
LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l);

LUAI_FUNC void luaS_share(TString *ts);

#endif

0 comments on commit fa95776

Please sign in to comment.