aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/deep.cpp41
-rw-r--r--src/keeper.cpp46
-rw-r--r--src/lanes.cpp107
-rw-r--r--src/lanes_private.h7
-rw-r--r--src/linda.cpp16
-rw-r--r--src/macros_and_utils.h116
-rw-r--r--src/state.cpp76
-rw-r--r--src/tools.cpp252
-rw-r--r--src/universe.cpp18
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 };
74static void set_deep_lookup( lua_State* L) 74static 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)
93static void get_deep_lookup( lua_State* L) 93static 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 };
170static void push_table(lua_State* L, int idx_) 170static 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
246int keepercall_clear(lua_State* L) 246int 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 */
638void init_keepers(Universe* U, lua_State* L) 638void 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
114static void securize_debug_threadname( lua_State* L, Lane* s) 114static 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;
155static bool push_registry_table( lua_State* L, UniqueKey key, bool create) 155static 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
676static int lane_error( lua_State* L) 677static 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
2136LANES_API void luaopen_lanes_embedded( lua_State* L, lua_CFunction _luaopen_lanes) 2137LANES_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
81static inline Lane* get_lane_from_registry( lua_State* L) 81static 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()
15extern char const* debugspew_indent; 17extern 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
45class 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*/
94void serialize_require( DEBUGSPEW_PARAM_COMMA( Universe* U) lua_State* L) 94void 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
197static void copy_one_time_settings( Universe* U, lua_State* L, lua_State* L2) 197static 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
219void initialize_on_state_create( Universe* U, lua_State* L) 219void 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
250lua_State* create_state( Universe* U, lua_State* from_) 250lua_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 = "----+----!----+----!----+----!--
62void push_registry_subtable_mode( lua_State* L, UniqueKey key_, const char* mode_) 62void 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?
194void initialize_allocator_function( Universe* U, lua_State* L) 194void 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
254void cleanup_allocator_function( Universe* U, lua_State* L) 254void 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
1394static bool push_cached_metatable(Universe* U, lua_State* L2, int L2_cache_i, lua_State* L, int i, LookupMode mode_, char const* upName_) 1394static 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
1626static 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_) 1626static 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
44Universe* universe_create( lua_State* L) 44Universe* 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
56void universe_store( lua_State* L, Universe* U) 56void 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
65Universe* universe_get( lua_State* L) 65Universe* 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}