Improving hash.
This commit is contained in:
parent
e7e59d4b0e
commit
21d8c27e73
45
limmutable.c
45
limmutable.c
@ -24,6 +24,10 @@
|
|||||||
#define luaL_register(L, _, R) luaL_setfuncs(L, R, 0)
|
#define luaL_register(L, _, R) luaL_setfuncs(L, R, 0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(LUAI_HASHLIMIT)
|
||||||
|
#define LUAI_HASHLIMIT 5
|
||||||
|
#endif
|
||||||
|
|
||||||
static int Lcreate_instance(lua_State *L)
|
static int Lcreate_instance(lua_State *L)
|
||||||
{
|
{
|
||||||
int n_args = lua_gettop(L);
|
int n_args = lua_gettop(L);
|
||||||
@ -47,20 +51,22 @@ static int Lcreate_instance(lua_State *L)
|
|||||||
// Stack [inst]
|
// Stack [inst]
|
||||||
|
|
||||||
// Copy in all the values, and simultaneously compute the hash:
|
// Copy in all the values, and simultaneously compute the hash:
|
||||||
lua_Integer hash = 0;
|
lua_Integer hash = (lua_Integer)lua_topointer(L, 1); // Hash depends on the metatable used in creation
|
||||||
for (lua_Integer i=1; i <=(lua_Integer)n; i++) {
|
for (lua_Integer i=1; i <=(lua_Integer)n; i++) {
|
||||||
lua_pushvalue(L, i+1);
|
lua_pushvalue(L, i+1);
|
||||||
// Stack [inst, args[i+1]]
|
// Stack [inst, args[i+1]]
|
||||||
lua_Integer item_hash;
|
lua_Integer item_hash;
|
||||||
switch (lua_type(L, -1)) {
|
switch (lua_type(L, -1)) {
|
||||||
case LUA_TNIL:
|
case LUA_TNIL:
|
||||||
item_hash = 0;
|
// Arbitrarily chosen value
|
||||||
|
item_hash = 0x97167da9;
|
||||||
break;
|
break;
|
||||||
case LUA_TNUMBER:
|
case LUA_TNUMBER:
|
||||||
item_hash = (lua_Integer)lua_tonumber(L, -1);
|
item_hash = (lua_Integer)lua_tonumber(L, -1);
|
||||||
break;
|
break;
|
||||||
case LUA_TBOOLEAN:
|
case LUA_TBOOLEAN:
|
||||||
item_hash = (lua_Integer)lua_toboolean(L, -1);
|
// Arbitrarily chosen values
|
||||||
|
item_hash = lua_toboolean(L, -1)? 0x82684f71 : 0x88d66f2a;
|
||||||
break;
|
break;
|
||||||
case LUA_TTABLE:
|
case LUA_TTABLE:
|
||||||
case LUA_TFUNCTION:
|
case LUA_TFUNCTION:
|
||||||
@ -71,12 +77,13 @@ static int Lcreate_instance(lua_State *L)
|
|||||||
break;
|
break;
|
||||||
case LUA_TSTRING:
|
case LUA_TSTRING:
|
||||||
{
|
{
|
||||||
size_t strlen;
|
// Algorithm taken from Lua 5.3's implementation
|
||||||
const char *str = lua_tolstring(L, -1, &strlen);
|
size_t len;
|
||||||
item_hash = *str << 7;
|
const char *str = lua_tolstring(L, -1, &len);
|
||||||
for (const char *end = &str[strlen]; str < end; str++)
|
item_hash = len ^ 0xd2e9e9ac; // Arbitrary seed
|
||||||
item_hash = (1000003*item_hash) ^ *str;
|
size_t step = (len >> LUAI_HASHLIMIT) + 1;
|
||||||
item_hash ^= strlen;
|
for (; len >= step; len -= step)
|
||||||
|
item_hash ^= ((item_hash<<5) + (item_hash>>2) + (unsigned char)(str[len - 1]));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -196,7 +203,9 @@ static int Lfrom_table(lua_State *L)
|
|||||||
|
|
||||||
static int Llen(lua_State *L)
|
static int Llen(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_getmetatable(L, 1);
|
if (! lua_getmetatable(L, 1)) {
|
||||||
|
luaL_error(L, "invalid type");
|
||||||
|
}
|
||||||
// Stack: [mt]
|
// Stack: [mt]
|
||||||
lua_getfield(L, -1, "__fields");
|
lua_getfield(L, -1, "__fields");
|
||||||
// Stack: [mt, fields]
|
// Stack: [mt, fields]
|
||||||
@ -206,7 +215,9 @@ static int Llen(lua_State *L)
|
|||||||
|
|
||||||
static int Lindex(lua_State *L)
|
static int Lindex(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_getmetatable(L, 1);
|
if (! lua_getmetatable(L, 1)) {
|
||||||
|
luaL_error(L, "invalid type");
|
||||||
|
}
|
||||||
// Stack: [mt]
|
// Stack: [mt]
|
||||||
lua_getfield(L, -1, "__indices");
|
lua_getfield(L, -1, "__indices");
|
||||||
// Stack: [mt, indices]
|
// Stack: [mt, indices]
|
||||||
@ -242,7 +253,9 @@ static int Ltostring(lua_State *L)
|
|||||||
luaL_Buffer b;
|
luaL_Buffer b;
|
||||||
luaL_buffinit(L, &b);
|
luaL_buffinit(L, &b);
|
||||||
|
|
||||||
lua_getmetatable(L, 1);
|
if (! lua_getmetatable(L, 1)) {
|
||||||
|
luaL_error(L, "invalid type");
|
||||||
|
}
|
||||||
// Stack: [mt]
|
// Stack: [mt]
|
||||||
|
|
||||||
lua_getfield(L, -1, "name");
|
lua_getfield(L, -1, "name");
|
||||||
@ -298,7 +311,9 @@ static int Ltostring(lua_State *L)
|
|||||||
|
|
||||||
static int Lnexti(lua_State *L)
|
static int Lnexti(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_getmetatable(L, 1);
|
if (! lua_getmetatable(L, 1)) {
|
||||||
|
luaL_error(L, "invalid type");
|
||||||
|
}
|
||||||
// Stack: [mt]
|
// Stack: [mt]
|
||||||
lua_getfield(L, -1, "__instances");
|
lua_getfield(L, -1, "__instances");
|
||||||
// Stack: [mt, buckets]
|
// Stack: [mt, buckets]
|
||||||
@ -336,7 +351,9 @@ static int Lipairs(lua_State *L)
|
|||||||
|
|
||||||
static int Lnext(lua_State *L)
|
static int Lnext(lua_State *L)
|
||||||
{
|
{
|
||||||
lua_getmetatable(L, 1);
|
if (! lua_getmetatable(L, 1)) {
|
||||||
|
luaL_error(L, "invalid type");
|
||||||
|
}
|
||||||
// Stack: [mt]
|
// Stack: [mt]
|
||||||
lua_getfield(L, -1, "__instances");
|
lua_getfield(L, -1, "__instances");
|
||||||
// Stack: [mt, buckets]
|
// Stack: [mt, buckets]
|
||||||
|
Loading…
Reference in New Issue
Block a user