diff options
| author | Benoit Germain <bnt.germain@gmail.com> | 2018-11-19 09:16:49 +0100 |
|---|---|---|
| committer | Benoit Germain <bnt.germain@gmail.com> | 2018-11-19 09:16:49 +0100 |
| commit | 7b4f59c5ebc84e426e2876906b24d7dd73342f07 (patch) | |
| tree | f05748fc2d75c43c25865be01677271fff5d86e4 /src | |
| parent | 01f83215a2ad235fbf306f591c6c0547b1bb7047 (diff) | |
| download | lanes-7b4f59c5ebc84e426e2876906b24d7dd73342f07.tar.gz lanes-7b4f59c5ebc84e426e2876906b24d7dd73342f07.tar.bz2 lanes-7b4f59c5ebc84e426e2876906b24d7dd73342f07.zip | |
Internal code tweaks
* Registry access code utility macros
* CONFIG_REGKEY and LOOKUP_REGKEY are now lightuserdata instead of strings
* Stack checking debug macros improvements
Diffstat (limited to 'src')
| -rw-r--r-- | src/deep.c | 39 | ||||
| -rw-r--r-- | src/keeper.c | 34 | ||||
| -rw-r--r-- | src/lanes.c | 62 | ||||
| -rw-r--r-- | src/lanes_private.h | 5 | ||||
| -rw-r--r-- | src/linda.c | 9 | ||||
| -rw-r--r-- | src/macros_and_utils.h | 68 | ||||
| -rw-r--r-- | src/tools.c | 107 | ||||
| -rw-r--r-- | src/tools.h | 11 | ||||
| -rw-r--r-- | src/universe.c | 25 |
9 files changed, 202 insertions, 158 deletions
| @@ -33,6 +33,7 @@ THE SOFTWARE. | |||
| 33 | */ | 33 | */ |
| 34 | 34 | ||
| 35 | #include <stdio.h> | 35 | #include <stdio.h> |
| 36 | #include <assert.h> | ||
| 36 | #include <string.h> | 37 | #include <string.h> |
| 37 | #include <ctype.h> | 38 | #include <ctype.h> |
| 38 | #include <stdlib.h> | 39 | #include <stdlib.h> |
| @@ -63,20 +64,18 @@ THE SOFTWARE. | |||
| 63 | static void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) | 64 | static void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) |
| 64 | { | 65 | { |
| 65 | STACK_GROW( L, 3); | 66 | STACK_GROW( L, 3); |
| 66 | STACK_CHECK( L); | 67 | STACK_CHECK( L, 0); |
| 67 | 68 | ||
| 68 | push_unique_key( L, key_); // key | 69 | REGISTRY_GET( L, key_); // {}|nil |
| 69 | lua_rawget( L, LUA_REGISTRYINDEX); // {}|nil | 70 | STACK_MID( L, 1); |
| 70 | 71 | ||
| 71 | if( lua_isnil( L, -1)) | 72 | if( lua_isnil( L, -1)) |
| 72 | { | 73 | { |
| 73 | lua_pop( L, 1); // | 74 | lua_pop( L, 1); // |
| 74 | lua_newtable( L); // {} | 75 | lua_newtable( L); // {} |
| 75 | push_unique_key( L, key_); // {} key | ||
| 76 | lua_pushvalue( L, -2); // {} key {} | ||
| 77 | |||
| 78 | // _R[key_] = {} | 76 | // _R[key_] = {} |
| 79 | lua_rawset( L, LUA_REGISTRYINDEX); // {} | 77 | REGISTRY_SET( L, key_, lua_pushvalue( L, -2)); // {} |
| 78 | STACK_MID( L, 1); | ||
| 80 | 79 | ||
| 81 | // Set its metatable if requested | 80 | // Set its metatable if requested |
| 82 | if( mode_) | 81 | if( mode_) |
| @@ -128,16 +127,16 @@ static DECLARE_CONST_UNIQUE_KEY( DEEP_PROXY_CACHE_KEY, 0x05773d6fc26be106); | |||
| 128 | static void set_deep_lookup( lua_State* L) | 127 | static void set_deep_lookup( lua_State* L) |
| 129 | { | 128 | { |
| 130 | STACK_GROW( L, 3); | 129 | STACK_GROW( L, 3); |
| 131 | STACK_CHECK( L); // a b | 130 | STACK_CHECK( L, 2); // a b |
| 132 | push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {} | 131 | push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {} |
| 133 | STACK_MID( L, 1); | 132 | STACK_MID( L, 3); |
| 134 | lua_insert( L, -3); // {} a b | 133 | lua_insert( L, -3); // {} a b |
| 135 | lua_pushvalue( L, -1); // {} a b b | 134 | lua_pushvalue( L, -1); // {} a b b |
| 136 | lua_pushvalue( L,-3); // {} a b b a | 135 | lua_pushvalue( L,-3); // {} a b b a |
| 137 | lua_rawset( L, -5); // {} a b | 136 | lua_rawset( L, -5); // {} a b |
| 138 | lua_rawset( L, -3); // {} | 137 | lua_rawset( L, -3); // {} |
| 139 | lua_pop( L, 1); // | 138 | lua_pop( L, 1); // |
| 140 | STACK_END( L, -2); | 139 | STACK_END( L, 0); |
| 141 | } | 140 | } |
| 142 | 141 | ||
| 143 | /* | 142 | /* |
| @@ -147,17 +146,15 @@ static void set_deep_lookup( lua_State* L) | |||
| 147 | static void get_deep_lookup( lua_State* L) | 146 | static void get_deep_lookup( lua_State* L) |
| 148 | { | 147 | { |
| 149 | STACK_GROW( L, 1); | 148 | STACK_GROW( L, 1); |
| 150 | STACK_CHECK( L); // a | 149 | STACK_CHECK( L, 1); // a |
| 151 | push_unique_key( L, DEEP_LOOKUP_KEY); // a DLK | 150 | REGISTRY_GET( L, DEEP_LOOKUP_KEY); // a {} |
| 152 | lua_rawget( L, LUA_REGISTRYINDEX); // a {} | ||
| 153 | |||
| 154 | if( !lua_isnil( L, -1)) | 151 | if( !lua_isnil( L, -1)) |
| 155 | { | 152 | { |
| 156 | lua_insert( L, -2); // {} a | 153 | lua_insert( L, -2); // {} a |
| 157 | lua_rawget( L, -2); // {} b | 154 | lua_rawget( L, -2); // {} b |
| 158 | } | 155 | } |
| 159 | lua_remove( L, -2); // a|b | 156 | lua_remove( L, -2); // a|b |
| 160 | STACK_END( L, 0); | 157 | STACK_END( L, 1); |
| 161 | } | 158 | } |
| 162 | 159 | ||
| 163 | /* | 160 | /* |
| @@ -180,7 +177,7 @@ static inline luaG_IdFunction get_idfunc( lua_State* L, int index, LookupMode mo | |||
| 180 | // of course, we could just trust the caller, but we won't | 177 | // of course, we could just trust the caller, but we won't |
| 181 | luaG_IdFunction ret; | 178 | luaG_IdFunction ret; |
| 182 | STACK_GROW( L, 1); | 179 | STACK_GROW( L, 1); |
| 183 | STACK_CHECK( L); | 180 | STACK_CHECK( L, 0); |
| 184 | 181 | ||
| 185 | if( !lua_getmetatable( L, index)) // deep ... metatable? | 182 | if( !lua_getmetatable( L, index)) // deep ... metatable? |
| 186 | { | 183 | { |
| @@ -284,7 +281,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
| 284 | if( U) MUTEX_UNLOCK( &U->deep_lock); | 281 | if( U) MUTEX_UNLOCK( &U->deep_lock); |
| 285 | 282 | ||
| 286 | STACK_GROW( L, 7); | 283 | STACK_GROW( L, 7); |
| 287 | STACK_CHECK( L); | 284 | STACK_CHECK( L, 0); |
| 288 | 285 | ||
| 289 | proxy = lua_newuserdata( L, sizeof(DeepPrelude*)); // DPC proxy | 286 | proxy = lua_newuserdata( L, sizeof(DeepPrelude*)); // DPC proxy |
| 290 | ASSERT_L( proxy); | 287 | ASSERT_L( proxy); |
| @@ -318,7 +315,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, Lo | |||
| 318 | lua_newtable( L); // DPC proxy metatable | 315 | lua_newtable( L); // DPC proxy metatable |
| 319 | lua_pushnil( L); // DPC proxy metatable nil | 316 | lua_pushnil( L); // DPC proxy metatable nil |
| 320 | } | 317 | } |
| 321 | if (lua_isnil(L, -1)) | 318 | if( lua_isnil( L, -1)) |
| 322 | { | 319 | { |
| 323 | // Add our own '__gc' method | 320 | // Add our own '__gc' method |
| 324 | lua_pop( L, 1); // DPC proxy metatable | 321 | lua_pop( L, 1); // DPC proxy metatable |
| @@ -438,9 +435,9 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction idfunc) | |||
| 438 | char const* errmsg; | 435 | char const* errmsg; |
| 439 | 436 | ||
| 440 | STACK_GROW( L, 1); | 437 | STACK_GROW( L, 1); |
| 441 | STACK_CHECK( L); | 438 | STACK_CHECK( L, 0); |
| 442 | { | 439 | { |
| 443 | int oldtop = lua_gettop( L); | 440 | int const oldtop = lua_gettop( L); |
| 444 | DeepPrelude* prelude = idfunc( L, eDO_new); | 441 | DeepPrelude* prelude = idfunc( L, eDO_new); |
| 445 | if( prelude == NULL) | 442 | if( prelude == NULL) |
| 446 | { | 443 | { |
| @@ -484,7 +481,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction idfunc, int index) | |||
| 484 | { | 481 | { |
| 485 | DeepPrelude** proxy; | 482 | DeepPrelude** proxy; |
| 486 | 483 | ||
| 487 | STACK_CHECK( L); | 484 | STACK_CHECK( L, 0); |
| 488 | // ensure it is actually a deep userdata | 485 | // ensure it is actually a deep userdata |
| 489 | if( get_idfunc( L, index, eLM_LaneBody) != idfunc) | 486 | if( get_idfunc( L, index, eLM_LaneBody) != idfunc) |
| 490 | { | 487 | { |
diff --git a/src/keeper.c b/src/keeper.c index 0471cb7..ae3e2a8 100644 --- a/src/keeper.c +++ b/src/keeper.c | |||
| @@ -166,10 +166,9 @@ static DECLARE_CONST_UNIQUE_KEY( FIFOS_KEY, 0xdce50bbc351cd465); | |||
| 166 | static void push_table( lua_State* L, int idx_) | 166 | static void push_table( lua_State* L, int idx_) |
| 167 | { | 167 | { |
| 168 | STACK_GROW( L, 4); | 168 | STACK_GROW( L, 4); |
| 169 | STACK_CHECK( L); | 169 | STACK_CHECK( L, 0); |
| 170 | idx_ = lua_absindex( L, idx_); | 170 | idx_ = lua_absindex( L, idx_); |
| 171 | push_unique_key( L, FIFOS_KEY); // ud fifos_key | 171 | REGISTRY_GET( L, FIFOS_KEY); // ud fifos |
| 172 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos | ||
| 173 | lua_pushvalue( L, idx_); // ud fifos ud | 172 | lua_pushvalue( L, idx_); // ud fifos ud |
| 174 | lua_rawget( L, -2); // ud fifos fifos[ud] | 173 | lua_rawget( L, -2); // ud fifos fifos[ud] |
| 175 | STACK_MID( L, 2); | 174 | STACK_MID( L, 2); |
| @@ -192,9 +191,8 @@ int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t | |||
| 192 | lua_State* const KL = K ? K->L : NULL; | 191 | lua_State* const KL = K ? K->L : NULL; |
| 193 | if( KL == NULL) return 0; | 192 | if( KL == NULL) return 0; |
| 194 | STACK_GROW( KL, 4); | 193 | STACK_GROW( KL, 4); |
| 195 | STACK_CHECK( KL); | 194 | STACK_CHECK( KL, 0); |
| 196 | push_unique_key( KL, FIFOS_KEY); // fifos_key | 195 | REGISTRY_GET( KL, FIFOS_KEY); // fifos |
| 197 | lua_rawget( KL, LUA_REGISTRYINDEX); // fifos | ||
| 198 | lua_pushlightuserdata( KL, ptr_); // fifos ud | 196 | lua_pushlightuserdata( KL, ptr_); // fifos ud |
| 199 | lua_rawget( KL, -2); // fifos storage | 197 | lua_rawget( KL, -2); // fifos storage |
| 200 | lua_remove( KL, -2); // storage | 198 | lua_remove( KL, -2); // storage |
| @@ -207,7 +205,7 @@ int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t | |||
| 207 | // move data from keeper to destination state KEEPER MAIN | 205 | // move data from keeper to destination state KEEPER MAIN |
| 208 | lua_pushnil( KL); // storage nil | 206 | lua_pushnil( KL); // storage nil |
| 209 | STACK_GROW( L, 5); | 207 | STACK_GROW( L, 5); |
| 210 | STACK_CHECK( L); | 208 | STACK_CHECK( L, 0); |
| 211 | lua_newtable( L); // out | 209 | lua_newtable( L); // out |
| 212 | while( lua_next( KL, -2)) // storage key fifo | 210 | while( lua_next( KL, -2)) // storage key fifo |
| 213 | { | 211 | { |
| @@ -240,12 +238,13 @@ int keeper_push_linda_storage( Universe* U, lua_State* L, void* ptr_, ptrdiff_t | |||
| 240 | int keepercall_clear( lua_State* L) | 238 | int keepercall_clear( lua_State* L) |
| 241 | { | 239 | { |
| 242 | STACK_GROW( L, 3); | 240 | STACK_GROW( L, 3); |
| 243 | push_unique_key( L, FIFOS_KEY); // ud fifos_key | 241 | STACK_CHECK( L, 0); |
| 244 | lua_rawget( L, LUA_REGISTRYINDEX); // ud fifos | 242 | REGISTRY_GET( L, FIFOS_KEY); // ud fifos |
| 245 | lua_pushvalue( L, 1); // ud fifos ud | 243 | lua_pushvalue( L, 1); // ud fifos ud |
| 246 | lua_pushnil( L); // ud fifos ud nil | 244 | lua_pushnil( L); // ud fifos ud nil |
| 247 | lua_rawset( L, -3); // ud fifos | 245 | lua_rawset( L, -3); // ud fifos |
| 248 | lua_pop( L, 1); // ud | 246 | lua_pop( L, 1); // ud |
| 247 | STACK_END( L, 0); | ||
| 249 | return 0; | 248 | return 0; |
| 250 | } | 249 | } |
| 251 | 250 | ||
| @@ -634,11 +633,14 @@ void init_keepers( Universe* U, lua_State* L) | |||
| 634 | void* allocUD; | 633 | void* allocUD; |
| 635 | lua_Alloc allocF = lua_getallocf( L, &allocUD); | 634 | lua_Alloc allocF = lua_getallocf( L, &allocUD); |
| 636 | 635 | ||
| 637 | STACK_CHECK( L); // L K | 636 | STACK_CHECK( L, 0); // L K |
| 638 | lua_getfield( L, 1, "nb_keepers"); // nb_keepers | 637 | lua_getfield( L, 1, "nb_keepers"); // nb_keepers |
| 639 | nb_keepers = (int) lua_tointeger( L, -1); | 638 | nb_keepers = (int) lua_tointeger( L, -1); |
| 640 | lua_pop( L, 1); // | 639 | lua_pop( L, 1); // |
| 641 | assert( nb_keepers >= 1); | 640 | if( nb_keepers < 1) |
| 641 | { | ||
| 642 | (void) luaL_error( L, "Bad number of keepers (%d)", nb_keepers); | ||
| 643 | } | ||
| 642 | 644 | ||
| 643 | // Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states | 645 | // Keepers contains an array of 1 s_Keeper, adjust for the actual number of keeper states |
| 644 | { | 646 | { |
| @@ -654,6 +656,7 @@ void init_keepers( Universe* U, lua_State* L) | |||
| 654 | } | 656 | } |
| 655 | for( i = 0; i < nb_keepers; ++ i) // keepersUD | 657 | for( i = 0; i < nb_keepers; ++ i) // keepersUD |
| 656 | { | 658 | { |
| 659 | // note that we will leak K if we raise an error later | ||
| 657 | lua_State* K = PROPAGATE_ALLOCF_ALLOC(); | 660 | lua_State* K = PROPAGATE_ALLOCF_ALLOC(); |
| 658 | if( K == NULL) | 661 | if( K == NULL) |
| 659 | { | 662 | { |
| @@ -667,10 +670,12 @@ void init_keepers( Universe* U, lua_State* L) | |||
| 667 | // therefore, we need a recursive mutex. | 670 | // therefore, we need a recursive mutex. |
| 668 | MUTEX_RECURSIVE_INIT( &U->keepers->keeper_array[i].keeper_cs); | 671 | MUTEX_RECURSIVE_INIT( &U->keepers->keeper_array[i].keeper_cs); |
| 669 | 672 | ||
| 673 | STACK_CHECK( K, 0); | ||
| 674 | |||
| 670 | // copy the universe pointer in the keeper itself | 675 | // copy the universe pointer in the keeper itself |
| 671 | universe_store( K, U); | 676 | universe_store( K, U); |
| 677 | STACK_MID( K, 0); | ||
| 672 | 678 | ||
| 673 | STACK_CHECK( K); | ||
| 674 | // make sure 'package' is initialized in keeper states, so that we have require() | 679 | // make sure 'package' is initialized in keeper states, so that we have require() |
| 675 | // this because this is needed when transferring deep userdata object | 680 | // this because this is needed when transferring deep userdata object |
| 676 | luaL_requiref( K, "package", luaopen_package, 1); // package | 681 | luaL_requiref( K, "package", luaopen_package, 1); // package |
| @@ -705,10 +710,7 @@ void init_keepers( Universe* U, lua_State* L) | |||
| 705 | lua_setglobal( K, "decoda_name"); // | 710 | lua_setglobal( K, "decoda_name"); // |
| 706 | 711 | ||
| 707 | // create the fifos table in the keeper state | 712 | // create the fifos table in the keeper state |
| 708 | push_unique_key( K, FIFOS_KEY); // fifo_key | 713 | REGISTRY_SET( K, FIFOS_KEY, lua_newtable( K)); |
| 709 | lua_newtable( K); // fifo_key {} | ||
| 710 | lua_rawset( K, LUA_REGISTRYINDEX); // | ||
| 711 | |||
| 712 | STACK_END( K, 0); | 714 | STACK_END( K, 0); |
| 713 | } | 715 | } |
| 714 | STACK_END( L, 0); | 716 | STACK_END( L, 0); |
diff --git a/src/lanes.c b/src/lanes.c index 037e44f..ae29af2 100644 --- a/src/lanes.c +++ b/src/lanes.c | |||
| @@ -114,7 +114,7 @@ THE SOFTWARE. | |||
| 114 | // intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed | 114 | // intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed |
| 115 | static void securize_debug_threadname( lua_State* L, Lane* s) | 115 | static void securize_debug_threadname( lua_State* L, Lane* s) |
| 116 | { | 116 | { |
| 117 | STACK_CHECK( L); | 117 | STACK_CHECK( L, 0); |
| 118 | STACK_GROW( L, 3); | 118 | STACK_GROW( L, 3); |
| 119 | lua_getuservalue( L, 1); | 119 | lua_getuservalue( L, 1); |
| 120 | lua_newtable( L); | 120 | lua_newtable( L); |
| @@ -196,10 +196,9 @@ struct s_Linda; | |||
| 196 | static bool_t push_registry_table( lua_State* L, UniqueKey key, bool_t create) | 196 | static bool_t push_registry_table( lua_State* L, UniqueKey key, bool_t create) |
| 197 | { | 197 | { |
| 198 | STACK_GROW( L, 3); | 198 | STACK_GROW( L, 3); |
| 199 | STACK_CHECK( L); | 199 | STACK_CHECK( L, 0); |
| 200 | push_unique_key( L, key); // key | ||
| 201 | lua_rawget( L, LUA_REGISTRYINDEX); // t? | ||
| 202 | 200 | ||
| 201 | REGISTRY_GET( L, key); // ? | ||
| 203 | if( lua_isnil( L, -1)) // nil? | 202 | if( lua_isnil( L, -1)) // nil? |
| 204 | { | 203 | { |
| 205 | lua_pop( L, 1); // | 204 | lua_pop( L, 1); // |
| @@ -1179,7 +1178,7 @@ LUAG_FUNC( require) | |||
| 1179 | char const* name = lua_tostring( L, 1); | 1178 | char const* name = lua_tostring( L, 1); |
| 1180 | int const nargs = lua_gettop( L); | 1179 | int const nargs = lua_gettop( L); |
| 1181 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 1180 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
| 1182 | STACK_CHECK( L); | 1181 | STACK_CHECK( L, 0); |
| 1183 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); | 1182 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); |
| 1184 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1183 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
| 1185 | lua_pushvalue( L, lua_upvalueindex(1)); // "name" require | 1184 | lua_pushvalue( L, lua_upvalueindex(1)); // "name" require |
| @@ -1204,7 +1203,7 @@ LUAG_FUNC( register) | |||
| 1204 | lua_settop( L, 2); | 1203 | lua_settop( L, 2); |
| 1205 | luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type"); | 1204 | luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type"); |
| 1206 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 1205 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
| 1207 | STACK_CHECK( L); // "name" mod_table | 1206 | STACK_CHECK( L, 0); // "name" mod_table |
| 1208 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); | 1207 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); |
| 1209 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1208 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
| 1210 | populate_func_lookup_table( L, -1, name); | 1209 | populate_func_lookup_table( L, -1, name); |
| @@ -1265,10 +1264,10 @@ LUAG_FUNC( lane_new) | |||
| 1265 | L2 = luaG_newstate( U, L, libs_str); // L // L2 | 1264 | L2 = luaG_newstate( U, L, libs_str); // L // L2 |
| 1266 | 1265 | ||
| 1267 | STACK_GROW( L2, nargs + 3); // | 1266 | STACK_GROW( L2, nargs + 3); // |
| 1268 | STACK_CHECK( L2); | 1267 | STACK_CHECK( L2, 0); |
| 1269 | 1268 | ||
| 1270 | STACK_GROW( L, 3); // func libs cancelstep priority globals package required gc_cb [... args ...] | 1269 | STACK_GROW( L, 3); // func libs cancelstep priority globals package required gc_cb [... args ...] |
| 1271 | STACK_CHECK( L); | 1270 | STACK_CHECK( L, 0); |
| 1272 | 1271 | ||
| 1273 | // give a default "Lua" name to the thread to see VM name in Decoda debugger | 1272 | // give a default "Lua" name to the thread to see VM name in Decoda debugger |
| 1274 | lua_pushfstring( L2, "Lane #%p", L2); // "..." | 1273 | lua_pushfstring( L2, "Lane #%p", L2); // "..." |
| @@ -1409,7 +1408,7 @@ LUAG_FUNC( lane_new) | |||
| 1409 | } | 1408 | } |
| 1410 | STACK_END( L, -nargs); | 1409 | STACK_END( L, -nargs); |
| 1411 | ASSERT_L( lua_gettop( L) == FIXED_ARGS); | 1410 | ASSERT_L( lua_gettop( L) == FIXED_ARGS); |
| 1412 | STACK_CHECK( L); | 1411 | STACK_CHECK( L, 0); |
| 1413 | STACK_MID( L2, 1 + nargs); | 1412 | STACK_MID( L2, 1 + nargs); |
| 1414 | 1413 | ||
| 1415 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) | 1414 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) |
| @@ -1463,9 +1462,7 @@ LUAG_FUNC( lane_new) | |||
| 1463 | lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane | 1462 | lua_setuservalue( L, -2); // func libs cancelstep priority globals package required gc_cb lane |
| 1464 | 1463 | ||
| 1465 | // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). | 1464 | // Store 's' in the lane's registry, for 'cancel_test()' (even if 'cs'==0 we still do cancel tests at pending send/receive). |
| 1466 | push_unique_key( L2, CANCEL_TEST_KEY); // func [... args ...] k | 1465 | REGISTRY_SET( L2, CANCEL_TEST_KEY, lua_pushlightuserdata( L2, s)); // func [... args ...] |
| 1467 | lua_pushlightuserdata( L2, s); // func [... args ...] k s | ||
| 1468 | lua_rawset( L2, LUA_REGISTRYINDEX); // func [... args ...] | ||
| 1469 | 1466 | ||
| 1470 | if( cancelstep_idx) | 1467 | if( cancelstep_idx) |
| 1471 | { | 1468 | { |
| @@ -1679,7 +1676,7 @@ LUAG_FUNC( thread_join) | |||
| 1679 | return 2; | 1676 | return 2; |
| 1680 | } | 1677 | } |
| 1681 | 1678 | ||
| 1682 | STACK_CHECK( L); | 1679 | STACK_CHECK( L, 0); |
| 1683 | // Thread is DONE/ERROR_ST/CANCELLED; all ours now | 1680 | // Thread is DONE/ERROR_ST/CANCELLED; all ours now |
| 1684 | 1681 | ||
| 1685 | if( s->mstatus == KILLED) // OS thread was killed if thread_cancel was forced | 1682 | if( s->mstatus == KILLED) // OS thread was killed if thread_cancel was forced |
| @@ -1961,7 +1958,7 @@ LUAG_FUNC( wakeup_conv ) | |||
| 1961 | // .yday (day of the year) | 1958 | // .yday (day of the year) |
| 1962 | // .isdst (daylight saving on/off) | 1959 | // .isdst (daylight saving on/off) |
| 1963 | 1960 | ||
| 1964 | STACK_CHECK( L); | 1961 | STACK_CHECK( L, 0); |
| 1965 | lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1); | 1962 | lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1); |
| 1966 | lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1); | 1963 | lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1); |
| 1967 | lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1); | 1964 | lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1); |
| @@ -1975,7 +1972,7 @@ LUAG_FUNC( wakeup_conv ) | |||
| 1975 | lua_getfield( L, 1, "isdst" ); | 1972 | lua_getfield( L, 1, "isdst" ); |
| 1976 | isdst= lua_isboolean(L,-1) ? lua_toboolean(L,-1) : -1; | 1973 | isdst= lua_isboolean(L,-1) ? lua_toboolean(L,-1) : -1; |
| 1977 | lua_pop(L,1); | 1974 | lua_pop(L,1); |
| 1978 | STACK_END( L, 0); | 1975 | STACK_END( L, 0); |
| 1979 | 1976 | ||
| 1980 | t.tm_year= year-1900; | 1977 | t.tm_year= year-1900; |
| 1981 | t.tm_mon= month-1; // 0..11 | 1978 | t.tm_mon= month-1; // 0..11 |
| @@ -2101,7 +2098,7 @@ LUAG_FUNC( configure) | |||
| 2101 | #endif // THREADAPI == THREADAPI_PTHREAD | 2098 | #endif // THREADAPI == THREADAPI_PTHREAD |
| 2102 | 2099 | ||
| 2103 | STACK_GROW( L, 4); | 2100 | STACK_GROW( L, 4); |
| 2104 | STACK_CHECK( L); | 2101 | STACK_CHECK_ABS( L, 1); // settings |
| 2105 | 2102 | ||
| 2106 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); | 2103 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); |
| 2107 | DEBUGSPEW_CODE( if( U) ++ U->debugspew_indent_depth); | 2104 | DEBUGSPEW_CODE( if( U) ++ U->debugspew_indent_depth); |
| @@ -2121,7 +2118,7 @@ LUAG_FUNC( configure) | |||
| 2121 | } | 2118 | } |
| 2122 | } | 2119 | } |
| 2123 | lua_pop( L, 1); // settings | 2120 | lua_pop( L, 1); // settings |
| 2124 | STACK_MID( L, 0); | 2121 | STACK_MID( L, 1); |
| 2125 | 2122 | ||
| 2126 | // grab or create the universe | 2123 | // grab or create the universe |
| 2127 | if( U == NULL) | 2124 | if( U == NULL) |
| @@ -2155,13 +2152,13 @@ LUAG_FUNC( configure) | |||
| 2155 | U->selfdestruct_first = SELFDESTRUCT_END; | 2152 | U->selfdestruct_first = SELFDESTRUCT_END; |
| 2156 | initialize_on_state_create( U, L); | 2153 | initialize_on_state_create( U, L); |
| 2157 | init_keepers( U, L); | 2154 | init_keepers( U, L); |
| 2158 | STACK_MID( L, 0); | 2155 | STACK_MID( L, 1); |
| 2159 | 2156 | ||
| 2160 | // Initialize 'timer_deep'; a common Linda object shared by all states | 2157 | // Initialize 'timer_deep'; a common Linda object shared by all states |
| 2161 | lua_pushcfunction( L, LG_linda); // settings lanes.linda | 2158 | lua_pushcfunction( L, LG_linda); // settings lanes.linda |
| 2162 | lua_pushliteral( L, "lanes-timer"); // settings lanes.linda "lanes-timer" | 2159 | lua_pushliteral( L, "lanes-timer"); // settings lanes.linda "lanes-timer" |
| 2163 | lua_call( L, 1, 1); // settings linda | 2160 | lua_call( L, 1, 1); // settings linda |
| 2164 | STACK_MID( L, 1); | 2161 | STACK_MID( L, 2); |
| 2165 | 2162 | ||
| 2166 | // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer | 2163 | // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer |
| 2167 | U->timer_deep = *(DeepPrelude**) lua_touserdata( L, -1); | 2164 | U->timer_deep = *(DeepPrelude**) lua_touserdata( L, -1); |
| @@ -2169,7 +2166,7 @@ LUAG_FUNC( configure) | |||
| 2169 | ++ U->timer_deep->refcount; | 2166 | ++ U->timer_deep->refcount; |
| 2170 | lua_pop( L, 1); // settings | 2167 | lua_pop( L, 1); // settings |
| 2171 | } | 2168 | } |
| 2172 | STACK_MID( L, 0); | 2169 | STACK_MID( L, 1); |
| 2173 | 2170 | ||
| 2174 | // Serialize calls to 'require' from now on, also in the primary state | 2171 | // Serialize calls to 'require' from now on, also in the primary state |
| 2175 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); | 2172 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); |
| @@ -2189,7 +2186,7 @@ LUAG_FUNC( configure) | |||
| 2189 | lua_setfield( L, -2, "threads"); // settings M | 2186 | lua_setfield( L, -2, "threads"); // settings M |
| 2190 | } | 2187 | } |
| 2191 | #endif // HAVE_LANE_TRACKING | 2188 | #endif // HAVE_LANE_TRACKING |
| 2192 | STACK_MID( L, 1); | 2189 | STACK_MID( L, 2); |
| 2193 | 2190 | ||
| 2194 | { | 2191 | { |
| 2195 | char const* errmsg; | 2192 | char const* errmsg; |
| @@ -2200,7 +2197,7 @@ LUAG_FUNC( configure) | |||
| 2200 | } | 2197 | } |
| 2201 | lua_setfield( L, -2, "timer_gateway"); // settings M | 2198 | lua_setfield( L, -2, "timer_gateway"); // settings M |
| 2202 | } | 2199 | } |
| 2203 | STACK_MID( L, 1); | 2200 | STACK_MID( L, 2); |
| 2204 | 2201 | ||
| 2205 | // prepare the metatable for threads | 2202 | // prepare the metatable for threads |
| 2206 | // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } | 2203 | // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } |
| @@ -2244,9 +2241,10 @@ LUAG_FUNC( configure) | |||
| 2244 | push_unique_key( L, CANCEL_ERROR); // settings M CANCEL_ERROR | 2241 | push_unique_key( L, CANCEL_ERROR); // settings M CANCEL_ERROR |
| 2245 | lua_setfield( L, -2, "cancel_error"); // settings M | 2242 | lua_setfield( L, -2, "cancel_error"); // settings M |
| 2246 | 2243 | ||
| 2244 | STACK_MID( L, 2); // reference stack contains only the function argument 'settings' | ||
| 2247 | // we'll need this every time we transfer some C function from/to this state | 2245 | // we'll need this every time we transfer some C function from/to this state |
| 2248 | lua_newtable( L); | 2246 | REGISTRY_SET( L, LOOKUP_REGKEY, lua_newtable( L)); |
| 2249 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); | 2247 | STACK_MID( L, 2); |
| 2250 | 2248 | ||
| 2251 | // register all native functions found in that module in the transferable functions database | 2249 | // register all native functions found in that module in the transferable functions database |
| 2252 | // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) | 2250 | // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) |
| @@ -2264,11 +2262,11 @@ LUAG_FUNC( configure) | |||
| 2264 | populate_func_lookup_table( L, -1, NULL); | 2262 | populate_func_lookup_table( L, -1, NULL); |
| 2265 | lua_pop( L, 1); // settings M | 2263 | lua_pop( L, 1); // settings M |
| 2266 | } | 2264 | } |
| 2267 | // set _R[CONFIG_REGKEY] = settings | 2265 | lua_pop( L, 1); // settings |
| 2268 | lua_pushvalue( L, -2); // settings M settings | 2266 | |
| 2269 | lua_setfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); // settings M | 2267 | // set _R[CONFIG_REGKEY] = settings |
| 2270 | lua_pop( L, 1); // settings | 2268 | REGISTRY_SET( L, CONFIG_REGKEY, lua_pushvalue( L, -2)); // -2 because CONFIG_REGKEY is pushed before the value itself |
| 2271 | STACK_END( L, 0); | 2269 | STACK_END( L, 1); |
| 2272 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); | 2270 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); |
| 2273 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2271 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
| 2274 | // Return the settings table | 2272 | // Return the settings table |
| @@ -2331,7 +2329,7 @@ int LANES_API luaopen_lanes_core( lua_State* L) | |||
| 2331 | #endif // defined PLATFORM_WIN32 && !defined NDEBUG | 2329 | #endif // defined PLATFORM_WIN32 && !defined NDEBUG |
| 2332 | 2330 | ||
| 2333 | STACK_GROW( L, 4); | 2331 | STACK_GROW( L, 4); |
| 2334 | STACK_CHECK( L); | 2332 | STACK_CHECK( L, 0); |
| 2335 | 2333 | ||
| 2336 | // Create main module interface table | 2334 | // Create main module interface table |
| 2337 | // we only have 1 closure, which must be called to configure Lanes | 2335 | // we only have 1 closure, which must be called to configure Lanes |
| @@ -2339,7 +2337,7 @@ int LANES_API luaopen_lanes_core( lua_State* L) | |||
| 2339 | lua_pushvalue( L, 1); // M "lanes.core" | 2337 | lua_pushvalue( L, 1); // M "lanes.core" |
| 2340 | lua_pushvalue( L, -2); // M "lanes.core" M | 2338 | lua_pushvalue( L, -2); // M "lanes.core" M |
| 2341 | lua_pushcclosure( L, LG_configure, 2); // M LG_configure() | 2339 | lua_pushcclosure( L, LG_configure, 2); // M LG_configure() |
| 2342 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); // M LG_configure() settings | 2340 | REGISTRY_GET( L, CONFIG_REGKEY); // M LG_configure() settings |
| 2343 | if( !lua_isnil( L, -1)) // this is not the first require "lanes.core": call configure() immediately | 2341 | if( !lua_isnil( L, -1)) // this is not the first require "lanes.core": call configure() immediately |
| 2344 | { | 2342 | { |
| 2345 | lua_pushvalue( L, -1); // M LG_configure() settings settings | 2343 | lua_pushvalue( L, -1); // M LG_configure() settings settings |
| @@ -2370,7 +2368,7 @@ static int default_luaopen_lanes( lua_State* L) | |||
| 2370 | // call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application | 2368 | // call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application |
| 2371 | void LANES_API luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes) | 2369 | void LANES_API luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes) |
| 2372 | { | 2370 | { |
| 2373 | STACK_CHECK( L); | 2371 | STACK_CHECK( L, 0); |
| 2374 | // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded | 2372 | // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded |
| 2375 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core | 2373 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core |
| 2376 | lua_pop( L, 1); // ... | 2374 | lua_pop( L, 1); // ... |
diff --git a/src/lanes_private.h b/src/lanes_private.h index 1adfa31..16c178d 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h | |||
| @@ -96,9 +96,8 @@ static inline Lane* get_lane_from_registry( lua_State* L) | |||
| 96 | { | 96 | { |
| 97 | Lane* s; | 97 | Lane* s; |
| 98 | STACK_GROW( L, 1); | 98 | STACK_GROW( L, 1); |
| 99 | STACK_CHECK( L); | 99 | STACK_CHECK( L, 0); |
| 100 | push_unique_key( L, CANCEL_TEST_KEY); | 100 | REGISTRY_GET( L, CANCEL_TEST_KEY); |
| 101 | lua_rawget( L, LUA_REGISTRYINDEX); | ||
| 102 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil | 101 | s = lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil |
| 103 | lua_pop( L, 1); | 102 | lua_pop( L, 1); |
| 104 | STACK_END( L, 0); | 103 | STACK_END( L, 0); |
diff --git a/src/linda.c b/src/linda.c index ee60ebc..4d1fa9f 100644 --- a/src/linda.c +++ b/src/linda.c | |||
| @@ -31,6 +31,7 @@ THE SOFTWARE. | |||
| 31 | */ | 31 | */ |
| 32 | 32 | ||
| 33 | #include <stdlib.h> | 33 | #include <stdlib.h> |
| 34 | #include <assert.h> | ||
| 34 | 35 | ||
| 35 | #include "threading.h" | 36 | #include "threading.h" |
| 36 | #include "compat.h" | 37 | #include "compat.h" |
| @@ -171,7 +172,7 @@ LUAG_FUNC( linda_send) | |||
| 171 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 172 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
| 172 | lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK' | 173 | lua_State* KL = K ? K->L : NULL; // need to do this for 'STACK_CHECK' |
| 173 | if( KL == NULL) return 0; | 174 | if( KL == NULL) return 0; |
| 174 | STACK_CHECK( KL); | 175 | STACK_CHECK( KL, 0); |
| 175 | for( ;;) | 176 | for( ;;) |
| 176 | { | 177 | { |
| 177 | if( s != NULL) | 178 | if( s != NULL) |
| @@ -832,7 +833,7 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
| 832 | case eDO_metatable: | 833 | case eDO_metatable: |
| 833 | { | 834 | { |
| 834 | 835 | ||
| 835 | STACK_CHECK( L); | 836 | STACK_CHECK( L, 0); |
| 836 | lua_newtable( L); | 837 | lua_newtable( L); |
| 837 | // metatable is its own index | 838 | // metatable is its own index |
| 838 | lua_pushvalue( L, -1); | 839 | lua_pushvalue( L, -1); |
| @@ -892,10 +893,10 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
| 892 | 893 | ||
| 893 | // some constants | 894 | // some constants |
| 894 | lua_pushliteral( L, BATCH_SENTINEL); | 895 | lua_pushliteral( L, BATCH_SENTINEL); |
| 895 | lua_setfield(L, -2, "batched"); | 896 | lua_setfield( L, -2, "batched"); |
| 896 | 897 | ||
| 897 | push_unique_key( L, NIL_SENTINEL); | 898 | push_unique_key( L, NIL_SENTINEL); |
| 898 | lua_setfield(L, -2, "null"); | 899 | lua_setfield( L, -2, "null"); |
| 899 | 900 | ||
| 900 | STACK_END( L, 1); | 901 | STACK_END( L, 1); |
| 901 | return NULL; | 902 | return NULL; |
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 550fc0a..acbe690 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
| @@ -46,26 +46,52 @@ extern char const* debugspew_indent; | |||
| 46 | 46 | ||
| 47 | #ifdef NDEBUG | 47 | #ifdef NDEBUG |
| 48 | 48 | ||
| 49 | #define _ASSERT_L(lua,c) /*nothing*/ | 49 | #define _ASSERT_L(lua,c) //nothing |
| 50 | #define STACK_CHECK(L) /*nothing*/ | 50 | #define STACK_CHECK(L,o) //nothing |
| 51 | #define STACK_MID(L,c) /*nothing*/ | 51 | #define STACK_CHECK_ABS(L,o) //nothing |
| 52 | #define STACK_END(L,c) /*nothing*/ | 52 | #define STACK_MID(L,c) //nothing |
| 53 | #define STACK_DUMP(L) /*nothing*/ | 53 | #define STACK_END(L,c) //nothing |
| 54 | #define STACK_DUMP(L) //nothing | ||
| 54 | 55 | ||
| 55 | #else // NDEBUG | 56 | #else // NDEBUG |
| 56 | 57 | ||
| 57 | #define _ASSERT_L( L, cond_) if( (cond_) == 0) { (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} | 58 | #define _ASSERT_L( L, cond_) if( (cond_) == 0) { (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} |
| 58 | 59 | ||
| 59 | #define STACK_CHECK(L) { int const _oldtop_##L = lua_gettop( L) | 60 | #define STACK_CHECK( L, offset_) \ |
| 60 | #define STACK_MID(L,change) \ | ||
| 61 | do \ | ||
| 62 | { \ | 61 | { \ |
| 63 | int stack_check_a = lua_gettop( L) - _oldtop_##L; \ | 62 | int const L##_delta = offset_; \ |
| 64 | int stack_check_b = (change); \ | 63 | if( (L##_delta < 0) || (lua_gettop( L) < L##_delta)) \ |
| 65 | if( stack_check_a != stack_check_b) \ | 64 | { \ |
| 66 | luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", stack_check_a, stack_check_b, __FILE__, __LINE__ ); \ | 65 | assert( FALSE); \ |
| 67 | } while( 0) | 66 | (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_delta, __FILE__, __LINE__); \ |
| 68 | #define STACK_END(L,change) STACK_MID(L,change); } | 67 | } \ |
| 68 | int const L##_oldtop = lua_gettop( L) - L##_delta | ||
| 69 | |||
| 70 | #define STACK_CHECK_ABS( L, offset_) \ | ||
| 71 | { \ | ||
| 72 | int const L##_pos = offset_; \ | ||
| 73 | if( lua_gettop( L) < L##_pos) \ | ||
| 74 | { \ | ||
| 75 | assert( FALSE); \ | ||
| 76 | (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_pos, __FILE__, __LINE__); \ | ||
| 77 | } \ | ||
| 78 | int const L##_oldtop = 0 | ||
| 79 | |||
| 80 | #define STACK_MID( L, change) \ | ||
| 81 | do \ | ||
| 82 | { \ | ||
| 83 | int stack_check_a = lua_gettop( L) - L##_oldtop; \ | ||
| 84 | int stack_check_b = (change); \ | ||
| 85 | if( stack_check_a != stack_check_b) \ | ||
| 86 | { \ | ||
| 87 | assert( FALSE); \ | ||
| 88 | luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", stack_check_a, stack_check_b, __FILE__, __LINE__); \ | ||
| 89 | } \ | ||
| 90 | } while( 0) | ||
| 91 | |||
| 92 | #define STACK_END( L, change) \ | ||
| 93 | STACK_MID( L, change); \ | ||
| 94 | } | ||
| 69 | 95 | ||
| 70 | #define STACK_DUMP( L) luaG_dump( L) | 96 | #define STACK_DUMP( L) luaG_dump( L) |
| 71 | 97 | ||
| @@ -75,4 +101,18 @@ extern char const* debugspew_indent; | |||
| 75 | 101 | ||
| 76 | #define STACK_GROW( L, n) do { if (!lua_checkstack(L,(int)(n))) luaL_error( L, "Cannot grow stack!" ); } while( 0) | 102 | #define STACK_GROW( L, n) do { if (!lua_checkstack(L,(int)(n))) luaL_error( L, "Cannot grow stack!" ); } while( 0) |
| 77 | 103 | ||
| 104 | // non-string keyed registry access | ||
| 105 | #define REGISTRY_SET( L, key_, value_) \ | ||
| 106 | { \ | ||
| 107 | push_unique_key( L, key_); \ | ||
| 108 | value_; \ | ||
| 109 | lua_rawset( L, LUA_REGISTRYINDEX); \ | ||
| 110 | } | ||
| 111 | |||
| 112 | #define REGISTRY_GET( L, key_) \ | ||
| 113 | { \ | ||
| 114 | push_unique_key( L, key_); \ | ||
| 115 | lua_rawget( L, LUA_REGISTRYINDEX); \ | ||
| 116 | } | ||
| 117 | |||
| 78 | #endif // MACROS_AND_UTILS_H | 118 | #endif // MACROS_AND_UTILS_H |
diff --git a/src/tools.c b/src/tools.c index 6f71dd8..e54e0c0 100644 --- a/src/tools.c +++ b/src/tools.c | |||
| @@ -32,6 +32,7 @@ THE SOFTWARE. | |||
| 32 | */ | 32 | */ |
| 33 | 33 | ||
| 34 | #include <stdio.h> | 34 | #include <stdio.h> |
| 35 | #include <assert.h> | ||
| 35 | #include <string.h> | 36 | #include <string.h> |
| 36 | #include <ctype.h> | 37 | #include <ctype.h> |
| 37 | #include <stdlib.h> | 38 | #include <stdlib.h> |
| @@ -50,14 +51,11 @@ THE SOFTWARE. | |||
| 50 | extern bool_t copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode mode_); | 51 | extern bool_t copydeep( Universe* U, lua_State* L, lua_State* L2, int index, LookupMode mode_); |
| 51 | extern void push_registry_subtable( lua_State* L, void* key_); | 52 | extern void push_registry_subtable( lua_State* L, void* key_); |
| 52 | 53 | ||
| 53 | char const* const CONFIG_REGKEY = "ee932492-a654-4506-9da8-f16540bdb5d4"; | ||
| 54 | char const* const LOOKUP_REGKEY = "ddea37aa-50c7-4d3f-8e0b-fb7a9d62bac5"; | ||
| 55 | |||
| 56 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); | 54 | DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!----+----!----+----!----+----!----+----!----+"); |
| 57 | 55 | ||
| 58 | 56 | ||
| 59 | /*---=== luaG_dump ===---*/ | 57 | /*---=== luaG_dump ===---*/ |
| 60 | 58 | #ifdef _DEBUG | |
| 61 | void luaG_dump( lua_State* L) | 59 | void luaG_dump( lua_State* L) |
| 62 | { | 60 | { |
| 63 | int top = lua_gettop( L); | 61 | int top = lua_gettop( L); |
| @@ -79,7 +77,7 @@ void luaG_dump( lua_State* L) | |||
| 79 | // Note: this requires 'tostring()' to be defined. If it is NOT, | 77 | // Note: this requires 'tostring()' to be defined. If it is NOT, |
| 80 | // enable it for more debugging. | 78 | // enable it for more debugging. |
| 81 | // | 79 | // |
| 82 | STACK_CHECK( L); | 80 | STACK_CHECK( L, 0); |
| 83 | STACK_GROW( L, 2); | 81 | STACK_GROW( L, 2); |
| 84 | 82 | ||
| 85 | lua_getglobal( L, "tostring"); | 83 | lua_getglobal( L, "tostring"); |
| @@ -105,10 +103,11 @@ void luaG_dump( lua_State* L) | |||
| 105 | } | 103 | } |
| 106 | fprintf( stderr, "\n"); | 104 | fprintf( stderr, "\n"); |
| 107 | } | 105 | } |
| 106 | #endif // _DEBUG | ||
| 108 | 107 | ||
| 109 | void initialize_on_state_create( Universe* U, lua_State* L) | 108 | void initialize_on_state_create( Universe* U, lua_State* L) |
| 110 | { | 109 | { |
| 111 | STACK_CHECK( L); | 110 | STACK_CHECK( L, 0); |
| 112 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil | 111 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil |
| 113 | if( !lua_isnil( L, -1)) | 112 | if( !lua_isnil( L, -1)) |
| 114 | { | 113 | { |
| @@ -142,14 +141,19 @@ void initialize_on_state_create( Universe* U, lua_State* L) | |||
| 142 | // just like lua_xmove, args are (from, to) | 141 | // just like lua_xmove, args are (from, to) |
| 143 | static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | 142 | static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) |
| 144 | { | 143 | { |
| 145 | STACK_GROW( L, 1); | 144 | STACK_GROW( L, 2); |
| 145 | STACK_CHECK( L, 0); | ||
| 146 | STACK_CHECK( L2, 0); | ||
| 147 | REGISTRY_GET( L, CONFIG_REGKEY); // config | ||
| 146 | // copy settings from from source to destination registry | 148 | // copy settings from from source to destination registry |
| 147 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); | 149 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // // config |
| 148 | if( luaG_inter_move( U, L, L2, 1, eLM_LaneBody) < 0) // error? | ||
| 149 | { | 150 | { |
| 150 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); | 151 | (void) luaL_error( L, "failed to copy settings when loading lanes.core"); |
| 151 | } | 152 | } |
| 152 | lua_setfield( L2, LUA_REGISTRYINDEX, CONFIG_REGKEY); | 153 | // set L2:_R[CONFIG_REGKEY] = settings |
| 154 | REGISTRY_SET( L2, CONFIG_REGKEY, lua_insert( L2, -2)); // | ||
| 155 | STACK_END( L2, 0); | ||
| 156 | STACK_END( L, 0); | ||
| 153 | } | 157 | } |
| 154 | 158 | ||
| 155 | 159 | ||
| @@ -212,7 +216,7 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con | |||
| 212 | { | 216 | { |
| 213 | bool_t const isLanesCore = (libfunc == require_lanes_core) ? TRUE : FALSE; // don't want to create a global for "lanes.core" | 217 | bool_t const isLanesCore = (libfunc == require_lanes_core) ? TRUE : FALSE; // don't want to create a global for "lanes.core" |
| 214 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); | 218 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); |
| 215 | STACK_CHECK( L); | 219 | STACK_CHECK( L, 0); |
| 216 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 220 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
| 217 | luaL_requiref( L, name_, libfunc, !isLanesCore); | 221 | luaL_requiref( L, name_, libfunc, !isLanesCore); |
| 218 | // lanes.core doesn't declare a global, so scan it here and now | 222 | // lanes.core doesn't declare a global, so scan it here and now |
| @@ -301,7 +305,7 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) | |||
| 301 | { | 305 | { |
| 302 | int i = 1; | 306 | int i = 1; |
| 303 | luaL_Buffer b; | 307 | luaL_Buffer b; |
| 304 | STACK_CHECK( L); | 308 | STACK_CHECK( L, 0); |
| 305 | luaL_buffinit( L, &b); | 309 | luaL_buffinit( L, &b); |
| 306 | for( ; i < last; ++ i) | 310 | for( ; i < last; ++ i) |
| 307 | { | 311 | { |
| @@ -339,7 +343,7 @@ static void update_lookup_entry( lua_State* L, int _ctx_base, int _depth) | |||
| 339 | DEBUGSPEW_CODE( char const *newName); | 343 | DEBUGSPEW_CODE( char const *newName); |
| 340 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 344 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
| 341 | 345 | ||
| 342 | STACK_CHECK( L); | 346 | STACK_CHECK( L, 0); |
| 343 | // first, raise an error if the function is already known | 347 | // first, raise an error if the function is already known |
| 344 | lua_pushvalue( L, -1); // ... {bfc} k o o | 348 | lua_pushvalue( L, -1); // ... {bfc} k o o |
| 345 | lua_rawget( L, dest); // ... {bfc} k o name? | 349 | lua_rawget( L, dest); // ... {bfc} k o name? |
| @@ -412,7 +416,7 @@ static void populate_func_lookup_table_recur( lua_State* L, int _ctx_base, int _ | |||
| 412 | 416 | ||
| 413 | STACK_GROW( L, 6); | 417 | STACK_GROW( L, 6); |
| 414 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) | 418 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) |
| 415 | STACK_CHECK( L); // ... {_i} | 419 | STACK_CHECK( L, 0); // ... {_i} |
| 416 | 420 | ||
| 417 | // if object is a userdata, replace it by its metatable | 421 | // if object is a userdata, replace it by its metatable |
| 418 | if( lua_type( L, _i) == LUA_TUSERDATA) | 422 | if( lua_type( L, _i) == LUA_TUSERDATA) |
| @@ -530,8 +534,9 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
| 530 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); | 534 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "NULL")); |
| 531 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 535 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
| 532 | STACK_GROW( L, 3); | 536 | STACK_GROW( L, 3); |
| 533 | STACK_CHECK( L); | 537 | STACK_CHECK( L, 0); |
| 534 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 538 | REGISTRY_GET( L, LOOKUP_REGKEY); // {} |
| 539 | STACK_MID( L, 1); | ||
| 535 | ASSERT_L( lua_istable( L, -1)); | 540 | ASSERT_L( lua_istable( L, -1)); |
| 536 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function | 541 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function |
| 537 | { | 542 | { |
| @@ -585,12 +590,12 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
| 585 | { | 590 | { |
| 586 | if( U->on_state_create_func != NULL) | 591 | if( U->on_state_create_func != NULL) |
| 587 | { | 592 | { |
| 588 | STACK_CHECK( L); | 593 | STACK_CHECK( L, 0); |
| 589 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 594 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
| 590 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) | 595 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) |
| 591 | { | 596 | { |
| 592 | // C function: recreate a closure in the new state, bypassing the lookup scheme | 597 | // C function: recreate a closure in the new state, bypassing the lookup scheme |
| 593 | lua_pushcfunction( L, U->on_state_create_func); | 598 | lua_pushcfunction( L, U->on_state_create_func); // on_state_create() |
| 594 | } | 599 | } |
| 595 | else // Lua function located in the config table, copied when we opened "lanes.core" | 600 | else // Lua function located in the config table, copied when we opened "lanes.core" |
| 596 | { | 601 | { |
| @@ -600,10 +605,12 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
| 600 | // this doesn't count as an error though | 605 | // this doesn't count as an error though |
| 601 | return; | 606 | return; |
| 602 | } | 607 | } |
| 603 | lua_getfield( L, LUA_REGISTRYINDEX, CONFIG_REGKEY); | 608 | REGISTRY_GET( L, CONFIG_REGKEY); // {} |
| 604 | lua_getfield( L, -1, "on_state_create"); | 609 | STACK_MID( L, 1); |
| 605 | lua_remove( L, -2); | 610 | lua_getfield( L, -1, "on_state_create"); // {} on_state_create() |
| 611 | lua_remove( L, -2); // on_state_create() | ||
| 606 | } | 612 | } |
| 613 | STACK_MID( L, 1); | ||
| 607 | // capture error and raise it in caller state | 614 | // capture error and raise it in caller state |
| 608 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 615 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) |
| 609 | { | 616 | { |
| @@ -640,16 +647,16 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
| 640 | } | 647 | } |
| 641 | 648 | ||
| 642 | STACK_GROW( L, 2); | 649 | STACK_GROW( L, 2); |
| 650 | STACK_CHECK_ABS( L, 0); | ||
| 643 | 651 | ||
| 644 | // copy the universe as a light userdata (only the master state holds the full userdata) | 652 | // copy the universe as a light userdata (only the master state holds the full userdata) |
| 645 | // that way, if Lanes is required in this new state, we'll know we are part of this universe | 653 | // that way, if Lanes is required in this new state, we'll know we are part of this universe |
| 646 | universe_store( L, U); | 654 | universe_store( L, U); |
| 647 | 655 | STACK_MID( L, 0); | |
| 648 | STACK_CHECK( L); | ||
| 649 | 656 | ||
| 650 | // we'll need this every time we transfer some C function from/to this state | 657 | // we'll need this every time we transfer some C function from/to this state |
| 651 | lua_newtable( L); | 658 | REGISTRY_SET( L, LOOKUP_REGKEY, lua_newtable( L)); |
| 652 | lua_setfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); | 659 | STACK_MID( L, 0); |
| 653 | 660 | ||
| 654 | // neither libs (not even 'base') nor special init func: we are done | 661 | // neither libs (not even 'base') nor special init func: we are done |
| 655 | if( libs_ == NULL && U->on_state_create_func == NULL) | 662 | if( libs_ == NULL && U->on_state_create_func == NULL) |
| @@ -724,7 +731,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
| 724 | // will raise an error in from_ in case of problem | 731 | // will raise an error in from_ in case of problem |
| 725 | call_on_state_create( U, L, from_, eLM_LaneBody); | 732 | call_on_state_create( U, L, from_, eLM_LaneBody); |
| 726 | 733 | ||
| 727 | STACK_CHECK( L); | 734 | STACK_CHECK( L, 0); |
| 728 | // after all this, register everything we find in our name<->function database | 735 | // after all this, register everything we find in our name<->function database |
| 729 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 736 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
| 730 | populate_func_lookup_table( L, -1, NULL); | 737 | populate_func_lookup_table( L, -1, NULL); |
| @@ -769,7 +776,7 @@ static uint_t get_mt_id( Universe* U, lua_State* L, int i) | |||
| 769 | 776 | ||
| 770 | STACK_GROW( L, 3); | 777 | STACK_GROW( L, 3); |
| 771 | 778 | ||
| 772 | STACK_CHECK( L); | 779 | STACK_CHECK( L, 0); |
| 773 | push_registry_subtable( L, REG_MTID); | 780 | push_registry_subtable( L, REG_MTID); |
| 774 | lua_pushvalue( L, i); | 781 | lua_pushvalue( L, i); |
| 775 | lua_rawget( L, -2); | 782 | lua_rawget( L, -2); |
| @@ -839,7 +846,7 @@ static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, c | |||
| 839 | DEBUGSPEW_CODE( Universe* const U = universe_get( L)); | 846 | DEBUGSPEW_CODE( Universe* const U = universe_get( L)); |
| 840 | char const* fqn; | 847 | char const* fqn; |
| 841 | ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... | 848 | ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... |
| 842 | STACK_CHECK( L); | 849 | STACK_CHECK( L, 0); |
| 843 | STACK_GROW( L, 3); // up to 3 slots are necessary on error | 850 | STACK_GROW( L, 3); // up to 3 slots are necessary on error |
| 844 | if( mode_ == eLM_FromKeeper) | 851 | if( mode_ == eLM_FromKeeper) |
| 845 | { | 852 | { |
| @@ -859,7 +866,8 @@ static char const* find_lookup_name( lua_State* L, uint_t i, LookupMode mode_, c | |||
| 859 | else | 866 | else |
| 860 | { | 867 | { |
| 861 | // fetch the name from the source state's lookup table | 868 | // fetch the name from the source state's lookup table |
| 862 | lua_getfield( L, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // ... v ... {} | 869 | REGISTRY_GET( L, LOOKUP_REGKEY); // ... v ... {} |
| 870 | STACK_MID( L, 1); | ||
| 863 | ASSERT_L( lua_istable( L, -1)); | 871 | ASSERT_L( lua_istable( L, -1)); |
| 864 | lua_pushvalue( L, i); // ... v ... {} v | 872 | lua_pushvalue( L, i); // ... v ... {} v |
| 865 | lua_rawget( L, -2); // ... v ... {} "f.q.n" | 873 | lua_rawget( L, -2); // ... v ... {} "f.q.n" |
| @@ -915,7 +923,7 @@ static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mo | |||
| 915 | return FALSE; | 923 | return FALSE; |
| 916 | } | 924 | } |
| 917 | // push the equivalent table in the destination's stack, retrieved from the lookup table | 925 | // push the equivalent table in the destination's stack, retrieved from the lookup table |
| 918 | STACK_CHECK( L2); // L // L2 | 926 | STACK_CHECK( L2, 0); // L // L2 |
| 919 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error | 927 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error |
| 920 | switch( mode_) | 928 | switch( mode_) |
| 921 | { | 929 | { |
| @@ -931,7 +939,8 @@ static bool_t lookup_table( lua_State* L2, lua_State* L, uint_t i, LookupMode mo | |||
| 931 | 939 | ||
| 932 | case eLM_LaneBody: | 940 | case eLM_LaneBody: |
| 933 | case eLM_FromKeeper: | 941 | case eLM_FromKeeper: |
| 934 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 942 | REGISTRY_GET( L2, LOOKUP_REGKEY); // {} |
| 943 | STACK_MID( L2, 1); | ||
| 935 | ASSERT_L( lua_istable( L2, -1)); | 944 | ASSERT_L( lua_istable( L2, -1)); |
| 936 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 945 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
| 937 | lua_rawget( L2, -2); // {} t | 946 | lua_rawget( L2, -2); // {} t |
| @@ -987,7 +996,7 @@ static bool_t push_cached_table( lua_State* L2, uint_t L2_cache_i, lua_State* L, | |||
| 987 | 996 | ||
| 988 | ASSERT_L( L2_cache_i != 0); | 997 | ASSERT_L( L2_cache_i != 0); |
| 989 | STACK_GROW( L2, 3); | 998 | STACK_GROW( L2, 3); |
| 990 | STACK_CHECK( L2); | 999 | STACK_CHECK( L2, 0); |
| 991 | 1000 | ||
| 992 | // We don't need to use the from state ('L') in ID since the life span | 1001 | // We don't need to use the from state ('L') in ID since the life span |
| 993 | // is only for the duration of a copy (both states are locked). | 1002 | // is only for the duration of a copy (both states are locked). |
| @@ -1027,7 +1036,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
| 1027 | return shortest_; | 1036 | return shortest_; |
| 1028 | } | 1037 | } |
| 1029 | STACK_GROW( L, 3); | 1038 | STACK_GROW( L, 3); |
| 1030 | STACK_CHECK( L); | 1039 | STACK_CHECK( L, 0); |
| 1031 | // stack top contains the table to search in | 1040 | // stack top contains the table to search in |
| 1032 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} | 1041 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} |
| 1033 | lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 | 1042 | lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 |
| @@ -1170,7 +1179,7 @@ int luaG_nameof( lua_State* L) | |||
| 1170 | } | 1179 | } |
| 1171 | 1180 | ||
| 1172 | STACK_GROW( L, 4); | 1181 | STACK_GROW( L, 4); |
| 1173 | STACK_CHECK( L); | 1182 | STACK_CHECK( L, 0); |
| 1174 | // this slot will contain the shortest name we found when we are done | 1183 | // this slot will contain the shortest name we found when we are done |
| 1175 | lua_pushnil( L); // o nil | 1184 | lua_pushnil( L); // o nil |
| 1176 | // push a cache that will contain all already visited tables | 1185 | // push a cache that will contain all already visited tables |
| @@ -1207,7 +1216,7 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, LookupMod | |||
| 1207 | size_t len; | 1216 | size_t len; |
| 1208 | char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); | 1217 | char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); |
| 1209 | // push the equivalent function in the destination's stack, retrieved from the lookup table | 1218 | // push the equivalent function in the destination's stack, retrieved from the lookup table |
| 1210 | STACK_CHECK( L2); // L // L2 | 1219 | STACK_CHECK( L2, 0); // L // L2 |
| 1211 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error | 1220 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error |
| 1212 | switch( mode_) | 1221 | switch( mode_) |
| 1213 | { | 1222 | { |
| @@ -1223,7 +1232,8 @@ static void lookup_native_func( lua_State* L2, lua_State* L, uint_t i, LookupMod | |||
| 1223 | 1232 | ||
| 1224 | case eLM_LaneBody: | 1233 | case eLM_LaneBody: |
| 1225 | case eLM_FromKeeper: | 1234 | case eLM_FromKeeper: |
| 1226 | lua_getfield( L2, LUA_REGISTRYINDEX, LOOKUP_REGKEY); // {} | 1235 | REGISTRY_GET( L2, LOOKUP_REGKEY); // {} |
| 1236 | STACK_MID( L2, 1); | ||
| 1227 | ASSERT_L( lua_istable( L2, -1)); | 1237 | ASSERT_L( lua_istable( L2, -1)); |
| 1228 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 1238 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
| 1229 | lua_rawget( L2, -2); // {} f | 1239 | lua_rawget( L2, -2); // {} f |
| @@ -1290,7 +1300,7 @@ static void inter_copy_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua_ | |||
| 1290 | luaL_Buffer b; | 1300 | luaL_Buffer b; |
| 1291 | ASSERT_L( L2_cache_i != 0); // ... {cache} ... p | 1301 | ASSERT_L( L2_cache_i != 0); // ... {cache} ... p |
| 1292 | STACK_GROW( L, 2); | 1302 | STACK_GROW( L, 2); |
| 1293 | STACK_CHECK( L); | 1303 | STACK_CHECK( L, 0); |
| 1294 | 1304 | ||
| 1295 | // 'lua_dump()' needs the function at top of stack | 1305 | // 'lua_dump()' needs the function at top of stack |
| 1296 | // if already on top of the stack, no need to push again | 1306 | // if already on top of the stack, no need to push again |
| @@ -1447,7 +1457,7 @@ static void push_cached_func( Universe* U, lua_State* L2, uint_t L2_cache_i, lua | |||
| 1447 | 1457 | ||
| 1448 | // L2_cache[id_str]= function | 1458 | // L2_cache[id_str]= function |
| 1449 | // | 1459 | // |
| 1450 | STACK_CHECK( L2); | 1460 | STACK_CHECK( L2, 0); |
| 1451 | 1461 | ||
| 1452 | // We don't need to use the from state ('L') in ID since the life span | 1462 | // We don't need to use the from state ('L') in ID since the life span |
| 1453 | // is only for the duration of a copy (both states are locked). | 1463 | // is only for the duration of a copy (both states are locked). |
| @@ -1492,7 +1502,7 @@ static bool_t push_cached_metatable( Universe* U, lua_State* L2, uint_t L2_cache | |||
| 1492 | { | 1502 | { |
| 1493 | uint_t const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable | 1503 | uint_t const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable |
| 1494 | 1504 | ||
| 1495 | STACK_CHECK( L2); | 1505 | STACK_CHECK( L2, 0); |
| 1496 | STACK_GROW( L2, 4); | 1506 | STACK_GROW( L2, 4); |
| 1497 | // do we already know this metatable? | 1507 | // do we already know this metatable? |
| 1498 | push_registry_subtable( L2, REG_MTID); // rst | 1508 | push_registry_subtable( L2, REG_MTID); // rst |
| @@ -1605,8 +1615,8 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
| 1605 | bool_t ret = TRUE; | 1615 | bool_t ret = TRUE; |
| 1606 | int val_type = lua_type( L, i); | 1616 | int val_type = lua_type( L, i); |
| 1607 | STACK_GROW( L2, 1); | 1617 | STACK_GROW( L2, 1); |
| 1608 | STACK_CHECK( L); // L // L2 | 1618 | STACK_CHECK( L, 0); // L // L2 |
| 1609 | STACK_CHECK( L2); // L // L2 | 1619 | STACK_CHECK( L2, 0); // L // L2 |
| 1610 | 1620 | ||
| 1611 | /* Skip the object if it has metatable with { __lanesignore = true } */ | 1621 | /* Skip the object if it has metatable with { __lanesignore = true } */ |
| 1612 | if( lua_getmetatable( L, i)) // ... mt | 1622 | if( lua_getmetatable( L, i)) // ... mt |
| @@ -1618,6 +1628,7 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
| 1618 | } | 1628 | } |
| 1619 | lua_pop( L, 2); // ... | 1629 | lua_pop( L, 2); // ... |
| 1620 | } | 1630 | } |
| 1631 | STACK_MID( L, 0); | ||
| 1621 | 1632 | ||
| 1622 | /* Lets push nil to L2 if the object should be ignored */ | 1633 | /* Lets push nil to L2 if the object should be ignored */ |
| 1623 | switch( val_type) | 1634 | switch( val_type) |
| @@ -1786,7 +1797,7 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
| 1786 | { | 1797 | { |
| 1787 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION %s\n" INDENT_END, upName_)); | 1798 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "FUNCTION %s\n" INDENT_END, upName_)); |
| 1788 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1799 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
| 1789 | STACK_CHECK( L2); | 1800 | STACK_CHECK( L2, 0); |
| 1790 | push_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_); | 1801 | push_cached_func( U, L2, L2_cache_i, L, i, mode_, upName_); |
| 1791 | STACK_END( L2, 1); | 1802 | STACK_END( L2, 1); |
| 1792 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1803 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
| @@ -1800,8 +1811,8 @@ static bool_t inter_copy_one_( Universe* U, lua_State* L2, uint_t L2_cache_i, lu | |||
| 1800 | break; | 1811 | break; |
| 1801 | } | 1812 | } |
| 1802 | { | 1813 | { |
| 1803 | STACK_CHECK( L); | 1814 | STACK_CHECK( L, 0); |
| 1804 | STACK_CHECK( L2); | 1815 | STACK_CHECK( L2, 0); |
| 1805 | 1816 | ||
| 1806 | /* | 1817 | /* |
| 1807 | * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) | 1818 | * First, let's try to see if this table is special (aka is it some table that we registered in our lookup databases during module registration?) |
| @@ -1943,8 +1954,8 @@ int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int packa | |||
| 1943 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); | 1954 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); |
| 1944 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1955 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
| 1945 | // package | 1956 | // package |
| 1946 | STACK_CHECK( L); | 1957 | STACK_CHECK( L, 0); |
| 1947 | STACK_CHECK( L2); | 1958 | STACK_CHECK( L2, 0); |
| 1948 | package_idx_ = lua_absindex( L, package_idx_); | 1959 | package_idx_ = lua_absindex( L, package_idx_); |
| 1949 | if( lua_type( L, package_idx_) != LUA_TTABLE) | 1960 | if( lua_type( L, package_idx_) != LUA_TTABLE) |
| 1950 | { | 1961 | { |
| @@ -2009,7 +2020,7 @@ int luaG_new_require( lua_State* L) | |||
| 2009 | //char const* modname = luaL_checkstring( L, 1); | 2020 | //char const* modname = luaL_checkstring( L, 1); |
| 2010 | 2021 | ||
| 2011 | STACK_GROW( L, args + 1); | 2022 | STACK_GROW( L, args + 1); |
| 2012 | STACK_CHECK( L); | 2023 | STACK_CHECK( L, 0); |
| 2013 | 2024 | ||
| 2014 | lua_pushvalue( L, lua_upvalueindex( 1)); | 2025 | lua_pushvalue( L, lua_upvalueindex( 1)); |
| 2015 | for( i = 1; i <= args; ++ i) | 2026 | for( i = 1; i <= args; ++ i) |
| @@ -2041,7 +2052,7 @@ int luaG_new_require( lua_State* L) | |||
| 2041 | void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) | 2052 | void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) |
| 2042 | { | 2053 | { |
| 2043 | STACK_GROW( L, 1); | 2054 | STACK_GROW( L, 1); |
| 2044 | STACK_CHECK( L); | 2055 | STACK_CHECK( L, 0); |
| 2045 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); | 2056 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); |
| 2046 | 2057 | ||
| 2047 | // Check 'require' is there and not already wrapped; if not, do nothing | 2058 | // Check 'require' is there and not already wrapped; if not, do nothing |
diff --git a/src/tools.h b/src/tools.h index 84e323c..ca0b9fc 100644 --- a/src/tools.h +++ b/src/tools.h | |||
| @@ -18,7 +18,9 @@ typedef struct s_Universe Universe; | |||
| 18 | #define luaG_optunsigned(L,i,d) ((uint_t) luaL_optinteger(L,i,d)) | 18 | #define luaG_optunsigned(L,i,d) ((uint_t) luaL_optinteger(L,i,d)) |
| 19 | #define luaG_tounsigned(L,i) ((uint_t) lua_tointeger(L,i)) | 19 | #define luaG_tounsigned(L,i) ((uint_t) lua_tointeger(L,i)) |
| 20 | 20 | ||
| 21 | void luaG_dump( lua_State* L ); | 21 | #ifdef _DEBUG |
| 22 | void luaG_dump( lua_State* L); | ||
| 23 | #endif // _DEBUG | ||
| 22 | 24 | ||
| 23 | lua_State* luaG_newstate( Universe* U, lua_State* _from, char const* libs); | 25 | lua_State* luaG_newstate( Universe* U, lua_State* _from, char const* libs); |
| 24 | 26 | ||
| @@ -39,7 +41,10 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
| 39 | 41 | ||
| 40 | // ################################################################################################ | 42 | // ################################################################################################ |
| 41 | 43 | ||
| 42 | extern char const* const CONFIG_REGKEY; | 44 | // crc64/we of string "CONFIG_REGKEY" generated at http://www.nitrxgen.net/hashgen/ |
| 43 | extern char const* const LOOKUP_REGKEY; | 45 | static DECLARE_CONST_UNIQUE_KEY( CONFIG_REGKEY, 0x31cd24894eae8624); // 'cancel_error' sentinel |
| 46 | |||
| 47 | // crc64/we of string "LOOKUP_REGKEY" generated at http://www.nitrxgen.net/hashgen/ | ||
| 48 | static DECLARE_CONST_UNIQUE_KEY( LOOKUP_REGKEY, 0x5051ed67ee7b51a1); // 'cancel_error' sentinel | ||
| 44 | 49 | ||
| 45 | #endif // __LANES_TOOLS_H__ | 50 | #endif // __LANES_TOOLS_H__ |
diff --git a/src/universe.c b/src/universe.c index 4689a09..d531bf2 100644 --- a/src/universe.c +++ b/src/universe.c | |||
| @@ -29,6 +29,7 @@ THE SOFTWARE. | |||
| 29 | */ | 29 | */ |
| 30 | 30 | ||
| 31 | #include <string.h> | 31 | #include <string.h> |
| 32 | #include <assert.h> | ||
| 32 | 33 | ||
| 33 | #include "universe.h" | 34 | #include "universe.h" |
| 34 | #include "compat.h" | 35 | #include "compat.h" |
| @@ -44,9 +45,9 @@ Universe* universe_create( lua_State* L) | |||
| 44 | { | 45 | { |
| 45 | Universe* U = (Universe*) lua_newuserdata( L, sizeof(Universe)); // universe | 46 | Universe* U = (Universe*) lua_newuserdata( L, sizeof(Universe)); // universe |
| 46 | memset( U, 0, sizeof( Universe)); | 47 | memset( U, 0, sizeof( Universe)); |
| 47 | push_unique_key( L, UNIVERSE_REGKEY); // universe UNIVERSE_REGKEY | 48 | STACK_CHECK( L, 1); |
| 48 | lua_pushvalue( L, -2); // universe UNIVERSE_REGKEY universe | 49 | REGISTRY_SET( L, UNIVERSE_REGKEY, lua_pushvalue(L, -2)); // universe |
| 49 | lua_rawset( L, LUA_REGISTRYINDEX); // universe | 50 | STACK_END( L, 1); |
| 50 | return U; | 51 | return U; |
| 51 | } | 52 | } |
| 52 | 53 | ||
| @@ -54,17 +55,8 @@ Universe* universe_create( lua_State* L) | |||
| 54 | 55 | ||
| 55 | void universe_store( lua_State* L, Universe* U) | 56 | void universe_store( lua_State* L, Universe* U) |
| 56 | { | 57 | { |
| 57 | STACK_CHECK( L); | 58 | STACK_CHECK( L, 0); |
| 58 | push_unique_key( L, UNIVERSE_REGKEY); | 59 | REGISTRY_SET( L, UNIVERSE_REGKEY, (NULL != U) ? lua_pushlightuserdata( L, U) : lua_pushnil( L)); |
| 59 | if( NULL != U) | ||
| 60 | { | ||
| 61 | lua_pushlightuserdata( L, U); | ||
| 62 | } | ||
| 63 | else | ||
| 64 | { | ||
| 65 | lua_pushnil( L); | ||
| 66 | } | ||
| 67 | lua_rawset( L, LUA_REGISTRYINDEX); | ||
| 68 | STACK_END( L, 0); | 60 | STACK_END( L, 0); |
| 69 | } | 61 | } |
| 70 | 62 | ||
| @@ -74,9 +66,8 @@ Universe* universe_get( lua_State* L) | |||
| 74 | { | 66 | { |
| 75 | Universe* universe; | 67 | Universe* universe; |
| 76 | STACK_GROW( L, 2); | 68 | STACK_GROW( L, 2); |
| 77 | STACK_CHECK( L); | 69 | STACK_CHECK( L, 0); |
| 78 | push_unique_key( L, UNIVERSE_REGKEY); | 70 | REGISTRY_GET( L, UNIVERSE_REGKEY); |
| 79 | lua_rawget( L, LUA_REGISTRYINDEX); | ||
| 80 | universe = lua_touserdata( L, -1); // NULL if nil | 71 | universe = lua_touserdata( L, -1); // NULL if nil |
| 81 | lua_pop( L, 1); | 72 | lua_pop( L, 1); |
| 82 | STACK_END( L, 0); | 73 | STACK_END( L, 0); |
