aboutsummaryrefslogtreecommitdiff
path: root/src/lane.cpp
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-10-08 18:42:39 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-10-08 18:42:39 +0200
commit16b5070c0cd56e10c5074eb9903dbc3ae4e15a61 (patch)
treef6d5cdb74b505e13aa3261f7ab6192da0133b7b9 /src/lane.cpp
parente939e5e6a894a042d3301e47faa05264445f27f6 (diff)
downloadlanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.gz
lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.tar.bz2
lanes-16b5070c0cd56e10c5074eb9903dbc3ae4e15a61.zip
Sprinkling StackIndex all over the place
Diffstat (limited to 'src/lane.cpp')
-rw-r--r--src/lane.cpp140
1 files changed, 71 insertions, 69 deletions
diff --git a/src/lane.cpp b/src/lane.cpp
index baba0fa..d4d409f 100644
--- a/src/lane.cpp
+++ b/src/lane.cpp
@@ -47,7 +47,7 @@ static constexpr UniqueKey kCachedTostring{ 0xAB5EA23BCEA0C35Cull };
47// lane:get_threadname() 47// lane:get_threadname()
48static LUAG_FUNC(get_threadname) 48static LUAG_FUNC(get_threadname)
49{ 49{
50 Lane* const _lane{ ToLane(L_, 1) }; 50 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) };
51 luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments"); 51 luaL_argcheck(L_, lua_gettop(L_) == 1, 2, "too many arguments");
52 luaG_pushstring(L_, _lane->getDebugName()); 52 luaG_pushstring(L_, _lane->getDebugName());
53 return 1; 53 return 1;
@@ -70,7 +70,7 @@ static LUAG_FUNC(set_finalizer)
70 // Get the current finalizer table (if any), create one if it doesn't exist 70 // Get the current finalizer table (if any), create one if it doesn't exist
71 std::ignore = kFinalizerRegKey.getSubTable(L_, 1, 0); // L_: finalizer {finalisers} 71 std::ignore = kFinalizerRegKey.getSubTable(L_, 1, 0); // L_: finalizer {finalisers}
72 // must cast to int, not lua_Integer, because LuaJIT signature of lua_rawseti is not the same as PUC-Lua. 72 // must cast to int, not lua_Integer, because LuaJIT signature of lua_rawseti is not the same as PUC-Lua.
73 int const _idx{ static_cast<int>(lua_rawlen(L_, -1) + 1) }; 73 int const _idx{ static_cast<int>(lua_rawlen(L_, kIdxTop) + 1) };
74 lua_pushvalue(L_, 1); // L_: finalizer {finalisers} finalizer 74 lua_pushvalue(L_, 1); // L_: finalizer {finalisers} finalizer
75 lua_rawseti(L_, -2, _idx); // L_: finalizer {finalisers} 75 lua_rawseti(L_, -2, _idx); // L_: finalizer {finalisers}
76 // no need to adjust the stack, Lua does this for us 76 // no need to adjust the stack, Lua does this for us
@@ -85,12 +85,12 @@ static LUAG_FUNC(set_finalizer)
85static LUAG_FUNC(lane_threadname) 85static LUAG_FUNC(lane_threadname)
86{ 86{
87 // C s_lane structure is a light userdata upvalue 87 // C s_lane structure is a light userdata upvalue
88 Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, lua_upvalueindex(1)) }; 88 Lane* const _lane{ luaG_tolightuserdata<Lane>(L_, StackIndex{ lua_upvalueindex(1) }) };
89 LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state 89 LUA_ASSERT(L_, L_ == _lane->L); // this function is exported in a lane's state, therefore it is callable only from inside the Lane's state
90 if (lua_gettop(L_) == 1) { 90 if (lua_gettop(L_) == 1) {
91 lua_settop(L_, 1); 91 lua_settop(L_, 1);
92 STACK_CHECK_START_REL(L_, 0); 92 STACK_CHECK_START_REL(L_, 0);
93 _lane->changeDebugName(-1); 93 _lane->changeDebugName(kIdxTop);
94 STACK_CHECK(L_, 0); 94 STACK_CHECK(L_, 0);
95 return 0; 95 return 0;
96 } else if (lua_gettop(L_) == 0) { 96 } else if (lua_gettop(L_) == 0) {
@@ -113,19 +113,19 @@ static LUAG_FUNC(lane_threadname)
113// 113//
114static LUAG_FUNC(thread_join) 114static LUAG_FUNC(thread_join)
115{ 115{
116 Lane* const _lane{ ToLane(L_, 1) }; 116 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) };
117 117
118 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() }; 118 std::chrono::time_point<std::chrono::steady_clock> _until{ std::chrono::time_point<std::chrono::steady_clock>::max() };
119 if (luaG_type(L_, 2) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion 119 if (luaG_type(L_, StackIndex{ 2 }) == LuaType::NUMBER) { // we don't want to use lua_isnumber() because of autocoercion
120 lua_Duration const duration{ lua_tonumber(L_, 2) }; 120 lua_Duration const duration{ lua_tonumber(L_, 2) };
121 if (duration.count() >= 0.0) { 121 if (duration.count() >= 0.0) {
122 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration); 122 _until = std::chrono::steady_clock::now() + std::chrono::duration_cast<std::chrono::steady_clock::duration>(duration);
123 } else { 123 } else {
124 raise_luaL_argerror(L_, 2, "duration cannot be < 0"); 124 raise_luaL_argerror(L_, StackIndex{ 2 }, "duration cannot be < 0");
125 } 125 }
126 126
127 } else if (!lua_isnoneornil(L_, 2)) { 127 } else if (!lua_isnoneornil(L_, 2)) {
128 raise_luaL_argerror(L_, 2, "incorrect duration type"); 128 raise_luaL_argerror(L_, StackIndex{ 2 }, "incorrect duration type");
129 } 129 }
130 130
131 lua_settop(L_, 1); // L_: lane 131 lua_settop(L_, 1); // L_: lane
@@ -150,7 +150,7 @@ static LUAG_FUNC(thread_join)
150 if (_stored == 0) { 150 if (_stored == 0) {
151 raise_luaL_error(L_, _lane->L ? "First return value must be non-nil when using join()" : "Can't join() more than once or after indexing"); 151 raise_luaL_error(L_, _lane->L ? "First return value must be non-nil when using join()" : "Can't join() more than once or after indexing");
152 } 152 }
153 lua_getiuservalue(L_, 1, 1); // L_: lane {uv} 153 lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv}
154 for (int _i = 2; _i <= _stored; ++_i) { 154 for (int _i = 2; _i <= _stored; ++_i) {
155 lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N 155 lua_rawgeti(L_, 2, _i); // L_: lane {uv} results2...N
156 } 156 }
@@ -163,7 +163,7 @@ static LUAG_FUNC(thread_join)
163 case Lane::Error: 163 case Lane::Error:
164 { 164 {
165 LUA_ASSERT(L_, _stored == 2 || _stored == 3); 165 LUA_ASSERT(L_, _stored == 2 || _stored == 3);
166 lua_getiuservalue(L_, 1, 1); // L_: lane {uv} 166 lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv}
167 lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error> 167 lua_rawgeti(L_, 2, 2); // L_: lane {uv} <error>
168 lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil 168 lua_rawgeti(L_, 2, 3); // L_: lane {uv} <error> <trace>|nil
169 if (lua_isnil(L_, -1)) { 169 if (lua_isnil(L_, -1)) {
@@ -178,11 +178,11 @@ static LUAG_FUNC(thread_join)
178 178
179 case Lane::Cancelled: 179 case Lane::Cancelled:
180 LUA_ASSERT(L_, _stored == 2); 180 LUA_ASSERT(L_, _stored == 2);
181 lua_getiuservalue(L_, 1, 1); // L_: lane {uv} 181 lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane {uv}
182 lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error 182 lua_rawgeti(L_, 2, 2); // L_: lane {uv} cancel_error
183 lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil 183 lua_rawgeti(L_, 2, 1); // L_: lane {uv} cancel_error nil
184 lua_replace(L_, -3); // L_: lane nil cancel_error 184 lua_replace(L_, -3); // L_: lane nil cancel_error
185 LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, -1)); 185 LUA_ASSERT(L_, lua_isnil(L_, -2) && kCancelError.equals(L_, kIdxTop));
186 _ret = 2; 186 _ret = 2;
187 break; 187 break;
188 188
@@ -199,8 +199,8 @@ static LUAG_FUNC(thread_join)
199 199
200LUAG_FUNC(thread_resume) 200LUAG_FUNC(thread_resume)
201{ 201{
202 static constexpr int kSelf{ 1 }; 202 static constexpr StackIndex kIdxSelf{ 1 };
203 Lane* const _lane{ ToLane(L_, kSelf) }; 203 Lane* const _lane{ ToLane(L_, kIdxSelf) };
204 lua_State* const _L2{ _lane->L }; 204 lua_State* const _L2{ _lane->L };
205 205
206 // wait until the lane yields 206 // wait until the lane yields
@@ -225,7 +225,7 @@ LUAG_FUNC(thread_resume)
225 STACK_CHECK_START_ABS(_L2, _nresults); 225 STACK_CHECK_START_ABS(_L2, _nresults);
226 226
227 // clear any fetched returned values that we might have stored previously 227 // clear any fetched returned values that we might have stored previously
228 _lane->resetResultsStorage(L_, 1); 228 _lane->resetResultsStorage(L_, kIdxSelf);
229 229
230 // to retrieve the yielded value of the coroutine on our stack 230 // to retrieve the yielded value of the coroutine on our stack
231 InterCopyContext _cin{ _lane->U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} }; 231 InterCopyContext _cin{ _lane->U, DestState{ L_ }, SourceState{ _L2 }, {}, {}, {}, {}, {} };
@@ -254,9 +254,9 @@ LUAG_FUNC(thread_resume)
254// Else If key is found in the environment, return it 254// Else If key is found in the environment, return it
255static int thread_index_number(lua_State* L_) 255static int thread_index_number(lua_State* L_)
256{ 256{
257 static constexpr int kSelf{ 1 }; 257 static constexpr StackIndex kIdxSelf{ 1 };
258 258
259 Lane* const _lane{ ToLane(L_, kSelf) }; 259 Lane* const _lane{ ToLane(L_, kIdxSelf) };
260 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane n 260 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane n
261 int const _key{ static_cast<int>(lua_tointeger(L_, 2)) }; 261 int const _key{ static_cast<int>(lua_tointeger(L_, 2)) };
262 lua_pop(L_, 1); // L_: lane 262 lua_pop(L_, 1); // L_: lane
@@ -284,13 +284,13 @@ static int thread_index_number(lua_State* L_)
284// Else raise an error 284// Else raise an error
285static int thread_index_string(lua_State* L_) 285static int thread_index_string(lua_State* L_)
286{ 286{
287 static constexpr int kSelf{ 1 }; 287 static constexpr StackIndex kIdxSelf{ 1 };
288 static constexpr int kKey{ 2 }; 288 static constexpr StackIndex kIdxKey{ 2 };
289 289
290 Lane* const _lane{ ToLane(L_, kSelf) }; 290 Lane* const _lane{ ToLane(L_, kIdxSelf) };
291 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key" 291 LUA_ASSERT(L_, lua_gettop(L_) == 2); // L_: lane "key"
292 292
293 std::string_view const _keystr{ luaG_tostring(L_, kKey) }; 293 std::string_view const _keystr{ luaG_tostring(L_, kIdxKey) };
294 lua_settop(L_, 2); // keep only our original arguments on the stack 294 lua_settop(L_, 2); // keep only our original arguments on the stack
295 if (_keystr == "status") { 295 if (_keystr == "status") {
296 _lane->pushStatusString(L_); // L_: lane "key" "<status>" 296 _lane->pushStatusString(L_); // L_: lane "key" "<status>"
@@ -301,7 +301,7 @@ static int thread_index_string(lua_State* L_)
301 return 1; 301 return 1;
302 } 302 }
303 // return self.metatable[key] 303 // return self.metatable[key]
304 lua_getmetatable(L_, kSelf); // L_: lane "key" mt 304 lua_getmetatable(L_, kIdxSelf); // L_: lane "key" mt
305 lua_replace(L_, -3); // L_: mt "key" 305 lua_replace(L_, -3); // L_: mt "key"
306 lua_rawget(L_, -2); // L_: mt value 306 lua_rawget(L_, -2); // L_: mt value
307 // only "cancel" and "join" are registered as functions, any other string will raise an error 307 // only "cancel" and "join" are registered as functions, any other string will raise an error
@@ -316,9 +316,9 @@ static int thread_index_string(lua_State* L_)
316// lane:__index(key,usr) -> value 316// lane:__index(key,usr) -> value
317static LUAG_FUNC(thread_index) 317static LUAG_FUNC(thread_index)
318{ 318{
319 static constexpr int kSelf{ 1 }; 319 static constexpr StackIndex kIdxSelf{ 1 };
320 static constexpr int kKey{ 2 }; 320 static constexpr StackIndex kKey{ 2 };
321 Lane* const _lane{ ToLane(L_, kSelf) }; 321 Lane* const _lane{ ToLane(L_, kIdxSelf) };
322 LUA_ASSERT(L_, lua_gettop(L_) == 2); 322 LUA_ASSERT(L_, lua_gettop(L_) == 2);
323 323
324 switch (luaG_type(L_, kKey)) { 324 switch (luaG_type(L_, kKey)) {
@@ -329,17 +329,17 @@ static LUAG_FUNC(thread_index)
329 return thread_index_string(L_); // stack modification is undefined, returned value is at the top 329 return thread_index_string(L_); // stack modification is undefined, returned value is at the top
330 330
331 default: // unknown key 331 default: // unknown key
332 lua_getmetatable(L_, kSelf); // L_: mt 332 lua_getmetatable(L_, kIdxSelf); // L_: mt
333 kCachedError.pushKey(L_); // L_: mt kCachedError 333 kCachedError.pushKey(L_); // L_: mt kCachedError
334 lua_rawget(L_, -2); // L_: mt error() 334 lua_rawget(L_, -2); // L_: mt error()
335 if (luaG_type(L_, -1) != LuaType::FUNCTION) { 335 if (luaG_type(L_, kIdxTop) != LuaType::FUNCTION) {
336 raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaG_typename(L_, -1).data()); 336 raise_luaL_error(L_, "INTERNAL ERROR: cached error() is a %s, not a function", luaG_typename(L_, kIdxTop).data());
337 } 337 }
338 luaG_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: " 338 luaG_pushstring(L_, "Unknown key: "); // L_: mt error() "Unknown key: "
339 kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring 339 kCachedTostring.pushKey(L_); // L_: mt error() "Unknown key: " kCachedTostring
340 lua_rawget(L_, -4); // L_: mt error() "Unknown key: " tostring() 340 lua_rawget(L_, -4); // L_: mt error() "Unknown key: " tostring()
341 if (luaG_type(L_, -1) != LuaType::FUNCTION) { 341 if (luaG_type(L_, kIdxTop) != LuaType::FUNCTION) {
342 raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaG_typename(L_, -1).data()); 342 raise_luaL_error(L_, "INTERNAL ERROR: cached tostring() is a %s, not a function", luaG_typename(L_, kIdxTop).data());
343 } 343 }
344 lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k 344 lua_pushvalue(L_, kKey); // L_: mt error() "Unknown key: " tostring() k
345 lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k" 345 lua_call(L_, 1, 1); // L_: mt error() "Unknown key: " "k"
@@ -417,7 +417,7 @@ int Lane::LuaErrorHandler(lua_State* L_)
417 417
418 // Don't do stack survey for cancelled lanes. 418 // Don't do stack survey for cancelled lanes.
419 // 419 //
420 if (kCancelError.equals(L_, 1)) { 420 if (kCancelError.equals(L_, StackIndex{ 1 })) {
421 return 1; // just pass on 421 return 1; // just pass on
422 } 422 }
423 423
@@ -436,6 +436,7 @@ int Lane::LuaErrorHandler(lua_State* L_)
436 // table of { "sourcefile.lua:<line>", ... } 436 // table of { "sourcefile.lua:<line>", ... }
437 // 437 //
438 lua_newtable(L_); // L_: some_error {} 438 lua_newtable(L_); // L_: some_error {}
439 StackIndex const kIdxTraceTbl{ luaG_absindex(L_, kIdxTop) };
439 440
440 // Best to start from level 1, but in some cases it might be a C function 441 // Best to start from level 1, but in some cases it might be a C function
441 // and we don't get '.currentline' for that. It's okay - just keep level 442 // and we don't get '.currentline' for that. It's okay - just keep level
@@ -446,27 +447,27 @@ int Lane::LuaErrorHandler(lua_State* L_)
446 lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar); 447 lua_getinfo(L_, _extended ? "Sln" : "Sl", &_ar);
447 if (_extended) { 448 if (_extended) {
448 lua_newtable(L_); // L_: some_error {} {} 449 lua_newtable(L_); // L_: some_error {} {}
449 450 StackIndex const kIdxFrameTbl{ luaG_absindex(L_, kIdxTop) };
450 lua_pushstring(L_, _ar.source); // L_: some_error {} {} source 451 lua_pushstring(L_, _ar.source); // L_: some_error {} {} source
451 luaG_setfield(L_, -2, std::string_view{ "source" }); // L_: some_error {} {} 452 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "source" }); // L_: some_error {} {}
452 453
453 lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline 454 lua_pushinteger(L_, _ar.currentline); // L_: some_error {} {} currentline
454 luaG_setfield(L_, -2, std::string_view{ "currentline" }); // L_: some_error {} {} 455 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "currentline" }); // L_: some_error {} {}
455 456
456 lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name 457 lua_pushstring(L_, _ar.name ? _ar.name : "<?>"); // L_: some_error {} {} name
457 luaG_setfield(L_, -2, std::string_view{ "name" }); // L_: some_error {} {} 458 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "name" }); // L_: some_error {} {}
458 459
459 lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat 460 lua_pushstring(L_, _ar.namewhat); // L_: some_error {} {} namewhat
460 luaG_setfield(L_, -2, std::string_view{ "namewhat" }); // L_: some_error {} {} 461 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "namewhat" }); // L_: some_error {} {}
461 462
462 lua_pushstring(L_, _ar.what); // L_: some_error {} {} what 463 lua_pushstring(L_, _ar.what); // L_: some_error {} {} what
463 luaG_setfield(L_, -2, std::string_view{ "what" }); // L_: some_error {} {} 464 luaG_setfield(L_, kIdxFrameTbl, std::string_view{ "what" }); // L_: some_error {} {}
464 } else if (_ar.currentline > 0) { 465 } else if (_ar.currentline > 0) {
465 luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah" 466 luaG_pushstring(L_, "%s:%d", _ar.short_src, _ar.currentline); // L_: some_error {} "blah:blah"
466 } else { 467 } else {
467 luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah" 468 luaG_pushstring(L_, "%s:?", _ar.short_src); // L_: some_error {} "blah"
468 } 469 }
469 lua_rawseti(L_, -2, static_cast<lua_Integer>(_n)); // L_: some_error {} 470 lua_rawseti(L_, kIdxTraceTbl, static_cast<lua_Integer>(_n)); // L_: some_error {}
470 } 471 }
471 472
472 // store the stack trace table in the registry 473 // store the stack trace table in the registry
@@ -480,10 +481,10 @@ int Lane::LuaErrorHandler(lua_State* L_)
480// ########################################## Finalizer ############################################ 481// ########################################## Finalizer ############################################
481// ################################################################################################# 482// #################################################################################################
482 483
483[[nodiscard]] static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] int const stk_base_) 484[[nodiscard]] static int PushStackTrace(lua_State* const L_, Lane::ErrorTraceLevel const errorTraceLevel_, LuaError const rc_, [[maybe_unused]] StackIndex const stk_base_)
484{ 485{
485 // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry 486 // Lua 5.1 error handler is limited to one return value; it stored the stack trace in the registry
486 int const _top{ lua_gettop(L_) }; 487 StackIndex const _top{ lua_gettop(L_) };
487 switch (rc_) { 488 switch (rc_) {
488 case LuaError::OK: // no error, body return values are on the stack 489 case LuaError::OK: // no error, body return values are on the stack
489 break; 490 break;
@@ -499,7 +500,7 @@ int Lane::LuaErrorHandler(lua_State* L_)
499 500
500 // For cancellation the error message is kCancelError, and a stack trace isn't placed 501 // For cancellation the error message is kCancelError, and a stack trace isn't placed
501 // For other errors, the message can be whatever was thrown, and we should have a stack trace table 502 // For other errors, the message can be whatever was thrown, and we should have a stack trace table
502 LUA_ASSERT(L_, luaG_type(L_, 1 + stk_base_) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE)); 503 LUA_ASSERT(L_, luaG_type(L_, StackIndex{ 1 + stk_base_ }) == (kCancelError.equals(L_, stk_base_) ? LuaType::NIL : LuaType::TABLE));
503 // Just leaving the stack trace table on the stack is enough to get it through to the master. 504 // Just leaving the stack trace table on the stack is enough to get it through to the master.
504 } else { 505 } else {
505 // any kind of error can be thrown with error(), or through a lane/linda cancellation 506 // any kind of error can be thrown with error(), or through a lane/linda cancellation
@@ -544,7 +545,7 @@ int Lane::LuaErrorHandler(lua_State* L_)
544 545
545 STACK_GROW(_L, 5); 546 STACK_GROW(_L, 5);
546 547
547 int const _finalizers{ lua_gettop(_L) }; 548 StackIndex const _finalizers{ lua_gettop(_L) };
548 // always push something as error handler, to have the same stack structure 549 // always push something as error handler, to have the same stack structure
549 int const _error_handler{ (errorTraceLevel_ != Lane::Minimal) 550 int const _error_handler{ (errorTraceLevel_ != Lane::Minimal)
550 ? (lua_pushcfunction(_L, Lane::LuaErrorHandler), lua_gettop(_L)) 551 ? (lua_pushcfunction(_L, Lane::LuaErrorHandler), lua_gettop(_L))
@@ -581,7 +582,8 @@ int Lane::LuaErrorHandler(lua_State* L_)
581 // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace 582 // if no error from the main body, finalizer doesn't receive any argument, else it gets the error message and optional stack trace
582 _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2? 583 _rc = ToLuaError(lua_pcall(_L, _args, 0, _error_handler)); // _L: ... finalizers error_handler() err_msg2?
583 if (_rc != LuaError::OK) { 584 if (_rc != LuaError::OK) {
584 _finalizer_pushed = 1 + PushStackTrace(_L, errorTraceLevel_, _rc, lua_gettop(_L)); // _L: ... finalizers error_handler() err_msg2? trace 585 StackIndex const _top{ lua_gettop(_L) };
586 _finalizer_pushed = 1 + PushStackTrace(_L, errorTraceLevel_, _rc, _top); // _L: ... finalizers error_handler() err_msg2? trace
585 // If one finalizer fails, don't run the others. Return this 587 // If one finalizer fails, don't run the others. Return this
586 // as the 'real' error, replacing what we could have had (or not) 588 // as the 'real' error, replacing what we could have had (or not)
587 // from the actual code. 589 // from the actual code.
@@ -610,7 +612,7 @@ int Lane::LuaErrorHandler(lua_State* L_)
610 612
611 if (lane_->isCoroutine()) { 613 if (lane_->isCoroutine()) {
612 // only the coroutine thread should remain on the master state when we are done 614 // only the coroutine thread should remain on the master state when we are done
613 LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaG_type(_L, 1) == LuaType::THREAD); 615 LUA_ASSERT(_L, lua_gettop(_L) == 1 && luaG_type(_L, StackIndex{ 1 }) == LuaType::THREAD);
614 } 616 }
615 617
616 return _rc; 618 return _rc;
@@ -670,7 +672,7 @@ static void PrepareLaneHelpers(Lane* const lane_)
670 lua_State* const _L{ lane_->L }; 672 lua_State* const _L{ lane_->L };
671 // Tie "set_finalizer()" to the state 673 // Tie "set_finalizer()" to the state
672 lua_pushcfunction(_L, LG_set_finalizer); 674 lua_pushcfunction(_L, LG_set_finalizer);
673 tools::PopulateFuncLookupTable(_L, -1, "set_finalizer"); 675 tools::PopulateFuncLookupTable(_L, kIdxTop, "set_finalizer");
674 lua_setglobal(_L, "set_finalizer"); 676 lua_setglobal(_L, "set_finalizer");
675 677
676 // Tie "lane_threadname()" to the state 678 // Tie "lane_threadname()" to the state
@@ -681,7 +683,7 @@ static void PrepareLaneHelpers(Lane* const lane_)
681 683
682 // Tie "cancel_test()" to the state 684 // Tie "cancel_test()" to the state
683 lua_pushcfunction(_L, LG_cancel_test); 685 lua_pushcfunction(_L, LG_cancel_test);
684 tools::PopulateFuncLookupTable(_L, -1, "cancel_test"); 686 tools::PopulateFuncLookupTable(_L, kIdxTop, "cancel_test");
685 lua_setglobal(_L, "cancel_test"); 687 lua_setglobal(_L, "cancel_test");
686} 688}
687 689
@@ -752,7 +754,7 @@ static void lane_main(Lane* const lane_)
752 } 754 }
753 755
754 // in case of error and if it exists, fetch stack trace from registry and push it 756 // in case of error and if it exists, fetch stack trace from registry and push it
755 lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, 1); // L: retvals|error [trace] 757 lane_->nresults += PushStackTrace(_L, lane_->errorTraceLevel, _rc, StackIndex{ 1 }); // L: retvals|error [trace]
756 758
757 DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl); 759 DEBUGSPEW_CODE(DebugSpew(lane_->U) << "Lane " << _L << " body: " << GetErrcodeName(_rc) << " (" << (kCancelError.equals(_L, 1) ? "cancelled" : luaG_typename(_L, 1)) << ")" << std::endl);
758 // Call finalizers, if the script has set them up. 760 // Call finalizers, if the script has set them up.
@@ -782,7 +784,7 @@ static void lane_main(Lane* const lane_)
782 } 784 }
783 785
784 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them 786 // leave results (1..top) or error message + stack trace (1..2) on the stack - master will copy them
785 Lane::Status const _st{ (_rc == LuaError::OK) ? Lane::Done : kCancelError.equals(_L, 1) ? Lane::Cancelled : Lane::Error }; 787 Lane::Status const _st{ (_rc == LuaError::OK) ? Lane::Done : kCancelError.equals(_L, StackIndex{ 1 }) ? Lane::Cancelled : Lane::Error };
786 // 'doneMutex' protects the -> Done|Error|Cancelled state change, and the Running|Suspended|Resuming state change too 788 // 'doneMutex' protects the -> Done|Error|Cancelled state change, and the Running|Suspended|Resuming state change too
787 std::lock_guard _guard{ lane_->doneMutex }; 789 std::lock_guard _guard{ lane_->doneMutex };
788 lane_->status = _st; 790 lane_->status = _st;
@@ -794,7 +796,7 @@ static void lane_main(Lane* const lane_)
794#if LUA_VERSION_NUM >= 504 796#if LUA_VERSION_NUM >= 504
795static LUAG_FUNC(lane_close) 797static LUAG_FUNC(lane_close)
796{ 798{
797 [[maybe_unused]] Lane* const _lane{ ToLane(L_, 1) }; // L_: lane err|nil 799 [[maybe_unused]] Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: lane err|nil
798 // drop the error if any 800 // drop the error if any
799 lua_settop(L_, 1); // L_: lane 801 lua_settop(L_, 1); // L_: lane
800 802
@@ -823,10 +825,10 @@ static LUAG_FUNC(lane_close)
823static LUAG_FUNC(lane_gc) 825static LUAG_FUNC(lane_gc)
824{ 826{
825 bool _have_gc_cb{ false }; 827 bool _have_gc_cb{ false };
826 Lane* const _lane{ ToLane(L_, 1) }; // L_: ud 828 Lane* const _lane{ ToLane(L_, StackIndex{ 1 }) }; // L_: ud
827 829
828 // if there a gc callback? 830 // if there a gc callback?
829 lua_getiuservalue(L_, 1, 1); // L_: ud uservalue 831 lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: ud uservalue
830 kLaneGC.pushKey(L_); // L_: ud uservalue __gc 832 kLaneGC.pushKey(L_); // L_: ud uservalue __gc
831 lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil 833 lua_rawget(L_, -2); // L_: ud uservalue gc_cb|nil
832 if (!lua_isnil(L_, -1)) { 834 if (!lua_isnil(L_, -1)) {
@@ -932,7 +934,7 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono:
932 934
933// ################################################################################################# 935// #################################################################################################
934 936
935[[nodiscard]] CancelResult Lane::cancelHard(std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_) 937[[nodiscard]] CancelResult Lane::cancelHard(std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_)
936{ 938{
937 cancelRequest = CancelRequest::Hard; // it's now signaled to stop 939 cancelRequest = CancelRequest::Hard; // it's now signaled to stop
938 // lane_->thread.get_stop_source().request_stop(); 940 // lane_->thread.get_stop_source().request_stop();
@@ -949,7 +951,7 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono:
949 951
950// ################################################################################################# 952// #################################################################################################
951 953
952[[nodiscard]] CancelResult Lane::cancelSoft(std::chrono::time_point<std::chrono::steady_clock> until_, bool wakeLane_) 954[[nodiscard]] CancelResult Lane::cancelSoft(std::chrono::time_point<std::chrono::steady_clock> const until_, bool const wakeLane_)
953{ 955{
954 cancelRequest = CancelRequest::Soft; // it's now signaled to stop 956 cancelRequest = CancelRequest::Soft; // it's now signaled to stop
955 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own 957 // negative timeout: we don't want to truly abort the lane, we just want it to react to cancel_test() on its own
@@ -966,9 +968,9 @@ CancelResult Lane::cancel(CancelOp const op_, int const hookCount_, std::chrono:
966 968
967// ################################################################################################# 969// #################################################################################################
968 970
969void Lane::changeDebugName(int const nameIdx_) 971void Lane::changeDebugName(StackIndex const nameIdx_)
970{ 972{
971 int const _nameIdx{ luaG_absindex(L, nameIdx_) }; 973 StackIndex const _nameIdx{ luaG_absindex(L, nameIdx_) };
972 luaL_checktype(L, _nameIdx, LUA_TSTRING); // L: ... "name" ... 974 luaL_checktype(L, _nameIdx, LUA_TSTRING); // L: ... "name" ...
973 STACK_CHECK_START_REL(L, 0); 975 STACK_CHECK_START_REL(L, 0);
974 // 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... 976 // 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...
@@ -1064,11 +1066,11 @@ void Lane::pushStatusString(lua_State* L_) const
1064 1066
1065void Lane::pushIndexedResult(lua_State* const L_, int const key_) const 1067void Lane::pushIndexedResult(lua_State* const L_, int const key_) const
1066{ 1068{
1067 static constexpr int kSelf{ 1 }; 1069 static constexpr StackIndex kIdxSelf{ 1 };
1068 LUA_ASSERT(L_, ToLane(L_, kSelf) == this); // L_: lane ... 1070 LUA_ASSERT(L_, ToLane(L_, kIdxSelf) == this); // L_: lane ...
1069 STACK_GROW(L_, 3); 1071 STACK_GROW(L_, 3);
1070 1072
1071 lua_getiuservalue(L_, kSelf, 1); // L_: lane ... {uv} 1073 lua_getiuservalue(L_, kIdxSelf, 1); // L_: lane ... {uv}
1072 if (status != Lane::Error) { 1074 if (status != Lane::Error) {
1073 lua_rawgeti(L_, -1, key_); // L_: lane ... {uv} uv[i] 1075 lua_rawgeti(L_, -1, key_); // L_: lane ... {uv} uv[i]
1074 lua_remove(L_, -2); // L_: lane ... uv[i] 1076 lua_remove(L_, -2); // L_: lane ... uv[i]
@@ -1083,7 +1085,7 @@ void Lane::pushIndexedResult(lua_State* const L_, int const key_) const
1083 lua_remove(L_, -2); // L_: lane ... <error> 1085 lua_remove(L_, -2); // L_: lane ... <error>
1084 return; 1086 return;
1085 } 1087 }
1086 lua_getmetatable(L_, kSelf); // L_: lane ... {uv} <error> {mt} 1088 lua_getmetatable(L_, kIdxSelf); // L_: lane ... {uv} <error> {mt}
1087 lua_replace(L_, -3); // L_: lane ... {mt} <error> 1089 lua_replace(L_, -3); // L_: lane ... {mt} <error>
1088 // Note: Lua 5.1 interpreter is not prepared to show 1090 // Note: Lua 5.1 interpreter is not prepared to show
1089 // non-string errors, so we use 'tostring()' here 1091 // non-string errors, so we use 'tostring()' here
@@ -1127,11 +1129,11 @@ void Lane::pushIndexedResult(lua_State* const L_, int const key_) const
1127 1129
1128// replace the current uservalue (a table holding the returned values of the lane body) 1130// replace the current uservalue (a table holding the returned values of the lane body)
1129// by a new empty one, but transfer the gc_cb that is stored in there so that it is not lost 1131// by a new empty one, but transfer the gc_cb that is stored in there so that it is not lost
1130void Lane::resetResultsStorage(lua_State* const L_, int const self_idx_) 1132void Lane::resetResultsStorage(lua_State* const L_, StackIndex const self_idx_)
1131{ 1133{
1132 STACK_GROW(L_, 4); 1134 STACK_GROW(L_, 4);
1133 STACK_CHECK_START_REL(L_, 0); 1135 STACK_CHECK_START_REL(L_, 0);
1134 int const _self_idx{ luaG_absindex(L_, self_idx_) }; 1136 StackIndex const _self_idx{ luaG_absindex(L_, self_idx_) };
1135 LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ... 1137 LUA_ASSERT(L_, ToLane(L_, _self_idx) == this); // L_: ... self ...
1136 // create the new table 1138 // create the new table
1137 lua_newtable(L_); // L_: ... self ... {} 1139 lua_newtable(L_); // L_: ... self ... {}
@@ -1154,12 +1156,12 @@ void Lane::resetResultsStorage(lua_State* const L_, int const self_idx_)
1154// ################################################################################################# 1156// #################################################################################################
1155 1157
1156// intern the debug name in the caller lua state so that the pointer remains valid after the lane's state is closed 1158// intern the debug name in the caller lua state so that the pointer remains valid after the lane's state is closed
1157void Lane::securizeDebugName(lua_State* L_) 1159void Lane::securizeDebugName(lua_State* const L_)
1158{ 1160{
1159 STACK_CHECK_START_REL(L_, 0); 1161 STACK_CHECK_START_REL(L_, 0);
1160 STACK_GROW(L_, 3); 1162 STACK_GROW(L_, 3);
1161 // a Lane's uservalue should be a table 1163 // a Lane's uservalue should be a table
1162 lua_getiuservalue(L_, 1, 1); // L_: lane ... {uv} 1164 lua_getiuservalue(L_, StackIndex{ 1 }, 1); // L_: lane ... {uv}
1163 LUA_ASSERT(L_, lua_istable(L_, -1)); 1165 LUA_ASSERT(L_, lua_istable(L_, -1));
1164 // we don't care about the actual key, so long as it's unique and can't collide with anything. 1166 // we don't care about the actual key, so long as it's unique and can't collide with anything.
1165 lua_newtable(L_); // L_: lane ... {uv} {} 1167 lua_newtable(L_); // L_: lane ... {uv} {}
@@ -1174,7 +1176,7 @@ void Lane::securizeDebugName(lua_State* L_)
1174 1176
1175// ################################################################################################# 1177// #################################################################################################
1176 1178
1177void Lane::startThread(int priority_) 1179void Lane::startThread(int const priority_)
1178{ 1180{
1179 thread = std::thread([this]() { lane_main(this); }); 1181 thread = std::thread([this]() { lane_main(this); });
1180 if (priority_ != kThreadPrioDefault) { 1182 if (priority_ != kThreadPrioDefault) {
@@ -1189,12 +1191,12 @@ void Lane::startThread(int priority_)
1189// t[i] = result #i 1191// t[i] = result #i
1190int Lane::storeResults(lua_State* const L_) 1192int Lane::storeResults(lua_State* const L_)
1191{ 1193{
1192 static constexpr int kSelf{ 1 }; 1194 static constexpr StackIndex kIdxSelf{ 1 };
1193 LUA_ASSERT(L_, ToLane(L_, kSelf) == this); 1195 LUA_ASSERT(L_, ToLane(L_, kIdxSelf) == this);
1194 1196
1195 STACK_CHECK_START_REL(L_, 0); 1197 STACK_CHECK_START_REL(L_, 0);
1196 lua_getiuservalue(L_, kSelf, 1); // L_: lane ... {uv} 1198 lua_getiuservalue(L_, kIdxSelf, 1); // L_: lane ... {uv}
1197 int const _tidx{ lua_gettop(L_) }; 1199 StackIndex const _tidx{ lua_gettop(L_) };
1198 1200
1199 int _stored{}; 1201 int _stored{};
1200 if (nresults == 0) { 1202 if (nresults == 0) {
@@ -1252,7 +1254,7 @@ int Lane::storeResults(lua_State* const L_)
1252 case Lane::Cancelled: 1254 case Lane::Cancelled:
1253 _stored = 2; 1255 _stored = 2;
1254 // we should have a single value, kCancelError, in the stack of L 1256 // we should have a single value, kCancelError, in the stack of L
1255 LUA_ASSERT(L_, nresults == 1 && lua_gettop(L) == 1 && kCancelError.equals(L, 1)); 1257 LUA_ASSERT(L_, nresults == 1 && lua_gettop(L) == 1 && kCancelError.equals(L, StackIndex{ 1 }));
1256 // store nil, cancel_error in the results 1258 // store nil, cancel_error in the results
1257 lua_pushnil(L_); // L_: lane ... {uv} nil 1259 lua_pushnil(L_); // L_: lane ... {uv} nil
1258 lua_rawseti(L_, _tidx, 1); // L_: lane ... {uv} 1260 lua_rawseti(L_, _tidx, 1); // L_: lane ... {uv}