Optimize wrapper: use pointers instead of strings as most frequent keys.

develop
Alexander Gavrilov 2012-04-01 18:34:04 +04:00
parent 604c84953b
commit e3d50b9b04
3 changed files with 83 additions and 58 deletions

@ -1032,7 +1032,7 @@ static int meta_call_function(lua_State *state)
static void AddMethodWrapper(lua_State *state, int meta_idx, int field_idx, static void AddMethodWrapper(lua_State *state, int meta_idx, int field_idx,
const char *name, function_identity_base *fun) const char *name, function_identity_base *fun)
{ {
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushvalue(state, meta_idx); lua_pushvalue(state, meta_idx);
lua_pushfstring(state, "%s()", name); lua_pushfstring(state, "%s()", name);
lua_pushlightuserdata(state, fun); lua_pushlightuserdata(state, fun);
@ -1331,7 +1331,7 @@ void LuaWrapper::push_adhoc_pointer(lua_State *state, void *ptr, type_identity *
return; return;
} }
LookupInTable(state, target, DFHACK_PTR_IDTABLE_NAME); LookupInTable(state, target, &DFHACK_PTR_IDTABLE_TOKEN);
type_identity *id = (type_identity*)lua_touserdata(state, -1); type_identity *id = (type_identity*)lua_touserdata(state, -1);
lua_pop(state, 1); lua_pop(state, 1);
@ -1347,7 +1347,7 @@ void LuaWrapper::push_adhoc_pointer(lua_State *state, void *ptr, type_identity *
void *newobj = lua_newuserdata(state, sizeof(pointer_identity)); void *newobj = lua_newuserdata(state, sizeof(pointer_identity));
id = new (newobj) pointer_identity(target); id = new (newobj) pointer_identity(target);
SaveInTable(state, target, DFHACK_PTR_IDTABLE_NAME); SaveInTable(state, target, &DFHACK_PTR_IDTABLE_TOKEN);
lua_pop(state, 1); lua_pop(state, 1);
} }

