diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-03-25 10:43:25 +0100 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-03-25 10:43:25 +0100 |
commit | 0c060e6e4b9f99dc887b5dfebdae76fcde9524f1 (patch) | |
tree | 2ba9a1923e3e983375e33aa5f41d9fbc21451832 /src | |
parent | dad1d5fbf7c7a30caea00694de608c6036789aa5 (diff) | |
download | lanes-0c060e6e4b9f99dc887b5dfebdae76fcde9524f1.tar.gz lanes-0c060e6e4b9f99dc887b5dfebdae76fcde9524f1.tar.bz2 lanes-0c060e6e4b9f99dc887b5dfebdae76fcde9524f1.zip |
C++ migration: revamped stack checking macros
Diffstat (limited to 'src')
-rw-r--r-- | src/deep.cpp | 41 | ||||
-rw-r--r-- | src/keeper.cpp | 46 | ||||
-rw-r--r-- | src/lanes.cpp | 107 | ||||
-rw-r--r-- | src/lanes_private.h | 7 | ||||
-rw-r--r-- | src/linda.cpp | 16 | ||||
-rw-r--r-- | src/macros_and_utils.h | 116 | ||||
-rw-r--r-- | src/state.cpp | 76 | ||||
-rw-r--r-- | src/tools.cpp | 252 | ||||
-rw-r--r-- | src/universe.cpp | 18 |
9 files changed, 359 insertions, 320 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index 1aab6ed..cd5a844 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -74,16 +74,16 @@ static constexpr UniqueKey DEEP_PROXY_CACHE_KEY{ 0x05773d6fc26be106ull }; | |||
74 | static void set_deep_lookup( lua_State* L) | 74 | static void set_deep_lookup( lua_State* L) |
75 | { | 75 | { |
76 | STACK_GROW( L, 3); | 76 | STACK_GROW( L, 3); |
77 | STACK_CHECK( L, 2); // a b | 77 | STACK_CHECK_START_REL(L, 2); // a b |
78 | push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {} | 78 | push_registry_subtable( L, DEEP_LOOKUP_KEY); // a b {} |
79 | STACK_MID( L, 3); | 79 | STACK_CHECK( L, 3); |
80 | lua_insert( L, -3); // {} a b | 80 | lua_insert( L, -3); // {} a b |
81 | lua_pushvalue( L, -1); // {} a b b | 81 | lua_pushvalue( L, -1); // {} a b b |
82 | lua_pushvalue( L,-3); // {} a b b a | 82 | lua_pushvalue( L,-3); // {} a b b a |
83 | lua_rawset( L, -5); // {} a b | 83 | lua_rawset( L, -5); // {} a b |
84 | lua_rawset( L, -3); // {} | 84 | lua_rawset( L, -3); // {} |
85 | lua_pop( L, 1); // | 85 | lua_pop( L, 1); // |
86 | STACK_END( L, 0); | 86 | STACK_CHECK( L, 0); |
87 | } | 87 | } |
88 | 88 | ||
89 | /* | 89 | /* |
@@ -93,7 +93,7 @@ static void set_deep_lookup( lua_State* L) | |||
93 | static void get_deep_lookup( lua_State* L) | 93 | static void get_deep_lookup( lua_State* L) |
94 | { | 94 | { |
95 | STACK_GROW( L, 1); | 95 | STACK_GROW( L, 1); |
96 | STACK_CHECK( L, 1); // a | 96 | STACK_CHECK_START_REL(L, 1); // a |
97 | DEEP_LOOKUP_KEY.query_registry(L); // a {} | 97 | DEEP_LOOKUP_KEY.query_registry(L); // a {} |
98 | if( !lua_isnil( L, -1)) | 98 | if( !lua_isnil( L, -1)) |
99 | { | 99 | { |
@@ -101,7 +101,7 @@ static void get_deep_lookup( lua_State* L) | |||
101 | lua_rawget( L, -2); // {} b | 101 | lua_rawget( L, -2); // {} b |
102 | } | 102 | } |
103 | lua_remove( L, -2); // a|b | 103 | lua_remove( L, -2); // a|b |
104 | STACK_END( L, 1); | 104 | STACK_CHECK( L, 1); |
105 | } | 105 | } |
106 | 106 | ||
107 | /* | 107 | /* |
@@ -122,9 +122,8 @@ static inline luaG_IdFunction* get_idfunc( lua_State* L, int index, LookupMode m | |||
122 | // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/idfunc database | 122 | // essentially we are making sure that the metatable of the object we want to copy is stored in our metatable/idfunc database |
123 | // it is the only way to ensure that the userdata is indeed a deep userdata! | 123 | // it is the only way to ensure that the userdata is indeed a deep userdata! |
124 | // of course, we could just trust the caller, but we won't | 124 | // of course, we could just trust the caller, but we won't |
125 | luaG_IdFunction* ret; | ||
126 | STACK_GROW( L, 1); | 125 | STACK_GROW( L, 1); |
127 | STACK_CHECK( L, 0); | 126 | STACK_CHECK_START_REL(L, 0); |
128 | 127 | ||
129 | if( !lua_getmetatable( L, index)) // deep ... metatable? | 128 | if( !lua_getmetatable( L, index)) // deep ... metatable? |
130 | { | 129 | { |
@@ -134,9 +133,9 @@ static inline luaG_IdFunction* get_idfunc( lua_State* L, int index, LookupMode m | |||
134 | // replace metatable with the idfunc pointer, if it is actually a deep userdata | 133 | // replace metatable with the idfunc pointer, if it is actually a deep userdata |
135 | get_deep_lookup( L); // deep ... idfunc|nil | 134 | get_deep_lookup( L); // deep ... idfunc|nil |
136 | 135 | ||
137 | ret = (luaG_IdFunction*) lua_touserdata( L, -1); // nullptr if not a userdata | 136 | luaG_IdFunction* const ret{ static_cast<luaG_IdFunction*>(lua_touserdata(L, -1)) }; // nullptr if not a userdata |
138 | lua_pop( L, 1); | 137 | lua_pop( L, 1); |
139 | STACK_END( L, 0); | 138 | STACK_CHECK( L, 0); |
140 | return ret; | 139 | return ret; |
141 | } | 140 | } |
142 | } | 141 | } |
@@ -228,7 +227,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in | |||
228 | if( U) MUTEX_UNLOCK( &U->deep_lock); | 227 | if( U) MUTEX_UNLOCK( &U->deep_lock); |
229 | 228 | ||
230 | STACK_GROW( L, 7); | 229 | STACK_GROW( L, 7); |
231 | STACK_CHECK( L, 0); | 230 | STACK_CHECK_START_REL(L, 0); |
232 | 231 | ||
233 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) | 232 | // a new full userdata, fitted with the specified number of uservalue slots (always 1 for Lua < 5.4) |
234 | proxy = (DeepPrelude**) lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy | 233 | proxy = (DeepPrelude**) lua_newuserdatauv( L, sizeof(DeepPrelude*), nuv_); // DPC proxy |
@@ -340,7 +339,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in | |||
340 | } | 339 | } |
341 | } | 340 | } |
342 | } | 341 | } |
343 | STACK_MID( L, 2); // DPC proxy metatable | 342 | STACK_CHECK( L, 2); // DPC proxy metatable |
344 | ASSERT_L( lua_isuserdata( L, -2)); | 343 | ASSERT_L( lua_isuserdata( L, -2)); |
345 | ASSERT_L( lua_istable( L, -1)); | 344 | ASSERT_L( lua_istable( L, -1)); |
346 | lua_setmetatable( L, -2); // DPC proxy | 345 | lua_setmetatable( L, -2); // DPC proxy |
@@ -351,7 +350,7 @@ char const* push_deep_proxy( Universe* U, lua_State* L, DeepPrelude* prelude, in | |||
351 | lua_rawset( L, -4); // DPC proxy | 350 | lua_rawset( L, -4); // DPC proxy |
352 | lua_remove( L, -2); // proxy | 351 | lua_remove( L, -2); // proxy |
353 | ASSERT_L( lua_isuserdata( L, -1)); | 352 | ASSERT_L( lua_isuserdata( L, -1)); |
354 | STACK_END( L, 0); | 353 | STACK_CHECK( L, 0); |
355 | return nullptr; | 354 | return nullptr; |
356 | } | 355 | } |
357 | 356 | ||
@@ -382,7 +381,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction* idfunc, int nuv_) | |||
382 | char const* errmsg; | 381 | char const* errmsg; |
383 | 382 | ||
384 | STACK_GROW( L, 1); | 383 | STACK_GROW( L, 1); |
385 | STACK_CHECK( L, 0); | 384 | STACK_CHECK_START_REL(L, 0); |
386 | { | 385 | { |
387 | int const oldtop = lua_gettop( L); | 386 | int const oldtop = lua_gettop( L); |
388 | DeepPrelude* prelude = (DeepPrelude*) idfunc( L, eDO_new); | 387 | DeepPrelude* prelude = (DeepPrelude*) idfunc( L, eDO_new); |
@@ -413,7 +412,7 @@ int luaG_newdeepuserdata( lua_State* L, luaG_IdFunction* idfunc, int nuv_) | |||
413 | return luaL_error( L, errmsg); | 412 | return luaL_error( L, errmsg); |
414 | } | 413 | } |
415 | } | 414 | } |
416 | STACK_END( L, 1); | 415 | STACK_CHECK( L, 1); |
417 | return 1; | 416 | return 1; |
418 | } | 417 | } |
419 | 418 | ||
@@ -428,7 +427,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction* idfunc, int index) | |||
428 | { | 427 | { |
429 | DeepPrelude** proxy; | 428 | DeepPrelude** proxy; |
430 | 429 | ||
431 | STACK_CHECK( L, 0); | 430 | STACK_CHECK_START_REL(L, 0); |
432 | // ensure it is actually a deep userdata | 431 | // ensure it is actually a deep userdata |
433 | if( get_idfunc( L, index, eLM_LaneBody) != idfunc) | 432 | if( get_idfunc( L, index, eLM_LaneBody) != idfunc) |
434 | { | 433 | { |
@@ -436,7 +435,7 @@ void* luaG_todeep( lua_State* L, luaG_IdFunction* idfunc, int index) | |||
436 | } | 435 | } |
437 | 436 | ||
438 | proxy = (DeepPrelude**) lua_touserdata( L, index); | 437 | proxy = (DeepPrelude**) lua_touserdata( L, index); |
439 | STACK_END( L, 0); | 438 | STACK_CHECK( L, 0); |
440 | 439 | ||
441 | return *proxy; | 440 | return *proxy; |
442 | } | 441 | } |
@@ -460,8 +459,8 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L | |||
460 | return false; // not a deep userdata | 459 | return false; // not a deep userdata |
461 | } | 460 | } |
462 | 461 | ||
463 | STACK_CHECK( L, 0); | 462 | STACK_CHECK_START_REL(L, 0); |
464 | STACK_CHECK( L2, 0); | 463 | STACK_CHECK_START_REL(L2, 0); |
465 | 464 | ||
466 | // extract all uservalues of the source | 465 | // extract all uservalues of the source |
467 | while( lua_getiuservalue( L, i, nuv + 1) != LUA_TNONE) // ... u [uv]* nil | 466 | while( lua_getiuservalue( L, i, nuv + 1) != LUA_TNONE) // ... u [uv]* nil |
@@ -470,7 +469,7 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L | |||
470 | } | 469 | } |
471 | // last call returned TNONE and pushed nil, that we don't need | 470 | // last call returned TNONE and pushed nil, that we don't need |
472 | lua_pop( L, 1); // ... u [uv]* | 471 | lua_pop( L, 1); // ... u [uv]* |
473 | STACK_MID( L, nuv); | 472 | STACK_CHECK( L, nuv); |
474 | 473 | ||
475 | errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u | 474 | errmsg = push_deep_proxy( U, L2, *(DeepPrelude**) lua_touserdata( L, i), nuv, mode_); // u |
476 | 475 | ||
@@ -487,8 +486,8 @@ bool copydeep(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, L | |||
487 | } | 486 | } |
488 | } | 487 | } |
489 | 488 | ||
490 | STACK_END( L2, 1); | 489 | STACK_CHECK( L2, 1); |
491 | STACK_END( L, 0); | 490 | STACK_CHECK( L, 0); |
492 | 491 | ||
493 | if (errmsg != nullptr) | 492 | if (errmsg != nullptr) |
494 | { | 493 | { |
diff --git a/src/keeper.cpp b/src/keeper.cpp index 0cb1a94..19f6ae1 100644 --- a/src/keeper.cpp +++ b/src/keeper.cpp | |||
@@ -170,12 +170,12 @@ static constexpr UniqueKey FIFOS_KEY{ 0xdce50bbc351cd465ull }; | |||
170 | static void push_table(lua_State* L, int idx_) | 170 | static void push_table(lua_State* L, int idx_) |
171 | { | 171 | { |
172 | STACK_GROW(L, 4); | 172 | STACK_GROW(L, 4); |
173 | STACK_CHECK(L, 0); | 173 | STACK_CHECK_START_REL(L, 0); |
174 | idx_ = lua_absindex(L, idx_); | 174 | idx_ = lua_absindex(L, idx_); |
175 | FIFOS_KEY.query_registry(L); // ud fifos | 175 | FIFOS_KEY.query_registry(L); // ud fifos |
176 | lua_pushvalue(L, idx_); // ud fifos ud | 176 | lua_pushvalue(L, idx_); // ud fifos ud |
177 | lua_rawget(L, -2); // ud fifos fifos[ud] | 177 | lua_rawget(L, -2); // ud fifos fifos[ud] |
178 | STACK_MID(L, 2); | 178 | STACK_CHECK(L, 2); |
179 | if (lua_isnil(L, -1)) | 179 | if (lua_isnil(L, -1)) |
180 | { | 180 | { |
181 | lua_pop(L, 1); // ud fifos | 181 | lua_pop(L, 1); // ud fifos |
@@ -186,7 +186,7 @@ static void push_table(lua_State* L, int idx_) | |||
186 | lua_rawset(L, -4); // ud fifos fifos[ud] | 186 | lua_rawset(L, -4); // ud fifos fifos[ud] |
187 | } | 187 | } |
188 | lua_remove(L, -2); // ud fifos[ud] | 188 | lua_remove(L, -2); // ud fifos[ud] |
189 | STACK_END(L, 1); | 189 | STACK_CHECK(L, 1); |
190 | } | 190 | } |
191 | 191 | ||
192 | // ################################################################################################## | 192 | // ################################################################################################## |
@@ -197,7 +197,7 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t m | |||
197 | lua_State* const KL = K ? K->L : nullptr; | 197 | lua_State* const KL = K ? K->L : nullptr; |
198 | if( KL == nullptr) return 0; | 198 | if( KL == nullptr) return 0; |
199 | STACK_GROW(KL, 4); | 199 | STACK_GROW(KL, 4); |
200 | STACK_CHECK(KL, 0); | 200 | STACK_CHECK_START_REL(KL, 0); |
201 | FIFOS_KEY.query_registry(KL); // fifos | 201 | FIFOS_KEY.query_registry(KL); // fifos |
202 | lua_pushlightuserdata(KL, ptr_); // fifos ud | 202 | lua_pushlightuserdata(KL, ptr_); // fifos ud |
203 | lua_rawget(KL, -2); // fifos storage | 203 | lua_rawget(KL, -2); // fifos storage |
@@ -205,38 +205,38 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t m | |||
205 | if( !lua_istable(KL, -1)) | 205 | if( !lua_istable(KL, -1)) |
206 | { | 206 | { |
207 | lua_pop(KL, 1); // | 207 | lua_pop(KL, 1); // |
208 | STACK_MID(KL, 0); | 208 | STACK_CHECK(KL, 0); |
209 | return 0; | 209 | return 0; |
210 | } | 210 | } |
211 | // move data from keeper to destination state KEEPER MAIN | 211 | // move data from keeper to destination state KEEPER MAIN |
212 | lua_pushnil(KL); // storage nil | 212 | lua_pushnil(KL); // storage nil |
213 | STACK_GROW(L, 5); | 213 | STACK_GROW(L, 5); |
214 | STACK_CHECK(L, 0); | 214 | STACK_CHECK_START_REL(L, 0); |
215 | lua_newtable(L); // out | 215 | lua_newtable(L); // out |
216 | while( lua_next(KL, -2)) // storage key fifo | 216 | while( lua_next(KL, -2)) // storage key fifo |
217 | { | 217 | { |
218 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifo | 218 | keeper_fifo* fifo = prepare_fifo_access(KL, -1); // storage key fifo |
219 | lua_pushvalue(KL, -2); // storage key fifo key | 219 | lua_pushvalue(KL, -2); // storage key fifo key |
220 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key | 220 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key fifo // out key |
221 | STACK_MID(L, 2); | 221 | STACK_CHECK(L, 2); |
222 | lua_newtable(L); // out key keyout | 222 | lua_newtable(L); // out key keyout |
223 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo | 223 | luaG_inter_move(U, KL, L, 1, eLM_FromKeeper); // storage key // out key keyout fifo |
224 | lua_pushinteger(L, fifo->first); // out key keyout fifo first | 224 | lua_pushinteger(L, fifo->first); // out key keyout fifo first |
225 | STACK_MID(L, 5); | 225 | STACK_CHECK(L, 5); |
226 | lua_setfield(L, -3, "first"); // out key keyout fifo | 226 | lua_setfield(L, -3, "first"); // out key keyout fifo |
227 | lua_pushinteger(L, fifo->count); // out key keyout fifo count | 227 | lua_pushinteger(L, fifo->count); // out key keyout fifo count |
228 | STACK_MID(L, 5); | 228 | STACK_CHECK(L, 5); |
229 | lua_setfield(L, -3, "count"); // out key keyout fifo | 229 | lua_setfield(L, -3, "count"); // out key keyout fifo |
230 | lua_pushinteger(L, fifo->limit); // out key keyout fifo limit | 230 | lua_pushinteger(L, fifo->limit); // out key keyout fifo limit |
231 | STACK_MID(L, 5); | 231 | STACK_CHECK(L, 5); |
232 | lua_setfield(L, -3, "limit"); // out key keyout fifo | 232 | lua_setfield(L, -3, "limit"); // out key keyout fifo |
233 | lua_setfield(L, -2, "fifo"); // out key keyout | 233 | lua_setfield(L, -2, "fifo"); // out key keyout |
234 | lua_rawset(L, -3); // out | 234 | lua_rawset(L, -3); // out |
235 | STACK_MID(L, 1); | 235 | STACK_CHECK(L, 1); |
236 | } | 236 | } |
237 | STACK_END(L, 1); | 237 | STACK_CHECK(L, 1); |
238 | lua_pop(KL, 1); // | 238 | lua_pop(KL, 1); // |
239 | STACK_END(KL, 0); | 239 | STACK_CHECK(KL, 0); |
240 | return 1; | 240 | return 1; |
241 | } | 241 | } |
242 | 242 | ||
@@ -246,13 +246,13 @@ int keeper_push_linda_storage(Universe* U, lua_State* L, void* ptr_, ptrdiff_t m | |||
246 | int keepercall_clear(lua_State* L) | 246 | int keepercall_clear(lua_State* L) |
247 | { | 247 | { |
248 | STACK_GROW(L, 3); | 248 | STACK_GROW(L, 3); |
249 | STACK_CHECK(L, 0); | 249 | STACK_CHECK_START_REL(L, 0); |
250 | FIFOS_KEY.query_registry(L); // ud fifos | 250 | FIFOS_KEY.query_registry(L); // ud fifos |
251 | lua_pushvalue(L, 1); // ud fifos ud | 251 | lua_pushvalue(L, 1); // ud fifos ud |
252 | lua_pushnil(L); // ud fifos ud nil | 252 | lua_pushnil(L); // ud fifos ud nil |
253 | lua_rawset(L, -3); // ud fifos | 253 | lua_rawset(L, -3); // ud fifos |
254 | lua_pop(L, 1); // ud | 254 | lua_pop(L, 1); // ud |
255 | STACK_END(L, 0); | 255 | STACK_CHECK(L, 0); |
256 | return 0; | 256 | return 0; |
257 | } | 257 | } |
258 | 258 | ||
@@ -637,7 +637,7 @@ void close_keepers(Universe* U) | |||
637 | */ | 637 | */ |
638 | void init_keepers(Universe* U, lua_State* L) | 638 | void init_keepers(Universe* U, lua_State* L) |
639 | { | 639 | { |
640 | STACK_CHECK(L, 0); // L K | 640 | STACK_CHECK_START_REL(L, 0); // L K |
641 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers | 641 | lua_getfield(L, 1, "nb_keepers"); // nb_keepers |
642 | int nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; | 642 | int nb_keepers{ static_cast<int>(lua_tointeger(L, -1)) }; |
643 | lua_pop(L, 1); // | 643 | lua_pop(L, 1); // |
@@ -677,19 +677,19 @@ void init_keepers(Universe* U, lua_State* L) | |||
677 | // therefore, we need a recursive mutex. | 677 | // therefore, we need a recursive mutex. |
678 | MUTEX_RECURSIVE_INIT(&U->keepers->keeper_array[i].keeper_cs); | 678 | MUTEX_RECURSIVE_INIT(&U->keepers->keeper_array[i].keeper_cs); |
679 | 679 | ||
680 | STACK_CHECK(K, 0); | 680 | STACK_CHECK_START_ABS(K, 0); |
681 | 681 | ||
682 | // copy the universe pointer in the keeper itself | 682 | // copy the universe pointer in the keeper itself |
683 | universe_store(K, U); | 683 | universe_store(K, U); |
684 | STACK_MID(K, 0); | 684 | STACK_CHECK(K, 0); |
685 | 685 | ||
686 | // make sure 'package' is initialized in keeper states, so that we have require() | 686 | // make sure 'package' is initialized in keeper states, so that we have require() |
687 | // this because this is needed when transferring deep userdata object | 687 | // this because this is needed when transferring deep userdata object |
688 | luaL_requiref(K, "package", luaopen_package, 1); // package | 688 | luaL_requiref(K, "package", luaopen_package, 1); // package |
689 | lua_pop(K, 1); // | 689 | lua_pop(K, 1); // |
690 | STACK_MID(K, 0); | 690 | STACK_CHECK(K, 0); |
691 | serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); | 691 | serialize_require(DEBUGSPEW_PARAM_COMMA(U) K); |
692 | STACK_MID(K, 0); | 692 | STACK_CHECK(K, 0); |
693 | 693 | ||
694 | // copy package.path and package.cpath from the source state | 694 | // copy package.path and package.cpath from the source state |
695 | lua_getglobal(L, "package"); // "..." keepersUD package | 695 | lua_getglobal(L, "package"); // "..." keepersUD package |
@@ -705,7 +705,7 @@ void init_keepers(Universe* U, lua_State* L) | |||
705 | } | 705 | } |
706 | } | 706 | } |
707 | lua_pop(L, 1); // | 707 | lua_pop(L, 1); // |
708 | STACK_MID(L, 0); | 708 | STACK_CHECK(L, 0); |
709 | 709 | ||
710 | // attempt to call on_state_create(), if we have one and it is a C function | 710 | // attempt to call on_state_create(), if we have one and it is a C function |
711 | // (only support a C function because we can't transfer executable Lua code in keepers) | 711 | // (only support a C function because we can't transfer executable Lua code in keepers) |
@@ -717,9 +717,9 @@ void init_keepers(Universe* U, lua_State* L) | |||
717 | lua_setglobal(K, "decoda_name"); // | 717 | lua_setglobal(K, "decoda_name"); // |
718 | // create the fifos table in the keeper state | 718 | // create the fifos table in the keeper state |
719 | FIFOS_KEY.set_registry(K, [](lua_State* L) { lua_newtable(L); }); | 719 | FIFOS_KEY.set_registry(K, [](lua_State* L) { lua_newtable(L); }); |
720 | STACK_END(K, 0); | 720 | STACK_CHECK(K, 0); |
721 | } | 721 | } |
722 | STACK_END(L, 0); | 722 | STACK_CHECK(L, 0); |
723 | } | 723 | } |
724 | 724 | ||
725 | // ################################################################################################## | 725 | // ################################################################################################## |
diff --git a/src/lanes.cpp b/src/lanes.cpp index 38dd92c..6123766 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -113,7 +113,7 @@ THE SOFTWARE. | |||
113 | // intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed | 113 | // intern the debug name in the specified lua state so that the pointer remains valid when the lane's state is closed |
114 | static void securize_debug_threadname( lua_State* L, Lane* s) | 114 | static void securize_debug_threadname( lua_State* L, Lane* s) |
115 | { | 115 | { |
116 | STACK_CHECK( L, 0); | 116 | STACK_CHECK_START_REL(L, 0); |
117 | STACK_GROW( L, 3); | 117 | STACK_GROW( L, 3); |
118 | lua_getiuservalue( L, 1, 1); | 118 | lua_getiuservalue( L, 1, 1); |
119 | lua_newtable( L); | 119 | lua_newtable( L); |
@@ -122,7 +122,7 @@ static void securize_debug_threadname( lua_State* L, Lane* s) | |||
122 | s->debug_name = lua_tostring( L, -1); | 122 | s->debug_name = lua_tostring( L, -1); |
123 | lua_rawset( L, -3); | 123 | lua_rawset( L, -3); |
124 | lua_pop( L, 1); | 124 | lua_pop( L, 1); |
125 | STACK_END( L, 0); | 125 | STACK_CHECK( L, 0); |
126 | } | 126 | } |
127 | 127 | ||
128 | #if ERROR_FULL_STACK | 128 | #if ERROR_FULL_STACK |
@@ -155,12 +155,13 @@ struct s_Linda; | |||
155 | static bool push_registry_table( lua_State* L, UniqueKey key, bool create) | 155 | static bool push_registry_table( lua_State* L, UniqueKey key, bool create) |
156 | { | 156 | { |
157 | STACK_GROW( L, 3); | 157 | STACK_GROW( L, 3); |
158 | STACK_CHECK( L, 0); | 158 | STACK_CHECK_START_REL(L, 0); |
159 | 159 | ||
160 | key.query_registry(L); // ? | 160 | key.query_registry(L); // ? |
161 | if( lua_isnil( L, -1)) // nil? | 161 | if( lua_isnil( L, -1)) // nil? |
162 | { | 162 | { |
163 | lua_pop( L, 1); // | 163 | lua_pop( L, 1); // |
164 | STACK_CHECK(L, 0); | ||
164 | 165 | ||
165 | if( !create) | 166 | if( !create) |
166 | { | 167 | { |
@@ -170,7 +171,7 @@ static bool push_registry_table( lua_State* L, UniqueKey key, bool create) | |||
170 | lua_newtable( L); // t | 171 | lua_newtable( L); // t |
171 | key.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 172 | key.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
172 | } | 173 | } |
173 | STACK_END( L, 1); | 174 | STACK_CHECK( L, 1); |
174 | return true; // table pushed | 175 | return true; // table pushed |
175 | } | 176 | } |
176 | 177 | ||
@@ -675,11 +676,8 @@ done: | |||
675 | 676 | ||
676 | static int lane_error( lua_State* L) | 677 | static int lane_error( lua_State* L) |
677 | { | 678 | { |
678 | lua_Debug ar; | ||
679 | int n; | ||
680 | |||
681 | // error message (any type) | 679 | // error message (any type) |
682 | STACK_CHECK_ABS( L, 1); // some_error | 680 | STACK_CHECK_START_ABS(L, 1); // some_error |
683 | 681 | ||
684 | // Don't do stack survey for cancelled lanes. | 682 | // Don't do stack survey for cancelled lanes. |
685 | // | 683 | // |
@@ -692,6 +690,7 @@ static int lane_error( lua_State* L) | |||
692 | EXTENDED_STACKTRACE_REGKEY.query_registry(L); // some_error basic|extended | 690 | EXTENDED_STACKTRACE_REGKEY.query_registry(L); // some_error basic|extended |
693 | bool const extended{ lua_toboolean(L, -1) ? true : false}; | 691 | bool const extended{ lua_toboolean(L, -1) ? true : false}; |
694 | lua_pop( L, 1); // some_error | 692 | lua_pop( L, 1); // some_error |
693 | STACK_CHECK(L, 1); | ||
695 | 694 | ||
696 | // Place stack trace at 'registry[STACKTRACE_REGKEY]' for the 'lua_pcall()' | 695 | // Place stack trace at 'registry[STACKTRACE_REGKEY]' for the 'lua_pcall()' |
697 | // caller to fetch. This bypasses the Lua 5.1 limitation of only one | 696 | // caller to fetch. This bypasses the Lua 5.1 limitation of only one |
@@ -709,7 +708,8 @@ static int lane_error( lua_State* L) | |||
709 | // and we don't get '.currentline' for that. It's okay - just keep level | 708 | // and we don't get '.currentline' for that. It's okay - just keep level |
710 | // and table index growing separate. --AKa 22-Jan-2009 | 709 | // and table index growing separate. --AKa 22-Jan-2009 |
711 | // | 710 | // |
712 | for( n = 1; lua_getstack( L, n, &ar); ++ n) | 711 | lua_Debug ar; |
712 | for (int n = 1; lua_getstack(L, n, &ar); ++n) | ||
713 | { | 713 | { |
714 | lua_getinfo( L, extended ? "Sln" : "Sl", &ar); | 714 | lua_getinfo( L, extended ? "Sln" : "Sl", &ar); |
715 | if( extended) | 715 | if( extended) |
@@ -745,8 +745,8 @@ static int lane_error( lua_State* L) | |||
745 | // store the stack trace table in the registry | 745 | // store the stack trace table in the registry |
746 | STACKTRACE_REGKEY.set_registry(L, [](lua_State* L) { lua_insert(L, -2); }); // some_error | 746 | STACKTRACE_REGKEY.set_registry(L, [](lua_State* L) { lua_insert(L, -2); }); // some_error |
747 | 747 | ||
748 | STACK_END( L, 1); | 748 | STACK_CHECK(L, 1); |
749 | return 1; // the untouched error value | 749 | return 1; // the untouched error value |
750 | } | 750 | } |
751 | #endif // ERROR_FULL_STACK | 751 | #endif // ERROR_FULL_STACK |
752 | 752 | ||
@@ -761,12 +761,12 @@ static void push_stack_trace( lua_State* L, int rc_, int stk_base_) | |||
761 | case LUA_ERRRUN: // cancellation or a runtime error | 761 | case LUA_ERRRUN: // cancellation or a runtime error |
762 | #if ERROR_FULL_STACK // when ERROR_FULL_STACK, we installed a handler | 762 | #if ERROR_FULL_STACK // when ERROR_FULL_STACK, we installed a handler |
763 | { | 763 | { |
764 | STACK_CHECK( L, 0); | 764 | STACK_CHECK_START_REL(L, 0); |
765 | // fetch the call stack table from the registry where the handler stored it | 765 | // fetch the call stack table from the registry where the handler stored it |
766 | STACK_GROW( L, 1); | 766 | STACK_GROW( L, 1); |
767 | // yields nil if no stack was generated (in case of cancellation for example) | 767 | // yields nil if no stack was generated (in case of cancellation for example) |
768 | STACKTRACE_REGKEY.query_registry(L); // err trace|nil | 768 | STACKTRACE_REGKEY.query_registry(L); // err trace|nil |
769 | STACK_END( L, 1); | 769 | STACK_CHECK( L, 1); |
770 | 770 | ||
771 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed | 771 | // For cancellation the error message is CANCEL_ERROR, and a stack trace isn't placed |
772 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table | 772 | // For other errors, the message can be whatever was thrown, and we should have a stack trace table |
@@ -793,16 +793,16 @@ LUAG_FUNC( set_debug_threadname) | |||
793 | Lane* s = (Lane*) lua_touserdata( L, lua_upvalueindex( 1)); | 793 | Lane* s = (Lane*) lua_touserdata( L, lua_upvalueindex( 1)); |
794 | luaL_checktype( L, -1, LUA_TSTRING); // "name" | 794 | luaL_checktype( L, -1, LUA_TSTRING); // "name" |
795 | lua_settop( L, 1); | 795 | lua_settop( L, 1); |
796 | STACK_CHECK_ABS( L, 1); | 796 | STACK_CHECK_START_ABS( L, 1); |
797 | // 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... | 797 | // 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... |
798 | hidden_regkey.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 798 | hidden_regkey.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
799 | STACK_MID( L, 1); | 799 | STACK_CHECK( L, 1); |
800 | s->debug_name = lua_tostring( L, -1); | 800 | s->debug_name = lua_tostring( L, -1); |
801 | // keep a direct pointer on the string | 801 | // keep a direct pointer on the string |
802 | THREAD_SETNAME( s->debug_name); | 802 | THREAD_SETNAME( s->debug_name); |
803 | // to see VM name in Decoda debugger Virtual Machine window | 803 | // to see VM name in Decoda debugger Virtual Machine window |
804 | lua_setglobal( L, "decoda_name"); // | 804 | lua_setglobal( L, "decoda_name"); // |
805 | STACK_END( L, 0); | 805 | STACK_CHECK( L, 0); |
806 | return 0; | 806 | return 0; |
807 | } | 807 | } |
808 | 808 | ||
@@ -990,7 +990,7 @@ LUAG_FUNC( require) | |||
990 | char const* name = lua_tostring( L, 1); | 990 | char const* name = lua_tostring( L, 1); |
991 | int const nargs = lua_gettop( L); | 991 | int const nargs = lua_gettop( L); |
992 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 992 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
993 | STACK_CHECK( L, 0); | 993 | STACK_CHECK_START_REL(L, 0); |
994 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); | 994 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s BEGIN\n" INDENT_END, name)); |
995 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 995 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
996 | lua_pushvalue( L, lua_upvalueindex(1)); // "name" require | 996 | lua_pushvalue( L, lua_upvalueindex(1)); // "name" require |
@@ -999,7 +999,7 @@ LUAG_FUNC( require) | |||
999 | populate_func_lookup_table( L, -1, name); | 999 | populate_func_lookup_table( L, -1, name); |
1000 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); | 1000 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.require %s END\n" INDENT_END, name)); |
1001 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1001 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1002 | STACK_END( L, 0); | 1002 | STACK_CHECK( L, 0); |
1003 | return 1; | 1003 | return 1; |
1004 | } | 1004 | } |
1005 | 1005 | ||
@@ -1015,13 +1015,13 @@ LUAG_FUNC( register) | |||
1015 | lua_settop( L, 2); | 1015 | lua_settop( L, 2); |
1016 | luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type"); | 1016 | luaL_argcheck( L, (mod_type == LUA_TTABLE) || (mod_type == LUA_TFUNCTION), 2, "unexpected module type"); |
1017 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); | 1017 | DEBUGSPEW_CODE( Universe* U = universe_get( L)); |
1018 | STACK_CHECK( L, 0); // "name" mod_table | 1018 | STACK_CHECK_START_REL(L, 0); // "name" mod_table |
1019 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); | 1019 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s BEGIN\n" INDENT_END, name)); |
1020 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1020 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
1021 | populate_func_lookup_table( L, -1, name); | 1021 | populate_func_lookup_table( L, -1, name); |
1022 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); | 1022 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lanes.register %s END\n" INDENT_END, name)); |
1023 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1023 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1024 | STACK_END( L, 0); | 1024 | STACK_CHECK( L, 0); |
1025 | return 0; | 1025 | return 0; |
1026 | } | 1026 | } |
1027 | 1027 | ||
@@ -1075,10 +1075,10 @@ LUAG_FUNC( lane_new) | |||
1075 | L2 = luaG_newstate( U, L, libs_str); // L // L2 | 1075 | L2 = luaG_newstate( U, L, libs_str); // L // L2 |
1076 | 1076 | ||
1077 | STACK_GROW( L2, nargs + 3); // | 1077 | STACK_GROW( L2, nargs + 3); // |
1078 | STACK_CHECK( L2, 0); | 1078 | STACK_CHECK_START_REL(L2, 0); |
1079 | 1079 | ||
1080 | STACK_GROW( L, 3); // func libs priority globals package required gc_cb [... args ...] | 1080 | STACK_GROW( L, 3); // func libs priority globals package required gc_cb [... args ...] |
1081 | STACK_CHECK( L, 0); | 1081 | STACK_CHECK_START_REL(L, 0); |
1082 | 1082 | ||
1083 | // give a default "Lua" name to the thread to see VM name in Decoda debugger | 1083 | // give a default "Lua" name to the thread to see VM name in Decoda debugger |
1084 | lua_pushfstring( L2, "Lane #%p", L2); // "..." | 1084 | lua_pushfstring( L2, "Lane #%p", L2); // "..." |
@@ -1146,8 +1146,8 @@ LUAG_FUNC( lane_new) | |||
1146 | } // func libs priority globals package required gc_cb [... args ...] | 1146 | } // func libs priority globals package required gc_cb [... args ...] |
1147 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1147 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1148 | } | 1148 | } |
1149 | STACK_MID( L, 0); | 1149 | STACK_CHECK( L, 0); |
1150 | STACK_MID( L2, 0); // | 1150 | STACK_CHECK( L2, 0); // |
1151 | 1151 | ||
1152 | // Appending the specified globals to the global environment | 1152 | // Appending the specified globals to the global environment |
1153 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... | 1153 | // *after* stdlibs have been loaded and modules required, in case we transfer references to native functions they exposed... |
@@ -1175,8 +1175,8 @@ LUAG_FUNC( lane_new) | |||
1175 | 1175 | ||
1176 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1176 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1177 | } | 1177 | } |
1178 | STACK_MID( L, 0); | 1178 | STACK_CHECK( L, 0); |
1179 | STACK_MID( L2, 0); | 1179 | STACK_CHECK( L2, 0); |
1180 | 1180 | ||
1181 | // Lane main function | 1181 | // Lane main function |
1182 | if( lua_type( L, 1) == LUA_TFUNCTION) | 1182 | if( lua_type( L, 1) == LUA_TFUNCTION) |
@@ -1200,8 +1200,8 @@ LUAG_FUNC( lane_new) | |||
1200 | return luaL_error( L, "error when parsing lane function code"); | 1200 | return luaL_error( L, "error when parsing lane function code"); |
1201 | } | 1201 | } |
1202 | } | 1202 | } |
1203 | STACK_MID( L, 0); | 1203 | STACK_CHECK( L, 0); |
1204 | STACK_MID( L2, 1); | 1204 | STACK_CHECK( L2, 1); |
1205 | ASSERT_L( lua_isfunction( L2, 1)); | 1205 | ASSERT_L( lua_isfunction( L2, 1)); |
1206 | 1206 | ||
1207 | // revive arguments | 1207 | // revive arguments |
@@ -1217,10 +1217,10 @@ LUAG_FUNC( lane_new) | |||
1217 | return luaL_error( L, "tried to copy unsupported types"); | 1217 | return luaL_error( L, "tried to copy unsupported types"); |
1218 | } | 1218 | } |
1219 | } | 1219 | } |
1220 | STACK_END( L, -nargs); | 1220 | STACK_CHECK( L, -nargs); |
1221 | ASSERT_L( lua_gettop( L) == FIXED_ARGS); | 1221 | ASSERT_L( lua_gettop( L) == FIXED_ARGS); |
1222 | STACK_CHECK( L, 0); | 1222 | STACK_CHECK_RESET_REL(L, 0); |
1223 | STACK_MID( L2, 1 + nargs); | 1223 | STACK_CHECK( L2, 1 + nargs); |
1224 | 1224 | ||
1225 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) | 1225 | // 's' is allocated from heap, not Lua, since its life span may surpass the handle's (if free running thread) |
1226 | // | 1226 | // |
@@ -1260,7 +1260,7 @@ LUAG_FUNC( lane_new) | |||
1260 | // | 1260 | // |
1261 | lua_pushvalue( L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt | 1261 | lua_pushvalue( L, lua_upvalueindex( 1)); // func libs priority globals package required gc_cb lane mt |
1262 | lua_setmetatable( L, -2); // func libs priority globals package required gc_cb lane | 1262 | lua_setmetatable( L, -2); // func libs priority globals package required gc_cb lane |
1263 | STACK_MID( L, 1); | 1263 | STACK_CHECK( L, 1); |
1264 | 1264 | ||
1265 | // Create uservalue for the userdata | 1265 | // Create uservalue for the userdata |
1266 | // (this is where lane body return values will be stored when the handle is indexed by a numeric key) | 1266 | // (this is where lane body return values will be stored when the handle is indexed by a numeric key) |
@@ -1279,8 +1279,8 @@ LUAG_FUNC( lane_new) | |||
1279 | // Store 's' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). | 1279 | // Store 's' in the lane's registry, for 'cancel_test()' (we do cancel tests at pending send/receive). |
1280 | CANCEL_TEST_KEY.set_registry(L2, [s](lua_State* L) { lua_pushlightuserdata(L, s); }); // func [... args ...] | 1280 | CANCEL_TEST_KEY.set_registry(L2, [s](lua_State* L) { lua_pushlightuserdata(L, s); }); // func [... args ...] |
1281 | 1281 | ||
1282 | STACK_END( L, 1); | 1282 | STACK_CHECK( L, 1); |
1283 | STACK_END( L2, 1 + nargs); | 1283 | STACK_CHECK( L2, 1 + nargs); |
1284 | 1284 | ||
1285 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END)); | 1285 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "lane_new: launching thread\n" INDENT_END)); |
1286 | THREAD_CREATE( &s->thread, lane_main, s, priority); | 1286 | THREAD_CREATE( &s->thread, lane_main, s, priority); |
@@ -1436,7 +1436,7 @@ LUAG_FUNC( thread_join) | |||
1436 | return 2; | 1436 | return 2; |
1437 | } | 1437 | } |
1438 | 1438 | ||
1439 | STACK_CHECK( L, 0); | 1439 | STACK_CHECK_START_REL(L, 0); |
1440 | // Thread is DONE/ERROR_ST/CANCELLED; all ours now | 1440 | // Thread is DONE/ERROR_ST/CANCELLED; all ours now |
1441 | 1441 | ||
1442 | if (s->mstatus == ThreadStatus::Killed) // OS thread was killed if thread_cancel was forced | 1442 | if (s->mstatus == ThreadStatus::Killed) // OS thread was killed if thread_cancel was forced |
@@ -1492,7 +1492,7 @@ LUAG_FUNC( thread_join) | |||
1492 | lua_close( L2); | 1492 | lua_close( L2); |
1493 | } | 1493 | } |
1494 | s->L = 0; | 1494 | s->L = 0; |
1495 | STACK_END( L, ret); | 1495 | STACK_CHECK( L, ret); |
1496 | return ret; | 1496 | return ret; |
1497 | } | 1497 | } |
1498 | 1498 | ||
@@ -1723,7 +1723,7 @@ LUAG_FUNC( wakeup_conv ) | |||
1723 | // .yday (day of the year) | 1723 | // .yday (day of the year) |
1724 | // .isdst (daylight saving on/off) | 1724 | // .isdst (daylight saving on/off) |
1725 | 1725 | ||
1726 | STACK_CHECK( L, 0); | 1726 | STACK_CHECK_START_REL(L, 0); |
1727 | lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1); | 1727 | lua_getfield( L, 1, "year" ); year= (int)lua_tointeger(L,-1); lua_pop(L,1); |
1728 | lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1); | 1728 | lua_getfield( L, 1, "month" ); month= (int)lua_tointeger(L,-1); lua_pop(L,1); |
1729 | lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1); | 1729 | lua_getfield( L, 1, "day" ); day= (int)lua_tointeger(L,-1); lua_pop(L,1); |
@@ -1737,7 +1737,7 @@ LUAG_FUNC( wakeup_conv ) | |||
1737 | lua_getfield( L, 1, "isdst" ); | 1737 | lua_getfield( L, 1, "isdst" ); |
1738 | isdst= lua_isboolean(L,-1) ? lua_toboolean(L,-1) : -1; | 1738 | isdst= lua_isboolean(L,-1) ? lua_toboolean(L,-1) : -1; |
1739 | lua_pop(L,1); | 1739 | lua_pop(L,1); |
1740 | STACK_END( L, 0); | 1740 | STACK_CHECK( L, 0); |
1741 | 1741 | ||
1742 | t.tm_year= year-1900; | 1742 | t.tm_year= year-1900; |
1743 | t.tm_mon= month-1; // 0..11 | 1743 | t.tm_mon= month-1; // 0..11 |
@@ -1863,7 +1863,7 @@ LUAG_FUNC( configure) | |||
1863 | #endif // THREADAPI == THREADAPI_PTHREAD | 1863 | #endif // THREADAPI == THREADAPI_PTHREAD |
1864 | 1864 | ||
1865 | STACK_GROW( L, 4); | 1865 | STACK_GROW( L, 4); |
1866 | STACK_CHECK_ABS( L, 1); // settings | 1866 | STACK_CHECK_START_ABS( L, 1); // settings |
1867 | 1867 | ||
1868 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); | 1868 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() BEGIN\n" INDENT_END, L)); |
1869 | DEBUGSPEW_CODE( if( U) ++ U->debugspew_indent_depth); | 1869 | DEBUGSPEW_CODE( if( U) ++ U->debugspew_indent_depth); |
@@ -1900,13 +1900,13 @@ LUAG_FUNC( configure) | |||
1900 | initialize_allocator_function( U, L); | 1900 | initialize_allocator_function( U, L); |
1901 | initialize_on_state_create( U, L); | 1901 | initialize_on_state_create( U, L); |
1902 | init_keepers( U, L); | 1902 | init_keepers( U, L); |
1903 | STACK_MID( L, 1); | 1903 | STACK_CHECK( L, 1); |
1904 | 1904 | ||
1905 | // Initialize 'timer_deep'; a common Linda object shared by all states | 1905 | // Initialize 'timer_deep'; a common Linda object shared by all states |
1906 | lua_pushcfunction( L, LG_linda); // settings lanes.linda | 1906 | lua_pushcfunction( L, LG_linda); // settings lanes.linda |
1907 | lua_pushliteral( L, "lanes-timer"); // settings lanes.linda "lanes-timer" | 1907 | lua_pushliteral( L, "lanes-timer"); // settings lanes.linda "lanes-timer" |
1908 | lua_call( L, 1, 1); // settings linda | 1908 | lua_call( L, 1, 1); // settings linda |
1909 | STACK_MID( L, 2); | 1909 | STACK_CHECK( L, 2); |
1910 | 1910 | ||
1911 | // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer | 1911 | // Proxy userdata contents is only a 'DEEP_PRELUDE*' pointer |
1912 | U->timer_deep = *(DeepPrelude**) lua_touserdata( L, -1); | 1912 | U->timer_deep = *(DeepPrelude**) lua_touserdata( L, -1); |
@@ -1914,7 +1914,7 @@ LUAG_FUNC( configure) | |||
1914 | ++ U->timer_deep->refcount; | 1914 | ++ U->timer_deep->refcount; |
1915 | lua_pop( L, 1); // settings | 1915 | lua_pop( L, 1); // settings |
1916 | } | 1916 | } |
1917 | STACK_MID( L, 1); | 1917 | STACK_CHECK( L, 1); |
1918 | 1918 | ||
1919 | // Serialize calls to 'require' from now on, also in the primary state | 1919 | // Serialize calls to 'require' from now on, also in the primary state |
1920 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); | 1920 | serialize_require( DEBUGSPEW_PARAM_COMMA( U) L); |
@@ -1934,7 +1934,7 @@ LUAG_FUNC( configure) | |||
1934 | lua_setfield( L, -2, "threads"); // settings M | 1934 | lua_setfield( L, -2, "threads"); // settings M |
1935 | } | 1935 | } |
1936 | #endif // HAVE_LANE_TRACKING() | 1936 | #endif // HAVE_LANE_TRACKING() |
1937 | STACK_MID( L, 2); | 1937 | STACK_CHECK( L, 2); |
1938 | 1938 | ||
1939 | { | 1939 | { |
1940 | char const* errmsg; | 1940 | char const* errmsg; |
@@ -1945,7 +1945,7 @@ LUAG_FUNC( configure) | |||
1945 | } | 1945 | } |
1946 | lua_setfield( L, -2, "timer_gateway"); // settings M | 1946 | lua_setfield( L, -2, "timer_gateway"); // settings M |
1947 | } | 1947 | } |
1948 | STACK_MID( L, 2); | 1948 | STACK_CHECK( L, 2); |
1949 | 1949 | ||
1950 | // prepare the metatable for threads | 1950 | // prepare the metatable for threads |
1951 | // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } | 1951 | // contains keys: { __gc, __index, cached_error, cached_tostring, cancel, join, get_debug_threadname } |
@@ -1992,16 +1992,16 @@ LUAG_FUNC( configure) | |||
1992 | CANCEL_ERROR.push(L); // settings M CANCEL_ERROR | 1992 | CANCEL_ERROR.push(L); // settings M CANCEL_ERROR |
1993 | lua_setfield( L, -2, "cancel_error"); // settings M | 1993 | lua_setfield( L, -2, "cancel_error"); // settings M |
1994 | 1994 | ||
1995 | STACK_MID( L, 2); // reference stack contains only the function argument 'settings' | 1995 | STACK_CHECK( L, 2); // reference stack contains only the function argument 'settings' |
1996 | // we'll need this every time we transfer some C function from/to this state | 1996 | // we'll need this every time we transfer some C function from/to this state |
1997 | LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); // settings M | 1997 | LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); // settings M |
1998 | STACK_MID( L, 2); | 1998 | STACK_CHECK( L, 2); |
1999 | 1999 | ||
2000 | // register all native functions found in that module in the transferable functions database | 2000 | // register all native functions found in that module in the transferable functions database |
2001 | // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) | 2001 | // we process it before _G because we don't want to find the module when scanning _G (this would generate longer names) |
2002 | // for example in package.loaded["lanes.core"].* | 2002 | // for example in package.loaded["lanes.core"].* |
2003 | populate_func_lookup_table( L, -1, name); | 2003 | populate_func_lookup_table( L, -1, name); |
2004 | STACK_MID( L, 2); | 2004 | STACK_CHECK( L, 2); |
2005 | 2005 | ||
2006 | // record all existing C/JIT-fast functions | 2006 | // record all existing C/JIT-fast functions |
2007 | // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 2007 | // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
@@ -2018,7 +2018,7 @@ LUAG_FUNC( configure) | |||
2018 | 2018 | ||
2019 | // set _R[CONFIG_REGKEY] = settings | 2019 | // set _R[CONFIG_REGKEY] = settings |
2020 | CONFIG_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 2020 | CONFIG_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
2021 | STACK_END( L, 1); | 2021 | STACK_CHECK( L, 1); |
2022 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); | 2022 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: lanes.configure() END\n" INDENT_END, L)); |
2023 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2023 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
2024 | // Return the settings table | 2024 | // Return the settings table |
@@ -2085,7 +2085,7 @@ LANES_API int luaopen_lanes_core( lua_State* L) | |||
2085 | #endif // defined PLATFORM_WIN32 && !defined NDEBUG | 2085 | #endif // defined PLATFORM_WIN32 && !defined NDEBUG |
2086 | 2086 | ||
2087 | STACK_GROW( L, 4); | 2087 | STACK_GROW( L, 4); |
2088 | STACK_CHECK( L, 0); | 2088 | STACK_CHECK_START_REL(L, 0); |
2089 | 2089 | ||
2090 | // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too | 2090 | // Prevent PUC-Lua/LuaJIT mismatch. Hopefully this works for MoonJIT too |
2091 | lua_getglobal( L, "jit"); // {jit?} | 2091 | lua_getglobal( L, "jit"); // {jit?} |
@@ -2097,6 +2097,7 @@ LANES_API int luaopen_lanes_core( lua_State* L) | |||
2097 | return luaL_error( L, "Lanes is built for LuaJIT, don't run from PUC-Lua"); | 2097 | return luaL_error( L, "Lanes is built for LuaJIT, don't run from PUC-Lua"); |
2098 | #endif | 2098 | #endif |
2099 | lua_pop( L, 1); // | 2099 | lua_pop( L, 1); // |
2100 | STACK_CHECK(L, 0); | ||
2100 | 2101 | ||
2101 | // Create main module interface table | 2102 | // Create main module interface table |
2102 | // we only have 1 closure, which must be called to configure Lanes | 2103 | // we only have 1 closure, which must be called to configure Lanes |
@@ -2118,7 +2119,7 @@ LANES_API int luaopen_lanes_core( lua_State* L) | |||
2118 | lua_setfield( L, -2, "configure"); // M | 2119 | lua_setfield( L, -2, "configure"); // M |
2119 | } | 2120 | } |
2120 | 2121 | ||
2121 | STACK_END( L, 1); | 2122 | STACK_CHECK( L, 1); |
2122 | return 1; | 2123 | return 1; |
2123 | } | 2124 | } |
2124 | 2125 | ||
@@ -2135,12 +2136,12 @@ static int default_luaopen_lanes( lua_State* L) | |||
2135 | // call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application | 2136 | // call this instead of luaopen_lanes_core() when embedding Lua and Lanes in a custom application |
2136 | LANES_API void luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes) | 2137 | LANES_API void luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes) |
2137 | { | 2138 | { |
2138 | STACK_CHECK( L, 0); | 2139 | STACK_CHECK_START_REL(L, 0); |
2139 | // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded | 2140 | // pre-require lanes.core so that when lanes.lua calls require "lanes.core" it finds it is already loaded |
2140 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core | 2141 | luaL_requiref( L, "lanes.core", luaopen_lanes_core, 0); // ... lanes.core |
2141 | lua_pop( L, 1); // ... | 2142 | lua_pop( L, 1); // ... |
2142 | STACK_MID( L, 0); | 2143 | STACK_CHECK( L, 0); |
2143 | // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it | 2144 | // call user-provided function that runs the chunk "lanes.lua" from wherever they stored it |
2144 | luaL_requiref( L, "lanes", _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // ... lanes | 2145 | luaL_requiref( L, "lanes", _luaopen_lanes ? _luaopen_lanes : default_luaopen_lanes, 0); // ... lanes |
2145 | STACK_END( L, 1); | 2146 | STACK_CHECK( L, 1); |
2146 | } | 2147 | } |
diff --git a/src/lanes_private.h b/src/lanes_private.h index 2fbbae9..b8d26d3 100644 --- a/src/lanes_private.h +++ b/src/lanes_private.h | |||
@@ -80,13 +80,12 @@ struct Lane | |||
80 | 80 | ||
81 | static inline Lane* get_lane_from_registry( lua_State* L) | 81 | static inline Lane* get_lane_from_registry( lua_State* L) |
82 | { | 82 | { |
83 | Lane* s; | ||
84 | STACK_GROW( L, 1); | 83 | STACK_GROW( L, 1); |
85 | STACK_CHECK( L, 0); | 84 | STACK_CHECK_START_REL(L, 0); |
86 | CANCEL_TEST_KEY.query_registry(L); | 85 | CANCEL_TEST_KEY.query_registry(L); |
87 | s = (Lane*) lua_touserdata( L, -1); // lightuserdata (true 's_lane' pointer) / nil | 86 | Lane* const s = static_cast<Lane*>(lua_touserdata(L, -1)); // lightuserdata (true 's_lane' pointer) / nil |
88 | lua_pop( L, 1); | 87 | lua_pop( L, 1); |
89 | STACK_END( L, 0); | 88 | STACK_CHECK( L, 0); |
90 | return s; | 89 | return s; |
91 | } | 90 | } |
92 | 91 | ||
diff --git a/src/linda.cpp b/src/linda.cpp index ff3d543..a6025ce 100644 --- a/src/linda.cpp +++ b/src/linda.cpp | |||
@@ -88,7 +88,7 @@ LUAG_FUNC( linda_protected_call) | |||
88 | 88 | ||
89 | // acquire the keeper | 89 | // acquire the keeper |
90 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED(linda)); | 90 | Keeper* K = keeper_acquire( linda->U->keepers, LINDA_KEEPER_HASHSEED(linda)); |
91 | lua_State* KL = K ? K->L : nullptr; // need to do this for 'STACK_CHECK' | 91 | lua_State* KL = K ? K->L : nullptr; |
92 | if( KL == nullptr) return 0; | 92 | if( KL == nullptr) return 0; |
93 | 93 | ||
94 | // retrieve the actual function to be called and move it before the arguments | 94 | // retrieve the actual function to be called and move it before the arguments |
@@ -168,10 +168,10 @@ LUAG_FUNC( linda_send) | |||
168 | 168 | ||
169 | { | 169 | { |
170 | Lane* const s = get_lane_from_registry( L); | 170 | Lane* const s = get_lane_from_registry( L); |
171 | Keeper* K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); | 171 | Keeper* const K = which_keeper( linda->U->keepers, LINDA_KEEPER_HASHSEED( linda)); |
172 | lua_State* KL = K ? K->L : nullptr; // need to do this for 'STACK_CHECK' | 172 | lua_State* KL = K ? K->L : nullptr; |
173 | if( KL == nullptr) return 0; | 173 | if( KL == nullptr) return 0; |
174 | STACK_CHECK( KL, 0); | 174 | STACK_CHECK_START_REL(KL, 0); |
175 | for(bool try_again{ true };;) | 175 | for(bool try_again{ true };;) |
176 | { | 176 | { |
177 | if( s != nullptr) | 177 | if( s != nullptr) |
@@ -186,7 +186,7 @@ LUAG_FUNC( linda_send) | |||
186 | break; | 186 | break; |
187 | } | 187 | } |
188 | 188 | ||
189 | STACK_MID( KL, 0); | 189 | STACK_CHECK( KL, 0); |
190 | pushed = keeper_call( linda->U, KL, KEEPER_API( send), L, linda, key_i); | 190 | pushed = keeper_call( linda->U, KL, KEEPER_API( send), L, linda, key_i); |
191 | if( pushed < 0) | 191 | if( pushed < 0) |
192 | { | 192 | { |
@@ -231,7 +231,7 @@ LUAG_FUNC( linda_send) | |||
231 | } | 231 | } |
232 | } | 232 | } |
233 | } | 233 | } |
234 | STACK_END( KL, 0); | 234 | STACK_CHECK( KL, 0); |
235 | } | 235 | } |
236 | 236 | ||
237 | if( pushed < 0) | 237 | if( pushed < 0) |
@@ -839,7 +839,7 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
839 | case eDO_metatable: | 839 | case eDO_metatable: |
840 | { | 840 | { |
841 | 841 | ||
842 | STACK_CHECK( L, 0); | 842 | STACK_CHECK_START_REL(L, 0); |
843 | lua_newtable( L); | 843 | lua_newtable( L); |
844 | // metatable is its own index | 844 | // metatable is its own index |
845 | lua_pushvalue( L, -1); | 845 | lua_pushvalue( L, -1); |
@@ -904,7 +904,7 @@ static void* linda_id( lua_State* L, DeepOp op_) | |||
904 | NIL_SENTINEL.push(L); | 904 | NIL_SENTINEL.push(L); |
905 | lua_setfield( L, -2, "null"); | 905 | lua_setfield( L, -2, "null"); |
906 | 906 | ||
907 | STACK_END( L, 1); | 907 | STACK_CHECK( L, 1); |
908 | return nullptr; | 908 | return nullptr; |
909 | } | 909 | } |
910 | 910 | ||
diff --git a/src/macros_and_utils.h b/src/macros_and_utils.h index 9982693..c549d72 100644 --- a/src/macros_and_utils.h +++ b/src/macros_and_utils.h | |||
@@ -10,6 +10,8 @@ extern "C" { | |||
10 | } | 10 | } |
11 | #endif // __cplusplus | 11 | #endif // __cplusplus |
12 | 12 | ||
13 | #include <cassert> | ||
14 | |||
13 | #define USE_DEBUG_SPEW() 0 | 15 | #define USE_DEBUG_SPEW() 0 |
14 | #if USE_DEBUG_SPEW() | 16 | #if USE_DEBUG_SPEW() |
15 | extern char const* debugspew_indent; | 17 | extern char const* debugspew_indent; |
@@ -27,53 +29,89 @@ extern char const* debugspew_indent; | |||
27 | #ifdef NDEBUG | 29 | #ifdef NDEBUG |
28 | 30 | ||
29 | #define _ASSERT_L(lua,c) //nothing | 31 | #define _ASSERT_L(lua,c) //nothing |
30 | #define STACK_CHECK(L,o) //nothing | ||
31 | #define STACK_CHECK_ABS(L,o) //nothing | ||
32 | #define STACK_MID(L,c) //nothing | ||
33 | #define STACK_END(L,c) //nothing | ||
34 | #define STACK_DUMP(L) //nothing | 32 | #define STACK_DUMP(L) //nothing |
35 | 33 | ||
34 | #define STACK_CHECK_START_REL(L, offset_) | ||
35 | #define STACK_CHECK_START_ABS(L, offset_) | ||
36 | #define STACK_CHECK_RESET_REL(L, offset_) | ||
37 | #define STACK_CHECK_RESET_ABS(L, offset_) | ||
38 | #define STACK_CHECK(L, offset_) | ||
39 | |||
36 | #else // NDEBUG | 40 | #else // NDEBUG |
37 | 41 | ||
38 | #define _ASSERT_L( L, cond_) if( (cond_) == 0) { (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} | 42 | #define _ASSERT_L( L, cond_) if( (cond_) == 0) { (void) luaL_error( L, "ASSERT failed: %s:%d '%s'", __FILE__, __LINE__, #cond_);} |
43 | #define STACK_DUMP( L) luaG_dump( L) | ||
44 | |||
45 | class StackChecker | ||
46 | { | ||
47 | private: | ||
48 | lua_State* const m_L; | ||
49 | int m_oldtop; | ||
50 | |||
51 | public: | ||
52 | struct Relative | ||
53 | { | ||
54 | int const m_offset; | ||
55 | |||
56 | operator int() const { return m_offset; } | ||
57 | }; | ||
58 | |||
59 | struct Absolute | ||
60 | { | ||
61 | int const m_offset; | ||
39 | 62 | ||
40 | #define STACK_CHECK( L, offset_) \ | 63 | operator int() const { return m_offset; } |
41 | { \ | 64 | }; |
42 | int const L##_delta = offset_; \ | 65 | |
43 | if( (L##_delta < 0) || (lua_gettop( L) < L##_delta)) \ | 66 | StackChecker(lua_State* const L_, Relative offset_, char const* file_, size_t const line_) |
44 | { \ | 67 | : m_L{ L_ } |
45 | assert( false); \ | 68 | , m_oldtop{ lua_gettop(L_) - offset_ } |
46 | (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_delta, __FILE__, __LINE__); \ | 69 | { |
47 | } \ | 70 | if ((offset_ < 0) || (m_oldtop < 0)) |
48 | int const L##_oldtop = lua_gettop( L) - L##_delta | 71 | { |
49 | 72 | assert(false); | |
50 | #define STACK_CHECK_ABS( L, offset_) \ | 73 | (void) luaL_error(m_L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop(m_L), offset_, file_, line_); |
51 | { \ | 74 | } |
52 | int const L##_pos = offset_; \ | ||
53 | if( lua_gettop( L) < L##_pos) \ | ||
54 | { \ | ||
55 | assert( false); \ | ||
56 | (void) luaL_error( L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop( L), L##_pos, __FILE__, __LINE__); \ | ||
57 | } \ | ||
58 | int const L##_oldtop = 0 | ||
59 | |||
60 | #define STACK_MID( L, change) \ | ||
61 | do if( change != LUA_MULTRET) \ | ||
62 | { \ | ||
63 | int stack_check_a = lua_gettop( L) - L##_oldtop; \ | ||
64 | int stack_check_b = (change); \ | ||
65 | if( stack_check_a != stack_check_b) \ | ||
66 | { \ | ||
67 | assert( false); \ | ||
68 | luaL_error( L, "STACK ASSERT failed (%d not %d): %s:%d", stack_check_a, stack_check_b, __FILE__, __LINE__); \ | ||
69 | } \ | ||
70 | } while( 0) | ||
71 | |||
72 | #define STACK_END( L, change) \ | ||
73 | STACK_MID( L, change); \ | ||
74 | } | 75 | } |
75 | 76 | ||
76 | #define STACK_DUMP( L) luaG_dump( L) | 77 | StackChecker(lua_State* const L_, Absolute pos_, char const* file_, size_t const line_) |
78 | : m_L{ L_ } | ||
79 | , m_oldtop{ 0 } | ||
80 | { | ||
81 | if (lua_gettop(m_L) != pos_) | ||
82 | { | ||
83 | assert(false); | ||
84 | (void) luaL_error(m_L, "STACK INIT ASSERT failed (%d not %d): %s:%d", lua_gettop(m_L), pos_, file_, line_); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | StackChecker& operator=(StackChecker const& rhs_) | ||
89 | { | ||
90 | assert(m_L == rhs_.m_L); | ||
91 | m_oldtop = rhs_.m_oldtop; | ||
92 | return *this; | ||
93 | } | ||
94 | |||
95 | // verify if the distance between the current top and the initial one is what we expect | ||
96 | void check(int expected_, char const* file_, size_t const line_) | ||
97 | { | ||
98 | if (expected_ != LUA_MULTRET) | ||
99 | { | ||
100 | int const actual{ lua_gettop(m_L) - m_oldtop }; | ||
101 | if (actual != expected_) | ||
102 | { | ||
103 | assert(false); | ||
104 | luaL_error(m_L, "STACK ASSERT failed (%d not %d): %s:%d", actual, expected_, file_, line_); | ||
105 | } | ||
106 | } | ||
107 | } | ||
108 | }; | ||
109 | |||
110 | #define STACK_CHECK_START_REL(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__) | ||
111 | #define STACK_CHECK_START_ABS(L, offset_) StackChecker stackChecker_##L(L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__) | ||
112 | #define STACK_CHECK_RESET_REL(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Relative{ offset_ }, __FILE__, __LINE__} | ||
113 | #define STACK_CHECK_RESET_ABS(L, offset_) stackChecker_##L = StackChecker{L, StackChecker::Absolute{ offset_ }, __FILE__, __LINE__} | ||
114 | #define STACK_CHECK(L, offset_) stackChecker_##L.check(offset_, __FILE__, __LINE__) | ||
77 | 115 | ||
78 | #endif // NDEBUG | 116 | #endif // NDEBUG |
79 | 117 | ||
diff --git a/src/state.cpp b/src/state.cpp index f53d180..aa6b38a 100644 --- a/src/state.cpp +++ b/src/state.cpp | |||
@@ -91,28 +91,28 @@ static int luaG_new_require( lua_State* L) | |||
91 | /* | 91 | /* |
92 | * Serialize calls to 'require', if it exists | 92 | * Serialize calls to 'require', if it exists |
93 | */ | 93 | */ |
94 | void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) | 94 | void serialize_require(DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) |
95 | { | 95 | { |
96 | STACK_GROW( L, 1); | 96 | STACK_GROW(L, 1); |
97 | STACK_CHECK( L, 0); | 97 | STACK_CHECK_START_REL(L, 0); |
98 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); | 98 | DEBUGSPEW_CODE(fprintf(stderr, INDENT_BEGIN "serializing require()\n" INDENT_END)); |
99 | 99 | ||
100 | // Check 'require' is there and not already wrapped; if not, do nothing | 100 | // Check 'require' is there and not already wrapped; if not, do nothing |
101 | // | 101 | // |
102 | lua_getglobal( L, "require"); | 102 | lua_getglobal(L, "require"); |
103 | if( lua_isfunction( L, -1) && lua_tocfunction( L, -1) != luaG_new_require) | 103 | if (lua_isfunction(L, -1) && lua_tocfunction(L, -1) != luaG_new_require) |
104 | { | 104 | { |
105 | // [-1]: original 'require' function | 105 | // [-1]: original 'require' function |
106 | lua_pushcclosure( L, luaG_new_require, 1 /*upvalues*/); | 106 | lua_pushcclosure(L, luaG_new_require, 1 /*upvalues*/); |
107 | lua_setglobal( L, "require"); | 107 | lua_setglobal(L, "require"); |
108 | } | 108 | } |
109 | else | 109 | else |
110 | { | 110 | { |
111 | // [-1]: nil | 111 | // [-1]: nil |
112 | lua_pop( L, 1); | 112 | lua_pop(L, 1); |
113 | } | 113 | } |
114 | 114 | ||
115 | STACK_END( L, 0); | 115 | STACK_CHECK(L, 0); |
116 | } | 116 | } |
117 | 117 | ||
118 | // ################################################################################################ | 118 | // ################################################################################################ |
@@ -176,7 +176,7 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con | |||
176 | { | 176 | { |
177 | bool const isLanesCore{ libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" | 177 | bool const isLanesCore{ libfunc == require_lanes_core }; // don't want to create a global for "lanes.core" |
178 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); | 178 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "opening %.*s library\n" INDENT_END, (int) len_, name_)); |
179 | STACK_CHECK( L, 0); | 179 | STACK_CHECK_START_REL(L, 0); |
180 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) | 180 | // open the library as if through require(), and create a global as well if necessary (the library table is left on the stack) |
181 | luaL_requiref( L, name_, libfunc, !isLanesCore); | 181 | luaL_requiref( L, name_, libfunc, !isLanesCore); |
182 | // lanes.core doesn't declare a global, so scan it here and now | 182 | // lanes.core doesn't declare a global, so scan it here and now |
@@ -185,7 +185,7 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con | |||
185 | populate_func_lookup_table( L, -1, name_); | 185 | populate_func_lookup_table( L, -1, name_); |
186 | } | 186 | } |
187 | lua_pop( L, 1); | 187 | lua_pop( L, 1); |
188 | STACK_END( L, 0); | 188 | STACK_CHECK( L, 0); |
189 | } | 189 | } |
190 | break; | 190 | break; |
191 | } | 191 | } |
@@ -197,8 +197,8 @@ static void open1lib( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L, char con | |||
197 | static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | 197 | static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) |
198 | { | 198 | { |
199 | STACK_GROW( L, 2); | 199 | STACK_GROW( L, 2); |
200 | STACK_CHECK( L, 0); | 200 | STACK_CHECK_START_REL(L, 0); |
201 | STACK_CHECK( L2, 0); | 201 | STACK_CHECK_START_REL(L2, 0); |
202 | 202 | ||
203 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); | 203 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "copy_one_time_settings()\n" INDENT_END)); |
204 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 204 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
@@ -211,31 +211,31 @@ static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) | |||
211 | } | 211 | } |
212 | // set L2:_R[CONFIG_REGKEY] = settings | 212 | // set L2:_R[CONFIG_REGKEY] = settings |
213 | CONFIG_REGKEY.set_registry(L2, [](lua_State* L) { lua_insert(L, -2); }); // config | 213 | CONFIG_REGKEY.set_registry(L2, [](lua_State* L) { lua_insert(L, -2); }); // config |
214 | STACK_END( L2, 0); | 214 | STACK_CHECK( L2, 0); |
215 | STACK_END( L, 0); | 215 | STACK_CHECK( L, 0); |
216 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 216 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
217 | } | 217 | } |
218 | 218 | ||
219 | void initialize_on_state_create( Universe* U, lua_State* L) | 219 | void initialize_on_state_create( Universe* U, lua_State* L) |
220 | { | 220 | { |
221 | STACK_CHECK( L, 0); | 221 | STACK_CHECK_START_REL(L, 1); // settings |
222 | lua_getfield( L, -1, "on_state_create"); // settings on_state_create|nil | 222 | lua_getfield(L, -1, "on_state_create"); // settings on_state_create|nil |
223 | if( !lua_isnil( L, -1)) | 223 | if( !lua_isnil(L, -1)) |
224 | { | 224 | { |
225 | // store C function pointer in an internal variable | 225 | // store C function pointer in an internal variable |
226 | U->on_state_create_func = lua_tocfunction( L, -1); // settings on_state_create | 226 | U->on_state_create_func = lua_tocfunction(L, -1); // settings on_state_create |
227 | if (U->on_state_create_func != nullptr) | 227 | if (U->on_state_create_func != nullptr) |
228 | { | 228 | { |
229 | // make sure the function doesn't have upvalues | 229 | // make sure the function doesn't have upvalues |
230 | char const* upname = lua_getupvalue( L, -1, 1); // settings on_state_create upval? | 230 | char const* upname = lua_getupvalue(L, -1, 1); // settings on_state_create upval? |
231 | if (upname != nullptr) // should be "" for C functions with upvalues if any | 231 | if (upname != nullptr) // should be "" for C functions with upvalues if any |
232 | { | 232 | { |
233 | (void) luaL_error( L, "on_state_create shouldn't have upvalues"); | 233 | (void) luaL_error(L, "on_state_create shouldn't have upvalues"); |
234 | } | 234 | } |
235 | // remove this C function from the config table so that it doesn't cause problems | 235 | // remove this C function from the config table so that it doesn't cause problems |
236 | // when we transfer the config table in newly created Lua states | 236 | // when we transfer the config table in newly created Lua states |
237 | lua_pushnil( L); // settings on_state_create nil | 237 | lua_pushnil(L); // settings on_state_create nil |
238 | lua_setfield( L, -3, "on_state_create"); // settings on_state_create | 238 | lua_setfield(L, -3, "on_state_create"); // settings on_state_create |
239 | } | 239 | } |
240 | else | 240 | else |
241 | { | 241 | { |
@@ -243,8 +243,8 @@ void initialize_on_state_create( Universe* U, lua_State* L) | |||
243 | U->on_state_create_func = (lua_CFunction) initialize_on_state_create; | 243 | U->on_state_create_func = (lua_CFunction) initialize_on_state_create; |
244 | } | 244 | } |
245 | } | 245 | } |
246 | lua_pop( L, 1); // settings | 246 | lua_pop(L, 1); // settings |
247 | STACK_END( L, 0); | 247 | STACK_CHECK(L, 1); |
248 | } | 248 | } |
249 | 249 | ||
250 | lua_State* create_state( Universe* U, lua_State* from_) | 250 | lua_State* create_state( Universe* U, lua_State* from_) |
@@ -282,7 +282,7 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
282 | { | 282 | { |
283 | if (U->on_state_create_func != nullptr) | 283 | if (U->on_state_create_func != nullptr) |
284 | { | 284 | { |
285 | STACK_CHECK( L, 0); | 285 | STACK_CHECK_START_REL(L, 0); |
286 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); | 286 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "calling on_state_create()\n" INDENT_END)); |
287 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) | 287 | if( U->on_state_create_func != (lua_CFunction) initialize_on_state_create) |
288 | { | 288 | { |
@@ -295,20 +295,21 @@ void call_on_state_create( Universe* U, lua_State* L, lua_State* from_, LookupMo | |||
295 | { | 295 | { |
296 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there | 296 | // if attempting to call in a keeper state, do nothing because the function doesn't exist there |
297 | // this doesn't count as an error though | 297 | // this doesn't count as an error though |
298 | STACK_CHECK(L, 0); | ||
298 | return; | 299 | return; |
299 | } | 300 | } |
300 | CONFIG_REGKEY.query_registry(L); // {} | 301 | CONFIG_REGKEY.query_registry(L); // {} |
301 | STACK_MID( L, 1); | 302 | STACK_CHECK( L, 1); |
302 | lua_getfield( L, -1, "on_state_create"); // {} on_state_create() | 303 | lua_getfield( L, -1, "on_state_create"); // {} on_state_create() |
303 | lua_remove( L, -2); // on_state_create() | 304 | lua_remove( L, -2); // on_state_create() |
304 | } | 305 | } |
305 | STACK_MID( L, 1); | 306 | STACK_CHECK( L, 1); |
306 | // capture error and raise it in caller state | 307 | // capture error and raise it in caller state |
307 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) | 308 | if( lua_pcall( L, 0, 0, 0) != LUA_OK) |
308 | { | 309 | { |
309 | luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); | 310 | luaL_error( from_, "on_state_create failed: \"%s\"", lua_isstring( L, -1) ? lua_tostring( L, -1) : lua_typename( L, lua_type( L, -1))); |
310 | } | 311 | } |
311 | STACK_END( L, 0); | 312 | STACK_CHECK( L, 0); |
312 | } | 313 | } |
313 | } | 314 | } |
314 | 315 | ||
@@ -330,16 +331,16 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
330 | lua_State* L = create_state( U, from_); | 331 | lua_State* L = create_state( U, from_); |
331 | 332 | ||
332 | STACK_GROW( L, 2); | 333 | STACK_GROW( L, 2); |
333 | STACK_CHECK_ABS( L, 0); | 334 | STACK_CHECK_START_ABS(L, 0); |
334 | 335 | ||
335 | // copy the universe as a light userdata (only the master state holds the full userdata) | 336 | // copy the universe as a light userdata (only the master state holds the full userdata) |
336 | // that way, if Lanes is required in this new state, we'll know we are part of this universe | 337 | // that way, if Lanes is required in this new state, we'll know we are part of this universe |
337 | universe_store( L, U); | 338 | universe_store( L, U); |
338 | STACK_MID( L, 0); | 339 | STACK_CHECK(L, 0); |
339 | 340 | ||
340 | // we'll need this every time we transfer some C function from/to this state | 341 | // we'll need this every time we transfer some C function from/to this state |
341 | LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); | 342 | LOOKUP_REGKEY.set_registry(L, [](lua_State* L) { lua_newtable(L); }); |
342 | STACK_MID( L, 0); | 343 | STACK_CHECK(L, 0); |
343 | 344 | ||
344 | // neither libs (not even 'base') nor special init func: we are done | 345 | // neither libs (not even 'base') nor special init func: we are done |
345 | if (libs_ == nullptr && U->on_state_create_func == nullptr) | 346 | if (libs_ == nullptr && U->on_state_create_func == nullptr) |
@@ -386,7 +387,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
386 | #endif // LUA_VERSION_NUM | 387 | #endif // LUA_VERSION_NUM |
387 | } | 388 | } |
388 | } | 389 | } |
389 | STACK_END( L, 0); | 390 | STACK_CHECK(L, 0); |
390 | 391 | ||
391 | // scan all libraries, open them one by one | 392 | // scan all libraries, open them one by one |
392 | if( libs_) | 393 | if( libs_) |
@@ -414,9 +415,10 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
414 | // will raise an error in from_ in case of problem | 415 | // will raise an error in from_ in case of problem |
415 | call_on_state_create( U, L, from_, eLM_LaneBody); | 416 | call_on_state_create( U, L, from_, eLM_LaneBody); |
416 | 417 | ||
417 | STACK_CHECK( L, 0); | 418 | STACK_CHECK(L, 0); |
418 | // after all this, register everything we find in our name<->function database | 419 | // after all this, register everything we find in our name<->function database |
419 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack | 420 | lua_pushglobaltable( L); // Lua 5.2 no longer has LUA_GLOBALSINDEX: we must push globals table on the stack |
421 | STACK_CHECK(L, 1); | ||
420 | populate_func_lookup_table(L, -1, nullptr); | 422 | populate_func_lookup_table(L, -1, nullptr); |
421 | 423 | ||
422 | #if 0 && USE_DEBUG_SPEW() | 424 | #if 0 && USE_DEBUG_SPEW() |
@@ -436,7 +438,7 @@ lua_State* luaG_newstate( Universe* U, lua_State* from_, char const* libs_) | |||
436 | #endif // USE_DEBUG_SPEW() | 438 | #endif // USE_DEBUG_SPEW() |
437 | 439 | ||
438 | lua_pop( L, 1); | 440 | lua_pop( L, 1); |
439 | STACK_END( L, 0); | 441 | STACK_CHECK(L, 0); |
440 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 442 | DEBUGSPEW_CODE(--U->debugspew_indent_depth); |
441 | return L; | 443 | return L; |
442 | } | 444 | } |
diff --git a/src/tools.cpp b/src/tools.cpp index 5196e7e..1e38144 100644 --- a/src/tools.cpp +++ b/src/tools.cpp | |||
@@ -62,10 +62,10 @@ DEBUGSPEW_CODE( char const* debugspew_indent = "----+----!----+----!----+----!-- | |||
62 | void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) | 62 | void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) |
63 | { | 63 | { |
64 | STACK_GROW(L, 3); | 64 | STACK_GROW(L, 3); |
65 | STACK_CHECK(L, 0); | 65 | STACK_CHECK_START_REL(L, 0); |
66 | 66 | ||
67 | key_.query_registry(L); // {}|nil | 67 | key_.query_registry(L); // {}|nil |
68 | STACK_MID(L, 1); | 68 | STACK_CHECK(L, 1); |
69 | 69 | ||
70 | if (lua_isnil(L, -1)) | 70 | if (lua_isnil(L, -1)) |
71 | { | 71 | { |
@@ -73,7 +73,7 @@ void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode | |||
73 | lua_newtable(L); // {} | 73 | lua_newtable(L); // {} |
74 | // _R[key_] = {} | 74 | // _R[key_] = {} |
75 | key_.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // {} | 75 | key_.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // {} |
76 | STACK_MID(L, 1); | 76 | STACK_CHECK(L, 1); |
77 | 77 | ||
78 | // Set its metatable if requested | 78 | // Set its metatable if requested |
79 | if (mode_) | 79 | if (mode_) |
@@ -85,7 +85,7 @@ void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode | |||
85 | lua_setmetatable(L, -2); // {} | 85 | lua_setmetatable(L, -2); // {} |
86 | } | 86 | } |
87 | } | 87 | } |
88 | STACK_END(L, 1); | 88 | STACK_CHECK(L, 1); |
89 | ASSERT_L(lua_istable(L, -1)); | 89 | ASSERT_L(lua_istable(L, -1)); |
90 | } | 90 | } |
91 | 91 | ||
@@ -125,7 +125,7 @@ void luaG_dump( lua_State* L) | |||
125 | // Note: this requires 'tostring()' to be defined. If it is NOT, | 125 | // Note: this requires 'tostring()' to be defined. If it is NOT, |
126 | // enable it for more debugging. | 126 | // enable it for more debugging. |
127 | // | 127 | // |
128 | STACK_CHECK( L, 0); | 128 | STACK_CHECK_START_REL(L, 0); |
129 | STACK_GROW( L, 2); | 129 | STACK_GROW( L, 2); |
130 | 130 | ||
131 | lua_getglobal( L, "tostring"); | 131 | lua_getglobal( L, "tostring"); |
@@ -146,7 +146,7 @@ void luaG_dump( lua_State* L) | |||
146 | fprintf( stderr, "%s", lua_tostring( L, -1)); | 146 | fprintf( stderr, "%s", lua_tostring( L, -1)); |
147 | } | 147 | } |
148 | lua_pop( L, 1); | 148 | lua_pop( L, 1); |
149 | STACK_END( L, 0); | 149 | STACK_CHECK( L, 0); |
150 | fprintf( stderr, "\n"); | 150 | fprintf( stderr, "\n"); |
151 | } | 151 | } |
152 | fprintf( stderr, "\n"); | 152 | fprintf( stderr, "\n"); |
@@ -193,7 +193,7 @@ static int luaG_provide_protected_allocator( lua_State* L) | |||
193 | // Do I need to disable this when compiling for LuaJIT to prevent issues? | 193 | // Do I need to disable this when compiling for LuaJIT to prevent issues? |
194 | void initialize_allocator_function( Universe* U, lua_State* L) | 194 | void initialize_allocator_function( Universe* U, lua_State* L) |
195 | { | 195 | { |
196 | STACK_CHECK( L, 0); | 196 | STACK_CHECK_START_REL(L, 1); // settings |
197 | lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected" | 197 | lua_getfield( L, -1, "allocator"); // settings allocator|nil|"protected" |
198 | if( !lua_isnil( L, -1)) | 198 | if( !lua_isnil( L, -1)) |
199 | { | 199 | { |
@@ -232,7 +232,7 @@ void initialize_allocator_function( Universe* U, lua_State* L) | |||
232 | U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); | 232 | U->protected_allocator.definition.allocF = lua_getallocf( L, &U->protected_allocator.definition.allocUD); |
233 | } | 233 | } |
234 | lua_pop( L, 1); // settings | 234 | lua_pop( L, 1); // settings |
235 | STACK_MID(L, 0); | 235 | STACK_CHECK(L, 1); |
236 | 236 | ||
237 | lua_getfield( L, -1, "internal_allocator"); // settings "libc"|"allocator" | 237 | lua_getfield( L, -1, "internal_allocator"); // settings "libc"|"allocator" |
238 | { | 238 | { |
@@ -248,7 +248,7 @@ void initialize_allocator_function( Universe* U, lua_State* L) | |||
248 | } | 248 | } |
249 | } | 249 | } |
250 | lua_pop( L, 1); // settings | 250 | lua_pop( L, 1); // settings |
251 | STACK_END( L, 0); | 251 | STACK_CHECK( L, 1); |
252 | } | 252 | } |
253 | 253 | ||
254 | void cleanup_allocator_function( Universe* U, lua_State* L) | 254 | void cleanup_allocator_function( Universe* U, lua_State* L) |
@@ -335,7 +335,7 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) | |||
335 | { | 335 | { |
336 | int i = 1; | 336 | int i = 1; |
337 | luaL_Buffer b; | 337 | luaL_Buffer b; |
338 | STACK_CHECK( L, 0); | 338 | STACK_CHECK_START_REL(L, 0); |
339 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... | 339 | // Lua 5.4 pushes &b as light userdata on the stack. be aware of it... |
340 | luaL_buffinit( L, &b); // ... {} ... &b? | 340 | luaL_buffinit( L, &b); // ... {} ... &b? |
341 | for( ; i < last; ++ i) | 341 | for( ; i < last; ++ i) |
@@ -351,7 +351,7 @@ static char const* luaG_pushFQN( lua_State* L, int t, int last, size_t* length) | |||
351 | } | 351 | } |
352 | // &b is popped at that point (-> replaced by the result) | 352 | // &b is popped at that point (-> replaced by the result) |
353 | luaL_pushresult( &b); // ... {} ... "<result>" | 353 | luaL_pushresult( &b); // ... {} ... "<result>" |
354 | STACK_END( L, 1); | 354 | STACK_CHECK( L, 1); |
355 | return lua_tolstring( L, -1, length); | 355 | return lua_tolstring( L, -1, length); |
356 | } | 356 | } |
357 | 357 | ||
@@ -376,7 +376,7 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* | |||
376 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); | 376 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "update_lookup_entry()\n" INDENT_END)); |
377 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 377 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
378 | 378 | ||
379 | STACK_CHECK( L, 0); | 379 | STACK_CHECK_START_REL(L, 0); |
380 | // first, raise an error if the function is already known | 380 | // first, raise an error if the function is already known |
381 | lua_pushvalue( L, -1); // ... {bfc} k o o | 381 | lua_pushvalue( L, -1); // ... {bfc} k o o |
382 | lua_rawget( L, dest); // ... {bfc} k o name? | 382 | lua_rawget( L, dest); // ... {bfc} k o name? |
@@ -433,7 +433,7 @@ static void update_lookup_entry( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* | |||
433 | lua_rawseti( L, fqn, _depth); // ... {bfc} k | 433 | lua_rawseti( L, fqn, _depth); // ... {bfc} k |
434 | } | 434 | } |
435 | -- _depth; | 435 | -- _depth; |
436 | STACK_END( L, -1); | 436 | STACK_CHECK( L, -1); |
437 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 437 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
438 | } | 438 | } |
439 | 439 | ||
@@ -451,13 +451,13 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U | |||
451 | 451 | ||
452 | STACK_GROW( L, 6); | 452 | STACK_GROW( L, 6); |
453 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) | 453 | // slot _i contains a table where we search for functions (or a full userdata with a metatable) |
454 | STACK_CHECK( L, 0); // ... {_i} | 454 | STACK_CHECK_START_REL(L, 0); // ... {_i} |
455 | 455 | ||
456 | // if object is a userdata, replace it by its metatable | 456 | // if object is a userdata, replace it by its metatable |
457 | if( lua_type( L, _i) == LUA_TUSERDATA) | 457 | if( lua_type( L, _i) == LUA_TUSERDATA) |
458 | { | 458 | { |
459 | lua_getmetatable( L, _i); // ... {_i} mt | 459 | lua_getmetatable( L, _i); // ... {_i} mt |
460 | lua_replace( L, _i); // ... {_i} | 460 | lua_replace( L, _i); // ... {_i} |
461 | } | 461 | } |
462 | 462 | ||
463 | // if table is already visited, we are done | 463 | // if table is already visited, we are done |
@@ -465,7 +465,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U | |||
465 | lua_rawget( L, cache); // ... {_i} nil|n | 465 | lua_rawget( L, cache); // ... {_i} nil|n |
466 | visit_count = lua_tointeger( L, -1); // 0 if nil, else n | 466 | visit_count = lua_tointeger( L, -1); // 0 if nil, else n |
467 | lua_pop( L, 1); // ... {_i} | 467 | lua_pop( L, 1); // ... {_i} |
468 | STACK_MID( L, 0); | 468 | STACK_CHECK( L, 0); |
469 | if( visit_count > 0) | 469 | if( visit_count > 0) |
470 | { | 470 | { |
471 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); | 471 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "already visited\n" INDENT_END)); |
@@ -477,7 +477,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U | |||
477 | lua_pushvalue( L, _i); // ... {_i} {} | 477 | lua_pushvalue( L, _i); // ... {_i} {} |
478 | lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1 | 478 | lua_pushinteger( L, visit_count + 1); // ... {_i} {} 1 |
479 | lua_rawset( L, cache); // ... {_i} | 479 | lua_rawset( L, cache); // ... {_i} |
480 | STACK_MID( L, 0); | 480 | STACK_CHECK( L, 0); |
481 | 481 | ||
482 | // this table is at breadth_first_cache index | 482 | // this table is at breadth_first_cache index |
483 | lua_newtable( L); // ... {_i} {bfc} | 483 | lua_newtable( L); // ... {_i} {bfc} |
@@ -515,7 +515,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U | |||
515 | { | 515 | { |
516 | lua_pop( L, 1); // ... {_i} {bfc} k | 516 | lua_pop( L, 1); // ... {_i} {bfc} k |
517 | } | 517 | } |
518 | STACK_MID( L, 2); | 518 | STACK_CHECK( L, 2); |
519 | } | 519 | } |
520 | // now process the tables we encountered at that depth | 520 | // now process the tables we encountered at that depth |
521 | ++ _depth; | 521 | ++ _depth; |
@@ -546,7 +546,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U | |||
546 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {} | 546 | lua_rawseti( L, fqn, _depth); // ... {_i} {bfc} k {} |
547 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); | 547 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, _ctx_base, lua_gettop( L), _depth); |
548 | lua_pop( L, 1); // ... {_i} {bfc} k | 548 | lua_pop( L, 1); // ... {_i} {bfc} k |
549 | STACK_MID( L, 2); | 549 | STACK_CHECK( L, 2); |
550 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 550 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
551 | } | 551 | } |
552 | // remove table name from fqn stack | 552 | // remove table name from fqn stack |
@@ -555,7 +555,7 @@ static void populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( Universe* U | |||
555 | -- _depth; | 555 | -- _depth; |
556 | // we are done with our cache | 556 | // we are done with our cache |
557 | lua_pop( L, 1); // ... {_i} | 557 | lua_pop( L, 1); // ... {_i} |
558 | STACK_END( L, 0); | 558 | STACK_CHECK( L, 0); |
559 | // we are done // ... {_i} {bfc} | 559 | // we are done // ... {_i} {bfc} |
560 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 560 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
561 | } | 561 | } |
@@ -572,9 +572,9 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
572 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); | 572 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "%p: populate_func_lookup_table('%s')\n" INDENT_END, L, name_ ? name_ : "nullptr")); |
573 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 573 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
574 | STACK_GROW( L, 3); | 574 | STACK_GROW( L, 3); |
575 | STACK_CHECK( L, 0); | 575 | STACK_CHECK_START_REL(L, 0); |
576 | LOOKUP_REGKEY.query_registry(L); // {} | 576 | LOOKUP_REGKEY.query_registry(L); // {} |
577 | STACK_MID( L, 1); | 577 | STACK_CHECK( L, 1); |
578 | ASSERT_L( lua_istable( L, -1)); | 578 | ASSERT_L( lua_istable( L, -1)); |
579 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function | 579 | if( lua_type( L, in_base) == LUA_TFUNCTION) // for example when a module is a simple function |
580 | { | 580 | { |
@@ -592,7 +592,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
592 | lua_newtable( L); // {} {fqn} | 592 | lua_newtable( L); // {} {fqn} |
593 | if( name_) | 593 | if( name_) |
594 | { | 594 | { |
595 | STACK_MID( L, 2); | 595 | STACK_CHECK( L, 2); |
596 | lua_pushstring( L, name_); // {} {fqn} "name" | 596 | lua_pushstring( L, name_); // {} {fqn} "name" |
597 | // generate a name, and if we already had one name, keep whichever is the shorter | 597 | // generate a name, and if we already had one name, keep whichever is the shorter |
598 | lua_pushvalue( L, in_base); // {} {fqn} "name" t | 598 | lua_pushvalue( L, in_base); // {} {fqn} "name" t |
@@ -600,7 +600,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
600 | // don't forget to store the name at the bottom of the fqn stack | 600 | // don't forget to store the name at the bottom of the fqn stack |
601 | ++ start_depth; | 601 | ++ start_depth; |
602 | lua_rawseti( L, -2, start_depth); // {} {fqn} | 602 | lua_rawseti( L, -2, start_depth); // {} {fqn} |
603 | STACK_MID( L, 2); | 603 | STACK_CHECK( L, 2); |
604 | } | 604 | } |
605 | // retrieve the cache, create it if we haven't done it yet | 605 | // retrieve the cache, create it if we haven't done it yet |
606 | LOOKUPCACHE_REGKEY.query_registry(L); // {} {fqn} {cache}? | 606 | LOOKUPCACHE_REGKEY.query_registry(L); // {} {fqn} {cache}? |
@@ -609,7 +609,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
609 | lua_pop( L, 1); // {} {fqn} | 609 | lua_pop( L, 1); // {} {fqn} |
610 | lua_newtable( L); // {} {fqn} {cache} | 610 | lua_newtable( L); // {} {fqn} {cache} |
611 | LOOKUPCACHE_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); | 611 | LOOKUPCACHE_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); |
612 | STACK_MID( L, 3); | 612 | STACK_CHECK( L, 3); |
613 | } | 613 | } |
614 | // process everything we find in that table, filling in lookup data for all functions and tables we see there | 614 | // process everything we find in that table, filling in lookup data for all functions and tables we see there |
615 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, in_base, start_depth); | 615 | populate_func_lookup_table_recur( DEBUGSPEW_PARAM_COMMA( U) L, ctx_base, in_base, start_depth); |
@@ -620,7 +620,7 @@ void populate_func_lookup_table( lua_State* L, int _i, char const* name_) | |||
620 | lua_pop( L, 1); // | 620 | lua_pop( L, 1); // |
621 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); | 621 | (void) luaL_error( L, "unsupported module type %s", lua_typename( L, lua_type( L, in_base))); |
622 | } | 622 | } |
623 | STACK_END( L, 0); | 623 | STACK_CHECK( L, 0); |
624 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 624 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
625 | } | 625 | } |
626 | 626 | ||
@@ -640,14 +640,14 @@ static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) | |||
640 | 640 | ||
641 | STACK_GROW( L, 3); | 641 | STACK_GROW( L, 3); |
642 | 642 | ||
643 | STACK_CHECK( L, 0); | 643 | STACK_CHECK_START_REL(L, 0); |
644 | push_registry_subtable( L, REG_MTID); // ... _R[REG_MTID] | 644 | push_registry_subtable( L, REG_MTID); // ... _R[REG_MTID] |
645 | lua_pushvalue( L, i); // ... _R[REG_MTID] {mt} | 645 | lua_pushvalue( L, i); // ... _R[REG_MTID] {mt} |
646 | lua_rawget( L, -2); // ... _R[REG_MTID] mtk? | 646 | lua_rawget( L, -2); // ... _R[REG_MTID] mtk? |
647 | 647 | ||
648 | id = lua_tointeger( L, -1); // 0 for nil | 648 | id = lua_tointeger( L, -1); // 0 for nil |
649 | lua_pop( L, 1); // ... _R[REG_MTID] | 649 | lua_pop( L, 1); // ... _R[REG_MTID] |
650 | STACK_MID( L, 1); | 650 | STACK_CHECK( L, 1); |
651 | 651 | ||
652 | if( id == 0) | 652 | if( id == 0) |
653 | { | 653 | { |
@@ -667,7 +667,7 @@ static lua_Integer get_mt_id( Universe* U, lua_State* L, int i) | |||
667 | } | 667 | } |
668 | lua_pop( L, 1); // ... | 668 | lua_pop( L, 1); // ... |
669 | 669 | ||
670 | STACK_END( L, 0); | 670 | STACK_CHECK( L, 0); |
671 | 671 | ||
672 | return id; | 672 | return id; |
673 | } | 673 | } |
@@ -699,7 +699,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char | |||
699 | DEBUGSPEW_CODE( Universe* const U = universe_get( L)); | 699 | DEBUGSPEW_CODE( Universe* const U = universe_get( L)); |
700 | char const* fqn; | 700 | char const* fqn; |
701 | ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... | 701 | ASSERT_L( lua_isfunction( L, i) || lua_istable( L, i)); // ... v ... |
702 | STACK_CHECK( L, 0); | 702 | STACK_CHECK_START_REL(L, 0); |
703 | STACK_GROW( L, 3); // up to 3 slots are necessary on error | 703 | STACK_GROW( L, 3); // up to 3 slots are necessary on error |
704 | if( mode_ == eLM_FromKeeper) | 704 | if( mode_ == eLM_FromKeeper) |
705 | { | 705 | { |
@@ -720,7 +720,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char | |||
720 | { | 720 | { |
721 | // fetch the name from the source state's lookup table | 721 | // fetch the name from the source state's lookup table |
722 | LOOKUP_REGKEY.query_registry(L); // ... v ... {} | 722 | LOOKUP_REGKEY.query_registry(L); // ... v ... {} |
723 | STACK_MID( L, 1); | 723 | STACK_CHECK( L, 1); |
724 | ASSERT_L( lua_istable( L, -1)); | 724 | ASSERT_L( lua_istable( L, -1)); |
725 | lua_pushvalue( L, i); // ... v ... {} v | 725 | lua_pushvalue( L, i); // ... v ... {} v |
726 | lua_rawget( L, -2); // ... v ... {} "f.q.n" | 726 | lua_rawget( L, -2); // ... v ... {} "f.q.n" |
@@ -729,7 +729,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char | |||
729 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); | 729 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "function [C] %s \n" INDENT_END, fqn)); |
730 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database | 730 | // popping doesn't invalidate the pointer since this is an interned string gotten from the lookup database |
731 | lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ... | 731 | lua_pop( L, (mode_ == eLM_FromKeeper) ? 1 : 2); // ... v ... |
732 | STACK_MID( L, 0); | 732 | STACK_CHECK( L, 0); |
733 | if (nullptr == fqn && !lua_istable(L, i)) // raise an error if we try to send an unknown function (but not for tables) | 733 | if (nullptr == fqn && !lua_istable(L, i)) // raise an error if we try to send an unknown function (but not for tables) |
734 | { | 734 | { |
735 | char const *from, *typewhat, *what, *gotchaA, *gotchaB; | 735 | char const *from, *typewhat, *what, *gotchaA, *gotchaB; |
@@ -758,7 +758,7 @@ static char const* find_lookup_name(lua_State* L, int i, LookupMode mode_, char | |||
758 | *len_ = 0; | 758 | *len_ = 0; |
759 | return nullptr; | 759 | return nullptr; |
760 | } | 760 | } |
761 | STACK_END( L, 0); | 761 | STACK_CHECK( L, 0); |
762 | return fqn; | 762 | return fqn; |
763 | } | 763 | } |
764 | 764 | ||
@@ -776,7 +776,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c | |||
776 | return false; | 776 | return false; |
777 | } | 777 | } |
778 | // push the equivalent table in the destination's stack, retrieved from the lookup table | 778 | // push the equivalent table in the destination's stack, retrieved from the lookup table |
779 | STACK_CHECK( L2, 0); // L // L2 | 779 | STACK_CHECK_START_REL(L2, 0); // L // L2 |
780 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error | 780 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error |
781 | switch( mode_) | 781 | switch( mode_) |
782 | { | 782 | { |
@@ -793,7 +793,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c | |||
793 | case eLM_LaneBody: | 793 | case eLM_LaneBody: |
794 | case eLM_FromKeeper: | 794 | case eLM_FromKeeper: |
795 | LOOKUP_REGKEY.query_registry(L2); // {} | 795 | LOOKUP_REGKEY.query_registry(L2); // {} |
796 | STACK_MID( L2, 1); | 796 | STACK_CHECK( L2, 1); |
797 | ASSERT_L( lua_istable( L2, -1)); | 797 | ASSERT_L( lua_istable( L2, -1)); |
798 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 798 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
799 | lua_rawget( L2, -2); // {} t | 799 | lua_rawget( L2, -2); // {} t |
@@ -802,7 +802,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c | |||
802 | if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody) | 802 | if( lua_isnil( L2, -1) && mode_ == eLM_LaneBody) |
803 | { | 803 | { |
804 | lua_pop( L2, 2); // | 804 | lua_pop( L2, 2); // |
805 | STACK_MID( L2, 0); | 805 | STACK_CHECK( L2, 0); |
806 | return false; | 806 | return false; |
807 | } | 807 | } |
808 | else if( !lua_istable( L2, -1)) | 808 | else if( !lua_istable( L2, -1)) |
@@ -827,7 +827,7 @@ static bool lookup_table(lua_State* L2, lua_State* L, int i, LookupMode mode_, c | |||
827 | lua_remove( L2, -2); // t | 827 | lua_remove( L2, -2); // t |
828 | break; | 828 | break; |
829 | } | 829 | } |
830 | STACK_END( L2, 1); | 830 | STACK_CHECK( L2, 1); |
831 | return true; | 831 | return true; |
832 | } | 832 | } |
833 | 833 | ||
@@ -849,7 +849,7 @@ static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i | |||
849 | 849 | ||
850 | ASSERT_L( L2_cache_i != 0); | 850 | ASSERT_L( L2_cache_i != 0); |
851 | STACK_GROW( L2, 3); | 851 | STACK_GROW( L2, 3); |
852 | STACK_CHECK( L2, 0); | 852 | STACK_CHECK_START_REL(L2, 0); |
853 | 853 | ||
854 | // We don't need to use the from state ('L') in ID since the life span | 854 | // We don't need to use the from state ('L') in ID since the life span |
855 | // is only for the duration of a copy (both states are locked). | 855 | // is only for the duration of a copy (both states are locked). |
@@ -868,7 +868,7 @@ static bool push_cached_table(lua_State* L2, int L2_cache_i, lua_State* L, int i | |||
868 | lua_pushvalue( L2, -2); // ... {} p {} | 868 | lua_pushvalue( L2, -2); // ... {} p {} |
869 | lua_rawset( L2, L2_cache_i); // ... {} | 869 | lua_rawset( L2, L2_cache_i); // ... {} |
870 | } | 870 | } |
871 | STACK_END( L2, 1); | 871 | STACK_CHECK( L2, 1); |
872 | ASSERT_L( lua_istable( L2, -1)); | 872 | ASSERT_L( lua_istable( L2, -1)); |
873 | return !not_found_in_cache; | 873 | return !not_found_in_cache; |
874 | } | 874 | } |
@@ -889,7 +889,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
889 | return shortest_; | 889 | return shortest_; |
890 | } | 890 | } |
891 | STACK_GROW( L, 3); | 891 | STACK_GROW( L, 3); |
892 | STACK_CHECK( L, 0); | 892 | STACK_CHECK_START_REL(L, 0); |
893 | // stack top contains the table to search in | 893 | // stack top contains the table to search in |
894 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} | 894 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} |
895 | lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 | 895 | lua_rawget( L, cache); // o "r" {c} {fqn} ... {?} nil/1 |
@@ -910,14 +910,14 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
910 | { | 910 | { |
911 | //char const *const strKey = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : nullptr; // only for debugging | 911 | //char const *const strKey = (lua_type( L, -2) == LUA_TSTRING) ? lua_tostring( L, -2) : nullptr; // only for debugging |
912 | //lua_Number const numKey = (lua_type( L, -2) == LUA_TNUMBER) ? lua_tonumber( L, -2) : -6666; // only for debugging | 912 | //lua_Number const numKey = (lua_type( L, -2) == LUA_TNUMBER) ? lua_tonumber( L, -2) : -6666; // only for debugging |
913 | STACK_MID( L, 2); | 913 | STACK_CHECK( L, 2); |
914 | // append key name to fqn stack | 914 | // append key name to fqn stack |
915 | ++ depth_; | 915 | ++ depth_; |
916 | lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k | 916 | lua_pushvalue( L, -2); // o "r" {c} {fqn} ... {?} k v k |
917 | lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v | 917 | lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k v |
918 | if( lua_rawequal( L, -1, what)) // is it what we are looking for? | 918 | if( lua_rawequal( L, -1, what)) // is it what we are looking for? |
919 | { | 919 | { |
920 | STACK_MID( L, 2); | 920 | STACK_CHECK( L, 2); |
921 | // update shortest name | 921 | // update shortest name |
922 | if( depth_ < shortest_) | 922 | if( depth_ < shortest_) |
923 | { | 923 | { |
@@ -927,7 +927,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
927 | } | 927 | } |
928 | // no need to search further at this level | 928 | // no need to search further at this level |
929 | lua_pop( L, 2); // o "r" {c} {fqn} ... {?} | 929 | lua_pop( L, 2); // o "r" {c} {fqn} ... {?} |
930 | STACK_MID( L, 0); | 930 | STACK_CHECK( L, 0); |
931 | break; | 931 | break; |
932 | } | 932 | } |
933 | switch( lua_type( L, -1)) // o "r" {c} {fqn} ... {?} k v | 933 | switch( lua_type( L, -1)) // o "r" {c} {fqn} ... {?} k v |
@@ -936,7 +936,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
936 | break; | 936 | break; |
937 | 937 | ||
938 | case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {} | 938 | case LUA_TTABLE: // o "r" {c} {fqn} ... {?} k {} |
939 | STACK_MID( L, 2); | 939 | STACK_CHECK( L, 2); |
940 | shortest_ = discover_object_name_recur( L, shortest_, depth_); | 940 | shortest_ = discover_object_name_recur( L, shortest_, depth_); |
941 | // search in the table's metatable too | 941 | // search in the table's metatable too |
942 | if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt} | 942 | if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k {} {mt} |
@@ -953,7 +953,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
953 | } | 953 | } |
954 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k {} | 954 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k {} |
955 | } | 955 | } |
956 | STACK_MID( L, 2); | 956 | STACK_CHECK( L, 2); |
957 | break; | 957 | break; |
958 | 958 | ||
959 | case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T | 959 | case LUA_TTHREAD: // o "r" {c} {fqn} ... {?} k T |
@@ -961,7 +961,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
961 | break; | 961 | break; |
962 | 962 | ||
963 | case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U | 963 | case LUA_TUSERDATA: // o "r" {c} {fqn} ... {?} k U |
964 | STACK_MID( L, 2); | 964 | STACK_CHECK( L, 2); |
965 | // search in the object's metatable (some modules are built that way) | 965 | // search in the object's metatable (some modules are built that way) |
966 | if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k U {mt} | 966 | if( lua_getmetatable( L, -1)) // o "r" {c} {fqn} ... {?} k U {mt} |
967 | { | 967 | { |
@@ -977,7 +977,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
977 | } | 977 | } |
978 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U | 978 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U |
979 | } | 979 | } |
980 | STACK_MID( L, 2); | 980 | STACK_CHECK( L, 2); |
981 | // search in the object's uservalues | 981 | // search in the object's uservalues |
982 | { | 982 | { |
983 | int uvi = 1; | 983 | int uvi = 1; |
@@ -999,7 +999,7 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
999 | // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now | 999 | // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now |
1000 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U | 1000 | lua_pop( L, 1); // o "r" {c} {fqn} ... {?} k U |
1001 | } | 1001 | } |
1002 | STACK_MID( L, 2); | 1002 | STACK_CHECK( L, 2); |
1003 | break; | 1003 | break; |
1004 | } | 1004 | } |
1005 | // make ready for next iteration | 1005 | // make ready for next iteration |
@@ -1007,15 +1007,15 @@ static int discover_object_name_recur( lua_State* L, int shortest_, int depth_) | |||
1007 | // remove name from fqn stack | 1007 | // remove name from fqn stack |
1008 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil | 1008 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} k nil |
1009 | lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k | 1009 | lua_rawseti( L, fqn, depth_); // o "r" {c} {fqn} ... {?} k |
1010 | STACK_MID( L, 1); | 1010 | STACK_CHECK( L, 1); |
1011 | -- depth_; | 1011 | -- depth_; |
1012 | } // o "r" {c} {fqn} ... {?} | 1012 | } // o "r" {c} {fqn} ... {?} |
1013 | STACK_MID( L, 0); | 1013 | STACK_CHECK( L, 0); |
1014 | // remove the visited table from the cache, in case a shorter path to the searched object exists | 1014 | // remove the visited table from the cache, in case a shorter path to the searched object exists |
1015 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} | 1015 | lua_pushvalue( L, -1); // o "r" {c} {fqn} ... {?} {?} |
1016 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil | 1016 | lua_pushnil( L); // o "r" {c} {fqn} ... {?} {?} nil |
1017 | lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} | 1017 | lua_rawset( L, cache); // o "r" {c} {fqn} ... {?} |
1018 | STACK_END( L, 0); | 1018 | STACK_CHECK( L, 0); |
1019 | return shortest_; | 1019 | return shortest_; |
1020 | } | 1020 | } |
1021 | 1021 | ||
@@ -1040,7 +1040,7 @@ int luaG_nameof( lua_State* L) | |||
1040 | } | 1040 | } |
1041 | 1041 | ||
1042 | STACK_GROW( L, 4); | 1042 | STACK_GROW( L, 4); |
1043 | STACK_CHECK( L, 0); | 1043 | STACK_CHECK_START_REL(L, 0); |
1044 | // this slot will contain the shortest name we found when we are done | 1044 | // this slot will contain the shortest name we found when we are done |
1045 | lua_pushnil( L); // o nil | 1045 | lua_pushnil( L); // o nil |
1046 | // push a cache that will contain all already visited tables | 1046 | // push a cache that will contain all already visited tables |
@@ -1061,7 +1061,7 @@ int luaG_nameof( lua_State* L) | |||
1061 | (void) discover_object_name_recur( L, 6666, 1); | 1061 | (void) discover_object_name_recur( L, 6666, 1); |
1062 | } | 1062 | } |
1063 | lua_pop( L, 3); // o "result" | 1063 | lua_pop( L, 3); // o "result" |
1064 | STACK_END( L, 1); | 1064 | STACK_CHECK( L, 1); |
1065 | lua_pushstring( L, luaL_typename( L, 1)); // o "result" "type" | 1065 | lua_pushstring( L, luaL_typename( L, 1)); // o "result" "type" |
1066 | lua_replace( L, -3); // "type" "result" | 1066 | lua_replace( L, -3); // "type" "result" |
1067 | return 2; | 1067 | return 2; |
@@ -1077,7 +1077,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo | |||
1077 | size_t len; | 1077 | size_t len; |
1078 | char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); | 1078 | char const* fqn = find_lookup_name( L, i, mode_, upName_, &len); |
1079 | // push the equivalent function in the destination's stack, retrieved from the lookup table | 1079 | // push the equivalent function in the destination's stack, retrieved from the lookup table |
1080 | STACK_CHECK( L2, 0); // L // L2 | 1080 | STACK_CHECK_START_REL(L2, 0); // L // L2 |
1081 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error | 1081 | STACK_GROW( L2, 3); // up to 3 slots are necessary on error |
1082 | switch( mode_) | 1082 | switch( mode_) |
1083 | { | 1083 | { |
@@ -1094,7 +1094,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo | |||
1094 | case eLM_LaneBody: | 1094 | case eLM_LaneBody: |
1095 | case eLM_FromKeeper: | 1095 | case eLM_FromKeeper: |
1096 | LOOKUP_REGKEY.query_registry(L2); // {} | 1096 | LOOKUP_REGKEY.query_registry(L2); // {} |
1097 | STACK_MID( L2, 1); | 1097 | STACK_CHECK( L2, 1); |
1098 | ASSERT_L( lua_istable( L2, -1)); | 1098 | ASSERT_L( lua_istable( L2, -1)); |
1099 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" | 1099 | lua_pushlstring( L2, fqn, len); // {} "f.q.n" |
1100 | lua_rawget( L2, -2); // {} f | 1100 | lua_rawget( L2, -2); // {} f |
@@ -1139,7 +1139,7 @@ static void lookup_native_func(lua_State* L2, lua_State* L, int i, LookupMode mo | |||
1139 | break; | 1139 | break; |
1140 | */ | 1140 | */ |
1141 | } | 1141 | } |
1142 | STACK_END( L2, 1); | 1142 | STACK_CHECK( L2, 1); |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | 1145 | ||
@@ -1194,7 +1194,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1194 | 1194 | ||
1195 | ASSERT_L( L2_cache_i != 0); // ... {cache} ... p | 1195 | ASSERT_L( L2_cache_i != 0); // ... {cache} ... p |
1196 | STACK_GROW( L, 2); | 1196 | STACK_GROW( L, 2); |
1197 | STACK_CHECK( L, 0); | 1197 | STACK_CHECK_START_REL(L, 0); |
1198 | 1198 | ||
1199 | 1199 | ||
1200 | // 'lua_dump()' needs the function at top of stack | 1200 | // 'lua_dump()' needs the function at top of stack |
@@ -1270,7 +1270,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1270 | // cache[p] = function | 1270 | // cache[p] = function |
1271 | lua_rawset( L2, L2_cache_i); // ... {cache} ... function | 1271 | lua_rawset( L2, L2_cache_i); // ... {cache} ... function |
1272 | } | 1272 | } |
1273 | STACK_MID( L, 0); | 1273 | STACK_CHECK( L, 0); |
1274 | 1274 | ||
1275 | /* push over any upvalues; references to this function will come from | 1275 | /* push over any upvalues; references to this function will come from |
1276 | * cache so we don't end up in eternal loop. | 1276 | * cache so we don't end up in eternal loop. |
@@ -1311,7 +1311,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1311 | } | 1311 | } |
1312 | // L2: function + 'n' upvalues (>=0) | 1312 | // L2: function + 'n' upvalues (>=0) |
1313 | 1313 | ||
1314 | STACK_MID( L, 0); | 1314 | STACK_CHECK( L, 0); |
1315 | 1315 | ||
1316 | // Set upvalues (originally set to 'nil' by 'lua_load') | 1316 | // Set upvalues (originally set to 'nil' by 'lua_load') |
1317 | { | 1317 | { |
@@ -1329,7 +1329,7 @@ static void copy_func(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1329 | // with the function at the top of the stack // ... {cache} ... function | 1329 | // with the function at the top of the stack // ... {cache} ... function |
1330 | } | 1330 | } |
1331 | } | 1331 | } |
1332 | STACK_END( L, 0); | 1332 | STACK_CHECK( L, 0); |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | /* | 1335 | /* |
@@ -1352,7 +1352,7 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta | |||
1352 | 1352 | ||
1353 | // L2_cache[id_str]= function | 1353 | // L2_cache[id_str]= function |
1354 | // | 1354 | // |
1355 | STACK_CHECK( L2, 0); | 1355 | STACK_CHECK_START_REL(L2, 0); |
1356 | 1356 | ||
1357 | // We don't need to use the from state ('L') in ID since the life span | 1357 | // We don't need to use the from state ('L') in ID since the life span |
1358 | // is only for the duration of a copy (both states are locked). | 1358 | // is only for the duration of a copy (both states are locked). |
@@ -1380,7 +1380,7 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta | |||
1380 | { | 1380 | { |
1381 | lua_remove( L2, -2); // ... {cache} ... function | 1381 | lua_remove( L2, -2); // ... {cache} ... function |
1382 | } | 1382 | } |
1383 | STACK_END( L2, 1); | 1383 | STACK_CHECK( L2, 1); |
1384 | ASSERT_L( lua_isfunction( L2, -1)); | 1384 | ASSERT_L( lua_isfunction( L2, -1)); |
1385 | } | 1385 | } |
1386 | else // function is native/LuaJIT: no need to cache | 1386 | else // function is native/LuaJIT: no need to cache |
@@ -1393,26 +1393,26 @@ static void copy_cached_func(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta | |||
1393 | 1393 | ||
1394 | static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) | 1394 | static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) |
1395 | { | 1395 | { |
1396 | STACK_CHECK( L, 0); | 1396 | STACK_CHECK_START_REL(L, 0); |
1397 | if( lua_getmetatable( L, i)) // ... mt | 1397 | if( lua_getmetatable( L, i)) // ... mt |
1398 | { | 1398 | { |
1399 | lua_Integer const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable | 1399 | lua_Integer const mt_id = get_mt_id( U, L, -1); // Unique id for the metatable |
1400 | 1400 | ||
1401 | STACK_CHECK( L2, 0); | 1401 | STACK_CHECK_START_REL(L2, 0); |
1402 | STACK_GROW( L2, 4); | 1402 | STACK_GROW( L2, 4); |
1403 | // do we already know this metatable? | 1403 | // do we already know this metatable? |
1404 | push_registry_subtable( L2, REG_MTID); // _R[REG_MTID] | 1404 | push_registry_subtable( L2, REG_MTID); // _R[REG_MTID] |
1405 | lua_pushinteger( L2, mt_id); // _R[REG_MTID] id | 1405 | lua_pushinteger( L2, mt_id); // _R[REG_MTID] id |
1406 | lua_rawget( L2, -2); // _R[REG_MTID] mt? | 1406 | lua_rawget( L2, -2); // _R[REG_MTID] mt? |
1407 | 1407 | ||
1408 | STACK_MID( L2, 2); | 1408 | STACK_CHECK( L2, 2); |
1409 | 1409 | ||
1410 | if( lua_isnil( L2, -1)) | 1410 | if( lua_isnil( L2, -1)) |
1411 | { // L2 did not know the metatable | 1411 | { // L2 did not know the metatable |
1412 | lua_pop( L2, 1); // _R[REG_MTID] | 1412 | lua_pop( L2, 1); // _R[REG_MTID] |
1413 | if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // _R[REG_MTID] mt | 1413 | if( inter_copy_one( U, L2, L2_cache_i, L, lua_gettop( L), VT_METATABLE, mode_, upName_)) // _R[REG_MTID] mt |
1414 | { | 1414 | { |
1415 | STACK_MID( L2, 2); | 1415 | STACK_CHECK( L2, 2); |
1416 | // mt_id -> metatable | 1416 | // mt_id -> metatable |
1417 | lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id | 1417 | lua_pushinteger( L2, mt_id); // _R[REG_MTID] mt id |
1418 | lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt | 1418 | lua_pushvalue( L2, -2); // _R[REG_MTID] mt id mt |
@@ -1427,16 +1427,16 @@ static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lu | |||
1427 | { | 1427 | { |
1428 | (void) luaL_error( L, "Error copying a metatable"); | 1428 | (void) luaL_error( L, "Error copying a metatable"); |
1429 | } | 1429 | } |
1430 | STACK_MID( L2, 2); | 1430 | STACK_CHECK( L2, 2); |
1431 | } | 1431 | } |
1432 | lua_remove( L2, -2); // mt | 1432 | lua_remove( L2, -2); // mt |
1433 | 1433 | ||
1434 | lua_pop( L, 1); // ... | 1434 | lua_pop( L, 1); // ... |
1435 | STACK_END( L2, 1); | 1435 | STACK_CHECK( L2, 1); |
1436 | STACK_MID( L, 0); | 1436 | STACK_CHECK( L, 0); |
1437 | return true; | 1437 | return true; |
1438 | } | 1438 | } |
1439 | STACK_END( L, 0); | 1439 | STACK_CHECK( L, 0); |
1440 | return false; | 1440 | return false; |
1441 | } | 1441 | } |
1442 | 1442 | ||
@@ -1515,27 +1515,27 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1515 | void* const source = lua_touserdata( L, source_i_); | 1515 | void* const source = lua_touserdata( L, source_i_); |
1516 | source_i_ = lua_absindex( L, source_i_); | 1516 | source_i_ = lua_absindex( L, source_i_); |
1517 | 1517 | ||
1518 | STACK_CHECK( L, 0); // L (source) // L2 (destination) | 1518 | STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination) |
1519 | STACK_CHECK( L2, 0); | 1519 | STACK_CHECK_START_REL(L2, 0); |
1520 | 1520 | ||
1521 | // Check if the source was already cloned during this copy | 1521 | // Check if the source was already cloned during this copy |
1522 | lua_pushlightuserdata( L2, source); // ... source | 1522 | lua_pushlightuserdata( L2, source); // ... source |
1523 | lua_rawget( L2, L2_cache_i); // ... clone? | 1523 | lua_rawget( L2, L2_cache_i); // ... clone? |
1524 | if ( !lua_isnil( L2, -1)) | 1524 | if ( !lua_isnil( L2, -1)) |
1525 | { | 1525 | { |
1526 | STACK_MID( L2, 1); | 1526 | STACK_CHECK( L2, 1); |
1527 | return true; | 1527 | return true; |
1528 | } | 1528 | } |
1529 | else | 1529 | else |
1530 | { | 1530 | { |
1531 | lua_pop( L2, 1); // ... | 1531 | lua_pop( L2, 1); // ... |
1532 | } | 1532 | } |
1533 | STACK_MID( L2, 0); | 1533 | STACK_CHECK( L2, 0); |
1534 | 1534 | ||
1535 | // no metatable? -> not clonable | 1535 | // no metatable? -> not clonable |
1536 | if( !lua_getmetatable( L, source_i_)) // ... mt? | 1536 | if( !lua_getmetatable( L, source_i_)) // ... mt? |
1537 | { | 1537 | { |
1538 | STACK_MID( L, 0); | 1538 | STACK_CHECK( L, 0); |
1539 | return false; | 1539 | return false; |
1540 | } | 1540 | } |
1541 | 1541 | ||
@@ -1544,7 +1544,7 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1544 | if( lua_isnil( L, -1)) | 1544 | if( lua_isnil( L, -1)) |
1545 | { | 1545 | { |
1546 | lua_pop( L, 2); // ... | 1546 | lua_pop( L, 2); // ... |
1547 | STACK_MID( L, 0); | 1547 | STACK_CHECK( L, 0); |
1548 | return false; | 1548 | return false; |
1549 | } | 1549 | } |
1550 | 1550 | ||
@@ -1578,7 +1578,7 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1578 | ASSERT_L( lua_istable( L2, -1)); | 1578 | ASSERT_L( lua_istable( L2, -1)); |
1579 | lua_setmetatable( L2, -2); // ... u | 1579 | lua_setmetatable( L2, -2); // ... u |
1580 | } | 1580 | } |
1581 | STACK_MID( L2, 1); | 1581 | STACK_CHECK( L2, 1); |
1582 | } | 1582 | } |
1583 | else | 1583 | else |
1584 | { | 1584 | { |
@@ -1597,7 +1597,7 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1597 | while( uvi > 0) | 1597 | while( uvi > 0) |
1598 | { | 1598 | { |
1599 | inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv | 1599 | inter_copy_one( U, L2, L2_cache_i, L, lua_absindex( L, -1), VT_NORMAL, mode_, upName_); // ... u uv |
1600 | lua_pop( L, 1); // ... mt __lanesclone [uv]* | 1600 | lua_pop( L, 1); // ... mt __lanesclone [uv]* |
1601 | // this pops the value from the stack | 1601 | // this pops the value from the stack |
1602 | lua_setiuservalue( L2, -2, uvi); // ... u | 1602 | lua_setiuservalue( L2, -2, uvi); // ... u |
1603 | -- uvi; | 1603 | -- uvi; |
@@ -1607,26 +1607,26 @@ static bool copyclone(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, | |||
1607 | { | 1607 | { |
1608 | lua_pop( L2, 1); // ... userdata_clone_sentinel | 1608 | lua_pop( L2, 1); // ... userdata_clone_sentinel |
1609 | } | 1609 | } |
1610 | STACK_MID( L2, 1); | 1610 | STACK_CHECK( L2, 1); |
1611 | STACK_MID( L, 2); | 1611 | STACK_CHECK( L, 2); |
1612 | // call cloning function in source state to perform the actual memory cloning | 1612 | // call cloning function in source state to perform the actual memory cloning |
1613 | lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone | 1613 | lua_pushlightuserdata( L, clone); // ... mt __lanesclone clone |
1614 | lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source | 1614 | lua_pushlightuserdata( L, source); // ... mt __lanesclone clone source |
1615 | lua_pushinteger( L, userdata_size); // ... mt __lanesclone clone source size | 1615 | lua_pushinteger( L, userdata_size); // ... mt __lanesclone clone source size |
1616 | lua_call( L, 3, 0); // ... mt | 1616 | lua_call( L, 3, 0); // ... mt |
1617 | STACK_MID( L, 1); | 1617 | STACK_CHECK( L, 1); |
1618 | } | 1618 | } |
1619 | 1619 | ||
1620 | STACK_END( L2, 1); | 1620 | STACK_CHECK( L2, 1); |
1621 | lua_pop( L, 1); // ... | 1621 | lua_pop( L, 1); // ... |
1622 | STACK_END( L, 0); | 1622 | STACK_CHECK( L, 0); |
1623 | return true; | 1623 | return true; |
1624 | } | 1624 | } |
1625 | 1625 | ||
1626 | static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, enum e_vt vt, LookupMode mode_, char const* upName_) | 1626 | static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, enum e_vt vt, LookupMode mode_, char const* upName_) |
1627 | { | 1627 | { |
1628 | STACK_CHECK( L, 0); | 1628 | STACK_CHECK_START_REL(L, 0); |
1629 | STACK_CHECK( L2, 0); | 1629 | STACK_CHECK_START_REL(L2, 0); |
1630 | if( vt == VT_KEY) | 1630 | if( vt == VT_KEY) |
1631 | { | 1631 | { |
1632 | return false; | 1632 | return false; |
@@ -1635,25 +1635,25 @@ static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1635 | // try clonable userdata first | 1635 | // try clonable userdata first |
1636 | if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_)) | 1636 | if( copyclone( U, L2, L2_cache_i, L, i, mode_, upName_)) |
1637 | { | 1637 | { |
1638 | STACK_MID( L, 0); | 1638 | STACK_CHECK( L, 0); |
1639 | STACK_MID( L2, 1); | 1639 | STACK_CHECK( L2, 1); |
1640 | return true; | 1640 | return true; |
1641 | } | 1641 | } |
1642 | 1642 | ||
1643 | STACK_MID( L, 0); | 1643 | STACK_CHECK( L, 0); |
1644 | STACK_MID( L2, 0); | 1644 | STACK_CHECK( L2, 0); |
1645 | 1645 | ||
1646 | // Allow only deep userdata entities to be copied across | 1646 | // Allow only deep userdata entities to be copied across |
1647 | DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n")); | 1647 | DEBUGSPEW_CODE( fprintf( stderr, "USERDATA\n")); |
1648 | if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_)) | 1648 | if( copydeep( U, L2, L2_cache_i, L, i, mode_, upName_)) |
1649 | { | 1649 | { |
1650 | STACK_MID( L, 0); | 1650 | STACK_CHECK( L, 0); |
1651 | STACK_MID( L2, 1); | 1651 | STACK_CHECK( L2, 1); |
1652 | return true; | 1652 | return true; |
1653 | } | 1653 | } |
1654 | 1654 | ||
1655 | STACK_MID( L, 0); | 1655 | STACK_CHECK( L, 0); |
1656 | STACK_MID( L2, 0); | 1656 | STACK_CHECK( L2, 0); |
1657 | 1657 | ||
1658 | // Not a deep or clonable full userdata | 1658 | // Not a deep or clonable full userdata |
1659 | if( U->demoteFullUserdata) // attempt demotion to light userdata | 1659 | if( U->demoteFullUserdata) // attempt demotion to light userdata |
@@ -1666,8 +1666,8 @@ static bool inter_copy_userdata(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1666 | (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); | 1666 | (void) luaL_error( L, "can't copy non-deep full userdata across lanes"); |
1667 | } | 1667 | } |
1668 | 1668 | ||
1669 | STACK_END( L2, 1); | 1669 | STACK_CHECK( L2, 1); |
1670 | STACK_END( L, 0); | 1670 | STACK_CHECK( L, 0); |
1671 | return true; | 1671 | return true; |
1672 | } | 1672 | } |
1673 | 1673 | ||
@@ -1678,8 +1678,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1678 | return false; | 1678 | return false; |
1679 | } | 1679 | } |
1680 | 1680 | ||
1681 | STACK_CHECK( L, 0); // L (source) // L2 (destination) | 1681 | STACK_CHECK_START_REL(L, 0); // L (source) // L2 (destination) |
1682 | STACK_CHECK( L2, 0); | 1682 | STACK_CHECK_START_REL(L2, 0); |
1683 | DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); | 1683 | DEBUGSPEW_CODE( fprintf( stderr, "FUNCTION %s\n", upName_)); |
1684 | 1684 | ||
1685 | if( lua_tocfunction( L, source_i_) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper | 1685 | if( lua_tocfunction( L, source_i_) == userdata_clone_sentinel) // we are actually copying a clonable full userdata from a keeper |
@@ -1697,8 +1697,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1697 | if( !lua_isnil( L2, -1)) | 1697 | if( !lua_isnil( L2, -1)) |
1698 | { | 1698 | { |
1699 | lua_pop( L, 1); // ... | 1699 | lua_pop( L, 1); // ... |
1700 | STACK_MID( L, 0); | 1700 | STACK_CHECK( L, 0); |
1701 | STACK_MID( L2, 1); | 1701 | STACK_CHECK( L2, 1); |
1702 | return true; | 1702 | return true; |
1703 | } | 1703 | } |
1704 | lua_pop( L2, 1); // ... | 1704 | lua_pop( L2, 1); // ... |
@@ -1717,7 +1717,7 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1717 | // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now | 1717 | // when lua_getiuservalue() returned LUA_TNONE, it pushed a nil. pop it now |
1718 | lua_pop( L, 1); // ... u [uv]* | 1718 | lua_pop( L, 1); // ... u [uv]* |
1719 | -- uvi; | 1719 | -- uvi; |
1720 | STACK_MID( L, uvi + 1); | 1720 | STACK_CHECK( L, uvi + 1); |
1721 | // create the clone userdata with the required number of uservalue slots | 1721 | // create the clone userdata with the required number of uservalue slots |
1722 | clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt u | 1722 | clone = lua_newuserdatauv( L2, userdata_size, uvi); // ... mt u |
1723 | // add it in the cache | 1723 | // add it in the cache |
@@ -1738,8 +1738,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1738 | } | 1738 | } |
1739 | // when we are done, all uservalues are popped from the stack, we can pop the source as well | 1739 | // when we are done, all uservalues are popped from the stack, we can pop the source as well |
1740 | lua_pop( L, 1); // ... | 1740 | lua_pop( L, 1); // ... |
1741 | STACK_MID( L, 0); | 1741 | STACK_CHECK( L, 0); |
1742 | STACK_MID( L2, 2); // ... mt u | 1742 | STACK_CHECK( L2, 2); // ... mt u |
1743 | } | 1743 | } |
1744 | // perform the custom cloning part | 1744 | // perform the custom cloning part |
1745 | lua_insert( L2, -2); // ... u mt | 1745 | lua_insert( L2, -2); // ... u mt |
@@ -1759,8 +1759,8 @@ static bool inter_copy_function(Universe* U, lua_State* L2, int L2_cache_i, lua_ | |||
1759 | copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f | 1759 | copy_cached_func( U, L2, L2_cache_i, L, source_i_, mode_, upName_); // ... f |
1760 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1760 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1761 | } | 1761 | } |
1762 | STACK_END( L2, 1); | 1762 | STACK_CHECK( L2, 1); |
1763 | STACK_END( L, 0); | 1763 | STACK_CHECK( L, 0); |
1764 | return true; | 1764 | return true; |
1765 | } | 1765 | } |
1766 | 1766 | ||
@@ -1771,8 +1771,8 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta | |||
1771 | return false; | 1771 | return false; |
1772 | } | 1772 | } |
1773 | 1773 | ||
1774 | STACK_CHECK( L, 0); | 1774 | STACK_CHECK_START_REL(L, 0); |
1775 | STACK_CHECK( L2, 0); | 1775 | STACK_CHECK_START_REL(L2, 0); |
1776 | DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_)); | 1776 | DEBUGSPEW_CODE( fprintf( stderr, "TABLE %s\n", upName_)); |
1777 | 1777 | ||
1778 | /* | 1778 | /* |
@@ -1811,16 +1811,16 @@ static bool inter_copy_table(Universe* U, lua_State* L2, int L2_cache_i, lua_Sta | |||
1811 | inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_); | 1811 | inter_copy_keyvaluepair( U, L2, L2_cache_i, L, vt, mode_, upName_); |
1812 | lua_pop( L, 1); // pop value (next round) | 1812 | lua_pop( L, 1); // pop value (next round) |
1813 | } | 1813 | } |
1814 | STACK_MID( L, 0); | 1814 | STACK_CHECK( L, 0); |
1815 | STACK_MID( L2, 1); | 1815 | STACK_CHECK( L2, 1); |
1816 | 1816 | ||
1817 | // Metatables are expected to be immutable, and copied only once. | 1817 | // Metatables are expected to be immutable, and copied only once. |
1818 | if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt? | 1818 | if( push_cached_metatable( U, L2, L2_cache_i, L, i, mode_, upName_)) // ... t mt? |
1819 | { | 1819 | { |
1820 | lua_setmetatable( L2, -2); // ... t | 1820 | lua_setmetatable( L2, -2); // ... t |
1821 | } | 1821 | } |
1822 | STACK_END( L2, 1); | 1822 | STACK_CHECK( L2, 1); |
1823 | STACK_END( L, 0); | 1823 | STACK_CHECK( L, 0); |
1824 | return true; | 1824 | return true; |
1825 | } | 1825 | } |
1826 | 1826 | ||
@@ -1840,8 +1840,8 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in | |||
1840 | int val_type = lua_type( L, i); | 1840 | int val_type = lua_type( L, i); |
1841 | static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING); | 1841 | static int const pod_mask = (1 << LUA_TNIL) | (1 << LUA_TBOOLEAN) | (1 << LUA_TLIGHTUSERDATA) | (1 << LUA_TNUMBER) | (1 << LUA_TSTRING); |
1842 | STACK_GROW( L2, 1); | 1842 | STACK_GROW( L2, 1); |
1843 | STACK_CHECK( L, 0); // L // L2 | 1843 | STACK_CHECK_START_REL(L, 0); // L // L2 |
1844 | STACK_CHECK( L2, 0); // L // L2 | 1844 | STACK_CHECK_START_REL(L2, 0); // L // L2 |
1845 | 1845 | ||
1846 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); | 1846 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "inter_copy_one()\n" INDENT_END)); |
1847 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 1847 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
@@ -1861,7 +1861,7 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in | |||
1861 | lua_pop( L, 2); // ... | 1861 | lua_pop( L, 2); // ... |
1862 | } | 1862 | } |
1863 | } | 1863 | } |
1864 | STACK_MID( L, 0); | 1864 | STACK_CHECK( L, 0); |
1865 | 1865 | ||
1866 | /* Lets push nil to L2 if the object should be ignored */ | 1866 | /* Lets push nil to L2 if the object should be ignored */ |
1867 | switch( val_type) | 1867 | switch( val_type) |
@@ -1945,8 +1945,8 @@ bool inter_copy_one(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, in | |||
1945 | 1945 | ||
1946 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 1946 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
1947 | 1947 | ||
1948 | STACK_END( L2, ret ? 1 : 0); | 1948 | STACK_CHECK( L2, ret ? 1 : 0); |
1949 | STACK_END( L, 0); | 1949 | STACK_CHECK( L, 0); |
1950 | return ret; | 1950 | return ret; |
1951 | } | 1951 | } |
1952 | 1952 | ||
@@ -1977,7 +1977,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode | |||
1977 | return -1; | 1977 | return -1; |
1978 | } | 1978 | } |
1979 | 1979 | ||
1980 | STACK_CHECK( L2, 0); | 1980 | STACK_CHECK_START_REL(L2, 0); |
1981 | STACK_GROW( L2, n + 1); | 1981 | STACK_GROW( L2, n + 1); |
1982 | 1982 | ||
1983 | /* | 1983 | /* |
@@ -1987,7 +1987,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode | |||
1987 | */ | 1987 | */ |
1988 | lua_newtable( L2); // ... cache | 1988 | lua_newtable( L2); // ... cache |
1989 | 1989 | ||
1990 | STACK_CHECK( L, 0); | 1990 | STACK_CHECK_START_REL(L, 0); |
1991 | for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j) | 1991 | for( i = top_L - n + 1, j = 1; i <= top_L; ++ i, ++ j) |
1992 | { | 1992 | { |
1993 | if( U->verboseErrors) | 1993 | if( U->verboseErrors) |
@@ -2000,13 +2000,13 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode | |||
2000 | break; | 2000 | break; |
2001 | } | 2001 | } |
2002 | } | 2002 | } |
2003 | STACK_END( L, 0); | 2003 | STACK_CHECK( L, 0); |
2004 | 2004 | ||
2005 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2005 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
2006 | 2006 | ||
2007 | if( copyok) | 2007 | if( copyok) |
2008 | { | 2008 | { |
2009 | STACK_MID( L2, n + 1); | 2009 | STACK_CHECK( L2, n + 1); |
2010 | // Remove the cache table. Persistent caching would cause i.e. multiple | 2010 | // Remove the cache table. Persistent caching would cause i.e. multiple |
2011 | // messages passed in the same table to use the same table also in receiving end. | 2011 | // messages passed in the same table to use the same table also in receiving end. |
2012 | lua_remove( L2, top_L2 + 1); | 2012 | lua_remove( L2, top_L2 + 1); |
@@ -2015,7 +2015,7 @@ int luaG_inter_copy(Universe* U, lua_State* L, lua_State* L2, int n, LookupMode | |||
2015 | 2015 | ||
2016 | // error -> pop everything from the target state stack | 2016 | // error -> pop everything from the target state stack |
2017 | lua_settop( L2, top_L2); | 2017 | lua_settop( L2, top_L2); |
2018 | STACK_END( L2, 0); | 2018 | STACK_CHECK( L2, 0); |
2019 | return -2; | 2019 | return -2; |
2020 | } | 2020 | } |
2021 | 2021 | ||
@@ -2032,13 +2032,13 @@ int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int packa | |||
2032 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); | 2032 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "luaG_inter_copy_package()\n" INDENT_END)); |
2033 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); | 2033 | DEBUGSPEW_CODE( ++ U->debugspew_indent_depth); |
2034 | // package | 2034 | // package |
2035 | STACK_CHECK( L, 0); | 2035 | STACK_CHECK_START_REL(L, 0); |
2036 | STACK_CHECK( L2, 0); | 2036 | STACK_CHECK_START_REL(L2, 0); |
2037 | package_idx_ = lua_absindex( L, package_idx_); | 2037 | package_idx_ = lua_absindex( L, package_idx_); |
2038 | if( lua_type( L, package_idx_) != LUA_TTABLE) | 2038 | if( lua_type( L, package_idx_) != LUA_TTABLE) |
2039 | { | 2039 | { |
2040 | lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_)); | 2040 | lua_pushfstring( L, "expected package as table, got %s", luaL_typename( L, package_idx_)); |
2041 | STACK_MID( L, 1); | 2041 | STACK_CHECK( L, 1); |
2042 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later | 2042 | // raise the error when copying from lane to lane, else just leave it on the stack to be raised later |
2043 | return ( mode_ == eLM_LaneBody) ? lua_error( L) : 1; | 2043 | return ( mode_ == eLM_LaneBody) ? lua_error( L) : 1; |
2044 | } | 2044 | } |
@@ -2073,8 +2073,8 @@ int luaG_inter_copy_package( Universe* U, lua_State* L, lua_State* L2, int packa | |||
2073 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); | 2073 | DEBUGSPEW_CODE( fprintf( stderr, INDENT_BEGIN "'package' not loaded, nothing to do\n" INDENT_END)); |
2074 | } | 2074 | } |
2075 | lua_pop( L2, 1); | 2075 | lua_pop( L2, 1); |
2076 | STACK_END( L2, 0); | 2076 | STACK_CHECK( L2, 0); |
2077 | STACK_END( L, 0); | 2077 | STACK_CHECK( L, 0); |
2078 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); | 2078 | DEBUGSPEW_CODE( -- U->debugspew_indent_depth); |
2079 | return 0; | 2079 | return 0; |
2080 | } | 2080 | } |
diff --git a/src/universe.cpp b/src/universe.cpp index 5d0d3b6..06c7313 100644 --- a/src/universe.cpp +++ b/src/universe.cpp | |||
@@ -41,35 +41,35 @@ static constexpr UniqueKey UNIVERSE_REGKEY{ 0x9f877b2cf078f17full }; | |||
41 | 41 | ||
42 | // ################################################################################################ | 42 | // ################################################################################################ |
43 | 43 | ||
44 | Universe* universe_create( lua_State* L) | 44 | Universe* universe_create(lua_State* L) |
45 | { | 45 | { |
46 | Universe* U = (Universe*) lua_newuserdatauv( L, sizeof(Universe), 0); // universe | 46 | Universe* U = (Universe*) lua_newuserdatauv( L, sizeof(Universe), 0); // universe |
47 | memset( U, 0, sizeof( Universe)); | 47 | memset( U, 0, sizeof( Universe)); |
48 | STACK_CHECK( L, 1); | 48 | STACK_CHECK_START_REL(L, 1); |
49 | UNIVERSE_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // universe | 49 | UNIVERSE_REGKEY.set_registry(L, [](lua_State* L) { lua_pushvalue(L, -2); }); // universe |
50 | STACK_END( L, 1); | 50 | STACK_CHECK( L, 1); |
51 | return U; | 51 | return U; |
52 | } | 52 | } |
53 | 53 | ||
54 | // ################################################################################################ | 54 | // ################################################################################################ |
55 | 55 | ||
56 | void universe_store( lua_State* L, Universe* U) | 56 | void universe_store(lua_State* L, Universe* U) |
57 | { | 57 | { |
58 | STACK_CHECK( L, 0); | 58 | STACK_CHECK_START_REL(L, 0); |
59 | UNIVERSE_REGKEY.set_registry(L, [U](lua_State* L) { U ? lua_pushlightuserdata( L, U) : lua_pushnil( L); }); | 59 | UNIVERSE_REGKEY.set_registry(L, [U](lua_State* L) { U ? lua_pushlightuserdata( L, U) : lua_pushnil( L); }); |
60 | STACK_END( L, 0); | 60 | STACK_CHECK( L, 0); |
61 | } | 61 | } |
62 | 62 | ||
63 | // ################################################################################################ | 63 | // ################################################################################################ |
64 | 64 | ||
65 | Universe* universe_get( lua_State* L) | 65 | Universe* universe_get(lua_State* L) |
66 | { | 66 | { |
67 | Universe* universe; | 67 | Universe* universe; |
68 | STACK_GROW( L, 2); | 68 | STACK_GROW( L, 2); |
69 | STACK_CHECK( L, 0); | 69 | STACK_CHECK_START_REL(L, 0); |
70 | UNIVERSE_REGKEY.query_registry(L); | 70 | UNIVERSE_REGKEY.query_registry(L); |
71 | universe = (Universe*) lua_touserdata( L, -1); // nullptr if nil | 71 | universe = (Universe*) lua_touserdata( L, -1); // nullptr if nil |
72 | lua_pop( L, 1); | 72 | lua_pop( L, 1); |
73 | STACK_END( L, 0); | 73 | STACK_CHECK( L, 0); |
74 | return universe; | 74 | return universe; |
75 | } | 75 | } |