From d82bf70e9db3a25ec451b599660f3a837f21caee Mon Sep 17 00:00:00 2001 From: Benoit Germain Date: Tue, 30 Oct 2018 14:18:10 +0100 Subject: Improve LuaJIT-x64 compatibility Restrict internal "light userdata constants" to 47 significant bits when compiling against LuaJIT-x64 --- src/deep.c | 20 ++++++++-------- src/keeper.c | 16 +++++++------ src/keeper.h | 4 +++- src/lanes.c | 74 ++++++++++++++++++++++++++++++++------------------------- src/tools.c | 7 +++--- src/uniquekey.h | 25 +++++++++++++++++++ src/universe.c | 11 +++++---- 7 files changed, 98 insertions(+), 59 deletions(-) create mode 100644 src/uniquekey.h (limited to 'src') diff --git a/src/deep.c b/src/deep.c index 82350f4..fe7a21f 100644 --- a/src/deep.c +++ b/src/deep.c @@ -44,6 +44,7 @@ THE SOFTWARE. #include "deep.h" #include "tools.h" #include "universe.h" +#include "uniquekey.h" /*-- Metatable copying --*/ @@ -59,19 +60,19 @@ THE SOFTWARE. /* * Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it */ -void push_registry_subtable_mode( lua_State* L, void* key_, const char* mode_) +static void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) { STACK_GROW( L, 3); STACK_CHECK( L); - lua_pushlightuserdata( L, key_); // key + push_unique_key( L, key_); // key lua_rawget( L, LUA_REGISTRYINDEX); // {}|nil if( lua_isnil( L, -1)) { lua_pop( L, 1); // lua_newtable( L); // {} - lua_pushlightuserdata( L, key_); // {} key + push_unique_key( L, key_); // {} key lua_pushvalue( L, -2); // {} key {} // _R[key_] = {} @@ -96,7 +97,7 @@ void push_registry_subtable_mode( lua_State* L, void* key_, const char* mode_) * Push a registry subtable (keyed by unique 'key_') onto the stack. * If the subtable does not exist, it is created and chained. */ -void push_registry_subtable( lua_State* L, void* key_) +void push_registry_subtable( lua_State* L, UniqueKey key_) { push_registry_subtable_mode( L, key_, NULL); } @@ -121,15 +122,14 @@ void luaG_pushdeepversion( lua_State* L) { (void) lua_pushliteral( L, "ab8743e5- * metatable -> idfunc * idfunc -> metatable */ -// crc64/we of string "DEEP_LOOKUP_KEY" generated at https://www.nitrxgen.net/hashgen/ -#define DEEP_LOOKUP_KEY ((void*)0x9fb9b4f3f633d83d) - +// crc64/we of string "DEEP_LOOKUP_KEY" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( DEEP_LOOKUP_KEY, (void*)0x9fb9b4f3f633d83d); /* * The deep proxy cache is a weak valued table listing all deep UD proxies indexed by the deep UD that they are proxying - * crc64/we of string "DEEP_PROXY_CACHE_KEY" generated at https://www.nitrxgen.net/hashgen/ + * crc64/we of string "DEEP_PROXY_CACHE_KEY" generated at http://www.nitrxgen.net/hashgen/ */ -#define DEEP_PROXY_CACHE_KEY ((void*)0x05773d6fc26be106) +static DECLARE_CONST_UNIQUE_KEY( DEEP_PROXY_CACHE_KEY, (void*)0x05773d6fc26be106); /* * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists. @@ -158,7 +158,7 @@ static void get_deep_lookup( lua_State* L) { STACK_GROW( L, 1); STACK_CHECK( L); // a - lua_pushlightuserdata( L, DEEP_LOOKUP_KEY); // a DLK + push_unique_key( L, DEEP_LOOKUP_KEY); // a DLK lua_rawget( L, LUA_REGISTRYINDEX); // a {} if( !lua_isnil( L, -1)) diff --git a/src/keeper.c b/src/keeper.c index 907334f..715583b 100644 --- a/src/keeper.c +++ b/src/keeper.c @@ -48,6 +48,7 @@ #include "compat.h" #include "tools.h" #include "universe.h" +#include "uniquekey.h" //################################################################################### // Keeper implementation @@ -160,13 +161,14 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) // in: linda_ud expected at *absolute* stack slot idx // out: fifos[ud] -static void* const fifos_key = (void*) prepare_fifo_access; +// crc64/we of string "FIFOS_KEY" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( FIFOS_KEY, 0xdce50bbc351cd465); static void push_table( lua_State* L, int idx_) { STACK_GROW( L, 4); STACK_CHECK( L); idx_ = lua_absindex( L, idx_); - lua_pushlightuserdata( L, fifos_key); // ud fifos_key + push_unique_key( L, FIFOS_KEY); // ud fifos_key lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos lua_pushvalue( L, idx_); // ud fifos ud lua_rawget( L, -2); // ud fifos fifos[ud] @@ -191,7 +193,7 @@ int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t if( KL == NULL) return 0; STACK_GROW( KL, 4); STACK_CHECK( KL); - lua_pushlightuserdata( KL, fifos_key); // fifos_key + push_unique_key( KL, FIFOS_KEY); // fifos_key lua_rawget( KL, LUA_REGISTRYINDEX); // fifos lua_pushlightuserdata( KL, ptr_); // fifos ud lua_rawget( KL, -2); // fifos storage @@ -239,7 +241,7 @@ int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t int keepercall_clear( lua_State* L) { STACK_GROW( L, 3); - lua_pushlightuserdata( L, fifos_key); // ud fifos_key + push_unique_key( L, FIFOS_KEY); // ud fifos_key lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos lua_pushvalue( L, 1); // ud fifos ud lua_pushnil( L); // ud fifos ud nil @@ -704,7 +706,7 @@ void init_keepers( Universe* U, lua_State* L) lua_setglobal( K, "decoda_name"); // // create the fifos table in the keeper state - lua_pushlightuserdata( K, fifos_key); // fifo_key + push_unique_key( K, FIFOS_KEY); // fifo_key lua_newtable( K); // fifo_key {} lua_rawset( K, LUA_REGISTRYINDEX); // @@ -754,13 +756,13 @@ void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode mode_) { if( lua_isnil( L, i)) { - lua_pushlightuserdata( L, NIL_SENTINEL); + push_unique_key( L, NIL_SENTINEL); lua_replace( L, i); } } else { - if( lua_touserdata( L, i) == NIL_SENTINEL) + if( equal_unique_key( L, i, NIL_SENTINEL)) { lua_pushnil( L); lua_replace( L, i); diff --git a/src/keeper.h b/src/keeper.h index 06cf3be..37922fb 100644 --- a/src/keeper.h +++ b/src/keeper.h @@ -3,6 +3,7 @@ #include "lua.h" #include "threading.h" +#include "uniquekey.h" // forwards struct s_Universe; @@ -34,7 +35,8 @@ void keeper_release( Keeper* K); void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_); int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); -#define NIL_SENTINEL ((void*)keeper_toggle_nil_sentinels) +// crc64/we of string "NIL_SENTINEL" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( NIL_SENTINEL, 0x7eaafa003a1d11a1); typedef lua_CFunction keeper_api_t; #define KEEPER_API( _op) keepercall_ ## _op diff --git a/src/lanes.c b/src/lanes.c index 0a04d88..5a1f94a 100644 --- a/src/lanes.c +++ b/src/lanes.c @@ -93,6 +93,7 @@ THE SOFTWARE. #include "tools.h" #include "universe.h" #include "keeper.h" +#include "uniquekey.h" #if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) # include @@ -193,13 +194,15 @@ typedef struct s_Lane Lane; // #define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) -#define CANCEL_TEST_KEY ((void*)get_lane_from_registry) // used as registry key +// crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( CANCEL_TEST_KEY, 0xe66f5960c57d133a); // used as registry key + static inline Lane* get_lane_from_registry( lua_State* L) { Lane* s; STACK_GROW( L, 1); STACK_CHECK( L); - lua_pushlightuserdata( L, CANCEL_TEST_KEY); + push_unique_key( L, CANCEL_TEST_KEY); lua_rawget( L, LUA_REGISTRYINDEX); s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil lua_pop( L, 1); @@ -238,11 +241,13 @@ static inline enum e_cancel_request cancel_test( lua_State* L) return s ? s->cancel_request : CANCEL_NONE; } -#define CANCEL_ERROR ((void*)cancel_error) // 'cancel_error' sentinel +// crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( CANCEL_ERROR, 0xe97d41626cc97577); // 'cancel_error' sentinel + static int cancel_error( lua_State* L) { STACK_GROW( L, 1); - lua_pushlightuserdata( L, CANCEL_ERROR); // special error value + push_unique_key( L, CANCEL_ERROR); // special error value return lua_error( L); // doesn't return } @@ -258,7 +263,8 @@ static void cancel_hook( lua_State* L, lua_Debug* ar) #if ERROR_FULL_STACK static int lane_error( lua_State* L); -#define STACK_TRACE_KEY ((void*)lane_error) // used as registry key +// crc64/we of string "STACK_TRACE_KEY" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( STACK_TRACE_KEY, 0x024d5411677ce879); #endif // ERROR_FULL_STACK /* @@ -463,7 +469,7 @@ LUAG_FUNC( linda_send) int pushed; time_d timeout = -1.0; uint_t key_i = 2; // index of first key, if timeout not there - void* as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided + bool_t as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion { @@ -475,8 +481,8 @@ LUAG_FUNC( linda_send) ++ key_i; } - as_nil_sentinel = lua_touserdata( L, key_i); - if( as_nil_sentinel == NIL_SENTINEL) + as_nil_sentinel = equal_unique_key( L, key_i, NIL_SENTINEL); + if( as_nil_sentinel) { // the real key to send data to is after the NIL_SENTINEL marker ++ key_i; @@ -490,10 +496,10 @@ LUAG_FUNC( linda_send) // make sure there is something to send if( (uint_t)lua_gettop( L) == key_i) { - if( as_nil_sentinel == NIL_SENTINEL) + if( as_nil_sentinel) { // send a single nil if nothing is provided - lua_pushlightuserdata( L, NIL_SENTINEL); + push_unique_key( L, NIL_SENTINEL); } else { @@ -584,7 +590,7 @@ LUAG_FUNC( linda_send) { case CANCEL_SOFT: // if user wants to soft-cancel, the call returns lanes.cancel_error - lua_pushlightuserdata( L, CANCEL_ERROR); + push_unique_key( L, CANCEL_ERROR); return 1; case CANCEL_HARD: @@ -741,7 +747,7 @@ LUAG_FUNC( linda_receive) { case CANCEL_SOFT: // if user wants to soft-cancel, the call returns CANCEL_ERROR - lua_pushlightuserdata( L, CANCEL_ERROR); + push_unique_key( L, CANCEL_ERROR); return 1; case CANCEL_HARD: @@ -803,7 +809,7 @@ LUAG_FUNC( linda_set) else // linda is cancelled { // do nothing and return lanes.cancel_error - lua_pushlightuserdata( L, CANCEL_ERROR); + push_unique_key( L, CANCEL_ERROR); pushed = 1; } keeper_release( K); @@ -871,7 +877,7 @@ LUAG_FUNC( linda_get) else // linda is cancelled { // do nothing and return lanes.cancel_error - lua_pushlightuserdata( L, CANCEL_ERROR); + push_unique_key( L, CANCEL_ERROR); pushed = 1; } keeper_release( K); @@ -922,7 +928,7 @@ LUAG_FUNC( linda_limit) else // linda is cancelled { // do nothing and return lanes.cancel_error - lua_pushlightuserdata( L, CANCEL_ERROR); + push_unique_key( L, CANCEL_ERROR); pushed = 1; } keeper_release( K); @@ -1249,7 +1255,7 @@ static void* linda_id( lua_State* L, enum eDeepOp op_) lua_pushliteral( L, BATCH_SENTINEL); lua_setfield(L, -2, "batched"); - lua_pushlightuserdata( L, NIL_SENTINEL); + push_unique_key( L, NIL_SENTINEL); lua_setfield(L, -2, "null"); luaG_pushdeepversion( L); @@ -1815,7 +1821,8 @@ LUAG_FUNC( set_singlethreaded) */ #if ERROR_FULL_STACK -# define EXTENDED_STACK_TRACE_KEY ((void*)LG_set_error_reporting) // used as registry key +// crc64/we of string "EXTENDED_STACK_TRACE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( EXTENDED_STACK_TRACE_REGKEY, 0x7a59821071066e49); // used as registry key LUAG_FUNC( set_error_reporting) { @@ -1836,7 +1843,7 @@ LUAG_FUNC( set_error_reporting) return luaL_error( L, "unsupported error reporting model"); } done: - lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); + push_unique_key( L, EXTENDED_STACK_TRACE_REGKEY); lua_pushboolean( L, equal); lua_rawset( L, LUA_REGISTRYINDEX); return 0; @@ -1853,13 +1860,13 @@ static int lane_error( lua_State* L) // Don't do stack survey for cancelled lanes. // - if( lua_touserdata( L, 1) == CANCEL_ERROR) + if( equal_unique_key( L, 1, CANCEL_ERROR)) { return 1; // just pass on } STACK_GROW( L, 3); - lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); // some_error estk + push_unique_key( L, EXTENDED_STACK_TRACE_REGKEY); // some_error estk lua_rawget( L, LUA_REGISTRYINDEX); // some_error basic|extended extended = lua_toboolean( L, -1); lua_pop( L, 1); // some_error @@ -1913,7 +1920,7 @@ static int lane_error( lua_State* L) lua_rawseti( L, -2, (lua_Integer) n); // some_error {} } - lua_pushlightuserdata( L, STACK_TRACE_KEY); // some_error {} stk + push_unique_key( L, STACK_TRACE_KEY); // some_error {} stk lua_insert( L, -2); // some_error stk {} lua_rawset( L, LUA_REGISTRYINDEX); // some_error @@ -1936,14 +1943,14 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) { // fetch the call stack table from the registry where the handler stored it STACK_GROW( L, 1); - lua_pushlightuserdata( L, STACK_TRACE_KEY); // err STACK_TRACE_KEY + push_unique_key( L, STACK_TRACE_KEY); // err STACK_TRACE_KEY // yields nil if no stack was generated (in case of cancellation for example) lua_rawget( L, LUA_REGISTRYINDEX); // err trace|nil ASSERT_L( lua_gettop( L) == 1 + stk_base_); // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed // For other errors, the message can be whatever was thrown, and we should have a stack trace table - ASSERT_L( lua_type( L, 1 + stk_base_) == ((lua_touserdata( L, stk_base_) == CANCEL_ERROR) ? LUA_TNIL : LUA_TTABLE)); + ASSERT_L( lua_type( L, 1 + stk_base_) == (equal_unique_key( L, stk_base_, CANCEL_ERROR) ? LUA_TNIL : LUA_TTABLE)); // Just leaving the stack trace table on the stack is enough to get it through to the master. break; } @@ -1953,18 +1960,19 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) default: // we should have a single value which is either a string (the error message) or CANCEL_ERROR - ASSERT_L( (lua_gettop( L) == stk_base_) && ((lua_type( L, stk_base_) == LUA_TSTRING) || (lua_touserdata( L, stk_base_) == CANCEL_ERROR))); + ASSERT_L( (lua_gettop( L) == stk_base_) && ((lua_type( L, stk_base_) == LUA_TSTRING) || equal_unique_key( L, stk_base_, CANCEL_ERROR))); break; } } LUAG_FUNC( set_debug_threadname) { + DECLARE_CONST_UNIQUE_KEY( hidden_regkey, LG_set_debug_threadname); // C s_lane structure is a light userdata upvalue Lane* s = lua_touserdata( L, lua_upvalueindex( 1)); luaL_checktype( L, -1, LUA_TSTRING); // "name" // store a hidden reference in the registry to make sure the string is kept around even if a lane decides to manually change the "decoda_name" global... - lua_pushlightuserdata( L, LG_set_debug_threadname); // "name" lud + push_unique_key( L, hidden_regkey); // "name" lud lua_pushvalue( L, -2); // "name" lud "name" lua_rawset( L, LUA_REGISTRYINDEX); // "name" s->debug_name = lua_tostring( L, -1); @@ -2089,7 +2097,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) // in case of error and if it exists, fetch stack trace from registry and push it push_stack_trace( L, rc, 1); // retvals|error [trace] - DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END, L, get_errcode_name( rc), (lua_touserdata( L, 1)==CANCEL_ERROR) ? "cancelled" : lua_typename( L, lua_type( L, 1)))); + DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "Lane %p body: %s (%s)\n" INDENT_END, L, get_errcode_name( rc), equal_unique_key( L, 1, CANCEL_ERROR) ? "cancelled" : lua_typename( L, lua_type( L, 1)))); //STACK_DUMP(L); // Call finalizers, if the script has set them up. // @@ -2118,7 +2126,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) { // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them - enum e_status st = (rc == 0) ? DONE : (lua_touserdata( L, 1) == CANCEL_ERROR) ? CANCELLED : ERROR_ST; + enum e_status st = (rc == 0) ? DONE : equal_unique_key( L, 1, CANCEL_ERROR) ? CANCELLED : ERROR_ST; // Posix no PTHREAD_TIMEDJOIN: // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change @@ -2183,9 +2191,9 @@ LUAG_FUNC( register) return 0; } +// crc64/we of string "GCCB_KEY" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_CONST_UNIQUE_KEY( GCCB_KEY, 0xcfb1f046ef074e88); -LUAG_FUNC( thread_gc); -#define GCCB_KEY (void*)LG_thread_gc //--- // lane_ud = lane_new( function // , [libs_str] @@ -2429,7 +2437,7 @@ LUAG_FUNC( lane_new) // Store the gc_cb callback in the uservalue if( gc_cb_idx > 0) { - lua_pushlightuserdata( L, GCCB_KEY); // func libs cancelstep priority globals package required gc_cb lane uv k + push_unique_key( L, GCCB_KEY); // func libs cancelstep priority globals package required gc_cb lane uv k lua_pushvalue( L, gc_cb_idx); // func libs cancelstep priority globals package required gc_cb lane uv k gc_cb lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv } @@ -2437,7 +2445,7 @@ LUAG_FUNC( lane_new) lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). - lua_pushlightuserdata( L2, CANCEL_TEST_KEY); // func [... args ...] k + push_unique_key( L2, CANCEL_TEST_KEY); // func [... args ...] k lua_pushlightuserdata( L2, s); // func [... args ...] k s lua_rawset( L2, LUA_REGISTRYINDEX); // func [... args ...] @@ -2476,7 +2484,7 @@ LUAG_FUNC( thread_gc) // if there a gc callback? lua_getuservalue( L, 1); // ud uservalue - lua_pushlightuserdata( L, GCCB_KEY); // ud uservalue __gc + push_unique_key( L, GCCB_KEY); // ud uservalue __gc lua_rawget( L, -2); // ud uservalue gc_cb|nil if( !lua_isnil( L, -1)) { @@ -3209,7 +3217,7 @@ LUAG_FUNC( configure) lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX lua_setfield( L, -2, "max_prio"); // settings M - lua_pushlightuserdata( L, CANCEL_ERROR); // settings M CANCEL_ERROR + push_unique_key( L, CANCEL_ERROR); // settings M CANCEL_ERROR lua_setfield( L, -2, "cancel_error"); // settings M // we'll need this every time we transfer some C function from/to this state diff --git a/src/tools.c b/src/tools.c index 051e3cc..c13d80d 100644 --- a/src/tools.c +++ b/src/tools.c @@ -44,6 +44,7 @@ THE SOFTWARE. #include "universe.h" #include "keeper.h" #include "lanes.h" +#include "uniquekey.h" // functions implemented in deep.c extern luaG_IdFunction copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode mode_); @@ -977,7 +978,7 @@ static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mo static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i) { bool_t not_found_in_cache; // L2 - void* const p = (void*)lua_topointer( L, i); + DECLARE_CONST_UNIQUE_KEY( p, lua_topointer( L, i)); ASSERT_L( L2_cache_i != 0); STACK_GROW( L2, 3); @@ -986,7 +987,7 @@ static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, // We don't need to use the from state ('L') in ID since the life span // is only for the duration of a copy (both states are locked). // push a light userdata uniquely representing the table - lua_pushlightuserdata( L2, p); // ... p + push_unique_key( L2, p); // ... p //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); @@ -996,7 +997,7 @@ static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, { lua_pop( L2, 1); // ... lua_newtable( L2); // ... {} - lua_pushlightuserdata( L2, p); // ... {} p + push_unique_key( L2, p); // ... {} p lua_pushvalue( L2, -2); // ... {} p {} lua_rawset( L2, L2_cache_i); // ... {} } diff --git a/src/uniquekey.h b/src/uniquekey.h new file mode 100644 index 0000000..c90d09a --- /dev/null +++ b/src/uniquekey.h @@ -0,0 +1,25 @@ +#if !defined __LANES_UNIQUEKEY_H__ +#define __LANES_UNIQUEKEY_H__ 1 + +#include "lualib.h" + +// Lua light userdata can hold a pointer. +struct s_UniqueKey +{ + void* value; +}; +typedef struct s_UniqueKey UniqueKey; + +#if defined(LUA_JITLIBNAME) && (defined(__x86_64__) || defined(_M_X64)) // building against LuaJIT headers, light userdata is restricted to 47 significant bits. +#define MAKE_UNIQUE_KEY( p_) ((void*)(p_) & 0x7fffffffffffull) +#else // LUA_JITLIBNAME +#define MAKE_UNIQUE_KEY( p_) ((void*) p_) +#endif // LUA_JITLIBNAME + +#define DECLARE_UNIQUE_KEY( name_) UniqueKey name_ +#define DECLARE_CONST_UNIQUE_KEY( name_, p_) UniqueKey const name_ = { MAKE_UNIQUE_KEY( p_)} + +#define push_unique_key( L, key_) lua_pushlightuserdata( L, key_.value) +#define equal_unique_key( L, i, key_) (lua_touserdata( L, i) == key_.value) + +#endif // __LANES_UNIQUEKEY_H__ diff --git a/src/universe.c b/src/universe.c index 8bcdcfe..ca94930 100644 --- a/src/universe.c +++ b/src/universe.c @@ -31,9 +31,10 @@ THE SOFTWARE. #include "universe.h" #include "compat.h" #include "macros_and_utils.h" +#include "uniquekey.h" -// crc64/we of string "UNIVERSE_REGKEY" generated at https://www.nitrxgen.net/hashgen/ -static void* const UNIVERSE_REGKEY = ((void*)0x9f877b2cf078f17f); +// crc64/we of string "UNIVERSE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ +static DECLARE_UNIQUE_KEY( UNIVERSE_REGKEY, 0x9f877b2cf078f17f); // ################################################################################################ @@ -41,7 +42,7 @@ Universe* universe_create( lua_State* L) { Universe* U = (Universe*) lua_newuserdata( L, sizeof(Universe)); // universe memset( U, 0, sizeof( Universe)); - lua_pushlightuserdata( L, UNIVERSE_REGKEY); // universe UNIVERSE_REGKEY + push_unique_key( L, UNIVERSE_REGKEY); // universe UNIVERSE_REGKEY lua_pushvalue( L, -2); // universe UNIVERSE_REGKEY universe lua_rawset( L, LUA_REGISTRYINDEX); // universe return U; @@ -52,7 +53,7 @@ Universe* universe_create( lua_State* L) void universe_store( lua_State* L, Universe* U) { STACK_CHECK( L); - lua_pushlightuserdata( L, UNIVERSE_REGKEY); + push_unique_key( L, UNIVERSE_REGKEY); lua_pushlightuserdata( L, U); lua_rawset( L, LUA_REGISTRYINDEX); STACK_END( L, 0); @@ -65,7 +66,7 @@ Universe* universe_get( lua_State* L) Universe* universe; STACK_GROW( L, 2); STACK_CHECK( L); - lua_pushlightuserdata( L, UNIVERSE_REGKEY); + push_unique_key( L, UNIVERSE_REGKEY); lua_rawget( L, LUA_REGISTRYINDEX); universe = lua_touserdata( L, -1); // NULL if nil lua_pop( L, 1); -- cgit v1.2.3-55-g6feb