diff options
| author | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2018-10-30 14:18:10 +0100 |
|---|---|---|
| committer | Benoit Germain <b n t DOT g e r m a i n AT g m a i l DOT c o m> | 2018-10-30 14:18:10 +0100 |
| commit | d82bf70e9db3a25ec451b599660f3a837f21caee (patch) | |
| tree | e9e861252a118c8c66e874fedb93c2a32733aa0f | |
| parent | ea9e8a3af1c2357c454ef18c8136c14a22b8675a (diff) | |
| download | lanes-d82bf70e9db3a25ec451b599660f3a837f21caee.tar.gz lanes-d82bf70e9db3a25ec451b599660f3a837f21caee.tar.bz2 lanes-d82bf70e9db3a25ec451b599660f3a837f21caee.zip | |
Improve LuaJIT-x64 compatibility
Restrict internal "light userdata constants" to 47 significant bits when
compiling against LuaJIT-x64
| -rw-r--r-- | src/deep.c | 20 | ||||
| -rw-r--r-- | src/keeper.c | 16 | ||||
| -rw-r--r-- | src/keeper.h | 4 | ||||
| -rw-r--r-- | src/lanes.c | 74 | ||||
| -rw-r--r-- | src/tools.c | 7 | ||||
| -rw-r--r-- | src/uniquekey.h | 25 | ||||
| -rw-r--r-- | src/universe.c | 11 |
7 files changed, 98 insertions, 59 deletions
| @@ -44,6 +44,7 @@ THE SOFTWARE. | |||
| 44 | #include "deep.h" | 44 | #include "deep.h" |
| 45 | #include "tools.h" | 45 | #include "tools.h" |
| 46 | #include "universe.h" | 46 | #include "universe.h" |
| 47 | #include "uniquekey.h" | ||
| 47 | 48 | ||
| 48 | /*-- Metatable copying --*/ | 49 | /*-- Metatable copying --*/ |
| 49 | 50 | ||
| @@ -59,19 +60,19 @@ THE SOFTWARE. | |||
| 59 | /* | 60 | /* |
| 60 | * Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it | 61 | * Does what the original 'push_registry_subtable' function did, but adds an optional mode argument to it |
| 61 | */ | 62 | */ |
| 62 | void push_registry_subtable_mode( lua_State* L, void* key_, const char* mode_) | 63 | static void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) |
| 63 | { | 64 | { |
| 64 | STACK_GROW( L, 3); | 65 | STACK_GROW( L, 3); |
| 65 | STACK_CHECK( L); | 66 | STACK_CHECK( L); |
| 66 | 67 | ||
| 67 | lua_pushlightuserdata( L, key_); // key | 68 | push_unique_key( L, key_); // key |
| 68 | lua_rawget( L, LUA_REGISTRYINDEX); // {}|nil | 69 | lua_rawget( L, LUA_REGISTRYINDEX); // {}|nil |
| 69 | 70 | ||
| 70 | if( lua_isnil( L, -1)) | 71 | if( lua_isnil( L, -1)) |
| 71 | { | 72 | { |
| 72 | lua_pop( L, 1); // | 73 | lua_pop( L, 1); // |
| 73 | lua_newtable( L); // {} | 74 | lua_newtable( L); // {} |
| 74 | lua_pushlightuserdata( L, key_); // {} key | 75 | push_unique_key( L, key_); // {} key |
| 75 | lua_pushvalue( L, -2); // {} key {} | 76 | lua_pushvalue( L, -2); // {} key {} |
| 76 | 77 | ||
| 77 | // _R[key_] = {} | 78 | // _R[key_] = {} |
| @@ -96,7 +97,7 @@ void push_registry_subtable_mode( lua_State* L, void* key_, const char* mode_) | |||
| 96 | * Push a registry subtable (keyed by unique 'key_') onto the stack. | 97 | * Push a registry subtable (keyed by unique 'key_') onto the stack. |
| 97 | * If the subtable does not exist, it is created and chained. | 98 | * If the subtable does not exist, it is created and chained. |
| 98 | */ | 99 | */ |
| 99 | void push_registry_subtable( lua_State* L, void* key_) | 100 | void push_registry_subtable( lua_State* L, UniqueKey key_) |
| 100 | { | 101 | { |
| 101 | push_registry_subtable_mode( L, key_, NULL); | 102 | push_registry_subtable_mode( L, key_, NULL); |
| 102 | } | 103 | } |
| @@ -121,15 +122,14 @@ void luaG_pushdeepversion( lua_State* L) { (void) lua_pushliteral( L, "ab8743e5- | |||
| 121 | * metatable -> idfunc | 122 | * metatable -> idfunc |
| 122 | * idfunc -> metatable | 123 | * idfunc -> metatable |
| 123 | */ | 124 | */ |
| 124 | // crc64/we of string "DEEP_LOOKUP_KEY" generated at https://www.nitrxgen.net/hashgen/ | 125 | // crc64/we of string "DEEP_LOOKUP_KEY" generated at http://www.nitrxgen.net/hashgen/ |
| 125 | #define DEEP_LOOKUP_KEY ((void*)0x9fb9b4f3f633d83d) | 126 | static DECLARE_CONST_UNIQUE_KEY( DEEP_LOOKUP_KEY, (void*)0x9fb9b4f3f633d83d); |
| 126 | |||
| 127 | 127 | ||
| 128 | /* | 128 | /* |
| 129 | * The deep proxy cache is a weak valued table listing all deep UD proxies indexed by the deep UD that they are proxying | 129 | * The deep proxy cache is a weak valued table listing all deep UD proxies indexed by the deep UD that they are proxying |
| 130 | * crc64/we of string "DEEP_PROXY_CACHE_KEY" generated at https://www.nitrxgen.net/hashgen/ | 130 | * crc64/we of string "DEEP_PROXY_CACHE_KEY" generated at http://www.nitrxgen.net/hashgen/ |
| 131 | */ | 131 | */ |
| 132 | #define DEEP_PROXY_CACHE_KEY ((void*)0x05773d6fc26be106) | 132 | static DECLARE_CONST_UNIQUE_KEY( DEEP_PROXY_CACHE_KEY, (void*)0x05773d6fc26be106); |
| 133 | 133 | ||
| 134 | /* | 134 | /* |
| 135 | * Sets up [-1]<->[-2] two-way lookups, and ensures the lookup table exists. | 135 | * 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) | |||
| 158 | { | 158 | { |
| 159 | STACK_GROW( L, 1); | 159 | STACK_GROW( L, 1); |
| 160 | STACK_CHECK( L); // a | 160 | STACK_CHECK( L); // a |
| 161 | lua_pushlightuserdata( L, DEEP_LOOKUP_KEY); // a DLK | 161 | push_unique_key( L, DEEP_LOOKUP_KEY); // a DLK |
| 162 | lua_rawget( L, LUA_REGISTRYINDEX); // a {} | 162 | lua_rawget( L, LUA_REGISTRYINDEX); // a {} |
| 163 | 163 | ||
| 164 | if( !lua_isnil( L, -1)) | 164 | 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 @@ | |||
| 48 | #include "compat.h" | 48 | #include "compat.h" |
| 49 | #include "tools.h" | 49 | #include "tools.h" |
| 50 | #include "universe.h" | 50 | #include "universe.h" |
| 51 | #include "uniquekey.h" | ||
| 51 | 52 | ||
| 52 | //################################################################################### | 53 | //################################################################################### |
| 53 | // Keeper implementation | 54 | // Keeper implementation |
| @@ -160,13 +161,14 @@ static void fifo_pop( lua_State* L, keeper_fifo* fifo_, lua_Integer count_) | |||
| 160 | 161 | ||
| 161 | // in: linda_ud expected at *absolute* stack slot idx | 162 | // in: linda_ud expected at *absolute* stack slot idx |
| 162 | // out: fifos[ud] | 163 | // out: fifos[ud] |
| 163 | static void* const fifos_key = (void*) prepare_fifo_access; | 164 | // crc64/we of string "FIFOS_KEY" generated at http://www.nitrxgen.net/hashgen/ |
| 165 | static DECLARE_CONST_UNIQUE_KEY( FIFOS_KEY, 0xdce50bbc351cd465); | ||
| 164 | static void push_table( lua_State* L, int idx_) | 166 | static void push_table( lua_State* L, int idx_) |
| 165 | { | 167 | { |
| 166 | STACK_GROW( L, 4); | 168 | STACK_GROW( L, 4); |
| 167 | STACK_CHECK( L); | 169 | STACK_CHECK( L); |
| 168 | idx_ = lua_absindex( L, idx_); | 170 | idx_ = lua_absindex( L, idx_); |
| 169 | lua_pushlightuserdata( L, fifos_key); // ud fifos_key | 171 | push_unique_key( L, FIFOS_KEY); // ud fifos_key |
| 170 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos | 172 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos |
| 171 | lua_pushvalue( L, idx_); // ud fifos ud | 173 | lua_pushvalue( L, idx_); // ud fifos ud |
| 172 | lua_rawget( L, -2); // ud fifos fifos[ud] | 174 | 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 | |||
| 191 | if( KL == NULL) return 0; | 193 | if( KL == NULL) return 0; |
| 192 | STACK_GROW( KL, 4); | 194 | STACK_GROW( KL, 4); |
| 193 | STACK_CHECK( KL); | 195 | STACK_CHECK( KL); |
| 194 | lua_pushlightuserdata( KL, fifos_key); // fifos_key | 196 | push_unique_key( KL, FIFOS_KEY); // fifos_key |
| 195 | lua_rawget( KL, LUA_REGISTRYINDEX); // fifos | 197 | lua_rawget( KL, LUA_REGISTRYINDEX); // fifos |
| 196 | lua_pushlightuserdata( KL, ptr_); // fifos ud | 198 | lua_pushlightuserdata( KL, ptr_); // fifos ud |
| 197 | lua_rawget( KL, -2); // fifos storage | 199 | lua_rawget( KL, -2); // fifos storage |
| @@ -239,7 +241,7 @@ int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t | |||
| 239 | int keepercall_clear( lua_State* L) | 241 | int keepercall_clear( lua_State* L) |
| 240 | { | 242 | { |
| 241 | STACK_GROW( L, 3); | 243 | STACK_GROW( L, 3); |
| 242 | lua_pushlightuserdata( L, fifos_key); // ud fifos_key | 244 | push_unique_key( L, FIFOS_KEY); // ud fifos_key |
| 243 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos | 245 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos |
| 244 | lua_pushvalue( L, 1); // ud fifos ud | 246 | lua_pushvalue( L, 1); // ud fifos ud |
| 245 | lua_pushnil( L); // ud fifos ud nil | 247 | lua_pushnil( L); // ud fifos ud nil |
| @@ -704,7 +706,7 @@ void init_keepers( Universe* U, lua_State* L) | |||
| 704 | lua_setglobal( K, "decoda_name"); // | 706 | lua_setglobal( K, "decoda_name"); // |
| 705 | 707 | ||
| 706 | // create the fifos table in the keeper state | 708 | // create the fifos table in the keeper state |
| 707 | lua_pushlightuserdata( K, fifos_key); // fifo_key | 709 | push_unique_key( K, FIFOS_KEY); // fifo_key |
| 708 | lua_newtable( K); // fifo_key {} | 710 | lua_newtable( K); // fifo_key {} |
| 709 | lua_rawset( K, LUA_REGISTRYINDEX); // | 711 | lua_rawset( K, LUA_REGISTRYINDEX); // |
| 710 | 712 | ||
| @@ -754,13 +756,13 @@ void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode mode_) | |||
| 754 | { | 756 | { |
| 755 | if( lua_isnil( L, i)) | 757 | if( lua_isnil( L, i)) |
| 756 | { | 758 | { |
| 757 | lua_pushlightuserdata( L, NIL_SENTINEL); | 759 | push_unique_key( L, NIL_SENTINEL); |
| 758 | lua_replace( L, i); | 760 | lua_replace( L, i); |
| 759 | } | 761 | } |
| 760 | } | 762 | } |
| 761 | else | 763 | else |
| 762 | { | 764 | { |
| 763 | if( lua_touserdata( L, i) == NIL_SENTINEL) | 765 | if( equal_unique_key( L, i, NIL_SENTINEL)) |
| 764 | { | 766 | { |
| 765 | lua_pushnil( L); | 767 | lua_pushnil( L); |
| 766 | lua_replace( L, i); | 768 | 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 @@ | |||
| 3 | 3 | ||
| 4 | #include "lua.h" | 4 | #include "lua.h" |
| 5 | #include "threading.h" | 5 | #include "threading.h" |
| 6 | #include "uniquekey.h" | ||
| 6 | 7 | ||
| 7 | // forwards | 8 | // forwards |
| 8 | struct s_Universe; | 9 | struct s_Universe; |
| @@ -34,7 +35,8 @@ void keeper_release( Keeper* K); | |||
| 34 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_); | 35 | void keeper_toggle_nil_sentinels( lua_State* L, int val_i_, LookupMode const mode_); |
| 35 | int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); | 36 | int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t magic_); |
| 36 | 37 | ||
| 37 | #define NIL_SENTINEL ((void*)keeper_toggle_nil_sentinels) | 38 | // crc64/we of string "NIL_SENTINEL" generated at http://www.nitrxgen.net/hashgen/ |
| 39 | static DECLARE_CONST_UNIQUE_KEY( NIL_SENTINEL, 0x7eaafa003a1d11a1); | ||
| 38 | 40 | ||
| 39 | typedef lua_CFunction keeper_api_t; | 41 | typedef lua_CFunction keeper_api_t; |
| 40 | #define KEEPER_API( _op) keepercall_ ## _op | 42 | #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. | |||
| 93 | #include "tools.h" | 93 | #include "tools.h" |
| 94 | #include "universe.h" | 94 | #include "universe.h" |
| 95 | #include "keeper.h" | 95 | #include "keeper.h" |
| 96 | #include "uniquekey.h" | ||
| 96 | 97 | ||
| 97 | #if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) | 98 | #if !(defined( PLATFORM_XBOX) || defined( PLATFORM_WIN32) || defined( PLATFORM_POCKETPC)) |
| 98 | # include <sys/time.h> | 99 | # include <sys/time.h> |
| @@ -193,13 +194,15 @@ typedef struct s_Lane Lane; | |||
| 193 | // | 194 | // |
| 194 | #define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) | 195 | #define lua_toLane( L, i) (*((Lane**) luaL_checkudata( L, i, "Lane"))) |
| 195 | 196 | ||
| 196 | #define CANCEL_TEST_KEY ((void*)get_lane_from_registry) // used as registry key | 197 | // crc64/we of string "CANCEL_TEST_KEY" generated at http://www.nitrxgen.net/hashgen/ |
| 198 | static DECLARE_CONST_UNIQUE_KEY( CANCEL_TEST_KEY, 0xe66f5960c57d133a); // used as registry key | ||
| 199 | |||
| 197 | static inline Lane* get_lane_from_registry( lua_State* L) | 200 | static inline Lane* get_lane_from_registry( lua_State* L) |
| 198 | { | 201 | { |
| 199 | Lane* s; | 202 | Lane* s; |
| 200 | STACK_GROW( L, 1); | 203 | STACK_GROW( L, 1); |
| 201 | STACK_CHECK( L); | 204 | STACK_CHECK( L); |
| 202 | lua_pushlightuserdata( L, CANCEL_TEST_KEY); | 205 | push_unique_key( L, CANCEL_TEST_KEY); |
| 203 | lua_rawget( L, LUA_REGISTRYINDEX); | 206 | lua_rawget( L, LUA_REGISTRYINDEX); |
| 204 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil | 207 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil |
| 205 | lua_pop( L, 1); | 208 | lua_pop( L, 1); |
| @@ -238,11 +241,13 @@ static inline enum e_cancel_request cancel_test( lua_State* L) | |||
| 238 | return s ? s->cancel_request : CANCEL_NONE; | 241 | return s ? s->cancel_request : CANCEL_NONE; |
| 239 | } | 242 | } |
| 240 | 243 | ||
| 241 | #define CANCEL_ERROR ((void*)cancel_error) // 'cancel_error' sentinel | 244 | // crc64/we of string "CANCEL_ERROR" generated at http://www.nitrxgen.net/hashgen/ |
| 245 | static DECLARE_CONST_UNIQUE_KEY( CANCEL_ERROR, 0xe97d41626cc97577); // 'cancel_error' sentinel | ||
| 246 | |||
| 242 | static int cancel_error( lua_State* L) | 247 | static int cancel_error( lua_State* L) |
| 243 | { | 248 | { |
| 244 | STACK_GROW( L, 1); | 249 | STACK_GROW( L, 1); |
| 245 | lua_pushlightuserdata( L, CANCEL_ERROR); // special error value | 250 | push_unique_key( L, CANCEL_ERROR); // special error value |
| 246 | return lua_error( L); // doesn't return | 251 | return lua_error( L); // doesn't return |
| 247 | } | 252 | } |
| 248 | 253 | ||
| @@ -258,7 +263,8 @@ static void cancel_hook( lua_State* L, lua_Debug* ar) | |||
| 258 | 263 | ||
| 259 | #if ERROR_FULL_STACK | 264 | #if ERROR_FULL_STACK |
| 260 | static int lane_error( lua_State* L); | 265 | static int lane_error( lua_State* L); |
| 261 | #define STACK_TRACE_KEY ((void*)lane_error) // used as registry key | 266 | // crc64/we of string "STACK_TRACE_KEY" generated at http://www.nitrxgen.net/hashgen/ |
| 267 | static DECLARE_CONST_UNIQUE_KEY( STACK_TRACE_KEY, 0x024d5411677ce879); | ||
| 262 | #endif // ERROR_FULL_STACK | 268 | #endif // ERROR_FULL_STACK |
| 263 | 269 | ||
| 264 | /* | 270 | /* |
| @@ -463,7 +469,7 @@ LUAG_FUNC( linda_send) | |||
| 463 | int pushed; | 469 | int pushed; |
| 464 | time_d timeout = -1.0; | 470 | time_d timeout = -1.0; |
| 465 | uint_t key_i = 2; // index of first key, if timeout not there | 471 | uint_t key_i = 2; // index of first key, if timeout not there |
| 466 | void* as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided | 472 | bool_t as_nil_sentinel; // if not NULL, send() will silently send a single nil if nothing is provided |
| 467 | 473 | ||
| 468 | if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion | 474 | if( lua_type( L, 2) == LUA_TNUMBER) // we don't want to use lua_isnumber() because of autocoercion |
| 469 | { | 475 | { |
| @@ -475,8 +481,8 @@ LUAG_FUNC( linda_send) | |||
| 475 | ++ key_i; | 481 | ++ key_i; |
| 476 | } | 482 | } |
| 477 | 483 | ||
| 478 | as_nil_sentinel = lua_touserdata( L, key_i); | 484 | as_nil_sentinel = equal_unique_key( L, key_i, NIL_SENTINEL); |
| 479 | if( as_nil_sentinel == NIL_SENTINEL) | 485 | if( as_nil_sentinel) |
| 480 | { | 486 | { |
| 481 | // the real key to send data to is after the NIL_SENTINEL marker | 487 | // the real key to send data to is after the NIL_SENTINEL marker |
| 482 | ++ key_i; | 488 | ++ key_i; |
| @@ -490,10 +496,10 @@ LUAG_FUNC( linda_send) | |||
| 490 | // make sure there is something to send | 496 | // make sure there is something to send |
| 491 | if( (uint_t)lua_gettop( L) == key_i) | 497 | if( (uint_t)lua_gettop( L) == key_i) |
| 492 | { | 498 | { |
| 493 | if( as_nil_sentinel == NIL_SENTINEL) | 499 | if( as_nil_sentinel) |
| 494 | { | 500 | { |
| 495 | // send a single nil if nothing is provided | 501 | // send a single nil if nothing is provided |
| 496 | lua_pushlightuserdata( L, NIL_SENTINEL); | 502 | push_unique_key( L, NIL_SENTINEL); |
| 497 | } | 503 | } |
| 498 | else | 504 | else |
| 499 | { | 505 | { |
| @@ -584,7 +590,7 @@ LUAG_FUNC( linda_send) | |||
| 584 | { | 590 | { |
| 585 | case CANCEL_SOFT: | 591 | case CANCEL_SOFT: |
| 586 | // if user wants to soft-cancel, the call returns lanes.cancel_error | 592 | // if user wants to soft-cancel, the call returns lanes.cancel_error |
| 587 | lua_pushlightuserdata( L, CANCEL_ERROR); | 593 | push_unique_key( L, CANCEL_ERROR); |
| 588 | return 1; | 594 | return 1; |
| 589 | 595 | ||
| 590 | case CANCEL_HARD: | 596 | case CANCEL_HARD: |
| @@ -741,7 +747,7 @@ LUAG_FUNC( linda_receive) | |||
| 741 | { | 747 | { |
| 742 | case CANCEL_SOFT: | 748 | case CANCEL_SOFT: |
| 743 | // if user wants to soft-cancel, the call returns CANCEL_ERROR | 749 | // if user wants to soft-cancel, the call returns CANCEL_ERROR |
| 744 | lua_pushlightuserdata( L, CANCEL_ERROR); | 750 | push_unique_key( L, CANCEL_ERROR); |
| 745 | return 1; | 751 | return 1; |
| 746 | 752 | ||
| 747 | case CANCEL_HARD: | 753 | case CANCEL_HARD: |
| @@ -803,7 +809,7 @@ LUAG_FUNC( linda_set) | |||
| 803 | else // linda is cancelled | 809 | else // linda is cancelled |
| 804 | { | 810 | { |
| 805 | // do nothing and return lanes.cancel_error | 811 | // do nothing and return lanes.cancel_error |
| 806 | lua_pushlightuserdata( L, CANCEL_ERROR); | 812 | push_unique_key( L, CANCEL_ERROR); |
| 807 | pushed = 1; | 813 | pushed = 1; |
| 808 | } | 814 | } |
| 809 | keeper_release( K); | 815 | keeper_release( K); |
| @@ -871,7 +877,7 @@ LUAG_FUNC( linda_get) | |||
| 871 | else // linda is cancelled | 877 | else // linda is cancelled |
| 872 | { | 878 | { |
| 873 | // do nothing and return lanes.cancel_error | 879 | // do nothing and return lanes.cancel_error |
| 874 | lua_pushlightuserdata( L, CANCEL_ERROR); | 880 | push_unique_key( L, CANCEL_ERROR); |
| 875 | pushed = 1; | 881 | pushed = 1; |
| 876 | } | 882 | } |
| 877 | keeper_release( K); | 883 | keeper_release( K); |
| @@ -922,7 +928,7 @@ LUAG_FUNC( linda_limit) | |||
| 922 | else // linda is cancelled | 928 | else // linda is cancelled |
| 923 | { | 929 | { |
| 924 | // do nothing and return lanes.cancel_error | 930 | // do nothing and return lanes.cancel_error |
| 925 | lua_pushlightuserdata( L, CANCEL_ERROR); | 931 | push_unique_key( L, CANCEL_ERROR); |
| 926 | pushed = 1; | 932 | pushed = 1; |
| 927 | } | 933 | } |
| 928 | keeper_release( K); | 934 | keeper_release( K); |
| @@ -1249,7 +1255,7 @@ static void* linda_id( lua_State* L, enum eDeepOp op_) | |||
| 1249 | lua_pushliteral( L, BATCH_SENTINEL); | 1255 | lua_pushliteral( L, BATCH_SENTINEL); |
| 1250 | lua_setfield(L, -2, "batched"); | 1256 | lua_setfield(L, -2, "batched"); |
| 1251 | 1257 | ||
| 1252 | lua_pushlightuserdata( L, NIL_SENTINEL); | 1258 | push_unique_key( L, NIL_SENTINEL); |
| 1253 | lua_setfield(L, -2, "null"); | 1259 | lua_setfield(L, -2, "null"); |
| 1254 | 1260 | ||
| 1255 | luaG_pushdeepversion( L); | 1261 | luaG_pushdeepversion( L); |
| @@ -1815,7 +1821,8 @@ LUAG_FUNC( set_singlethreaded) | |||
| 1815 | */ | 1821 | */ |
| 1816 | #if ERROR_FULL_STACK | 1822 | #if ERROR_FULL_STACK |
| 1817 | 1823 | ||
| 1818 | # define EXTENDED_STACK_TRACE_KEY ((void*)LG_set_error_reporting) // used as registry key | 1824 | // crc64/we of string "EXTENDED_STACK_TRACE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ |
| 1825 | static DECLARE_CONST_UNIQUE_KEY( EXTENDED_STACK_TRACE_REGKEY, 0x7a59821071066e49); // used as registry key | ||
| 1819 | 1826 | ||
| 1820 | LUAG_FUNC( set_error_reporting) | 1827 | LUAG_FUNC( set_error_reporting) |
| 1821 | { | 1828 | { |
| @@ -1836,7 +1843,7 @@ LUAG_FUNC( set_error_reporting) | |||
| 1836 | return luaL_error( L, "unsupported error reporting model"); | 1843 | return luaL_error( L, "unsupported error reporting model"); |
| 1837 | } | 1844 | } |
| 1838 | done: | 1845 | done: |
| 1839 | lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); | 1846 | push_unique_key( L, EXTENDED_STACK_TRACE_REGKEY); |
| 1840 | lua_pushboolean( L, equal); | 1847 | lua_pushboolean( L, equal); |
| 1841 | lua_rawset( L, LUA_REGISTRYINDEX); | 1848 | lua_rawset( L, LUA_REGISTRYINDEX); |
| 1842 | return 0; | 1849 | return 0; |
| @@ -1853,13 +1860,13 @@ static int lane_error( lua_State* L) | |||
| 1853 | 1860 | ||
| 1854 | // Don't do stack survey for cancelled lanes. | 1861 | // Don't do stack survey for cancelled lanes. |
| 1855 | // | 1862 | // |
| 1856 | if( lua_touserdata( L, 1) == CANCEL_ERROR) | 1863 | if( equal_unique_key( L, 1, CANCEL_ERROR)) |
| 1857 | { | 1864 | { |
| 1858 | return 1; // just pass on | 1865 | return 1; // just pass on |
| 1859 | } | 1866 | } |
| 1860 | 1867 | ||
| 1861 | STACK_GROW( L, 3); | 1868 | STACK_GROW( L, 3); |
| 1862 | lua_pushlightuserdata( L, EXTENDED_STACK_TRACE_KEY); // some_error estk | 1869 | push_unique_key( L, EXTENDED_STACK_TRACE_REGKEY); // some_error estk |
| 1863 | lua_rawget( L, LUA_REGISTRYINDEX); // some_error basic|extended | 1870 | lua_rawget( L, LUA_REGISTRYINDEX); // some_error basic|extended |
| 1864 | extended = lua_toboolean( L, -1); | 1871 | extended = lua_toboolean( L, -1); |
| 1865 | lua_pop( L, 1); // some_error | 1872 | lua_pop( L, 1); // some_error |
| @@ -1913,7 +1920,7 @@ static int lane_error( lua_State* L) | |||
| 1913 | lua_rawseti( L, -2, (lua_Integer) n); // some_error {} | 1920 | lua_rawseti( L, -2, (lua_Integer) n); // some_error {} |
| 1914 | } | 1921 | } |
| 1915 | 1922 | ||
| 1916 | lua_pushlightuserdata( L, STACK_TRACE_KEY); // some_error {} stk | 1923 | push_unique_key( L, STACK_TRACE_KEY); // some_error {} stk |
| 1917 | lua_insert( L, -2); // some_error stk {} | 1924 | lua_insert( L, -2); // some_error stk {} |
| 1918 | lua_rawset( L, LUA_REGISTRYINDEX); // some_error | 1925 | lua_rawset( L, LUA_REGISTRYINDEX); // some_error |
| 1919 | 1926 | ||
| @@ -1936,14 +1943,14 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) | |||
| 1936 | { | 1943 | { |
| 1937 | // fetch the call stack table from the registry where the handler stored it | 1944 | // fetch the call stack table from the registry where the handler stored it |
| 1938 | STACK_GROW( L, 1); | 1945 | STACK_GROW( L, 1); |
| 1939 | lua_pushlightuserdata( L, STACK_TRACE_KEY); // err STACK_TRACE_KEY | 1946 | push_unique_key( L, STACK_TRACE_KEY); // err STACK_TRACE_KEY |
| 1940 | // yields nil if no stack was generated (in case of cancellation for example) | 1947 | // yields nil if no stack was generated (in case of cancellation for example) |
| 1941 | lua_rawget( L, LUA_REGISTRYINDEX); // err trace|nil | 1948 | lua_rawget( L, LUA_REGISTRYINDEX); // err trace|nil |
| 1942 | ASSERT_L( lua_gettop( L) == 1 + stk_base_); | 1949 | ASSERT_L( lua_gettop( L) == 1 + stk_base_); |
| 1943 | 1950 | ||
| 1944 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed | 1951 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed |
| 1945 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table | 1952 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table |
| 1946 | ASSERT_L( lua_type( L, 1 + stk_base_) == ((lua_touserdata( L, stk_base_) == CANCEL_ERROR) ? LUA_TNIL : LUA_TTABLE)); | 1953 | ASSERT_L( lua_type( L, 1 + stk_base_) == (equal_unique_key( L, stk_base_, CANCEL_ERROR) ? LUA_TNIL : LUA_TTABLE)); |
| 1947 | // Just leaving the stack trace table on the stack is enough to get it through to the master. | 1954 | // Just leaving the stack trace table on the stack is enough to get it through to the master. |
| 1948 | break; | 1955 | break; |
| 1949 | } | 1956 | } |
| @@ -1953,18 +1960,19 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) | |||
| 1953 | case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) | 1960 | case LUA_ERRERR: // error while running the error handler (if any, for example an out-of-memory condition) |
| 1954 | default: | 1961 | default: |
| 1955 | // we should have a single value which is either a string (the error message) or CANCEL_ERROR | 1962 | // we should have a single value which is either a string (the error message) or CANCEL_ERROR |
| 1956 | ASSERT_L( (lua_gettop( L) == stk_base_) && ((lua_type( L, stk_base_) == LUA_TSTRING) || (lua_touserdata( L, stk_base_) == CANCEL_ERROR))); | 1963 | ASSERT_L( (lua_gettop( L) == stk_base_) && ((lua_type( L, stk_base_) == LUA_TSTRING) || equal_unique_key( L, stk_base_, CANCEL_ERROR))); |
| 1957 | break; | 1964 | break; |
| 1958 | } | 1965 | } |
| 1959 | } | 1966 | } |
| 1960 | 1967 | ||
| 1961 | LUAG_FUNC( set_debug_threadname) | 1968 | LUAG_FUNC( set_debug_threadname) |
| 1962 | { | 1969 | { |
| 1970 | DECLARE_CONST_UNIQUE_KEY( hidden_regkey, LG_set_debug_threadname); | ||
| 1963 | // C s_lane structure is a light userdata upvalue | 1971 | // C s_lane structure is a light userdata upvalue |
| 1964 | Lane* s = lua_touserdata( L, lua_upvalueindex( 1)); | 1972 | Lane* s = lua_touserdata( L, lua_upvalueindex( 1)); |
| 1965 | luaL_checktype( L, -1, LUA_TSTRING); // "name" | 1973 | luaL_checktype( L, -1, LUA_TSTRING); // "name" |
| 1966 | // 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... | 1974 | // 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... |
| 1967 | lua_pushlightuserdata( L, LG_set_debug_threadname); // "name" lud | 1975 | push_unique_key( L, hidden_regkey); // "name" lud |
| 1968 | lua_pushvalue( L, -2); // "name" lud "name" | 1976 | lua_pushvalue( L, -2); // "name" lud "name" |
| 1969 | lua_rawset( L, LUA_REGISTRYINDEX); // "name" | 1977 | lua_rawset( L, LUA_REGISTRYINDEX); // "name" |
| 1970 | s->debug_name = lua_tostring( L, -1); | 1978 | s->debug_name = lua_tostring( L, -1); |
| @@ -2089,7 +2097,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) | |||
| 2089 | // in case of error and if it exists, fetch stack trace from registry and push it | 2097 | // in case of error and if it exists, fetch stack trace from registry and push it |
| 2090 | push_stack_trace( L, rc, 1); // retvals|error [trace] | 2098 | push_stack_trace( L, rc, 1); // retvals|error [trace] |
| 2091 | 2099 | ||
| 2092 | 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)))); | 2100 | 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)))); |
| 2093 | //STACK_DUMP(L); | 2101 | //STACK_DUMP(L); |
| 2094 | // Call finalizers, if the script has set them up. | 2102 | // Call finalizers, if the script has set them up. |
| 2095 | // | 2103 | // |
| @@ -2118,7 +2126,7 @@ static THREAD_RETURN_T THREAD_CALLCONV lane_main( void* vs) | |||
| 2118 | { | 2126 | { |
| 2119 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them | 2127 | // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them |
| 2120 | 2128 | ||
| 2121 | enum e_status st = (rc == 0) ? DONE : (lua_touserdata( L, 1) == CANCEL_ERROR) ? CANCELLED : ERROR_ST; | 2129 | enum e_status st = (rc == 0) ? DONE : equal_unique_key( L, 1, CANCEL_ERROR) ? CANCELLED : ERROR_ST; |
| 2122 | 2130 | ||
| 2123 | // Posix no PTHREAD_TIMEDJOIN: | 2131 | // Posix no PTHREAD_TIMEDJOIN: |
| 2124 | // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change | 2132 | // 'done_lock' protects the -> DONE|ERROR_ST|CANCELLED state change |
| @@ -2183,9 +2191,9 @@ LUAG_FUNC( register) | |||
| 2183 | return 0; | 2191 | return 0; |
| 2184 | } | 2192 | } |
| 2185 | 2193 | ||
| 2194 | // crc64/we of string "GCCB_KEY" generated at http://www.nitrxgen.net/hashgen/ | ||
| 2195 | static DECLARE_CONST_UNIQUE_KEY( GCCB_KEY, 0xcfb1f046ef074e88); | ||
| 2186 | 2196 | ||
| 2187 | LUAG_FUNC( thread_gc); | ||
| 2188 | #define GCCB_KEY (void*)LG_thread_gc | ||
| 2189 | //--- | 2197 | //--- |
| 2190 | // lane_ud = lane_new( function | 2198 | // lane_ud = lane_new( function |
| 2191 | // , [libs_str] | 2199 | // , [libs_str] |
| @@ -2429,7 +2437,7 @@ LUAG_FUNC( lane_new) | |||
| 2429 | // Store the gc_cb callback in the uservalue | 2437 | // Store the gc_cb callback in the uservalue |
| 2430 | if( gc_cb_idx > 0) | 2438 | if( gc_cb_idx > 0) |
| 2431 | { | 2439 | { |
| 2432 | lua_pushlightuserdata( L, GCCB_KEY); // func libs cancelstep priority globals package required gc_cb lane uv k | 2440 | push_unique_key( L, GCCB_KEY); // func libs cancelstep priority globals package required gc_cb lane uv k |
| 2433 | lua_pushvalue( L, gc_cb_idx); // func libs cancelstep priority globals package required gc_cb lane uv k gc_cb | 2441 | lua_pushvalue( L, gc_cb_idx); // func libs cancelstep priority globals package required gc_cb lane uv k gc_cb |
| 2434 | lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv | 2442 | lua_rawset( L, -3); // func libs cancelstep priority globals package required gc_cb lane uv |
| 2435 | } | 2443 | } |
| @@ -2437,7 +2445,7 @@ LUAG_FUNC( lane_new) | |||
| 2437 | lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane | 2445 | lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane |
| 2438 | 2446 | ||
| 2439 | // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). | 2447 | // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). |
| 2440 | lua_pushlightuserdata( L2, CANCEL_TEST_KEY); // func [... args ...] k | 2448 | push_unique_key( L2, CANCEL_TEST_KEY); // func [... args ...] k |
| 2441 | lua_pushlightuserdata( L2, s); // func [... args ...] k s | 2449 | lua_pushlightuserdata( L2, s); // func [... args ...] k s |
| 2442 | lua_rawset( L2, LUA_REGISTRYINDEX); // func [... args ...] | 2450 | lua_rawset( L2, LUA_REGISTRYINDEX); // func [... args ...] |
| 2443 | 2451 | ||
| @@ -2476,7 +2484,7 @@ LUAG_FUNC( thread_gc) | |||
| 2476 | 2484 | ||
| 2477 | // if there a gc callback? | 2485 | // if there a gc callback? |
| 2478 | lua_getuservalue( L, 1); // ud uservalue | 2486 | lua_getuservalue( L, 1); // ud uservalue |
| 2479 | lua_pushlightuserdata( L, GCCB_KEY); // ud uservalue __gc | 2487 | push_unique_key( L, GCCB_KEY); // ud uservalue __gc |
| 2480 | lua_rawget( L, -2); // ud uservalue gc_cb|nil | 2488 | lua_rawget( L, -2); // ud uservalue gc_cb|nil |
| 2481 | if( !lua_isnil( L, -1)) | 2489 | if( !lua_isnil( L, -1)) |
| 2482 | { | 2490 | { |
| @@ -3209,7 +3217,7 @@ LUAG_FUNC( configure) | |||
| 3209 | lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX | 3217 | lua_pushinteger(L, THREAD_PRIO_MAX); // settings M THREAD_PRIO_MAX |
| 3210 | lua_setfield( L, -2, "max_prio"); // settings M | 3218 | lua_setfield( L, -2, "max_prio"); // settings M |
| 3211 | 3219 | ||
| 3212 | lua_pushlightuserdata( L, CANCEL_ERROR); // settings M CANCEL_ERROR | 3220 | push_unique_key( L, CANCEL_ERROR); // settings M CANCEL_ERROR |
| 3213 | lua_setfield( L, -2, "cancel_error"); // settings M | 3221 | lua_setfield( L, -2, "cancel_error"); // settings M |
| 3214 | 3222 | ||
| 3215 | // we'll need this every time we transfer some C function from/to this state | 3223 | // 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. | |||
| 44 | #include "universe.h" | 44 | #include "universe.h" |
| 45 | #include "keeper.h" | 45 | #include "keeper.h" |
| 46 | #include "lanes.h" | 46 | #include "lanes.h" |
| 47 | #include "uniquekey.h" | ||
| 47 | 48 | ||
| 48 | // functions implemented in deep.c | 49 | // functions implemented in deep.c |
| 49 | extern luaG_IdFunction copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode mode_); | 50 | 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 | |||
| 977 | static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i) | 978 | static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, uint_t i) |
| 978 | { | 979 | { |
| 979 | bool_t not_found_in_cache; // L2 | 980 | bool_t not_found_in_cache; // L2 |
| 980 | void* const p = (void*)lua_topointer( L, i); | 981 | DECLARE_CONST_UNIQUE_KEY( p, lua_topointer( L, i)); |
| 981 | 982 | ||
| 982 | ASSERT_L( L2_cache_i != 0); | 983 | ASSERT_L( L2_cache_i != 0); |
| 983 | STACK_GROW( L2, 3); | 984 | 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, | |||
| 986 | // We don't need to use the from state ('L') in ID since the life span | 987 | // We don't need to use the from state ('L') in ID since the life span |
| 987 | // is only for the duration of a copy (both states are locked). | 988 | // is only for the duration of a copy (both states are locked). |
| 988 | // push a light userdata uniquely representing the table | 989 | // push a light userdata uniquely representing the table |
| 989 | lua_pushlightuserdata( L2, p); // ... p | 990 | push_unique_key( L2, p); // ... p |
| 990 | 991 | ||
| 991 | //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); | 992 | //fprintf( stderr, "<< ID: %s >>\n", lua_tostring( L2, -1)); |
| 992 | 993 | ||
| @@ -996,7 +997,7 @@ static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, | |||
| 996 | { | 997 | { |
| 997 | lua_pop( L2, 1); // ... | 998 | lua_pop( L2, 1); // ... |
| 998 | lua_newtable( L2); // ... {} | 999 | lua_newtable( L2); // ... {} |
| 999 | lua_pushlightuserdata( L2, p); // ... {} p | 1000 | push_unique_key( L2, p); // ... {} p |
| 1000 | lua_pushvalue( L2, -2); // ... {} p {} | 1001 | lua_pushvalue( L2, -2); // ... {} p {} |
| 1001 | lua_rawset( L2, L2_cache_i); // ... {} | 1002 | lua_rawset( L2, L2_cache_i); // ... {} |
| 1002 | } | 1003 | } |
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 @@ | |||
| 1 | #if !defined __LANES_UNIQUEKEY_H__ | ||
| 2 | #define __LANES_UNIQUEKEY_H__ 1 | ||
| 3 | |||
| 4 | #include "lualib.h" | ||
| 5 | |||
| 6 | // Lua light userdata can hold a pointer. | ||
| 7 | struct s_UniqueKey | ||
| 8 | { | ||
| 9 | void* value; | ||
| 10 | }; | ||
| 11 | typedef struct s_UniqueKey UniqueKey; | ||
| 12 | |||
| 13 | #if defined(LUA_JITLIBNAME) && (defined(__x86_64__) || defined(_M_X64)) // building against LuaJIT headers, light userdata is restricted to 47 significant bits. | ||
| 14 | #define MAKE_UNIQUE_KEY( p_) ((void*)(p_) & 0x7fffffffffffull) | ||
| 15 | #else // LUA_JITLIBNAME | ||
| 16 | #define MAKE_UNIQUE_KEY( p_) ((void*) p_) | ||
| 17 | #endif // LUA_JITLIBNAME | ||
| 18 | |||
| 19 | #define DECLARE_UNIQUE_KEY( name_) UniqueKey name_ | ||
| 20 | #define DECLARE_CONST_UNIQUE_KEY( name_, p_) UniqueKey const name_ = { MAKE_UNIQUE_KEY( p_)} | ||
| 21 | |||
| 22 | #define push_unique_key( L, key_) lua_pushlightuserdata( L, key_.value) | ||
| 23 | #define equal_unique_key( L, i, key_) (lua_touserdata( L, i) == key_.value) | ||
| 24 | |||
| 25 | #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. | |||
| 31 | #include "universe.h" | 31 | #include "universe.h" |
| 32 | #include "compat.h" | 32 | #include "compat.h" |
| 33 | #include "macros_and_utils.h" | 33 | #include "macros_and_utils.h" |
| 34 | #include "uniquekey.h" | ||
| 34 | 35 | ||
| 35 | // crc64/we of string "UNIVERSE_REGKEY" generated at https://www.nitrxgen.net/hashgen/ | 36 | // crc64/we of string "UNIVERSE_REGKEY" generated at http://www.nitrxgen.net/hashgen/ |
| 36 | static void* const UNIVERSE_REGKEY = ((void*)0x9f877b2cf078f17f); | 37 | static DECLARE_UNIQUE_KEY( UNIVERSE_REGKEY, 0x9f877b2cf078f17f); |
| 37 | 38 | ||
| 38 | // ################################################################################################ | 39 | // ################################################################################################ |
| 39 | 40 | ||
| @@ -41,7 +42,7 @@ Universe* universe_create( lua_State* L) | |||
| 41 | { | 42 | { |
| 42 | Universe* U = (Universe*) lua_newuserdata( L, sizeof(Universe)); // universe | 43 | Universe* U = (Universe*) lua_newuserdata( L, sizeof(Universe)); // universe |
| 43 | memset( U, 0, sizeof( Universe)); | 44 | memset( U, 0, sizeof( Universe)); |
| 44 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); // universe UNIVERSE_REGKEY | 45 | push_unique_key( L, UNIVERSE_REGKEY); // universe UNIVERSE_REGKEY |
| 45 | lua_pushvalue( L, -2); // universe UNIVERSE_REGKEY universe | 46 | lua_pushvalue( L, -2); // universe UNIVERSE_REGKEY universe |
| 46 | lua_rawset( L, LUA_REGISTRYINDEX); // universe | 47 | lua_rawset( L, LUA_REGISTRYINDEX); // universe |
| 47 | return U; | 48 | return U; |
| @@ -52,7 +53,7 @@ Universe* universe_create( lua_State* L) | |||
| 52 | void universe_store( lua_State* L, Universe* U) | 53 | void universe_store( lua_State* L, Universe* U) |
| 53 | { | 54 | { |
| 54 | STACK_CHECK( L); | 55 | STACK_CHECK( L); |
| 55 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); | 56 | push_unique_key( L, UNIVERSE_REGKEY); |
| 56 | lua_pushlightuserdata( L, U); | 57 | lua_pushlightuserdata( L, U); |
| 57 | lua_rawset( L, LUA_REGISTRYINDEX); | 58 | lua_rawset( L, LUA_REGISTRYINDEX); |
| 58 | STACK_END( L, 0); | 59 | STACK_END( L, 0); |
| @@ -65,7 +66,7 @@ Universe* universe_get( lua_State* L) | |||
| 65 | Universe* universe; | 66 | Universe* universe; |
| 66 | STACK_GROW( L, 2); | 67 | STACK_GROW( L, 2); |
| 67 | STACK_CHECK( L); | 68 | STACK_CHECK( L); |
| 68 | lua_pushlightuserdata( L, UNIVERSE_REGKEY); | 69 | push_unique_key( L, UNIVERSE_REGKEY); |
| 69 | lua_rawget( L, LUA_REGISTRYINDEX); | 70 | lua_rawget( L, LUA_REGISTRYINDEX); |
| 70 | universe = lua_touserdata( L, -1); // NULL if nil | 71 | universe = lua_touserdata( L, -1); // NULL if nil |
| 71 | lua_pop( L, 1); | 72 | lua_pop( L, 1); |