@ -93,9 +93,9 @@ static void freeze_table(lua_State *state, bool leave_metatable = false, const c
lua_pop(state, 1); lua_pop(state, 1);
} }
static void LookupInTable(lua_State *state, const char *tname) static void LookupInTable(lua_State *state, LuaToken *tname)
{ {
lua_getfield(state, LUA_REGISTRYINDEX, tname); lua_rawgetp(state, LUA_REGISTRYINDEX, tname);
lua_swap(state); lua_swap(state);
lua_rawget(state, -2); lua_rawget(state, -2);
lua_remove(state, -2); lua_remove(state, -2);
@ -115,7 +115,7 @@ bool LuaWrapper::LookupTypeInfo(lua_State *state, bool in_method)
} }
else else
{ {
LookupInTable(state, DFHACK_TYPETABLE_NAME); LookupInTable(state, &DFHACK_TYPETABLE_TOKEN);
} }
// stack: [info] // stack: [info]
@ -129,17 +129,17 @@ bool LuaWrapper::LookupTypeInfo(lua_State *state, bool in_method)
return true; return true;
} }
void LuaWrapper::LookupInTable(lua_State *state, void *id, const char *tname) void LuaWrapper::LookupInTable(lua_State *state, void *id, LuaToken *tname)
{ {
lua_getfield(state, LUA_REGISTRYINDEX, tname); lua_rawgetp(state, LUA_REGISTRYINDEX, tname);
lua_rawgetp(state, -1, id); lua_rawgetp(state, -1, id);
lua_remove(state, -2); lua_remove(state, -2);
} }
void LuaWrapper::SaveInTable(lua_State *state, void *node, const char *tname) void LuaWrapper::SaveInTable(lua_State *state, void *node, LuaToken *tname)
{ {
// stack: [info] // stack: [info]
lua_getfield(state, LUA_REGISTRYINDEX, tname); lua_rawgetp(state, LUA_REGISTRYINDEX, tname);
lua_pushvalue(state, -2); lua_pushvalue(state, -2);
lua_rawsetp(state, -2, node); lua_rawsetp(state, -2, node);
@ -154,7 +154,7 @@ void LuaWrapper::SaveInTable(lua_State *state, void *node, const char *tname)
void LuaWrapper::SaveTypeInfo(lua_State *state, void *node) void LuaWrapper::SaveTypeInfo(lua_State *state, void *node)
{ {
SaveInTable(state, node, DFHACK_TYPETABLE_NAME); SaveInTable(state, node, &DFHACK_TYPETABLE_TOKEN);
} }
static void BuildTypeMetatable(lua_State *state, type_identity *type); static void BuildTypeMetatable(lua_State *state, type_identity *type);
@ -309,7 +309,7 @@ bool LuaWrapper::is_type_compatible(lua_State *state, type_identity *type1, int
static bool is_type_compatible(lua_State *state, type_identity *type1, int meta1, static bool is_type_compatible(lua_State *state, type_identity *type1, int meta1,
int meta2, bool exact_equal) int meta2, bool exact_equal)
{ {
lua_getfield(state, meta2, "_identity"); lua_rawgetp(state, meta2, &DFHACK_IDENTITY_FIELD_TOKEN);
auto type2 = (type_identity*)lua_touserdata(state, -1); auto type2 = (type_identity*)lua_touserdata(state, -1);
lua_pop(state, 1); lua_pop(state, 1);
@ -321,7 +321,7 @@ static bool is_type_compatible(lua_State *state, int meta1, int meta2, bool exac
if (lua_rawequal(state, meta1, meta2)) if (lua_rawequal(state, meta1, meta2))
return true; return true;
lua_getfield(state, meta1, "_identity"); lua_rawgetp(state, meta1, &DFHACK_IDENTITY_FIELD_TOKEN);
auto type1 = (type_identity*)lua_touserdata(state, -1); auto type1 = (type_identity*)lua_touserdata(state, -1);
lua_pop(state, 1); lua_pop(state, 1);
@ -394,7 +394,7 @@ static bool is_valid_metatable(lua_State *state, int objidx, int metaidx)
else else
{ {
lua_pushvalue(state, objidx); lua_pushvalue(state, objidx);
LookupInTable(state, DFHACK_TYPEID_TABLE_NAME); LookupInTable(state, &DFHACK_TYPEID_TABLE_TOKEN);
} }
bool ok = !lua_isnil(state, -1); bool ok = !lua_isnil(state, -1);
@ -419,7 +419,7 @@ type_identity *LuaWrapper::get_object_identity(lua_State *state, int objidx,
luaL_error(state, "Invalid object metatable in %s", ctx); luaL_error(state, "Invalid object metatable in %s", ctx);
// Extract identity from metatable // Extract identity from metatable
lua_getfield(state, -1, "_identity"); lua_rawgetp(state, -1, &DFHACK_IDENTITY_FIELD_TOKEN);
type_identity *id = (type_identity*)lua_touserdata(state, -1); type_identity *id = (type_identity*)lua_touserdata(state, -1);
if (!id) if (!id)
@ -894,9 +894,9 @@ void LuaWrapper::MakeMetatable(lua_State *state, type_identity *type, const char
lua_setfield(state, base+1, "__metatable"); lua_setfield(state, base+1, "__metatable");
lua_pushlightuserdata(state, type); lua_pushlightuserdata(state, type);
lua_setfield(state, base+1, "_identity"); lua_rawsetp(state, base+1, &DFHACK_IDENTITY_FIELD_TOKEN);
LookupInTable(state, type, DFHACK_TYPEID_TABLE_NAME); LookupInTable(state, type, &DFHACK_TYPEID_TABLE_TOKEN);
if (lua_isnil(state, -1)) if (lua_isnil(state, -1))
{ {
// Copy the string from __metatable if no real type // Copy the string from __metatable if no real type
@ -929,7 +929,7 @@ void LuaWrapper::SetPtrMethods(lua_State *state, int meta_idx, int read_idx)
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_COMPARE_NAME); lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_COMPARE_NAME);
lua_setfield(state, meta_idx, "__eq"); lua_setfield(state, meta_idx, "__eq");
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushvalue(state, meta_idx); lua_pushvalue(state, meta_idx);
lua_pushcclosure(state, meta_ptr_tostring, 2); lua_pushcclosure(state, meta_ptr_tostring, 2);
lua_setfield(state, meta_idx, "__tostring"); lua_setfield(state, meta_idx, "__tostring");
@ -981,7 +981,7 @@ void LuaWrapper::SetPairsMethod(lua_State *state, int meta_idx, const char *name
void LuaWrapper::PushStructMethod(lua_State *state, int meta_idx, int ftable_idx, void LuaWrapper::PushStructMethod(lua_State *state, int meta_idx, int ftable_idx,
lua_CFunction function) lua_CFunction function)
{ {
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushvalue(state, meta_idx); lua_pushvalue(state, meta_idx);
lua_pushvalue(state, ftable_idx); lua_pushvalue(state, ftable_idx);
lua_pushcclosure(state, function, 3); lua_pushcclosure(state, function, 3);
@ -1004,7 +1004,7 @@ void LuaWrapper::PushContainerMethod(lua_State *state, int meta_idx, int ftable_
lua_CFunction function, lua_CFunction function,
type_identity *container, type_identity *item, int count) type_identity *container, type_identity *item, int count)
{ {
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushvalue(state, meta_idx); lua_pushvalue(state, meta_idx);
lua_pushvalue(state, ftable_idx); lua_pushvalue(state, ftable_idx);
@ -1037,10 +1037,10 @@ void LuaWrapper::AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx,
{ {
EnableMetaField(state, ftable_idx, "_enum"); EnableMetaField(state, ftable_idx, "_enum");
LookupInTable(state, ienum, DFHACK_TYPEID_TABLE_NAME); LookupInTable(state, ienum, &DFHACK_TYPEID_TABLE_TOKEN);
lua_setfield(state, meta_idx, "_enum"); lua_setfield(state, meta_idx, "_enum");
LookupInTable(state, ienum, DFHACK_ENUM_TABLE_NAME); LookupInTable(state, ienum, &DFHACK_ENUM_TABLE_TOKEN);
if (!lua_isnil(state, -1)) if (!lua_isnil(state, -1))
{ {
@ -1053,7 +1053,7 @@ void LuaWrapper::AttachEnumKeys(lua_State *state, int meta_idx, int ftable_idx,
else else
{ {
lua_pop(state, 1); lua_pop(state, 1);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_EMPTY_TABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_EMPTY_TABLE_TOKEN);
} }
lua_dup(state); lua_dup(state);
@ -1111,12 +1111,12 @@ static void FillEnumKeys(lua_State *state, int ftable, enum_identity *eid)
lua_setfield(state, base+1, "_last_item"); lua_setfield(state, base+1, "_last_item");
} }
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME); SaveInTable(state, eid, &DFHACK_ENUM_TABLE_TOKEN);
// Add an attribute table if any // Add an attribute table if any
if (eid->getAttrs()) if (eid->getAttrs())
{ {
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushlightuserdata(state, eid); lua_pushlightuserdata(state, eid);
lua_pushvalue(state, base+1); lua_pushvalue(state, base+1);
lua_pushcclosure(state, meta_enum_attr_index, 3); lua_pushcclosure(state, meta_enum_attr_index, 3);
@ -1152,7 +1152,7 @@ static void FillBitfieldKeys(lua_State *state, int ftable, bitfield_identity *ei
lua_pushinteger(state, eid->getNumBits()-1); lua_pushinteger(state, eid->getNumBits()-1);
lua_setfield(state, base+1, "_last_item"); lua_setfield(state, base+1, "_last_item");
SaveInTable(state, eid, DFHACK_ENUM_TABLE_NAME); SaveInTable(state, eid, &DFHACK_ENUM_TABLE_TOKEN);
lua_setfield(state, base, "__index"); lua_setfield(state, base, "__index");
lua_setmetatable(state, ftable); lua_setmetatable(state, ftable);
@ -1169,7 +1169,7 @@ static void RenderType(lua_State *state, compound_identity *node)
if (!lua_checkstack(state, 20)) if (!lua_checkstack(state, 20))
return; return;
SaveInTable(state, node, DFHACK_TYPEID_TABLE_NAME); SaveInTable(state, node, &DFHACK_TYPEID_TABLE_TOKEN);
// metatable // metatable
lua_newtable(state); lua_newtable(state);
@ -1184,7 +1184,7 @@ static void RenderType(lua_State *state, compound_identity *node)
lua_setfield(state, base+2, "__tostring"); lua_setfield(state, base+2, "__tostring");
lua_pushlightuserdata(state, node); lua_pushlightuserdata(state, node);
lua_setfield(state, base+2, "_identity"); lua_rawsetp(state, base+2, &DFHACK_IDENTITY_FIELD_TOKEN);
// inner table // inner table
lua_newtable(state); lua_newtable(state);
@ -1272,16 +1272,16 @@ static int DoAttach(lua_State *state)
int base = lua_gettop(state); int base = lua_gettop(state);
lua_newtable(state); lua_newtable(state);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_PTR_IDTABLE_NAME); lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_PTR_IDTABLE_TOKEN);
lua_newtable(state); lua_newtable(state);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_TYPEID_TABLE_NAME); lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPEID_TABLE_TOKEN);
lua_newtable(state); lua_newtable(state);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_ENUM_TABLE_NAME); lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_ENUM_TABLE_TOKEN);
lua_newtable(state); lua_newtable(state);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_EMPTY_TABLE_NAME); lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_EMPTY_TABLE_TOKEN);
lua_pushcfunction(state, change_error); lua_pushcfunction(state, change_error);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_CHANGEERROR_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_CHANGEERROR_NAME);
@ -1292,27 +1292,27 @@ static int DoAttach(lua_State *state)
lua_pushcfunction(state, meta_type_tostring); lua_pushcfunction(state, meta_type_tostring);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_TYPE_TOSTRING_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_TYPE_TOSTRING_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushcclosure(state, meta_sizeof, 1); lua_pushcclosure(state, meta_sizeof, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_SIZEOF_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushcclosure(state, meta_displace, 1); lua_pushcclosure(state, meta_displace, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DISPLACE_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DISPLACE_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushcclosure(state, meta_new, 1); lua_pushcclosure(state, meta_new, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_NEW_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushcclosure(state, meta_assign, 1); lua_pushcclosure(state, meta_assign, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_ASSIGN_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushcclosure(state, meta_is_instance, 1); lua_pushcclosure(state, meta_is_instance, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_IS_INSTANCE_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_IS_INSTANCE_NAME);
lua_getfield(state, LUA_REGISTRYINDEX, DFHACK_TYPETABLE_NAME); lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
lua_pushcclosure(state, meta_delete, 1); lua_pushcclosure(state, meta_delete, 1);
lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME); lua_setfield(state, LUA_REGISTRYINDEX, DFHACK_DELETE_NAME);
@ -1353,11 +1353,29 @@ static int DoAttach(lua_State *state)
*/ */
void LuaWrapper::AttachDFGlobals(lua_State *state) void LuaWrapper::AttachDFGlobals(lua_State *state)
{ {
if (luaL_newmetatable(state, DFHACK_TYPETABLE_NAME)) lua_rawgetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
if (lua_isnil(state, -1))
{ {
lua_pop(state, 1);
lua_newtable(state);
lua_dup(state);
lua_rawsetp(state, LUA_REGISTRYINDEX, &DFHACK_TYPETABLE_TOKEN);
luaL_requiref(state, "df", DoAttach, 1); luaL_requiref(state, "df", DoAttach, 1);
lua_pop(state, 1); lua_pop(state, 1);
} }
lua_pop(state, 1); lua_pop(state, 1);
} }
namespace DFHack { namespace LuaWrapper {
struct LuaToken { int reserved; };
LuaToken DFHACK_IDENTITY_FIELD_TOKEN;
LuaToken DFHACK_TYPETABLE_TOKEN;
LuaToken DFHACK_TYPEID_TABLE_TOKEN;
LuaToken DFHACK_ENUM_TABLE_TOKEN;
LuaToken DFHACK_PTR_IDTABLE_TOKEN;
LuaToken DFHACK_EMPTY_TABLE_TOKEN;
}}

@ -39,26 +39,32 @@ distribution.
*/ */
namespace DFHack { namespace LuaWrapper { namespace DFHack { namespace LuaWrapper {
struct LuaToken;
/* /**
* Registry name: hash of type metatables <-> type identities. * Metatable pkey: type identity of the object
*/ */
#define DFHACK_TYPETABLE_NAME "DFHack::DFTypes" extern LuaToken DFHACK_IDENTITY_FIELD_TOKEN;
/* /**
* Registry name: hash of type identity -> node in df.etc... * Registry pkey: hash of type metatables <-> type identities.
*/ */
#define DFHACK_TYPEID_TABLE_NAME "DFHack::DFTypeIds" extern LuaToken DFHACK_TYPETABLE_TOKEN;
/* /**
* Registry name: hash of enum/bitfield identity -> index lookup table * Registry pkey: hash of type identity -> node in df.etc...
*/ */
#define DFHACK_ENUM_TABLE_NAME "DFHack::DFEnums" extern LuaToken DFHACK_TYPEID_TABLE_TOKEN;
/* /**
* Registry name: hash of pointer target identity <-> adhoc pointer identity userdata. * Registry pkey: hash of enum/bitfield identity -> index lookup table
*/ */
#define DFHACK_PTR_IDTABLE_NAME "DFHack::PtrDFTypes" extern LuaToken DFHACK_ENUM_TABLE_TOKEN;
/**
* Registry pkey: hash of pointer target identity <-> adhoc pointer identity userdata.
*/
extern LuaToken DFHACK_PTR_IDTABLE_TOKEN;
// Function registry names // Function registry names
#define DFHACK_CHANGEERROR_NAME "DFHack::ChangeError" #define DFHACK_CHANGEERROR_NAME "DFHack::ChangeError"
@ -70,7 +76,8 @@ namespace DFHack { namespace LuaWrapper {
#define DFHACK_ASSIGN_NAME "DFHack::Assign" #define DFHACK_ASSIGN_NAME "DFHack::Assign"
#define DFHACK_IS_INSTANCE_NAME "DFHack::IsInstance" #define DFHACK_IS_INSTANCE_NAME "DFHack::IsInstance"
#define DFHACK_DELETE_NAME "DFHack::Delete" #define DFHACK_DELETE_NAME "DFHack::Delete"
#define DFHACK_EMPTY_TABLE_NAME "DFHack::EmptyTable"
extern LuaToken DFHACK_EMPTY_TABLE_TOKEN;
/* /*
* Upvalue: contents of DFHACK_TYPETABLE_NAME * Upvalue: contents of DFHACK_TYPETABLE_NAME
@ -158,8 +165,8 @@ namespace DFHack { namespace LuaWrapper {
const char *ctx, bool allow_type = false, const char *ctx, bool allow_type = false,
bool keep_metatable = false); bool keep_metatable = false);
void LookupInTable(lua_State *state, void *id, const char *tname); void LookupInTable(lua_State *state, void *id, LuaToken *tname);
void SaveInTable(lua_State *state, void *node, const char *tname); void SaveInTable(lua_State *state, void *node, LuaToken *tname);
void SaveTypeInfo(lua_State *state, void *node); void SaveTypeInfo(lua_State *state, void *node);
void AssociateId(lua_State *state, int table, int val, const char *name); void AssociateId(lua_State *state, int table, int val, const char *name);